summaryrefslogtreecommitdiffstats
path: root/sw/source/uibase
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /sw/source/uibase
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/uibase')
-rw-r--r--sw/source/uibase/app/appenv.cxx497
-rw-r--r--sw/source/uibase/app/appenv.hxx19
-rw-r--r--sw/source/uibase/app/apphdl.cxx1128
-rw-r--r--sw/source/uibase/app/applab.cxx397
-rw-r--r--sw/source/uibase/app/appopt.cxx527
-rw-r--r--sw/source/uibase/app/docsh.cxx1433
-rw-r--r--sw/source/uibase/app/docsh2.cxx1805
-rw-r--r--sw/source/uibase/app/docshdrw.cxx100
-rw-r--r--sw/source/uibase/app/docshini.cxx711
-rw-r--r--sw/source/uibase/app/docst.cxx1693
-rw-r--r--sw/source/uibase/app/docstyle.cxx3380
-rw-r--r--sw/source/uibase/app/mainwn.cxx133
-rw-r--r--sw/source/uibase/app/swdll.cxx184
-rw-r--r--sw/source/uibase/app/swdllimpl.hxx45
-rw-r--r--sw/source/uibase/app/swmodul1.cxx693
-rw-r--r--sw/source/uibase/app/swmodule.cxx401
-rw-r--r--sw/source/uibase/app/swwait.cxx83
-rw-r--r--sw/source/uibase/chrdlg/ccoll.cxx161
-rw-r--r--sw/source/uibase/config/StoredChapterNumbering.cxx459
-rw-r--r--sw/source/uibase/config/barcfg.cxx124
-rw-r--r--sw/source/uibase/config/caption.cxx39
-rw-r--r--sw/source/uibase/config/cfgitems.cxx261
-rw-r--r--sw/source/uibase/config/dbconfig.cxx96
-rw-r--r--sw/source/uibase/config/fontcfg.cxx314
-rw-r--r--sw/source/uibase/config/modcfg.cxx1336
-rw-r--r--sw/source/uibase/config/prtopt.cxx168
-rw-r--r--sw/source/uibase/config/uinums.cxx260
-rw-r--r--sw/source/uibase/config/usrpref.cxx622
-rw-r--r--sw/source/uibase/config/viewopt.cxx631
-rw-r--r--sw/source/uibase/dbui/README48
-rw-r--r--sw/source/uibase/dbui/dbmgr.cxx3298
-rw-r--r--sw/source/uibase/dbui/dbtree.cxx454
-rw-r--r--sw/source/uibase/dbui/dbui.cxx86
-rw-r--r--sw/source/uibase/dbui/maildispatcher.cxx249
-rw-r--r--sw/source/uibase/dbui/mailmergehelper.cxx832
-rw-r--r--sw/source/uibase/dbui/mailmergetoolbarcontrols.cxx370
-rw-r--r--sw/source/uibase/dbui/mmconfigitem.cxx1708
-rw-r--r--sw/source/uibase/dialog/SwSpellDialogChildWindow.cxx828
-rw-r--r--sw/source/uibase/dialog/regionsw.cxx234
-rw-r--r--sw/source/uibase/dialog/swabstdlg.cxx55
-rw-r--r--sw/source/uibase/dialog/swwrtshitem.cxx40
-rw-r--r--sw/source/uibase/dialog/watermarkdialog.cxx119
-rw-r--r--sw/source/uibase/dialog/wordcountwrapper.cxx48
-rw-r--r--sw/source/uibase/dochdl/gloshdl.cxx725
-rw-r--r--sw/source/uibase/dochdl/swdtflvr.cxx4597
-rw-r--r--sw/source/uibase/docvw/AnchorOverlayObject.cxx385
-rw-r--r--sw/source/uibase/docvw/AnchorOverlayObject.hxx120
-rw-r--r--sw/source/uibase/docvw/AnnotationMenuButton.cxx111
-rw-r--r--sw/source/uibase/docvw/AnnotationWin.cxx495
-rw-r--r--sw/source/uibase/docvw/AnnotationWin2.cxx1436
-rw-r--r--sw/source/uibase/docvw/DashedLine.cxx91
-rw-r--r--sw/source/uibase/docvw/FrameControlsManager.cxx296
-rw-r--r--sw/source/uibase/docvw/HeaderFooterWin.cxx594
-rw-r--r--sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx252
-rw-r--r--sw/source/uibase/docvw/OverlayRanges.cxx176
-rw-r--r--sw/source/uibase/docvw/OverlayRanges.hxx70
-rw-r--r--sw/source/uibase/docvw/PageBreakWin.cxx506
-rw-r--r--sw/source/uibase/docvw/PostItMgr.cxx2541
-rw-r--r--sw/source/uibase/docvw/ShadowOverlayObject.cxx241
-rw-r--r--sw/source/uibase/docvw/ShadowOverlayObject.hxx67
-rw-r--r--sw/source/uibase/docvw/SidebarTxtControl.cxx473
-rw-r--r--sw/source/uibase/docvw/SidebarTxtControl.hxx84
-rw-r--r--sw/source/uibase/docvw/SidebarWinAcc.cxx142
-rw-r--r--sw/source/uibase/docvw/SidebarWinAcc.hxx53
-rw-r--r--sw/source/uibase/docvw/UnfloatTableButton.cxx245
-rw-r--r--sw/source/uibase/docvw/contentcontrolaliasbutton.cxx151
-rw-r--r--sw/source/uibase/docvw/edtdd.cxx501
-rw-r--r--sw/source/uibase/docvw/edtwin.cxx6897
-rw-r--r--sw/source/uibase/docvw/edtwin2.cxx685
-rw-r--r--sw/source/uibase/docvw/edtwin3.cxx175
-rw-r--r--sw/source/uibase/docvw/frmsidebarwincontainer.cxx172
-rw-r--r--sw/source/uibase/docvw/frmsidebarwincontainer.hxx62
-rw-r--r--sw/source/uibase/docvw/romenu.cxx344
-rw-r--r--sw/source/uibase/docvw/romenu.hxx81
-rw-r--r--sw/source/uibase/docvw/srcedtw.cxx979
-rw-r--r--sw/source/uibase/envelp/envimg.cxx333
-rw-r--r--sw/source/uibase/envelp/labelcfg.cxx330
-rw-r--r--sw/source/uibase/envelp/labimg.cxx465
-rw-r--r--sw/source/uibase/envelp/syncbtn.cxx86
-rw-r--r--sw/source/uibase/fldui/fldmgr.cxx1932
-rw-r--r--sw/source/uibase/fldui/fldwrap.cxx132
-rw-r--r--sw/source/uibase/fldui/xfldui.cxx171
-rw-r--r--sw/source/uibase/frmdlg/colex.cxx602
-rw-r--r--sw/source/uibase/frmdlg/colmgr.cxx158
-rw-r--r--sw/source/uibase/frmdlg/frmmgr.cxx675
-rw-r--r--sw/source/uibase/globdoc/globdoc.cxx64
-rw-r--r--sw/source/uibase/inc/AccessibilityStatusBarControl.hxx36
-rw-r--r--sw/source/uibase/inc/DashedLine.hxx30
-rw-r--r--sw/source/uibase/inc/DateFormFieldDialog.hxx54
-rw-r--r--sw/source/uibase/inc/DropDownFieldDialog.hxx66
-rw-r--r--sw/source/uibase/inc/DropDownFormFieldDialog.hxx65
-rw-r--r--sw/source/uibase/inc/FrameControl.hxx84
-rw-r--r--sw/source/uibase/inc/FrameControlsManager.hxx58
-rw-r--r--sw/source/uibase/inc/HeaderFooterWin.hxx100
-rw-r--r--sw/source/uibase/inc/OutlineContentVisibilityWin.hxx57
-rw-r--r--sw/source/uibase/inc/PageBreakWin.hxx93
-rw-r--r--sw/source/uibase/inc/SidebarWindowsConsts.hxx33
-rw-r--r--sw/source/uibase/inc/SwSpellDialogChildWindow.hxx66
-rw-r--r--sw/source/uibase/inc/SwXFilterOptions.hxx81
-rw-r--r--sw/source/uibase/inc/UnfloatTableButton.hxx50
-rw-r--r--sw/source/uibase/inc/abstract.hxx36
-rw-r--r--sw/source/uibase/inc/addrdlg.hxx32
-rw-r--r--sw/source/uibase/inc/annotsh.hxx80
-rw-r--r--sw/source/uibase/inc/ascfldlg.hxx65
-rw-r--r--sw/source/uibase/inc/autoformatpreview.hxx82
-rw-r--r--sw/source/uibase/inc/barcfg.hxx46
-rw-r--r--sw/source/uibase/inc/basesh.hxx123
-rw-r--r--sw/source/uibase/inc/beziersh.hxx42
-rw-r--r--sw/source/uibase/inc/bmpwin.hxx53
-rw-r--r--sw/source/uibase/inc/bookctrl.hxx41
-rw-r--r--sw/source/uibase/inc/bookmark.hxx117
-rw-r--r--sw/source/uibase/inc/break.hxx69
-rw-r--r--sw/source/uibase/inc/caption.hxx89
-rw-r--r--sw/source/uibase/inc/cfgitems.hxx166
-rw-r--r--sw/source/uibase/inc/changedb.hxx60
-rw-r--r--sw/source/uibase/inc/chartins.hxx38
-rw-r--r--sw/source/uibase/inc/chldwrap.hxx47
-rw-r--r--sw/source/uibase/inc/chrdlg.hxx75
-rw-r--r--sw/source/uibase/inc/chrdlgmodes.hxx20
-rw-r--r--sw/source/uibase/inc/cnttab.hxx57
-rw-r--r--sw/source/uibase/inc/colex.hxx105
-rw-r--r--sw/source/uibase/inc/colmgr.hxx126
-rw-r--r--sw/source/uibase/inc/column.hxx203
-rw-r--r--sw/source/uibase/inc/conarc.hxx43
-rw-r--r--sw/source/uibase/inc/concustomshape.hxx58
-rw-r--r--sw/source/uibase/inc/condedit.hxx75
-rw-r--r--sw/source/uibase/inc/conform.hxx39
-rw-r--r--sw/source/uibase/inc/conpoly.hxx38
-rw-r--r--sw/source/uibase/inc/conrect.hxx45
-rw-r--r--sw/source/uibase/inc/content.hxx228
-rw-r--r--sw/source/uibase/inc/contentcontrolaliasbutton.hxx42
-rw-r--r--sw/source/uibase/inc/contentcontroldlg.hxx79
-rw-r--r--sw/source/uibase/inc/contentcontrollistitemdlg.hxx40
-rw-r--r--sw/source/uibase/inc/conttree.hxx423
-rw-r--r--sw/source/uibase/inc/convert.hxx68
-rw-r--r--sw/source/uibase/inc/cption.hxx83
-rw-r--r--sw/source/uibase/inc/dbconfig.hxx48
-rw-r--r--sw/source/uibase/inc/dbinsdlg.hxx162
-rw-r--r--sw/source/uibase/inc/dbtree.hxx68
-rw-r--r--sw/source/uibase/inc/dbui.hxx69
-rw-r--r--sw/source/uibase/inc/docfnote.hxx40
-rw-r--r--sw/source/uibase/inc/docstdlg.hxx61
-rw-r--r--sw/source/uibase/inc/drawbase.hxx74
-rw-r--r--sw/source/uibase/inc/drawsh.hxx56
-rw-r--r--sw/source/uibase/inc/drformsh.hxx45
-rw-r--r--sw/source/uibase/inc/drpcps.hxx165
-rw-r--r--sw/source/uibase/inc/drwbassh.hxx55
-rw-r--r--sw/source/uibase/inc/drwtxtsh.hxx85
-rw-r--r--sw/source/uibase/inc/dselect.hxx35
-rw-r--r--sw/source/uibase/inc/edtdd.hxx19
-rw-r--r--sw/source/uibase/inc/edtwin.hxx306
-rw-r--r--sw/source/uibase/inc/envimg.hxx89
-rw-r--r--sw/source/uibase/inc/envlop.hxx124
-rw-r--r--sw/source/uibase/inc/fldedt.hxx59
-rw-r--r--sw/source/uibase/inc/fldmgr.hxx203
-rw-r--r--sw/source/uibase/inc/fldtdlg.hxx68
-rw-r--r--sw/source/uibase/inc/fldwrap.hxx57
-rw-r--r--sw/source/uibase/inc/fontcfg.hxx113
-rw-r--r--sw/source/uibase/inc/formatclipboard.hxx95
-rw-r--r--sw/source/uibase/inc/frmdlg.hxx55
-rw-r--r--sw/source/uibase/inc/frmmgr.hxx177
-rw-r--r--sw/source/uibase/inc/frmpage.hxx330
-rw-r--r--sw/source/uibase/inc/frmsh.hxx54
-rw-r--r--sw/source/uibase/inc/globals.h31
-rw-r--r--sw/source/uibase/inc/glosbib.hxx80
-rw-r--r--sw/source/uibase/inc/glosdoc.hxx129
-rw-r--r--sw/source/uibase/inc/gloshdl.hxx100
-rw-r--r--sw/source/uibase/inc/gloslst.hxx82
-rw-r--r--sw/source/uibase/inc/glossary.hxx126
-rw-r--r--sw/source/uibase/inc/glshell.hxx83
-rw-r--r--sw/source/uibase/inc/grfsh.hxx56
-rw-r--r--sw/source/uibase/inc/hyp.hxx53
-rw-r--r--sw/source/uibase/inc/idxmrk.hxx60
-rw-r--r--sw/source/uibase/inc/imaildsplistener.hxx61
-rw-r--r--sw/source/uibase/inc/initui.hxx42
-rw-r--r--sw/source/uibase/inc/inpdlg.hxx68
-rw-r--r--sw/source/uibase/inc/inputwin.hxx211
-rw-r--r--sw/source/uibase/inc/insfnote.hxx84
-rw-r--r--sw/source/uibase/inc/instable.hxx89
-rw-r--r--sw/source/uibase/inc/javaedit.hxx77
-rw-r--r--sw/source/uibase/inc/label.hxx84
-rw-r--r--sw/source/uibase/inc/labelcfg.hxx61
-rw-r--r--sw/source/uibase/inc/labimg.hxx125
-rw-r--r--sw/source/uibase/inc/labimp.hxx36
-rw-r--r--sw/source/uibase/inc/labrec.hxx58
-rw-r--r--sw/source/uibase/inc/langhelper.hxx64
-rw-r--r--sw/source/uibase/inc/linenum.hxx61
-rw-r--r--sw/source/uibase/inc/listsh.hxx42
-rw-r--r--sw/source/uibase/inc/macassgn.hxx49
-rw-r--r--sw/source/uibase/inc/mailconfigpage.hxx78
-rw-r--r--sw/source/uibase/inc/maildispatcher.hxx156
-rw-r--r--sw/source/uibase/inc/mailmergehelper.hxx273
-rw-r--r--sw/source/uibase/inc/mailmergewizard.hxx85
-rw-r--r--sw/source/uibase/inc/mailmrge.hxx167
-rw-r--r--sw/source/uibase/inc/mediash.hxx46
-rw-r--r--sw/source/uibase/inc/mergetbl.hxx40
-rw-r--r--sw/source/uibase/inc/mmconfigitem.hxx259
-rw-r--r--sw/source/uibase/inc/multmrk.hxx45
-rw-r--r--sw/source/uibase/inc/navicfg.hxx144
-rw-r--r--sw/source/uibase/inc/navicont.hxx56
-rw-r--r--sw/source/uibase/inc/navipi.hxx180
-rw-r--r--sw/source/uibase/inc/navmgr.hxx58
-rw-r--r--sw/source/uibase/inc/navsh.hxx36
-rw-r--r--sw/source/uibase/inc/num.hxx138
-rw-r--r--sw/source/uibase/inc/numberingtypelistbox.hxx60
-rw-r--r--sw/source/uibase/inc/numfmtlb.hxx141
-rw-r--r--sw/source/uibase/inc/numpara.hxx88
-rw-r--r--sw/source/uibase/inc/numprevw.hxx67
-rw-r--r--sw/source/uibase/inc/olesh.hxx43
-rw-r--r--sw/source/uibase/inc/olmenu.hxx139
-rw-r--r--sw/source/uibase/inc/optcomp.hxx72
-rw-r--r--sw/source/uibase/inc/optload.hxx221
-rw-r--r--sw/source/uibase/inc/optpage.hxx482
-rw-r--r--sw/source/uibase/inc/outline.hxx122
-rw-r--r--sw/source/uibase/inc/pagenumberdlg.hxx62
-rw-r--r--sw/source/uibase/inc/pardlg.hxx28
-rw-r--r--sw/source/uibase/inc/pattern.hxx33
-rw-r--r--sw/source/uibase/inc/pgfnote.hxx66
-rw-r--r--sw/source/uibase/inc/pggrid.hxx91
-rw-r--r--sw/source/uibase/inc/prcntfld.hxx87
-rw-r--r--sw/source/uibase/inc/pview.hxx303
-rw-r--r--sw/source/uibase/inc/redlndlg.hxx172
-rw-r--r--sw/source/uibase/inc/regionsw.hxx255
-rw-r--r--sw/source/uibase/inc/rowht.hxx43
-rw-r--r--sw/source/uibase/inc/scroll.hxx48
-rw-r--r--sw/source/uibase/inc/selglos.hxx53
-rw-r--r--sw/source/uibase/inc/sharedconnection.hxx30
-rw-r--r--sw/source/uibase/inc/shdwcrsr.hxx46
-rw-r--r--sw/source/uibase/inc/splittbl.hxx71
-rw-r--r--sw/source/uibase/inc/srcedtw.hxx144
-rw-r--r--sw/source/uibase/inc/srcview.hxx88
-rw-r--r--sw/source/uibase/inc/srtdlg.hxx89
-rw-r--r--sw/source/uibase/inc/swcont.hxx108
-rw-r--r--sw/source/uibase/inc/swdtflvr.hxx251
-rw-r--r--sw/source/uibase/inc/swmessdialog.hxx27
-rw-r--r--sw/source/uibase/inc/swmodalredlineacceptdlg.hxx38
-rw-r--r--sw/source/uibase/inc/swrenamexnameddlg.hxx61
-rw-r--r--sw/source/uibase/inc/swruler.hxx119
-rw-r--r--sw/source/uibase/inc/swtablerep.hxx94
-rw-r--r--sw/source/uibase/inc/swuiccoll.hxx69
-rw-r--r--sw/source/uibase/inc/swuicnttab.hxx449
-rw-r--r--sw/source/uibase/inc/swuiidxmrk.hxx236
-rw-r--r--sw/source/uibase/inc/swuipardlg.hxx46
-rw-r--r--sw/source/uibase/inc/swwrtshitem.hxx42
-rw-r--r--sw/source/uibase/inc/syncbtn.hxx49
-rw-r--r--sw/source/uibase/inc/tabledlg.hxx40
-rw-r--r--sw/source/uibase/inc/tablemgr.hxx75
-rw-r--r--sw/source/uibase/inc/tabsh.hxx56
-rw-r--r--sw/source/uibase/inc/tautofmt.hxx89
-rw-r--r--sw/source/uibase/inc/tblnumfm.hxx41
-rw-r--r--sw/source/uibase/inc/textsh.hxx91
-rw-r--r--sw/source/uibase/inc/titlepage.hxx65
-rw-r--r--sw/source/uibase/inc/tmpdlg.hxx55
-rw-r--r--sw/source/uibase/inc/tmplctrl.hxx44
-rw-r--r--sw/source/uibase/inc/toxmgr.hxx275
-rw-r--r--sw/source/uibase/inc/translatehelper.hxx49
-rw-r--r--sw/source/uibase/inc/translatelangselect.hxx68
-rw-r--r--sw/source/uibase/inc/uiborder.hxx39
-rw-r--r--sw/source/uibase/inc/uiitems.hxx108
-rw-r--r--sw/source/uibase/inc/uinums.hxx119
-rw-r--r--sw/source/uibase/inc/uiobject.hxx85
-rw-r--r--sw/source/uibase/inc/uitool.hxx115
-rw-r--r--sw/source/uibase/inc/uivwimp.hxx173
-rw-r--r--sw/source/uibase/inc/unoatxt.hxx254
-rw-r--r--sw/source/uibase/inc/unodispatch.hxx121
-rw-r--r--sw/source/uibase/inc/unomailmerge.hxx175
-rw-r--r--sw/source/uibase/inc/unomod.hxx139
-rw-r--r--sw/source/uibase/inc/unotools.hxx90
-rw-r--r--sw/source/uibase/inc/unotxvw.hxx250
-rw-r--r--sw/source/uibase/inc/usrpref.hxx273
-rw-r--r--sw/source/uibase/inc/viewlayoutctrl.hxx47
-rw-r--r--sw/source/uibase/inc/watermarkdialog.hxx40
-rw-r--r--sw/source/uibase/inc/wformsh.hxx39
-rw-r--r--sw/source/uibase/inc/wfrmsh.hxx41
-rw-r--r--sw/source/uibase/inc/wgrfsh.hxx39
-rw-r--r--sw/source/uibase/inc/wlistsh.hxx38
-rw-r--r--sw/source/uibase/inc/wolesh.hxx40
-rw-r--r--sw/source/uibase/inc/wordcountctrl.hxx36
-rw-r--r--sw/source/uibase/inc/wordcountdialog.hxx77
-rw-r--r--sw/source/uibase/inc/workctrl.hxx190
-rw-r--r--sw/source/uibase/inc/wrap.hxx100
-rw-r--r--sw/source/uibase/inc/wrtsh.hxx724
-rw-r--r--sw/source/uibase/inc/wtabsh.hxx38
-rw-r--r--sw/source/uibase/inc/wtextsh.hxx37
-rw-r--r--sw/source/uibase/inc/wview.hxx43
-rw-r--r--sw/source/uibase/inc/zoomctrl.hxx41
-rw-r--r--sw/source/uibase/index/idxmrk.cxx73
-rw-r--r--sw/source/uibase/index/toxmgr.cxx495
-rw-r--r--sw/source/uibase/lingu/hhcwrp.cxx680
-rw-r--r--sw/source/uibase/lingu/hyp.cxx124
-rw-r--r--sw/source/uibase/lingu/olmenu.cxx885
-rw-r--r--sw/source/uibase/lingu/sdrhhcwrap.cxx165
-rw-r--r--sw/source/uibase/lingu/sdrhhcwrap.hxx53
-rw-r--r--sw/source/uibase/misc/glosdoc.cxx622
-rw-r--r--sw/source/uibase/misc/glshell.cxx270
-rw-r--r--sw/source/uibase/misc/numberingtypelistbox.cxx138
-rw-r--r--sw/source/uibase/misc/redlndlg.cxx1550
-rw-r--r--sw/source/uibase/misc/swruler.cxx367
-rw-r--r--sw/source/uibase/ribbar/conarc.cxx101
-rw-r--r--sw/source/uibase/ribbar/concustomshape.cxx196
-rw-r--r--sw/source/uibase/ribbar/conform.cxx112
-rw-r--r--sw/source/uibase/ribbar/conpoly.cxx103
-rw-r--r--sw/source/uibase/ribbar/conrect.cxx214
-rw-r--r--sw/source/uibase/ribbar/drawbase.cxx576
-rw-r--r--sw/source/uibase/ribbar/dselect.cxx44
-rw-r--r--sw/source/uibase/ribbar/inputwin.cxx640
-rw-r--r--sw/source/uibase/ribbar/workctrl.cxx900
-rw-r--r--sw/source/uibase/shells/annotsh.cxx1855
-rw-r--r--sw/source/uibase/shells/basesh.cxx3372
-rw-r--r--sw/source/uibase/shells/beziersh.cxx325
-rw-r--r--sw/source/uibase/shells/drawdlg.cxx368
-rw-r--r--sw/source/uibase/shells/drawsh.cxx629
-rw-r--r--sw/source/uibase/shells/drformsh.cxx251
-rw-r--r--sw/source/uibase/shells/drwbassh.cxx1245
-rw-r--r--sw/source/uibase/shells/drwtxtex.cxx1241
-rw-r--r--sw/source/uibase/shells/drwtxtsh.cxx849
-rw-r--r--sw/source/uibase/shells/frmsh.cxx1463
-rw-r--r--sw/source/uibase/shells/grfsh.cxx1018
-rw-r--r--sw/source/uibase/shells/grfshex.cxx155
-rw-r--r--sw/source/uibase/shells/langhelper.cxx549
-rw-r--r--sw/source/uibase/shells/listsh.cxx264
-rw-r--r--sw/source/uibase/shells/mediash.cxx99
-rw-r--r--sw/source/uibase/shells/navsh.cxx100
-rw-r--r--sw/source/uibase/shells/olesh.cxx95
-rw-r--r--sw/source/uibase/shells/slotadd.cxx134
-rw-r--r--sw/source/uibase/shells/tabsh.cxx1682
-rw-r--r--sw/source/uibase/shells/textdrw.cxx126
-rw-r--r--sw/source/uibase/shells/textfld.cxx1805
-rw-r--r--sw/source/uibase/shells/textglos.cxx126
-rw-r--r--sw/source/uibase/shells/textidx.cxx324
-rw-r--r--sw/source/uibase/shells/textsh.cxx1107
-rw-r--r--sw/source/uibase/shells/textsh1.cxx2822
-rw-r--r--sw/source/uibase/shells/textsh2.cxx252
-rw-r--r--sw/source/uibase/shells/translatehelper.cxx216
-rw-r--r--sw/source/uibase/shells/txtattr.cxx849
-rw-r--r--sw/source/uibase/shells/txtcrsr.cxx464
-rw-r--r--sw/source/uibase/shells/txtnum.cxx330
-rw-r--r--sw/source/uibase/sidebar/A11yCheckIssuesPanel.cxx377
-rw-r--r--sw/source/uibase/sidebar/A11yCheckIssuesPanel.hxx106
-rw-r--r--sw/source/uibase/sidebar/PageColumnControl.cxx123
-rw-r--r--sw/source/uibase/sidebar/PageColumnControl.hxx56
-rw-r--r--sw/source/uibase/sidebar/PageColumnPopup.cxx75
-rw-r--r--sw/source/uibase/sidebar/PageFooterPanel.cxx285
-rw-r--r--sw/source/uibase/sidebar/PageFooterPanel.hxx101
-rw-r--r--sw/source/uibase/sidebar/PageFormatPanel.cxx418
-rw-r--r--sw/source/uibase/sidebar/PageFormatPanel.hxx103
-rw-r--r--sw/source/uibase/sidebar/PageHeaderPanel.cxx287
-rw-r--r--sw/source/uibase/sidebar/PageHeaderPanel.hxx99
-rw-r--r--sw/source/uibase/sidebar/PageMarginControl.cxx597
-rw-r--r--sw/source/uibase/sidebar/PageMarginControl.hxx114
-rw-r--r--sw/source/uibase/sidebar/PageMarginPopup.cxx75
-rw-r--r--sw/source/uibase/sidebar/PageMarginUtils.hxx194
-rw-r--r--sw/source/uibase/sidebar/PageOrientationControl.cxx197
-rw-r--r--sw/source/uibase/sidebar/PageOrientationControl.hxx57
-rw-r--r--sw/source/uibase/sidebar/PageOrientationPopup.cxx75
-rw-r--r--sw/source/uibase/sidebar/PageSizeControl.cxx237
-rw-r--r--sw/source/uibase/sidebar/PageSizeControl.hxx65
-rw-r--r--sw/source/uibase/sidebar/PageSizePopup.cxx75
-rw-r--r--sw/source/uibase/sidebar/PageStylesPanel.cxx619
-rw-r--r--sw/source/uibase/sidebar/PageStylesPanel.hxx115
-rw-r--r--sw/source/uibase/sidebar/StylePresetsPanel.cxx205
-rw-r--r--sw/source/uibase/sidebar/StylePresetsPanel.hxx63
-rw-r--r--sw/source/uibase/sidebar/SwPanelFactory.cxx220
-rw-r--r--sw/source/uibase/sidebar/TableEditPanel.cxx233
-rw-r--r--sw/source/uibase/sidebar/TableEditPanel.hxx85
-rw-r--r--sw/source/uibase/sidebar/ThemePanel.cxx111
-rw-r--r--sw/source/uibase/sidebar/ThemePanel.hxx55
-rw-r--r--sw/source/uibase/sidebar/WrapPropertyPanel.cxx175
-rw-r--r--sw/source/uibase/sidebar/WrapPropertyPanel.hxx87
-rw-r--r--sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx773
-rw-r--r--sw/source/uibase/sidebar/WriterInspectorTextPanel.hxx50
-rw-r--r--sw/source/uibase/table/chartins.cxx231
-rw-r--r--sw/source/uibase/table/swtablerep.cxx149
-rw-r--r--sw/source/uibase/table/tablemgr.cxx352
-rw-r--r--sw/source/uibase/table/tablepg.hxx185
-rw-r--r--sw/source/uibase/uitest/uiobject.cxx249
-rw-r--r--sw/source/uibase/uiview/formatclipboard.cxx590
-rw-r--r--sw/source/uibase/uiview/pview.cxx1905
-rw-r--r--sw/source/uibase/uiview/scroll.cxx116
-rw-r--r--sw/source/uibase/uiview/srcview.cxx839
-rw-r--r--sw/source/uibase/uiview/swcli.cxx193
-rw-r--r--sw/source/uibase/uiview/uivwimp.cxx333
-rw-r--r--sw/source/uibase/uiview/view.cxx2120
-rw-r--r--sw/source/uibase/uiview/view0.cxx770
-rw-r--r--sw/source/uibase/uiview/view1.cxx213
-rw-r--r--sw/source/uibase/uiview/view2.cxx3197
-rw-r--r--sw/source/uibase/uiview/viewcoll.cxx78
-rw-r--r--sw/source/uibase/uiview/viewdlg.cxx66
-rw-r--r--sw/source/uibase/uiview/viewdlg2.cxx305
-rw-r--r--sw/source/uibase/uiview/viewdraw.cxx755
-rw-r--r--sw/source/uibase/uiview/viewfunc.hxx54
-rw-r--r--sw/source/uibase/uiview/viewling.cxx856
-rw-r--r--sw/source/uibase/uiview/viewmdi.cxx791
-rw-r--r--sw/source/uibase/uiview/viewport.cxx1262
-rw-r--r--sw/source/uibase/uiview/viewprt.cxx376
-rw-r--r--sw/source/uibase/uiview/viewsrch.cxx895
-rw-r--r--sw/source/uibase/uiview/viewstat.cxx691
-rw-r--r--sw/source/uibase/uiview/viewtab.cxx2562
-rw-r--r--sw/source/uibase/uno/SwXDocumentSettings.cxx1709
-rw-r--r--sw/source/uibase/uno/SwXDocumentSettings.hxx78
-rw-r--r--sw/source/uibase/uno/SwXFilterOptions.cxx147
-rw-r--r--sw/source/uibase/uno/dlelstnr.cxx134
-rw-r--r--sw/source/uibase/uno/loktxdoc.cxx492
-rw-r--r--sw/source/uibase/uno/unoatxt.cxx993
-rw-r--r--sw/source/uibase/uno/unodefaults.cxx46
-rw-r--r--sw/source/uibase/uno/unodefaults.hxx36
-rw-r--r--sw/source/uibase/uno/unodispatch.cxx374
-rw-r--r--sw/source/uibase/uno/unodoc.cxx93
-rw-r--r--sw/source/uibase/uno/unomailmerge.cxx1168
-rw-r--r--sw/source/uibase/uno/unomod.cxx976
-rw-r--r--sw/source/uibase/uno/unomodule.cxx150
-rw-r--r--sw/source/uibase/uno/unomodule.hxx74
-rw-r--r--sw/source/uibase/uno/unotxdoc.cxx4816
-rw-r--r--sw/source/uibase/uno/unotxvw.cxx1707
-rw-r--r--sw/source/uibase/utlui/AccessibilityStatusBarControl.cxx81
-rw-r--r--sw/source/uibase/utlui/attrdesc.cxx846
-rw-r--r--sw/source/uibase/utlui/bookctrl.cxx112
-rw-r--r--sw/source/uibase/utlui/condedit.cxx84
-rw-r--r--sw/source/uibase/utlui/content.cxx6647
-rw-r--r--sw/source/uibase/utlui/glbltree.cxx1185
-rw-r--r--sw/source/uibase/utlui/gloslst.cxx445
-rw-r--r--sw/source/uibase/utlui/gotodlg.cxx105
-rw-r--r--sw/source/uibase/utlui/initui.cxx311
-rw-r--r--sw/source/uibase/utlui/navicfg.cxx196
-rw-r--r--sw/source/uibase/utlui/navipi.cxx1277
-rw-r--r--sw/source/uibase/utlui/numfmtlb.cxx470
-rw-r--r--sw/source/uibase/utlui/prcntfld.cxx231
-rw-r--r--sw/source/uibase/utlui/shdwcrsr.cxx56
-rw-r--r--sw/source/uibase/utlui/tmplctrl.cxx121
-rw-r--r--sw/source/uibase/utlui/uiitems.cxx277
-rw-r--r--sw/source/uibase/utlui/uitool.cxx921
-rw-r--r--sw/source/uibase/utlui/unotools.cxx496
-rw-r--r--sw/source/uibase/utlui/viewlayoutctrl.cxx213
-rw-r--r--sw/source/uibase/utlui/wordcountctrl.cxx45
-rw-r--r--sw/source/uibase/utlui/zoomctrl.cxx65
-rw-r--r--sw/source/uibase/web/wdocsh.cxx80
-rw-r--r--sw/source/uibase/web/wformsh.cxx50
-rw-r--r--sw/source/uibase/web/wfrmsh.cxx50
-rw-r--r--sw/source/uibase/web/wgrfsh.cxx54
-rw-r--r--sw/source/uibase/web/wlistsh.cxx49
-rw-r--r--sw/source/uibase/web/wolesh.cxx48
-rw-r--r--sw/source/uibase/web/wtabsh.cxx52
-rw-r--r--sw/source/uibase/web/wtextsh.cxx56
-rw-r--r--sw/source/uibase/web/wview.cxx292
-rw-r--r--sw/source/uibase/wrtsh/delete.cxx665
-rw-r--r--sw/source/uibase/wrtsh/move.cxx773
-rw-r--r--sw/source/uibase/wrtsh/navmgr.cxx221
-rw-r--r--sw/source/uibase/wrtsh/select.cxx1057
-rw-r--r--sw/source/uibase/wrtsh/wrtsh1.cxx2731
-rw-r--r--sw/source/uibase/wrtsh/wrtsh2.cxx686
-rw-r--r--sw/source/uibase/wrtsh/wrtsh3.cxx392
-rw-r--r--sw/source/uibase/wrtsh/wrtsh4.cxx253
-rw-r--r--sw/source/uibase/wrtsh/wrtundo.cxx151
453 files changed, 168247 insertions, 0 deletions
diff --git a/sw/source/uibase/app/appenv.cxx b/sw/source/uibase/app/appenv.cxx
new file mode 100644
index 0000000000..6c744867ad
--- /dev/null
+++ b/sw/source/uibase/app/appenv.cxx
@@ -0,0 +1,497 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+
+#include <comphelper/string.hxx>
+#include <sfx2/request.hxx>
+
+#include <sfx2/bindings.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/pbinitem.hxx>
+#include <editeng/paperinf.hxx>
+#include <osl/diagnose.h>
+#include <fmthdft.hxx>
+#include <swwait.hxx>
+#include <swmodule.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <frmatr.hxx>
+#include <fldbas.hxx>
+#include <swundo.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <dialoghelp.hxx>
+#include <fmtcol.hxx>
+#include <frmmgr.hxx>
+#include <fldmgr.hxx>
+#include <pagedesc.hxx>
+#include <poolfmt.hxx>
+#include <expfld.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <fmtpdsc.hxx>
+
+#include <cmdid.h>
+#include <strings.hrc>
+#include <swabstdlg.hxx>
+#include <envimg.hxx>
+#include "appenv.hxx"
+
+#define ENV_NEWDOC RET_OK
+#define ENV_INSERT RET_USER
+
+// Function used for labels and envelopes in applab.cxx and appenv.cxx
+OUString InsertLabEnvText( SwWrtShell& rSh, SwFieldMgr& rFieldMgr, const OUString& rText )
+{
+ OUString sRet;
+ OUString aText = rText.replaceAll("\r", "");
+
+ sal_Int32 nTokenPos = 0;
+ while( -1 != nTokenPos )
+ {
+ OUString aLine = aText.getToken( 0, '\n', nTokenPos );
+ while ( !aLine.isEmpty() )
+ {
+ OUString sTmpText;
+ bool bField = false;
+
+ sal_Int32 nPos = aLine.indexOf( '<' );
+ if (0 != nPos)
+ {
+ sal_Int32 const nCopy((nPos != -1) ? nPos : aLine.getLength());
+ sTmpText = aLine.copy(0, nCopy);
+ aLine = aLine.copy(nCopy);
+ }
+ else
+ {
+ nPos = aLine.indexOf( '>' );
+ if ( nPos == -1 )
+ {
+ sTmpText = aLine;
+ aLine.clear();
+ }
+ else
+ {
+ sTmpText = aLine.copy( 0, nPos + 1);
+ aLine = aLine.copy( nPos + 1);
+
+ // Database fields must contain at least 3 points!
+ OUString sDBName( sTmpText.copy( 1, sTmpText.getLength() - 2));
+ if (comphelper::string::getTokenCount(sDBName, '.') >= 3)
+ {
+ sDBName = ::ReplacePoint(sDBName, true);
+ SwInsertField_Data aData(SwFieldTypesEnum::Database, 0, sDBName, OUString(), 0, &rSh);
+ rFieldMgr.InsertField( aData );
+ sRet = sDBName;
+ bField = true;
+ }
+ }
+ }
+ if ( !bField )
+ rSh.Insert( sTmpText );
+ }
+ rSh.SplitNode();
+ }
+ rSh.DelLeft(); // Again remove last linebreak
+
+ return sRet;
+}
+
+static void lcl_CopyCollAttr(SwWrtShell const * pOldSh, SwWrtShell* pNewSh, sal_uInt16 nCollId)
+{
+ sal_uInt16 nCollCnt = pOldSh->GetTextFormatCollCount();
+ for( sal_uInt16 nCnt = 0; nCnt < nCollCnt; ++nCnt )
+ {
+ SwTextFormatColl* pColl = &pOldSh->GetTextFormatColl(nCnt);
+ if(nCollId == pColl->GetPoolFormatId())
+ pNewSh->GetTextCollFromPool(nCollId)->SetFormatAttr(pColl->GetAttrSet());
+ }
+}
+
+void SwModule::InsertEnv( SfxRequest& rReq )
+{
+ static sal_uInt16 nTitleNo = 0;
+
+ SwDocShell *pMyDocSh;
+ SfxViewFrame *pFrame;
+ SwView *pNewView;
+ SwWrtShell *pOldSh,
+ *pSh;
+
+ // Get current shell
+ pMyDocSh = static_cast<SwDocShell*>( SfxObjectShell::Current());
+ pOldSh = pMyDocSh ? pMyDocSh->GetWrtShell() : nullptr;
+
+ // Create new document (don't show!)
+ SfxObjectShellLock xDocSh( new SwDocShell( SfxObjectCreateMode::STANDARD ) );
+ xDocSh->DoInitNew();
+ pFrame = SfxViewFrame::LoadHiddenDocument( *xDocSh, SFX_INTERFACE_NONE );
+ pNewView = static_cast<SwView*>( pFrame->GetViewShell());
+ pNewView->AttrChangedNotify(nullptr); // so that SelectShell is being called
+ pSh = pNewView->GetWrtShellPtr();
+
+ if (!pSh)
+ return;
+
+ OUString aTmp = SwResId(STR_ENV_TITLE) + OUString::number( ++nTitleNo );
+ xDocSh->SetTitle( aTmp );
+
+ // if applicable, copy the old Collections "Sender" and "Receiver" to
+ // a new document
+ if ( pOldSh )
+ {
+ ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_ENVELOPE_ADDRESS);
+ ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_SEND_ADDRESS);
+ }
+
+ // Read SwEnvItem from config
+ SwEnvCfgItem aEnvCfg;
+
+ // Check if there's already an envelope.
+ bool bEnvChange = false;
+
+ SfxItemSetFixed<FN_ENVELOP, FN_ENVELOP> aSet(GetPool());
+ aSet.Put(aEnvCfg.GetItem());
+
+ SfxPrinter* pTempPrinter = pSh->getIDocumentDeviceAccess().getPrinter( true );
+ if(pOldSh )
+ {
+ const SwPageDesc& rCurPageDesc = pOldSh->GetPageDesc(pOldSh->GetCurPageDesc());
+ OUString sEnvelope;
+ SwStyleNameMapper::FillUIName( RES_POOLPAGE_ENVELOPE, sEnvelope );
+ bEnvChange = rCurPageDesc.GetName() == sEnvelope;
+
+ IDocumentDeviceAccess& rIDDA_old = pOldSh->getIDocumentDeviceAccess();
+ if( rIDDA_old.getPrinter( false ) )
+ {
+ IDocumentDeviceAccess& rIDDA = pSh->getIDocumentDeviceAccess();
+ rIDDA.setJobsetup( *rIDDA_old.getJobsetup() );
+ //#69563# if it isn't the same printer then the pointer has been invalidated!
+ pTempPrinter = rIDDA.getPrinter( true );
+ }
+ pTempPrinter->SetPaperBin(rCurPageDesc.GetMaster().GetPaperBin().GetValue());
+
+ }
+
+ ScopedVclPtr<SfxAbstractTabDialog> pDlg;
+ short nMode = ENV_INSERT;
+
+ const SwEnvItem* pItem = rReq.GetArg<SwEnvItem>(FN_ENVELOP);
+ if ( !pItem )
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ pDlg.disposeAndReset(pFact->CreateSwEnvDlg(GetFrameWeld(pMyDocSh), aSet, pOldSh, pTempPrinter, !bEnvChange));
+ nMode = pDlg->Execute();
+ }
+ else
+ {
+ const SfxBoolItem* pBoolItem = rReq.GetArg<SfxBoolItem>(FN_PARAM_1);
+ if ( pBoolItem && pBoolItem->GetValue() )
+ nMode = ENV_NEWDOC;
+ }
+
+ if (nMode == ENV_NEWDOC || nMode == ENV_INSERT)
+ {
+ SwWait aWait( static_cast<SwDocShell&>(*xDocSh), true );
+
+ // Read dialog and save item to config
+ const SwEnvItem& rItem = pItem ? *pItem : static_cast<const SwEnvItem&>( pDlg->GetOutputItemSet()->Get(FN_ENVELOP) );
+ aEnvCfg.GetItem() = rItem;
+ aEnvCfg.Commit();
+
+ // When we print we take the Jobsetup that is set up in the dialog.
+ // Information has to be set here, before a possible destruction of
+ // the new shell because the shell's printer has been handed to the
+ // dialog.
+ if ( nMode != ENV_NEWDOC )
+ {
+ OSL_ENSURE(pOldSh, "No document - wasn't 'Insert' disabled???");
+ SvxPaperBinItem aItem( RES_PAPER_BIN );
+ aItem.SetValue(static_cast<sal_uInt8>(pSh->getIDocumentDeviceAccess().getPrinter(true)->GetPaperBin()));
+ pOldSh->GetPageDescFromPool(RES_POOLPAGE_ENVELOPE)->GetMaster().SetFormatAttr(aItem);
+ }
+
+ SwWrtShell *pTmp = nMode == ENV_INSERT ? pOldSh : pSh;
+ const SwPageDesc* pFollow = nullptr;
+ SwTextFormatColl *pSend = pTmp->GetTextCollFromPool(RES_POOLCOLL_SEND_ADDRESS),
+ *pAddr = pTmp->GetTextCollFromPool(RES_POOLCOLL_ENVELOPE_ADDRESS);
+ const OUString sSendMark = pSend->GetName();
+ const OUString sAddrMark = pAddr->GetName();
+
+ if (nMode == ENV_INSERT)
+ {
+
+ SetView(&pOldSh->GetView()); // Set pointer to top view
+
+ // Delete new document
+ xDocSh->DoClose();
+ pSh = pOldSh;
+ //#i4251# selected text or objects in the document should
+ //not be deleted on inserting envelopes
+ pSh->EnterStdMode();
+ // Here it goes (insert)
+ pSh->StartUndo(SwUndoId::UI_INSERT_ENVELOPE);
+ pSh->StartAllAction();
+ pSh->SttEndDoc(true);
+
+ if (bEnvChange)
+ {
+ // followup template: page 2
+ pFollow = pSh->GetPageDesc(pSh->GetCurPageDesc()).GetFollow();
+
+ // Delete text from the first page
+ if ( !pSh->SttNxtPg(true) )
+ pSh->EndPg(true);
+ pSh->DelRight();
+ // Delete frame of the first page
+ if ( pSh->GotoFly(sSendMark) )
+ {
+ pSh->EnterSelFrameMode();
+ pSh->DelRight();
+ }
+ if ( pSh->GotoFly(sAddrMark) )
+ {
+ pSh->EnterSelFrameMode();
+ pSh->DelRight();
+ }
+ pSh->SttEndDoc(true);
+ }
+ else
+ // Followup template: page 1
+ pFollow = &pSh->GetPageDesc(pSh->GetCurPageDesc());
+
+ // Insert page break
+ if ( pSh->IsCursorInTable() )
+ {
+ pSh->SplitNode();
+ pSh->Right( SwCursorSkipMode::Chars, false, 1, false );
+ SfxItemSetFixed<RES_PAGEDESC, RES_PAGEDESC> aBreakSet( pSh->GetAttrPool() );
+ aBreakSet.Put( SwFormatPageDesc( pFollow ) );
+ pSh->SetTableAttr( aBreakSet );
+ }
+ else
+ {
+ OUString sFollowName(pFollow->GetName());
+ pSh->InsertPageBreak(&sFollowName, std::nullopt);
+ }
+ pSh->SttEndDoc(true);
+ }
+ else
+ {
+ pFollow = &pSh->GetPageDesc(pSh->GetCurPageDesc());
+ // Let's go (print)
+ pSh->StartAllAction();
+ pSh->DoUndo(false);
+
+ // Again, copy the new collections "Sender" and "Receiver" to
+ // a new document
+ if ( pOldSh )
+ {
+ ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_ENVELOPE_ADDRESS);
+ ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_SEND_ADDRESS);
+ }
+ }
+
+ CurrShell aCurr(pSh);
+ pSh->SetNewDoc(); // Avoid performance problems
+
+ // Remember Flys of this site
+ std::vector<SwFrameFormat*> aFlyArr;
+ if( ENV_NEWDOC != nMode && !bEnvChange )
+ pSh->GetPageObjs( aFlyArr );
+
+ // Get page description
+ SwPageDesc* pDesc = pSh->GetPageDescFromPool(RES_POOLPAGE_ENVELOPE);
+ SwFrameFormat& rFormat = pDesc->GetMaster();
+
+ Printer *pPrt = pSh->getIDocumentDeviceAccess().getPrinter( true );
+
+ // Borders (are put together by Shift-Offset and alignment)
+ Size aPaperSize = pPrt->PixelToLogic( pPrt->GetPaperSizePixel(),
+ MapMode(MapUnit::MapTwip));
+ if ( !aPaperSize.Width() && !aPaperSize.Height() )
+ aPaperSize = SvxPaperInfo::GetPaperSize(PAPER_A4);
+ if ( aPaperSize.Width() > aPaperSize.Height() )
+ Swap( aPaperSize );
+
+ tools::Long lLeft = rItem.m_nShiftRight,
+ lUpper = rItem.m_nShiftDown;
+
+ sal_uInt16 nPageW = o3tl::narrowing<sal_uInt16>(std::max(rItem.m_nWidth, rItem.m_nHeight)),
+ nPageH = o3tl::narrowing<sal_uInt16>(std::min(rItem.m_nWidth, rItem.m_nHeight));
+
+ switch (rItem.m_eAlign)
+ {
+ case ENV_HOR_LEFT: break;
+ case ENV_HOR_CNTR: lLeft += std::max(tools::Long(0), aPaperSize.Width() - nPageW) / 2;
+ break;
+ case ENV_HOR_RGHT: lLeft += std::max(tools::Long(0), aPaperSize.Width() - nPageW);
+ break;
+ case ENV_VER_LEFT: lUpper += std::max(tools::Long(0), aPaperSize.Width() - nPageH);
+ break;
+ case ENV_VER_CNTR: lUpper += std::max(tools::Long(0), aPaperSize.Width() - nPageH) / 2;
+ break;
+ case ENV_VER_RGHT: break;
+ }
+ SvxLRSpaceItem aLRMargin( RES_LR_SPACE );
+ SvxULSpaceItem aULMargin( RES_UL_SPACE );
+ aLRMargin.SetLeft (o3tl::narrowing<sal_uInt16>(lLeft) );
+ aULMargin.SetUpper(o3tl::narrowing<sal_uInt16>(lUpper));
+ aLRMargin.SetRight(0);
+ aULMargin.SetLower(0);
+ rFormat.SetFormatAttr(aLRMargin);
+ rFormat.SetFormatAttr(aULMargin);
+
+ // Header and footer
+ rFormat.SetFormatAttr(SwFormatHeader(false));
+ pDesc->ChgHeaderShare(false);
+ rFormat.SetFormatAttr(SwFormatFooter(false));
+ pDesc->ChgFooterShare(false);
+
+ // Page numbering
+ pDesc->SetUseOn(UseOnPage::All);
+
+ // Page size
+ rFormat.SetFormatAttr(SwFormatFrameSize(SwFrameSize::Fixed,
+ nPageW + lLeft, nPageH + lUpper));
+
+ // Set type of page numbering
+ SvxNumberType aType;
+ aType.SetNumberingType(SVX_NUM_NUMBER_NONE);
+ pDesc->SetNumType(aType);
+
+ // Followup template
+ if (pFollow)
+ pDesc->SetFollow(pFollow);
+
+ // Landscape
+ pDesc->SetLandscape( rItem.m_eAlign >= ENV_VER_LEFT &&
+ rItem.m_eAlign <= ENV_VER_RGHT);
+
+ // Apply page description
+
+ size_t nPos;
+ pSh->FindPageDescByName( pDesc->GetName(),
+ false,
+ &nPos );
+
+ pSh->ChgPageDesc( nPos, *pDesc);
+ pSh->ChgCurPageDesc(*pDesc);
+
+ // Insert Frame
+ SwFlyFrameAttrMgr aMgr(false, pSh, Frmmgr_Type::ENVELP, nullptr);
+ SwFieldMgr aFieldMgr;
+ aMgr.SetHeightSizeType(SwFrameSize::Variable);
+
+ // Overwrite defaults!
+ aMgr.GetAttrSet().Put( SvxBoxItem(RES_BOX) );
+ aMgr.SetULSpace( 0, 0 );
+ aMgr.SetLRSpace( 0, 0 );
+
+ // Sender
+ if (rItem.m_bSend)
+ {
+ pSh->SttEndDoc(true);
+ aMgr.InsertFlyFrame(RndStdIds::FLY_AT_PAGE,
+ Point(rItem.m_nSendFromLeft + lLeft, rItem.m_nSendFromTop + lUpper),
+ Size (rItem.m_nAddrFromLeft - rItem.m_nSendFromLeft, 0));
+
+ pSh->EnterSelFrameMode();
+ pSh->SetFlyName(sSendMark);
+ pSh->UnSelectFrame();
+ pSh->LeaveSelFrameMode();
+ pSh->SetTextFormatColl( pSend );
+ InsertLabEnvText( *pSh, aFieldMgr, rItem.m_aSendText );
+ aMgr.UpdateAttrMgr();
+ }
+
+ // Addressee
+ pSh->SttEndDoc(true);
+
+ aMgr.InsertFlyFrame(RndStdIds::FLY_AT_PAGE,
+ Point(rItem.m_nAddrFromLeft + lLeft, rItem.m_nAddrFromTop + lUpper),
+ Size (nPageW - rItem.m_nAddrFromLeft - 566, 0));
+ pSh->EnterSelFrameMode();
+ pSh->SetFlyName(sAddrMark);
+ pSh->UnSelectFrame();
+ pSh->LeaveSelFrameMode();
+ pSh->SetTextFormatColl( pAddr );
+ InsertLabEnvText(*pSh, aFieldMgr, rItem.m_aAddrText);
+
+ // Move Flys to the "old" pages
+ if (!aFlyArr.empty())
+ pSh->SetPageObjsNewPage(aFlyArr);
+
+ // Finished
+ pSh->SttEndDoc(true);
+
+ pSh->EndAllAction();
+
+ if (nMode == ENV_NEWDOC)
+ pSh->DoUndo();
+ else
+ pSh->EndUndo(SwUndoId::UI_INSERT_ENVELOPE);
+
+ if (nMode == ENV_NEWDOC)
+ {
+ pFrame->GetFrame().Appear();
+
+ if ( rItem.m_aAddrText.indexOf('<') >= 0 )
+ {
+ static sal_uInt16 const aInva[] =
+ {
+ SID_SBA_BRW_UPDATE,
+ SID_SBA_BRW_INSERT,
+ SID_SBA_BRW_MERGE,
+ 0
+ };
+ pFrame->GetBindings().Invalidate( aInva );
+
+ // Open database beamer
+ ShowDBObj(*pNewView, pSh->GetDBData());
+ }
+ }
+
+ if ( !pItem )
+ {
+ rReq.AppendItem( rItem );
+ if ( nMode == ENV_NEWDOC )
+ rReq.AppendItem( SfxBoolItem( FN_PARAM_1, true ) );
+ }
+
+ rReq.Done();
+ }
+ else // Abort
+ {
+ rReq.Ignore();
+
+ xDocSh->DoClose();
+ --nTitleNo;
+
+ // Set pointer to top view
+ if (pOldSh)
+ SetView(&pOldSh->GetView());
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/app/appenv.hxx b/sw/source/uibase/app/appenv.hxx
new file mode 100644
index 0000000000..f077702bb9
--- /dev/null
+++ b/sw/source/uibase/app/appenv.hxx
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <rtl/ustring.hxx>
+
+class SwWrtShell;
+class SwFieldMgr;
+
+OUString InsertLabEnvText(SwWrtShell&, SwFieldMgr&, const OUString&);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/app/apphdl.cxx b/sw/source/uibase/app/apphdl.cxx
new file mode 100644
index 0000000000..bca9d20dbd
--- /dev/null
+++ b/sw/source/uibase/app/apphdl.cxx
@@ -0,0 +1,1128 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+#include <config_fuzzers.h>
+#include <config_wasm_strip.h>
+
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/event.hxx>
+#include <sfx2/objitem.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#include <svtools/restartdialog.hxx>
+#include <svl/eitem.hxx>
+#include <svl/whiter.hxx>
+#include <svl/stritem.hxx>
+#include <svl/voiditem.hxx>
+#include <sfx2/lokhelper.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <svl/ctloptions.hxx>
+#include <svtools/colorcfg.hxx>
+#include <svtools/accessibilityoptions.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <unotools/useroptions.hxx>
+#include <com/sun/star/document/UpdateDocMode.hpp>
+#include <sfx2/docfile.hxx>
+#include <sfx2/objface.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <view.hxx>
+#include <pview.hxx>
+#include <srcview.hxx>
+#include <wrtsh.hxx>
+#include <docsh.hxx>
+#include <cmdid.h>
+#include <initui.hxx>
+#include <uitool.hxx>
+#include <swmodule.hxx>
+#include <wview.hxx>
+#include <usrpref.hxx>
+#include <gloslst.hxx>
+#include <glosdoc.hxx>
+#include <doc.hxx>
+#include <IDocumentLayoutAccess.hxx>
+#include <IDocumentFieldsAccess.hxx>
+#include <prtopt.hxx>
+#include <modcfg.hxx>
+#include <fontcfg.hxx>
+#include <barcfg.hxx>
+#include <navicfg.hxx>
+#include <uinums.hxx>
+#include <dbconfig.hxx>
+#include <mmconfigitem.hxx>
+#include <strings.hrc>
+#include <unotxdoc.hxx>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdb/TextConnectionSettings.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/task/OfficeRestartManager.hpp>
+#include <org/freedesktop/PackageKit/SyncDbusSessionHelper.hpp>
+#include <swabstdlg.hxx>
+#include <comphelper/dispatchcommand.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/lok.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+#include <salhelper/simplereferenceobject.hxx>
+#include <rtl/ref.hxx>
+
+#include <officecfg/Office/Common.hxx>
+
+using namespace ::com::sun::star;
+
+// Slotmaps for the application's methods
+
+// here are the SlotID's being included
+// see Idl-file
+#define ShellClass_SwModule
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+
+SFX_IMPL_INTERFACE(SwModule, SfxModule)
+
+void SwModule::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterStatusBar(StatusBarId::WriterStatusBar);
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_APPLICATION,
+ SfxVisibilityFlags::Standard | SfxVisibilityFlags::Client | SfxVisibilityFlags::Viewer,
+ ToolbarId::Module_Toolbox);
+}
+
+// other states
+void SwModule::StateOther(SfxItemSet &rSet)
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ SwView* pActView = ::GetActiveView();
+ bool bWebView = dynamic_cast<SwWebView*>( pActView ) != nullptr;
+
+ while(nWhich)
+ {
+ switch(nWhich)
+ {
+ case FN_BUSINESS_CARD:
+ case FN_LABEL:
+ case FN_ENVELOP:
+ {
+ bool bDisable = false;
+ SfxViewShell* pCurrView = SfxViewShell::Current();
+ if( !pCurrView || dynamic_cast< const SwView *>( pCurrView ) == nullptr )
+ bDisable = true;
+ SwDocShell *pDocSh = static_cast<SwDocShell*>( SfxObjectShell::Current());
+ if ( bDisable ||
+ (pDocSh && (pDocSh->IsReadOnly() ||
+ pDocSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED)) )
+ rSet.DisableItem( nWhich );
+
+ }
+ break;
+ case FN_XFORMS_INIT:
+ // slot is always active!
+ break;
+ case FN_EDIT_FORMULA:
+ {
+ SwWrtShell* pSh = nullptr;
+ SelectionType nSelection = SelectionType::NONE;
+ if( pActView )
+ pSh = &pActView->GetWrtShell();
+ if( pSh )
+ nSelection = pSh->GetSelectionType();
+
+ if( (pSh && pSh->HasSelection()) ||
+ !(nSelection & (SelectionType::Text | SelectionType::Table)))
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_ATTR_METRIC:
+ rSet.Put( SfxUInt16Item( SID_ATTR_METRIC, static_cast< sal_uInt16 >(::GetDfltMetric(bWebView))));
+ break;
+ case FN_SET_MODOPT_TBLNUMFMT:
+ rSet.Put( SfxBoolItem( nWhich, m_pModuleConfig->
+ IsInsTableFormatNum( bWebView )));
+ break;
+ case FN_MAILMERGE_WIZARD:
+ {
+ SfxObjectShell* pObjectShell = GetObjectShell();
+ if (pObjectShell && pObjectShell->isExportLocked())
+ rSet.DisableItem(nWhich);
+ break;
+ }
+ case FN_MAILMERGE_FIRST_ENTRY:
+ case FN_MAILMERGE_PREV_ENTRY:
+ case FN_MAILMERGE_NEXT_ENTRY:
+ case FN_MAILMERGE_LAST_ENTRY:
+ {
+ std::shared_ptr<SwMailMergeConfigItem> xConfigItem;
+ if (SwView* pView = GetActiveView())
+ xConfigItem = pView->GetMailMergeConfigItem();
+ if (!xConfigItem)
+ rSet.DisableItem(nWhich);
+ else if (xConfigItem->GetConnection().is()
+ && !xConfigItem->GetConnection()->isClosed())
+ {
+ bool bFirst, bLast;
+ bool bValid = xConfigItem->IsResultSetFirstLast(bFirst, bLast);
+
+ if (!bValid ||
+ (bFirst && (nWhich == FN_MAILMERGE_FIRST_ENTRY || nWhich == FN_MAILMERGE_PREV_ENTRY)) ||
+ (bLast && (nWhich == FN_MAILMERGE_LAST_ENTRY || nWhich == FN_MAILMERGE_NEXT_ENTRY)))
+ {
+ rSet.DisableItem(nWhich);
+ }
+ }
+ }
+ break;
+ case FN_MAILMERGE_CURRENT_ENTRY:
+ case FN_MAILMERGE_EXCLUDE_ENTRY:
+ {
+ // just trigger calling statusChanged() of MMExcludeEntryController
+ // resp. MMCurrentEntryController
+ rSet.InvalidateItem(nWhich);
+ }
+ break;
+ case FN_MAILMERGE_CREATE_DOCUMENTS:
+ case FN_MAILMERGE_SAVE_DOCUMENTS:
+ case FN_MAILMERGE_PRINT_DOCUMENTS:
+ case FN_MAILMERGE_EMAIL_DOCUMENTS:
+ {
+ std::shared_ptr<SwMailMergeConfigItem> xConfigItem;
+ if (SwView* pView = GetActiveView())
+ xConfigItem = pView->EnsureMailMergeConfigItem();
+
+ // #i51949# hide e-Mail option if e-Mail is not supported
+ // #i63267# printing might be disabled
+ // Without attempting to open the database, (in case it is remote or passworded),
+ // hide everything after determining there are no valid results. tdf#121606
+ if (!xConfigItem ||
+ xConfigItem->GetCurrentDBData().sDataSource.isEmpty() ||
+ xConfigItem->GetCurrentDBData().sCommand.isEmpty() ||
+ (xConfigItem->GetConnection().is() && !xConfigItem->GetConnection()->isClosed() && !xConfigItem->GetResultSet().is()) ||
+ (nWhich == FN_MAILMERGE_PRINT_DOCUMENTS && Application::GetSettings().GetMiscSettings().GetDisablePrinting()) ||
+ (nWhich == FN_MAILMERGE_EMAIL_DOCUMENTS && !xConfigItem->IsMailAvailable()))
+ {
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+ default:
+ OSL_FAIL("::StateOther: default");
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+// start field dialog
+static void NewXForms( SfxRequest& rReq ); // implementation: below
+
+std::shared_ptr<SwMailMergeConfigItem> SwView::EnsureMailMergeConfigItem(const SfxItemSet* pArgs)
+{
+ // create if it does not exist yet
+ std::shared_ptr<SwMailMergeConfigItem> xMMConfig = GetMailMergeConfigItem();
+ if (!xMMConfig)
+ {
+ xMMConfig = std::make_shared<SwMailMergeConfigItem>();
+ xMMConfig->SetSourceView(this);
+
+ //set the first used database as default source on the config item
+ const SfxUnoAnyItem* pItem = nullptr;
+ if (pArgs && (pItem = pArgs->GetItemIfSet(
+ FN_PARAM_DATABASE_PROPERTIES, false)))
+ {
+ //mailmerge has been called from the database beamer
+ uno::Sequence< beans::PropertyValue> aDBValues;
+ if (pItem->GetValue() >>= aDBValues)
+ {
+ SwDBData aDBData;
+ svx::ODataAccessDescriptor aDescriptor(aDBValues);
+ aDescriptor[svx::DataAccessDescriptorProperty::DataSource] >>= aDBData.sDataSource;
+ aDescriptor[svx::DataAccessDescriptorProperty::Command] >>= aDBData.sCommand;
+ aDescriptor[svx::DataAccessDescriptorProperty::CommandType] >>= aDBData.nCommandType;
+
+ uno::Reference< sdbc::XConnection> xConnection;
+ uno::Reference< sdbc::XDataSource> xSource;
+ uno::Reference< sdbcx::XColumnsSupplier> xColumnsSupplier;
+ if (aDescriptor.has(svx::DataAccessDescriptorProperty::Connection))
+ aDescriptor[svx::DataAccessDescriptorProperty::Connection] >>= xConnection;
+ uno::Reference<container::XChild> xChild(xConnection, uno::UNO_QUERY);
+ if (xChild.is())
+ xSource.set(xChild->getParent(), uno::UNO_QUERY);
+ xMMConfig->SetCurrentConnection(
+ xSource, SharedConnection(xConnection, SharedConnection::NoTakeOwnership),
+ xColumnsSupplier, aDBData);
+ }
+ }
+ else
+ {
+ std::vector<OUString> aDBNameList;
+ std::vector<OUString> aAllDBNames;
+ GetWrtShell().GetAllUsedDB(aDBNameList, &aAllDBNames);
+ if (!aDBNameList.empty())
+ {
+ OUString sDBName(aDBNameList[0]);
+ SwDBData aDBData;
+ sal_Int32 nIdx{ 0 };
+ aDBData.sDataSource = sDBName.getToken(0, DB_DELIM, nIdx);
+ aDBData.sCommand = sDBName.getToken(0, DB_DELIM, nIdx);
+ aDBData.nCommandType = o3tl::toInt32(o3tl::getToken(sDBName, 0, DB_DELIM, nIdx));
+ //set the currently used database for the wizard
+ xMMConfig->SetCurrentDBData(aDBData);
+ }
+ }
+
+ SetMailMergeConfigItem(xMMConfig);
+ }
+ return xMMConfig;
+}
+
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+
+namespace
+{
+
+SwView* lcl_LoadDoc(SwView* pView, const OUString& rURL)
+{
+ SwView* pNewView = nullptr;
+ if(!rURL.isEmpty())
+ {
+ SfxStringItem aURL(SID_FILE_NAME, rURL);
+ SfxStringItem aTargetFrameName( SID_TARGETNAME, "_blank" );
+ SfxBoolItem aHidden( SID_HIDDEN, true );
+ SfxStringItem aReferer(SID_REFERER, pView->GetDocShell()->GetTitle());
+ const SfxPoolItemHolder aResult(
+ pView->GetViewFrame().GetDispatcher()->ExecuteList(SID_OPENDOC,
+ SfxCallMode::SYNCHRON,
+ { &aURL, &aHidden, &aReferer, &aTargetFrameName }));
+ const SfxObjectItem* pItem(static_cast<const SfxObjectItem*>(aResult.getItem()));
+ SfxShell* pShell = pItem ? pItem->GetShell() : nullptr;
+
+ if(pShell)
+ {
+ SfxViewShell* pViewShell = pShell->GetViewShell();
+ if(pViewShell)
+ {
+ pNewView = dynamic_cast<SwView*>(pViewShell);
+ if (pNewView)
+ {
+ pNewView->GetViewFrame().GetFrame().Appear();
+ }
+ else
+ {
+ pViewShell->GetViewFrame().DoClose();
+ }
+ }
+ }
+ }
+ else
+ {
+ SfxStringItem aFactory(SID_NEWDOCDIRECT, SwDocShell::Factory().GetFilterContainer()->GetName());
+ const SfxPoolItemHolder aResult(pView->GetViewFrame().GetDispatcher()->ExecuteList(
+ SID_NEWDOCDIRECT,
+ SfxCallMode::SYNCHRON, { &aFactory }));
+ const SfxFrameItem* pItem(static_cast<const SfxFrameItem*>(aResult.getItem()));
+ SfxFrame* pFrame = pItem ? pItem->GetFrame() : nullptr;
+ SfxViewFrame* pViewFrame = pFrame ? pFrame->GetCurrentViewFrame() : nullptr;
+ pNewView = pViewFrame ? dynamic_cast<SwView*>( pViewFrame->GetViewShell() ) : nullptr;
+ }
+
+ return pNewView;
+}
+
+class SwMailMergeWizardExecutor : public salhelper::SimpleReferenceObject
+{
+ SwView* m_pView; // never owner
+ SwView* m_pView2Close; // never owner
+ VclPtr<AbstractMailMergeWizard> m_pWizard; // always owner
+ VclPtr<AbstractMailMergeWizard> m_pWizardToDestroyInCallback;
+
+ void EndDialogHdl(sal_Int32 nResponse);
+ DECL_LINK( DestroyDialogHdl, void*, void );
+ DECL_LINK( DestroyWizardHdl, void*, void );
+ DECL_LINK( CancelHdl, void*, void );
+ DECL_LINK( CloseFrameHdl, void*, void );
+
+ void ExecutionFinished();
+ void ExecuteWizard();
+
+public:
+ SwMailMergeWizardExecutor();
+ virtual ~SwMailMergeWizardExecutor() override;
+
+ void ExecuteMailMergeWizard( const SfxItemSet * pArgs );
+};
+
+SwMailMergeWizardExecutor::SwMailMergeWizardExecutor()
+ : m_pView( nullptr ),
+ m_pView2Close( nullptr ),
+ m_pWizard( nullptr )
+{
+}
+
+SwMailMergeWizardExecutor::~SwMailMergeWizardExecutor()
+{
+ OSL_ENSURE( m_pWizard == nullptr, "SwMailMergeWizardExecutor: m_pWizard must be Null!" );
+}
+
+bool lcl_hasAllComponentsAvailable()
+{
+ try
+ {
+ return css::sdb::TextConnectionSettings::create(comphelper::getProcessComponentContext()).is();
+ }
+ catch (const css::uno::Exception &)
+ {
+ TOOLS_INFO_EXCEPTION(
+ "sw.core", "assuming Base to be missing; caught ");
+ return false;
+ }
+}
+
+void SwMailMergeWizardExecutor::ExecuteMailMergeWizard( const SfxItemSet * pArgs )
+{
+ if(!lcl_hasAllComponentsAvailable())
+ {
+ if (officecfg::Office::Common::PackageKit::EnableBaseInstallation::get())
+ {
+ try
+ {
+ using namespace org::freedesktop::PackageKit;
+ using namespace svtools;
+ css::uno::Reference< XSyncDbusSessionHelper > xSyncDbusSessionHelper(SyncDbusSessionHelper::create(comphelper::getProcessComponentContext()));
+ const css::uno::Sequence< OUString > vPackages{ "libreoffice-base" };
+ xSyncDbusSessionHelper->InstallPackageNames(vPackages, OUString());
+ SolarMutexGuard aGuard;
+ executeRestartDialog(comphelper::getProcessComponentContext(), nullptr, RESTART_REASON_MAILMERGE_INSTALL);
+ }
+ catch (const css::uno::Exception &)
+ {
+ TOOLS_INFO_EXCEPTION(
+ "sw.core",
+ "trying to install LibreOffice Base, caught");
+ auto xRestartManager
+ = css::task::OfficeRestartManager::get(comphelper::getProcessComponentContext());
+ if (!xRestartManager->isRestartRequested(false))
+ {
+ // Base is absent, and could not initiate its install - ask user to do that manually
+ // Only show the dialog if restart is not initiated yet
+ std::unique_ptr<weld::MessageDialog> xWarnBox(Application::CreateMessageDialog(
+ nullptr, VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_NO_BASE_FOR_MERGE)));
+ xWarnBox->run();
+ }
+ }
+ } else {
+ auto xRestartManager
+ = css::task::OfficeRestartManager::get(comphelper::getProcessComponentContext());
+ if (!xRestartManager->isRestartRequested(false))
+ {
+ // Base is absent, and could not initiate its install - ask user to do that manually
+ // Only show the dialog if restart is not initiated yet
+ std::unique_ptr<weld::MessageDialog> xWarnBox(Application::CreateMessageDialog(
+ nullptr, VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_NO_BASE_FOR_MERGE)));
+ xWarnBox->run();
+ }
+ }
+ return;
+ }
+ if ( m_pView )
+ {
+ OSL_FAIL("SwMailMergeWizardExecutor::ExecuteMailMergeWizard: Already executing the wizard!" );
+ return;
+ }
+
+ m_pView = ::GetActiveView();
+ if (!m_pView)
+ return;
+
+ // keep self alive until done.
+ acquire();
+
+ // create if it does not exist yet
+ std::shared_ptr<SwMailMergeConfigItem> xMMConfig = m_pView->EnsureMailMergeConfigItem(pArgs);
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ m_pWizard = pFact->CreateMailMergeWizard(*m_pView, xMMConfig);
+
+ ExecuteWizard();
+}
+
+void SwMailMergeWizardExecutor::ExecutionFinished()
+{
+ std::shared_ptr<SwMailMergeConfigItem> xMMConfig = m_pView->GetMailMergeConfigItem();
+ if (xMMConfig)
+ xMMConfig->Commit();
+
+ SwDoc* pDoc = m_pView->GetDocShell()->GetDoc();
+ if (pDoc)
+ {
+ SwDBManager* pDbManager = pDoc->GetDBManager();
+ if (pDbManager)
+ pDbManager->CommitLastRegistrations();
+
+ // Show the toolbar
+ m_pView->ShowUIElement("private:resource/toolbar/mailmerge");
+
+ // Update Mail Merge controls
+ const sal_uInt16 slotIds[] = { FN_MAILMERGE_FIRST_ENTRY,
+ FN_MAILMERGE_PREV_ENTRY,
+ FN_MAILMERGE_NEXT_ENTRY,
+ FN_MAILMERGE_LAST_ENTRY,
+ FN_MAILMERGE_CURRENT_ENTRY,
+ FN_MAILMERGE_EXCLUDE_ENTRY,
+ FN_MAILMERGE_CREATE_DOCUMENTS,
+ FN_MAILMERGE_SAVE_DOCUMENTS,
+ FN_MAILMERGE_PRINT_DOCUMENTS,
+ FN_MAILMERGE_EMAIL_DOCUMENTS,
+ 0 };
+ m_pView->GetViewFrame().GetBindings().Invalidate(slotIds);
+ }
+
+ // release/destroy asynchronously
+ Application::PostUserEvent( LINK( this, SwMailMergeWizardExecutor, DestroyDialogHdl ) );
+}
+
+void SwMailMergeWizardExecutor::ExecuteWizard()
+{
+ m_pWizard->StartExecuteAsync([this](sal_Int32 nResult){
+ EndDialogHdl(nResult);
+ });
+}
+
+void SwMailMergeWizardExecutor::EndDialogHdl(sal_Int32 nRet)
+{
+ sal_uInt16 nRestartPage = m_pWizard->GetRestartPage();
+
+ switch ( nRet )
+ {
+ case RET_LOAD_DOC:
+ {
+ SwView* pNewView = lcl_LoadDoc(m_pView, m_pWizard->GetReloadDocument());
+
+ // Destroy wizard asynchronously, since we are deep inside the wizard and dialog
+ // machinery code here
+ m_pWizardToDestroyInCallback = m_pWizard;
+ Application::PostUserEvent(
+ LINK( this, SwMailMergeWizardExecutor, DestroyWizardHdl ), nullptr );
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ std::shared_ptr<SwMailMergeConfigItem> xMMConfig = m_pView->GetMailMergeConfigItem();
+ if (pNewView)
+ {
+ pNewView->SetMailMergeConfigItem(xMMConfig);
+ m_pView = pNewView;
+ xMMConfig->DocumentReloaded();
+ //new source view!
+ xMMConfig->SetSourceView( m_pView );
+ m_pWizard = pFact->CreateMailMergeWizard(*m_pView, xMMConfig);
+ m_pWizard->ShowPage( nRestartPage );
+ }
+ else
+ {
+ m_pWizard = pFact->CreateMailMergeWizard(*m_pView, xMMConfig);
+ }
+
+ // execute the wizard again
+ ExecuteWizard();
+ break;
+ }
+ case RET_TARGET_CREATED:
+ {
+ std::shared_ptr<SwMailMergeConfigItem> xMMConfig = m_pView->GetMailMergeConfigItem();
+ SwView* pTargetView = xMMConfig->GetTargetView();
+ OSL_ENSURE(pTargetView, "No target view has been created");
+ if(pTargetView)
+ {
+ // destroy wizard asynchronously
+ m_pWizardToDestroyInCallback = m_pWizard;
+ Application::PostUserEvent(
+ LINK( this, SwMailMergeWizardExecutor, DestroyWizardHdl ), nullptr );
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ m_pWizard = pFact->CreateMailMergeWizard(*pTargetView, xMMConfig);
+ m_pWizard->ShowPage( nRestartPage );
+
+ // execute the wizard again
+ ExecuteWizard();
+ }
+ else
+ {
+ // should not happen - just in case no target view has been created
+ ExecutionFinished();
+ }
+ break;
+ }
+ case RET_REMOVE_TARGET:
+ {
+ std::shared_ptr<SwMailMergeConfigItem> xMMConfig = m_pView->GetMailMergeConfigItem();
+ SwView* pTargetView = xMMConfig->GetTargetView();
+ SwView* pSourceView = xMMConfig->GetSourceView();
+ OSL_ENSURE(pTargetView && pSourceView, "source or target view not available" );
+ if(pTargetView && pSourceView)
+ {
+ m_pView2Close = pTargetView;
+ pTargetView->GetViewFrame().GetTopViewFrame()->GetWindow().Hide();
+ pSourceView->GetViewFrame().GetFrame().AppearWithUpdate();
+ // the current view has be set when the target is destroyed
+ m_pView = pSourceView;
+ xMMConfig->SetTargetView(nullptr);
+
+ // destroy wizard asynchronously
+ m_pWizardToDestroyInCallback = m_pWizard;
+ Application::PostUserEvent(
+ LINK( this, SwMailMergeWizardExecutor, CloseFrameHdl ), m_pWizard );
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ m_pWizard = pFact->CreateMailMergeWizard(*pSourceView, xMMConfig);
+ m_pWizard->ShowPage( nRestartPage );
+
+ // execute the wizard again
+ ExecuteWizard();
+ }
+ else
+ {
+ // should not happen - just in case no target view has been created
+ ExecutionFinished();
+ }
+ break;
+ }
+ case RET_CANCEL:
+ {
+ // close frame and destroy wizard asynchronously
+ Application::PostUserEvent(
+ LINK( this, SwMailMergeWizardExecutor, CancelHdl ), m_pWizard );
+ break;
+ }
+ default: // finish
+ {
+ std::shared_ptr<SwMailMergeConfigItem> xMMConfig = m_pView->GetMailMergeConfigItem();
+ SwView* pSourceView = xMMConfig ? xMMConfig->GetSourceView() : nullptr;
+ if(pSourceView)
+ {
+ xMMConfig->GetSourceView()->GetViewFrame().GetFrame().Appear();
+ }
+ ExecutionFinished();
+ break;
+ }
+
+ } // switch
+}
+
+IMPL_LINK_NOARG(SwMailMergeWizardExecutor, DestroyDialogHdl, void*, void)
+{
+ m_pWizard.disposeAndClear();
+
+ release();
+}
+
+IMPL_LINK_NOARG(SwMailMergeWizardExecutor, DestroyWizardHdl, void*, void)
+{
+ m_pWizardToDestroyInCallback.disposeAndClear();
+}
+
+IMPL_LINK_NOARG(SwMailMergeWizardExecutor, CancelHdl, void*, void)
+{
+ std::shared_ptr<SwMailMergeConfigItem> xMMConfig = m_pView->GetMailMergeConfigItem();
+ if (xMMConfig)
+ {
+ if (xMMConfig->GetTargetView())
+ {
+ xMMConfig->GetTargetView()->GetViewFrame().DoClose();
+ xMMConfig->SetTargetView(nullptr);
+ }
+ if (xMMConfig->GetSourceView())
+ {
+ auto& rViewFrame(xMMConfig->GetSourceView()->GetViewFrame());
+ rViewFrame.GetFrame().AppearWithUpdate();
+ }
+ xMMConfig->Commit();
+ }
+
+ // Revoke created connections
+ SwDoc* pDoc = m_pView->GetDocShell()->GetDoc();
+ SwDBManager* pDbManager = pDoc->GetDBManager();
+ if (pDbManager)
+ pDbManager->RevokeLastRegistrations();
+
+ m_pWizard.disposeAndClear();
+ release();
+}
+
+IMPL_LINK_NOARG(SwMailMergeWizardExecutor, CloseFrameHdl, void*, void)
+{
+ if ( m_pView2Close )
+ {
+ m_pView2Close->GetViewFrame().DoClose();
+ m_pView2Close = nullptr;
+ }
+ m_pWizardToDestroyInCallback.disposeAndClear();
+}
+} // namespace
+
+#endif // HAVE_FEATURE_DBCONNECTIVITY
+
+void SwModule::ExecOther(SfxRequest& rReq)
+{
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem = nullptr;
+
+ sal_uInt16 nWhich = rReq.GetSlot();
+ switch (nWhich)
+ {
+ case FN_ENVELOP:
+ InsertEnv( rReq );
+ break;
+
+ case FN_BUSINESS_CARD:
+ case FN_LABEL:
+ InsertLab(rReq, nWhich == FN_LABEL);
+ break;
+
+ case FN_XFORMS_INIT:
+ NewXForms( rReq );
+ break;
+
+ case SID_ATTR_METRIC:
+ if(pArgs && SfxItemState::SET == pArgs->GetItemState(nWhich, false, &pItem))
+ {
+ FieldUnit eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pItem)->GetValue());
+ switch( eUnit )
+ {
+ case FieldUnit::MM:
+ case FieldUnit::CM:
+ case FieldUnit::INCH:
+ case FieldUnit::PICA:
+ case FieldUnit::POINT:
+ {
+ SwView* pActView = ::GetActiveView();
+ bool bWebView = dynamic_cast<SwWebView*>( pActView ) != nullptr;
+ ::SetDfltMetric(eUnit, bWebView);
+ }
+ break;
+ default:;//prevent warning
+ }
+ }
+ break;
+
+ case FN_SET_MODOPT_TBLNUMFMT:
+ {
+ bool bWebView = dynamic_cast<SwWebView*>( ::GetActiveView() )!= nullptr ,
+ bSet;
+
+ if( pArgs && SfxItemState::SET == pArgs->GetItemState(
+ nWhich, false, &pItem ))
+ bSet = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ else
+ bSet = !m_pModuleConfig->IsInsTableFormatNum( bWebView );
+
+ m_pModuleConfig->SetInsTableFormatNum( bWebView, bSet );
+ }
+ break;
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+ case FN_MAILMERGE_WIZARD:
+ {
+ // show the mailmerge wizard
+ rtl::Reference< SwMailMergeWizardExecutor > xEx( new SwMailMergeWizardExecutor );
+ xEx->ExecuteMailMergeWizard( pArgs );
+ }
+ break;
+ case FN_MAILMERGE_FIRST_ENTRY:
+ case FN_MAILMERGE_PREV_ENTRY:
+ case FN_MAILMERGE_NEXT_ENTRY:
+ case FN_MAILMERGE_LAST_ENTRY:
+ case FN_MAILMERGE_CURRENT_ENTRY:
+ {
+ SwView* pView = ::GetActiveView();
+ if (!pView)
+ return;
+
+ const std::shared_ptr<SwMailMergeConfigItem>& xConfigItem = pView->GetMailMergeConfigItem();
+ if (!xConfigItem)
+ return;
+
+ const bool bHadConnection
+ = xConfigItem->GetConnection().is() && !xConfigItem->GetConnection()->isClosed();
+
+ sal_Int32 nPos = xConfigItem->GetResultSetPosition();
+ switch (nWhich)
+ {
+ case FN_MAILMERGE_FIRST_ENTRY: xConfigItem->MoveResultSet(1); break;
+ case FN_MAILMERGE_PREV_ENTRY: xConfigItem->MoveResultSet(nPos - 1); break;
+ case FN_MAILMERGE_NEXT_ENTRY: xConfigItem->MoveResultSet(nPos + 1); break;
+ case FN_MAILMERGE_LAST_ENTRY: xConfigItem->MoveResultSet(-1); break;
+ case FN_MAILMERGE_CURRENT_ENTRY: /* don't move the result set, just update the document */ break;
+ default: break;
+ }
+
+ // now the record has to be merged into the source document
+ // TODO can we re-use PerformMailMerge() here somehow?
+ const SwDBData& rDBData = xConfigItem->GetCurrentDBData();
+ uno::Sequence<uno::Any> vSelection({ uno::Any(xConfigItem->GetResultSetPosition()) });
+ svx::ODataAccessDescriptor aDescriptor(::comphelper::InitPropertySequence({
+ {"Selection", uno::Any(vSelection)},
+ {"DataSourceName", uno::Any(rDBData.sDataSource)},
+ {"Command", uno::Any(rDBData.sCommand)},
+ {"CommandType", uno::Any(rDBData.nCommandType)},
+ {"ActiveConnection", uno::Any(xConfigItem->GetConnection().getTyped())},
+ {"Filter", uno::Any(xConfigItem->GetFilter())},
+ {"Cursor", uno::Any(xConfigItem->GetResultSet())}
+ }));
+
+ SwWrtShell& rSh = pView->GetWrtShell();
+ SwMergeDescriptor aMergeDesc(DBMGR_MERGE, rSh, aDescriptor);
+ rSh.GetDBManager()->Merge(aMergeDesc);
+
+ // update enabled / disabled status of the buttons in the toolbar
+ SfxBindings& rBindings = rSh.GetView().GetViewFrame().GetBindings();
+ rBindings.Invalidate(FN_MAILMERGE_FIRST_ENTRY);
+ rBindings.Invalidate(FN_MAILMERGE_PREV_ENTRY);
+ rBindings.Invalidate(FN_MAILMERGE_NEXT_ENTRY);
+ rBindings.Invalidate(FN_MAILMERGE_LAST_ENTRY);
+ rBindings.Invalidate(FN_MAILMERGE_CURRENT_ENTRY);
+ rBindings.Invalidate(FN_MAILMERGE_EXCLUDE_ENTRY);
+ if (!bHadConnection && xConfigItem->GetConnection().is()
+ && !xConfigItem->GetConnection()->isClosed())
+ {
+ // The connection has been activated. Update controls that were disabled
+ rBindings.Invalidate(FN_MAILMERGE_CREATE_DOCUMENTS);
+ rBindings.Invalidate(FN_MAILMERGE_SAVE_DOCUMENTS);
+ rBindings.Invalidate(FN_MAILMERGE_PRINT_DOCUMENTS);
+ rBindings.Invalidate(FN_MAILMERGE_EMAIL_DOCUMENTS);
+ }
+ rBindings.Update();
+ }
+ break;
+ case FN_MAILMERGE_CREATE_DOCUMENTS:
+ case FN_MAILMERGE_SAVE_DOCUMENTS:
+ case FN_MAILMERGE_PRINT_DOCUMENTS:
+ case FN_MAILMERGE_EMAIL_DOCUMENTS:
+ {
+ SwView* pView = ::GetActiveView();
+ if (!pView)
+ return;
+
+ std::shared_ptr<SwMailMergeConfigItem> xConfigItem = pView->GetMailMergeConfigItem();
+ assert(xConfigItem);
+ if (!xConfigItem->GetResultSet().is())
+ {
+ // The connection has been attempted, but failed or no results found,
+ // so invalidate the toolbar buttons in case they need to be disabled.
+ SfxBindings& rBindings
+ = pView->GetWrtShell().GetView().GetViewFrame().GetBindings();
+ rBindings.Invalidate(FN_MAILMERGE_CREATE_DOCUMENTS);
+ rBindings.Invalidate(FN_MAILMERGE_SAVE_DOCUMENTS);
+ rBindings.Invalidate(FN_MAILMERGE_PRINT_DOCUMENTS);
+ rBindings.Invalidate(FN_MAILMERGE_EMAIL_DOCUMENTS);
+ rBindings.Invalidate(FN_MAILMERGE_FIRST_ENTRY);
+ rBindings.Invalidate(FN_MAILMERGE_PREV_ENTRY);
+ rBindings.Invalidate(FN_MAILMERGE_NEXT_ENTRY);
+ rBindings.Invalidate(FN_MAILMERGE_LAST_ENTRY);
+ rBindings.Update();
+ return;
+ }
+
+ if (nWhich == FN_MAILMERGE_CREATE_DOCUMENTS)
+ {
+ xConfigItem = SwDBManager::PerformMailMerge(pView);
+
+ if (xConfigItem && xConfigItem->GetTargetView())
+ xConfigItem->GetTargetView()->GetViewFrame().GetFrame().Appear();
+ }
+ else
+ {
+ xConfigItem->SetTargetView(nullptr);
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ if (nWhich == FN_MAILMERGE_SAVE_DOCUMENTS)
+ pFact->ExecuteMMResultSaveDialog(rReq.GetFrameWeld());
+ else if (nWhich == FN_MAILMERGE_PRINT_DOCUMENTS)
+ pFact->ExecuteMMResultPrintDialog(rReq.GetFrameWeld());
+ else if (nWhich == FN_MAILMERGE_EMAIL_DOCUMENTS)
+ pFact->ExecuteMMResultEmailDialog(rReq.GetFrameWeld());
+ }
+ }
+ break;
+#endif
+ }
+}
+
+// Catch notifications
+
+// Catch hint for DocInfo
+void SwModule::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
+{
+ if (rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint)
+ {
+ const SfxEventHint& rEvHint = static_cast<const SfxEventHint&>(rHint);
+ SwDocShell* pDocSh = dynamic_cast<SwDocShell*>(rEvHint.GetObjShell());
+ if( pDocSh )
+ {
+ SwWrtShell* pWrtSh = pDocSh->GetWrtShell();
+ switch (rEvHint.GetEventId())
+ {
+ case SfxEventHintId::LoadFinished:
+ // if it is a new document created from a template,
+ // update fixed fields
+ if (pDocSh->GetMedium())
+ {
+ const SfxBoolItem* pTemplateItem = pDocSh->GetMedium()->GetItemSet().GetItem(SID_TEMPLATE, false);
+ if (pTemplateItem && pTemplateItem->GetValue())
+ {
+ // assume that not calling via SwEditShell::SetFixFields
+ // is allowed, because the shell hasn't been created yet
+ assert(!pWrtSh || pWrtSh->GetView().GetViewFrame().GetFrame().IsClosing_Impl());
+ pDocSh->GetDoc()->getIDocumentFieldsAccess().SetFixFields(nullptr);
+ }
+ }
+ break;
+ case SfxEventHintId::CreateDoc:
+ // Update all FIX-Date/Time fields
+ if( pWrtSh )
+ {
+ const SfxUInt16Item* pUpdateDocItem = pDocSh->GetMedium()->GetItemSet().GetItem(SID_UPDATEDOCMODE, false);
+ bool bUpdateFields = true;
+ if( pUpdateDocItem && pUpdateDocItem->GetValue() == document::UpdateDocMode::NO_UPDATE)
+ bUpdateFields = false;
+ if(bUpdateFields)
+ {
+ comphelper::dispatchCommand(".uno:UpdateInputFields", {});
+
+ // Are database fields contained?
+ // Get all used databases for the first time
+ SwDoc *pDoc = pDocSh->GetDoc();
+ std::vector<OUString> aDBNameList;
+ pDoc->GetAllUsedDB( aDBNameList );
+ if(!aDBNameList.empty())
+ { // Open database beamer
+ ShowDBObj(pWrtSh->GetView(), pDoc->GetDBData());
+ }
+ }
+ }
+ break;
+ default: break;
+ }
+ }
+ }
+ else
+ {
+ if (rHint.GetId() == SfxHintId::Deinitializing)
+ {
+ m_pWebUsrPref.reset();
+ m_pUsrPref.reset();
+ m_pModuleConfig.reset();
+ m_pPrintOptions.reset();
+ m_pWebPrintOptions.reset();
+ m_pChapterNumRules.reset();
+ m_pStdFontConfig.reset();
+ m_pNavigationConfig.reset();
+ m_pToolbarConfig.reset();
+ m_pWebToolbarConfig.reset();
+ m_pDBConfig.reset();
+ if( m_pColorConfig )
+ {
+ m_pColorConfig->RemoveListener(this);
+ m_pColorConfig.reset();
+ }
+ if( m_pAccessibilityOptions )
+ {
+ m_pAccessibilityOptions->RemoveListener(this);
+ m_pAccessibilityOptions.reset();
+ }
+ if( m_pCTLOptions )
+ {
+ m_pCTLOptions->RemoveListener(this);
+ m_pCTLOptions.reset();
+ }
+ if( m_pUserOptions )
+ {
+ m_pUserOptions->RemoveListener(this);
+ m_pUserOptions.reset();
+ }
+ }
+ }
+}
+
+void SwModule::ConfigurationChanged(utl::ConfigurationBroadcaster* pBrdCst, ConfigurationHints eHints)
+{
+ if( pBrdCst == m_pUserOptions.get() )
+ {
+ m_bAuthorInitialised = false;
+ }
+ else if ( pBrdCst == m_pColorConfig.get() )
+ {
+ //invalidate only the current view in tiled rendering mode, or all views otherwise
+ const bool bKit = comphelper::LibreOfficeKit::isActive();
+ SfxViewShell* pViewShell = bKit ? SfxViewShell::Current() : SfxViewShell::GetFirst();
+ while(pViewShell)
+ {
+ if(pViewShell->GetWindow())
+ {
+ auto pSwView = dynamic_cast<SwView *>(pViewShell);
+ if (pSwView)
+ {
+ SwViewOption aNewOptions = *pSwView->GetWrtShell().GetViewOptions();
+ aNewOptions.SetThemeName(svtools::ColorConfig::GetCurrentSchemeName());
+ SwViewColors aViewColors(*m_pColorConfig);
+ aNewOptions.SetColorConfig(aViewColors);
+ const bool bChanged(aNewOptions != *pSwView->GetWrtShell().GetViewOptions());
+ if (bChanged)
+ pSwView->GetWrtShell().ApplyViewOptions(aNewOptions);
+ else if (bKit)
+ {
+ SwXTextDocument* pModel = comphelper::getFromUnoTunnel<SwXTextDocument>(pViewShell->GetCurrentDocument());
+ SfxLokHelper::notifyViewRenderState(pViewShell, pModel);
+ }
+
+ if (bKit)
+ {
+ pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_APPLICATION_BACKGROUND_COLOR,
+ aViewColors.m_aAppBackgroundColor.AsRGBHexString().toUtf8());
+ pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_DOCUMENT_BACKGROUND_COLOR,
+ aViewColors.m_aAppBackgroundColor.AsRGBHexString().toUtf8());
+ }
+
+ // if nothing changed, and the hint was OnlyCurrentDocumentColorScheme we can skip invalidate
+ const bool bSkipInvalidate = !bChanged && bKit && eHints == ConfigurationHints::OnlyCurrentDocumentColorScheme;
+ if (!bSkipInvalidate)
+ pViewShell->GetWindow()->Invalidate();
+ }
+ else if (dynamic_cast< const SwPagePreview *>( pViewShell ) != nullptr ||
+ dynamic_cast< const SwSrcView *>( pViewShell ) != nullptr)
+ {
+ pViewShell->GetWindow()->Invalidate();
+ }
+ }
+ if (bKit)
+ break;
+ pViewShell = SfxViewShell::GetNext( *pViewShell );
+ }
+ }
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ else if ( pBrdCst == m_pAccessibilityOptions.get() )
+ {
+ //set Accessibility options
+ SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+ while(pViewShell)
+ {
+ if(pViewShell->GetWindow())
+ {
+ auto pSwView = dynamic_cast<SwView *>( pViewShell );
+ auto pPagePreview = dynamic_cast<SwPagePreview *>( pViewShell );
+
+ if(pSwView)
+ pSwView->ApplyAccessibilityOptions();
+ else if(pPagePreview)
+ pPagePreview->ApplyAccessibilityOptions();
+
+ if(pSwView || pPagePreview || dynamic_cast< const SwSrcView *>( pViewShell ) != nullptr)
+ {
+ pViewShell->GetWindow()->Invalidate();
+ }
+ }
+ pViewShell = SfxViewShell::GetNext( *pViewShell );
+ }
+ }
+#endif
+ else if( pBrdCst == m_pCTLOptions.get() )
+ {
+ const SfxObjectShell* pObjSh = SfxObjectShell::GetFirst();
+ while( pObjSh )
+ {
+ if( auto pDocShell = dynamic_cast<const SwDocShell*>(pObjSh) )
+ {
+ SwDoc* pDoc = const_cast<SwDocShell*>(pDocShell)->GetDoc();
+ SwViewShell* pVSh = pDoc->getIDocumentLayoutAccess().GetCurrentViewShell();
+ if ( pVSh )
+ pVSh->ChgNumberDigits();
+ }
+ pObjSh = SfxObjectShell::GetNext(*pObjSh);
+ }
+ }
+
+}
+
+SwDBConfig* SwModule::GetDBConfig()
+{
+ if(!m_pDBConfig)
+ m_pDBConfig.reset(new SwDBConfig);
+ return m_pDBConfig.get();
+}
+
+svtools::ColorConfig& SwModule::GetColorConfig()
+{
+ if(!m_pColorConfig)
+ {
+ m_pColorConfig.reset(new svtools::ColorConfig);
+ SwViewOption::SetInitialColorConfig(*m_pColorConfig);
+ m_pColorConfig->AddListener(this);
+ }
+ return *m_pColorConfig;
+}
+
+SvtUserOptions& SwModule::GetUserOptions()
+{
+ if(!m_pUserOptions)
+ {
+ m_pUserOptions.reset(new SvtUserOptions);
+ m_pUserOptions->AddListener(this);
+ }
+ return *m_pUserOptions;
+}
+
+const SwMasterUsrPref *SwModule::GetUsrPref(bool bWeb) const
+{
+ SwModule* pNonConstModule = const_cast<SwModule*>(this);
+ if(bWeb && !m_pWebUsrPref)
+ {
+ // The SpellChecker is needed in SwMasterUsrPref's Load, but it must not
+ // be created there #58256#
+ pNonConstModule->m_pWebUsrPref.reset(new SwMasterUsrPref(true));
+ }
+ else if(!bWeb && !m_pUsrPref)
+ {
+ pNonConstModule->m_pUsrPref.reset(new SwMasterUsrPref(false));
+ }
+ return bWeb ? m_pWebUsrPref.get() : m_pUsrPref.get();
+}
+
+void NewXForms( SfxRequest& rReq )
+{
+ // copied & excerpted from SwModule::InsertLab(..)
+
+ // create new document
+ SwDocShellRef xDocSh( new SwDocShell( SfxObjectCreateMode::STANDARD) );
+ xDocSh->DoInitNew();
+
+ // initialize XForms
+ xDocSh->GetDoc()->initXForms(true);
+
+ // load document into frame
+ SfxViewFrame::DisplayNewDocument( *xDocSh, rReq );
+
+ // set return value
+ rReq.SetReturnValue( SfxVoidItem( rReq.GetSlot() ) );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/app/applab.cxx b/sw/source/uibase/app/applab.cxx
new file mode 100644
index 0000000000..f440fefe86
--- /dev/null
+++ b/sw/source/uibase/app/applab.cxx
@@ -0,0 +1,397 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+#include <config_fuzzers.h>
+
+#include <hintids.hxx>
+
+#include <comphelper/string.hxx>
+#include <svl/voiditem.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <editeng/pbinitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <osl/diagnose.h>
+#include <fmthdft.hxx>
+#include <fmtanchr.hxx>
+#include <fmtfsize.hxx>
+#include <fmtornt.hxx>
+#include <swwait.hxx>
+#include <gloshdl.hxx>
+#include <swmodule.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <fldbas.hxx>
+#include <wrtsh.hxx>
+#include <cmdid.h>
+#include <dbmgr.hxx>
+#include <fldmgr.hxx>
+#include <labimg.hxx>
+#include <section.hxx>
+#include <pagedesc.hxx>
+#include <poolfmt.hxx>
+
+#include <strings.hrc>
+#include <swabstdlg.hxx>
+
+#include <IDocumentDeviceAccess.hxx>
+
+#include "appenv.hxx"
+#include <memory>
+
+using namespace ::com::sun::star;
+
+constexpr OUString MASTER_LABEL = u"MasterLabel"_ustr;
+
+static const SwFrameFormat *lcl_InsertBCText( SwWrtShell& rSh, const SwLabItem& rItem,
+ SwFrameFormat &rFormat,
+ sal_uInt16 nCol, sal_uInt16 nRow )
+{
+ SfxItemSetFixed<RES_VERT_ORIENT, RES_ANCHOR> aSet( rSh.GetAttrPool() );
+ sal_uInt16 nPhyPageNum, nVirtPageNum;
+ rSh.GetPageNum( nPhyPageNum, nVirtPageNum );
+
+ //anchor frame to page
+ aSet.Put( SwFormatAnchor( RndStdIds::FLY_AT_PAGE, nPhyPageNum ) );
+ aSet.Put( SwFormatHoriOrient( rItem.m_lLeft + static_cast<SwTwips>(nCol) * rItem.m_lHDist,
+ text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME ) );
+ aSet.Put( SwFormatVertOrient( rItem.m_lUpper + static_cast<SwTwips>(nRow) * rItem.m_lVDist,
+ text::VertOrientation::NONE, text::RelOrientation::PAGE_FRAME ) );
+ const SwFrameFormat *pFormat = rSh.NewFlyFrame(aSet, true, &rFormat ); // Insert Fly
+ OSL_ENSURE( pFormat, "Fly not inserted" );
+
+ rSh.UnSelectFrame(); //Frame was selected automatically
+
+ rSh.SetTextFormatColl( rSh.GetTextCollFromPool( RES_POOLCOLL_STANDARD ) );
+
+ if(!rItem.m_bSynchron || !(nCol|nRow))
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ::GlossarySetActGroup fnSetActGroup = pFact->SetGlossaryActGroupFunc();
+ if ( fnSetActGroup )
+ (*fnSetActGroup)( rItem.m_sGlossaryGroup );
+ SwGlossaryHdl* pGlosHdl = rSh.GetView().GetGlosHdl();
+ pGlosHdl->SetCurGroup(rItem.m_sGlossaryGroup, true);
+ pGlosHdl->InsertGlossary( rItem.m_sGlossaryBlockName );
+ }
+
+ return pFormat;
+}
+
+static const SwFrameFormat *lcl_InsertLabText( SwWrtShell& rSh, const SwLabItem& rItem,
+ SwFrameFormat &rFormat, SwFieldMgr& rFieldMgr,
+ sal_uInt16 nCol, sal_uInt16 nRow, bool bLast )
+{
+ SfxItemSetFixed<RES_VERT_ORIENT, RES_ANCHOR> aSet( rSh.GetAttrPool() );
+ sal_uInt16 nPhyPageNum, nVirtPageNum;
+ rSh.GetPageNum( nPhyPageNum, nVirtPageNum );
+
+ //anchor frame to page
+ aSet.Put( SwFormatAnchor( RndStdIds::FLY_AT_PAGE, nPhyPageNum ) );
+ aSet.Put( SwFormatHoriOrient( rItem.m_lLeft + static_cast<SwTwips>(nCol) * rItem.m_lHDist,
+ text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME ) );
+ aSet.Put( SwFormatVertOrient( rItem.m_lUpper + static_cast<SwTwips>(nRow) * rItem.m_lVDist,
+ text::VertOrientation::NONE, text::RelOrientation::PAGE_FRAME ) );
+ const SwFrameFormat *pFormat = rSh.NewFlyFrame(aSet, true, &rFormat ); // Insert Fly
+ OSL_ENSURE( pFormat, "Fly not inserted" );
+
+ rSh.UnSelectFrame(); //Frame was selected automatically
+
+ rSh.SetTextFormatColl( rSh.GetTextCollFromPool( RES_POOLCOLL_STANDARD ) );
+
+ // If applicable "next dataset"
+ OUString sDBName;
+ if( (!rItem.m_bSynchron || !(nCol|nRow)) && !(sDBName = InsertLabEnvText( rSh, rFieldMgr, rItem.m_aWriting )).isEmpty() && !bLast )
+ {
+ sDBName = comphelper::string::setToken(sDBName, 3, DB_DELIM, u"True");
+ SwInsertField_Data aData(SwFieldTypesEnum::DatabaseNextSet, 0, sDBName, OUString(), 0, &rSh);
+ rFieldMgr.InsertField( aData );
+ }
+
+ return pFormat;
+}
+
+void SwModule::InsertLab(SfxRequest& rReq, bool bLabel)
+{
+ static sal_uInt16 nLabelTitleNo = 0;
+ static sal_uInt16 nBCTitleNo = 0;
+
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+ // Create DB-Manager
+ std::unique_ptr<SwDBManager> pDBManager(new SwDBManager(nullptr));
+#endif
+
+ // Read SwLabItem from Config
+ SwLabCfgItem aLabCfg(bLabel);
+
+ // Move up Dialog
+ SfxItemSetFixed<FN_LABEL, FN_LABEL> aSet( GetPool() );
+ aSet.Put( aLabCfg.GetItem() );
+
+ SwAbstractDialogFactory* pDialogFactory = SwAbstractDialogFactory::Create();
+
+ ScopedVclPtr<AbstractSwLabDlg> pDlg(pDialogFactory->CreateSwLabDlg(rReq.GetFrameWeld(), aSet,
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+ pDBManager.get(),
+#else
+ NULL,
+#endif
+ bLabel));
+
+ if ( RET_OK != pDlg->Execute() )
+ return;
+
+ // Read dialog, store item in config
+ const SwLabItem& rItem = static_cast<const SwLabItem&>( pDlg->
+ GetOutputItemSet()->Get(FN_LABEL));
+ aLabCfg.GetItem() = rItem;
+ aLabCfg.Commit();
+
+ // Create new document
+ SfxObjectShellLock xDocSh( new SwDocShell( SfxObjectCreateMode::STANDARD));
+ xDocSh->DoInitNew();
+
+ // Printer
+ Printer *pPrt = pDlg->GetPrt();
+ if (pPrt)
+ {
+ SwDocShell *pDocSh = static_cast<SwDocShell*>(&*xDocSh);
+ pDocSh->getIDocumentDeviceAccess().setJobsetup(pPrt->GetJobSetup());
+ }
+
+ SfxViewFrame* pViewFrame = SfxViewFrame::DisplayNewDocument( *xDocSh, rReq );
+ if (!pViewFrame)
+ return;
+
+ SwView *pNewView = static_cast<SwView*>( pViewFrame->GetViewShell());
+ pNewView->AttrChangedNotify(nullptr);// So that SelectShell is being called.
+
+ // Set document title
+ OUString aTmp;
+ if(bLabel)
+ {
+ aTmp = SwResId( STR_LAB_TITLE) +
+ OUString::number(++nLabelTitleNo );
+ }
+ else
+ {
+ aTmp = pDlg->GetBusinessCardStr() +
+ OUString::number( ++nBCTitleNo );
+ }
+ xDocSh->SetTitle( aTmp );
+
+ pViewFrame->GetFrame().Appear();
+
+ // Determine Shell
+ SwWrtShell *pSh = pNewView->GetWrtShellPtr();
+ OSL_ENSURE( pSh, "missing WrtShell" );
+
+ if (pSh)
+ { // block for locks the dispatcher!!
+
+ SwWait aWait( static_cast<SwDocShell&>(*xDocSh), true );
+
+ CurrShell aCurr(pSh);
+ pSh->SetLabelDoc(rItem.m_bSynchron);
+ pSh->DoUndo( false );
+ pSh->StartAllAction();
+
+ pSh->SetNewDoc(); // Avoid performance problems
+
+ SwPageDesc aDesc = pSh->GetPageDesc( 0 );
+ SwFrameFormat& rFormat = aDesc.GetMaster();
+
+ // Borders
+ SvxLRSpaceItem aLRMargin( RES_LR_SPACE );
+ SvxULSpaceItem aULMargin( RES_UL_SPACE );
+ aLRMargin.SetLeft (o3tl::narrowing<sal_uInt16>(rItem.m_lLeft) );
+ aULMargin.SetUpper(o3tl::narrowing<sal_uInt16>(rItem.m_lUpper));
+ aLRMargin.SetRight( 0 );
+ aULMargin.SetLower( 0 );
+ rFormat.SetFormatAttr(aLRMargin);
+ rFormat.SetFormatAttr(aULMargin);
+
+ // Header and footer
+ rFormat.SetFormatAttr(SwFormatHeader(false));
+ aDesc.ChgHeaderShare(false);
+ rFormat.SetFormatAttr(SwFormatFooter(false));
+ aDesc.ChgFooterShare(false);
+
+ aDesc.SetUseOn(UseOnPage::All); // Site numbering
+
+ // Set page size
+ tools::Long lPgWidth, lPgHeight;
+ lPgWidth = std::max<sal_Int32>(rItem.m_lPWidth, MINLAY);
+ lPgHeight = std::max<sal_Int32>(rItem.m_lPHeight, MINLAY);
+ rFormat.SetFormatAttr( SwFormatFrameSize( SwFrameSize::Fixed, lPgWidth, lPgHeight ));
+ // Numbering type
+ SvxNumberType aType;
+ aType.SetNumberingType(SVX_NUM_NUMBER_NONE);
+ aDesc.SetNumType( aType );
+
+ // Followup template
+ const SwPageDesc &rFollow = pSh->GetPageDesc( pSh->GetCurPageDesc() );
+ aDesc.SetFollow( &rFollow );
+
+ pPrt = pSh->getIDocumentDeviceAccess().getPrinter( true );
+ SvxPaperBinItem aItem( RES_PAPER_BIN );
+ aItem.SetValue(static_cast<sal_Int8>(pPrt->GetPaperBin()));
+ rFormat.SetFormatAttr(aItem);
+
+ // Determine orientation of the resulting page
+ aDesc.SetLandscape(rItem.m_lPWidth > rItem.m_lPHeight);
+
+ pSh->ChgPageDesc( 0, aDesc );
+
+ // Insert frame
+ std::optional<SwFieldMgr> pFieldMgr;
+ pFieldMgr.emplace();
+ pFieldMgr->SetEvalExpFields(false);
+
+ // Prepare border template
+ SwFrameFormat* pFormat = pSh->GetFrameFormatFromPool( RES_POOLFRM_LABEL );
+ sal_Int32 iResultWidth = rItem.m_lLeft + (rItem.m_nCols - 1) * rItem.m_lHDist + rItem.m_lWidth - rItem.m_lPWidth;
+ sal_Int32 iResultHeight = rItem.m_lUpper + (rItem.m_nRows - 1) * rItem.m_lVDist + rItem.m_lHeight - rItem.m_lPHeight;
+ sal_Int32 iWidth = (iResultWidth > 0 ? rItem.m_lWidth - (iResultWidth / rItem.m_nCols) - 1 : rItem.m_lWidth);
+ sal_Int32 iHeight = (iResultHeight > 0 ? rItem.m_lHeight - (iResultHeight / rItem.m_nRows) - 1 : rItem.m_lHeight);
+ SwFormatFrameSize aFrameSize( SwFrameSize::Fixed, iWidth, iHeight );
+ pFormat->SetFormatAttr( aFrameSize );
+
+ //frame represents label itself, no border space
+ SvxULSpaceItem aFrameNoULSpace( 0, 0, RES_UL_SPACE );
+ SvxLRSpaceItem aFrameNoLRSpace( 0, 0, 0, RES_LR_SPACE );
+ pFormat->SetFormatAttr( aFrameNoULSpace );
+ pFormat->SetFormatAttr( aFrameNoLRSpace );
+
+ const SwFrameFormat *pFirstFlyFormat = nullptr;
+ if ( rItem.m_bPage )
+ {
+ SwFormatVertOrient aFrameVertOrient( pFormat->GetVertOrient() );
+ aFrameVertOrient.SetVertOrient( text::VertOrientation::TOP );
+ pFormat->SetFormatAttr(aFrameVertOrient);
+
+ for ( sal_Int32 i = 0; i < rItem.m_nRows; ++i )
+ {
+ for ( sal_Int32 j = 0; j < rItem.m_nCols; ++j )
+ {
+ pSh->Push();
+ const SwFrameFormat *pTmp = ( bLabel ?
+ lcl_InsertLabText( *pSh, rItem, *pFormat, *pFieldMgr, j, i,
+ i == rItem.m_nRows - 1 && j == rItem.m_nCols - 1 ) :
+ lcl_InsertBCText( *pSh, rItem, *pFormat, j, i ) );
+ if (!(i|j))
+ {
+ pFirstFlyFormat = pTmp;
+
+ if (rItem.m_bSynchron)
+ {
+ // if there is no content in the fly then
+ // don't leave the fly!!!
+ pSh->Push();
+ pSh->StartOfSection();
+ bool bInFly = nullptr != pSh->WizardGetFly();
+ pSh->Pop(bInFly ? SwCursorShell::PopMode::DeleteStack : SwCursorShell::PopMode::DeleteCurrent);
+
+ if( bInFly )
+ pSh->EndOfSection(true); // select all content
+ // in the fly
+ else
+ pSh->SetMark(); // set only the mark
+
+ SwSectionData aSect(SectionType::Content, MASTER_LABEL);
+ pSh->InsertSection(aSect);
+ }
+ }
+ else if (rItem.m_bSynchron)
+ {
+ SwSectionData aSect(SectionType::FileLink,
+ pSh->GetUniqueSectionName());
+ OUString sLinkName =
+ OUStringChar(sfx2::cTokenSeparator) +
+ OUStringChar(sfx2::cTokenSeparator) +
+ MASTER_LABEL;
+ aSect.SetLinkFileName(sLinkName);
+ aSect.SetProtectFlag(true);
+ pSh->Insert("."); // Dummytext to allocate the Section
+ pSh->StartOfSection();
+ pSh->EndOfSection(true); // Select everything in the frame
+ pSh->InsertSection(aSect);
+ }
+ pSh->Pop(SwCursorShell::PopMode::DeleteCurrent);
+ }
+ }
+ }
+ else
+ {
+ pFirstFlyFormat = bLabel ?
+ lcl_InsertLabText( *pSh, rItem, *pFormat, *pFieldMgr,
+ static_cast< sal_uInt16 >(rItem.m_nCol - 1),
+ static_cast< sal_uInt16 >(rItem.m_nRow - 1), true ) :
+ lcl_InsertBCText(*pSh, rItem, *pFormat,
+ static_cast< sal_uInt16 >(rItem.m_nCol - 1),
+ static_cast< sal_uInt16 >(rItem.m_nRow - 1));
+ }
+
+ //fill the user fields
+ if(!bLabel)
+ {
+ uno::Reference< frame::XModel > xModel = pSh->GetView().GetDocShell()->GetBaseModel();
+ OSL_ENSURE(pDialogFactory, "SwAbstractDialogFactory fail!");
+ SwLabDlgMethod SwLabDlgUpdateFieldInformation = pDialogFactory->GetSwLabDlgStaticMethod ();
+ SwLabDlgUpdateFieldInformation(xModel, rItem);
+ }
+
+ pFieldMgr->SetEvalExpFields(true);
+ pFieldMgr->EvalExpFields(pSh);
+
+ pFieldMgr.reset();
+
+ if (pFirstFlyFormat)
+ pSh->GotoFly(pFirstFlyFormat->GetName(), FLYCNTTYPE_ALL, false);
+
+ if (pSh->IsAnyDatabaseFieldInDoc())
+ pSh->GetView().ShowUIElement("private:resource/toolbar/mailmerge");
+
+ pSh->EndAllAction();
+ pSh->DoUndo();
+ }
+
+ if (pSh && rItem.m_aWriting.indexOf('<') >= 0)
+ {
+ // Open database browser on recently used database
+ ShowDBObj( *pNewView, pSh->GetDBData() );
+ }
+
+ if( rItem.m_bSynchron )
+ {
+ SfxDispatcher* pDisp = pViewFrame->GetDispatcher();
+ assert(pDisp && "No dispatcher in frame?");
+ pDisp->Execute(FN_SYNC_LABELS, SfxCallMode::ASYNCHRON);
+ }
+ rReq.SetReturnValue(SfxVoidItem(bLabel ? FN_LABEL : FN_BUSINESS_CARD));
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/app/appopt.cxx b/sw/source/uibase/app/appopt.cxx
new file mode 100644
index 0000000000..7be59a1dab
--- /dev/null
+++ b/sw/source/uibase/app/appopt.cxx
@@ -0,0 +1,527 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <cmdid.h>
+
+#include <com/sun/star/i18n/ScriptType.hpp>
+
+#include <sal/log.hxx>
+#include <hintids.hxx>
+#include <svl/eitem.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/htmlmode.hxx>
+#include <sfx2/bindings.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <svx/optgrid.hxx>
+#include <svx/dialogs.hrc>
+#include <tools/UnitConversion.hxx>
+#include <i18nlangtag/mslangid.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <fontcfg.hxx>
+#include <swmodule.hxx>
+#include <view.hxx>
+#include <doc.hxx>
+#include <wrtsh.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <uitool.hxx>
+#include <wview.hxx>
+#include <cfgitems.hxx>
+#include <prtopt.hxx>
+#include <pview.hxx>
+#include <usrpref.hxx>
+#include <uiitems.hxx>
+#include <editeng/langitem.hxx>
+#include <unotools/lingucfg.hxx>
+#include <globals.hrc>
+#include <swabstdlg.hxx>
+#include <swwrtshitem.hxx>
+
+#include <sfx2/dispatch.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+
+std::optional<SfxItemSet> SwModule::CreateItemSet( sal_uInt16 nId )
+{
+ bool bTextDialog = (nId == SID_SW_EDITOPTIONS);
+
+ // the options for the Web- and Textdialog are put together here
+ SwViewOption aViewOpt = *GetUsrPref(!bTextDialog);
+ SwMasterUsrPref* pPref = bTextDialog ? m_pUsrPref.get() : m_pWebUsrPref.get();
+ // no MakeUsrPref, because only options from textdoks can be used here
+ SwView* pAppView = GetView();
+ if(pAppView && &pAppView->GetViewFrame() != SfxViewFrame::Current())
+ pAppView = nullptr;
+ if(pAppView)
+ {
+ bool bWebView = dynamic_cast<SwWebView*>( pAppView ) != nullptr;
+ // if Text then no WebView and vice versa
+ if (bWebView != bTextDialog)
+ {
+ aViewOpt = *pAppView->GetWrtShell().GetViewOptions();
+ }
+ else
+ pAppView = nullptr; // with View, there's nothing to win here
+ }
+
+ // Options/Edit
+ SfxItemSetFixed<
+ RES_BACKGROUND, RES_BACKGROUND,
+ XATTR_FILL_FIRST, XATTR_FILL_LAST,
+ SID_PRINTPREVIEW, SID_PRINTPREVIEW,
+ SID_ATTR_GRID_OPTIONS, SID_ATTR_GRID_OPTIONS,
+ SID_HTML_MODE, SID_HTML_MODE,
+ SID_ATTR_CHAR_CJK_LANGUAGE, SID_ATTR_CHAR_CJK_LANGUAGE,
+ SID_ATTR_CHAR_CTL_LANGUAGE, SID_ATTR_CHAR_CTL_LANGUAGE,
+ SID_ATTR_LANGUAGE, SID_ATTR_METRIC,
+ SID_ATTR_DEFTABSTOP, SID_ATTR_DEFTABSTOP,
+ SID_ATTR_APPLYCHARUNIT, SID_ATTR_APPLYCHARUNIT,
+ FN_HSCROLL_METRIC, FN_VSCROLL_METRIC,
+ FN_PARAM_ADDPRINTER, FN_PARAM_ADDPRINTER,
+ FN_PARAM_DOCDISP, FN_PARAM_ELEM,
+ FN_PARAM_PRINTER, FN_PARAM_STDFONTS,
+ FN_PARAM_WRTSHELL, FN_PARAM_WRTSHELL,
+ FN_PARAM_SHADOWCURSOR, FN_PARAM_SHADOWCURSOR,
+ FN_PARAM_CRSR_IN_PROTECTED, FN_PARAM_CRSR_IN_PROTECTED>
+ aRet(GetPool());
+
+ aRet.Put( SwDocDisplayItem( aViewOpt ) );
+ aRet.Put( SwElemItem( aViewOpt ) );
+ if( bTextDialog )
+ {
+ aRet.Put( SwShadowCursorItem( aViewOpt ));
+ aRet.Put( SfxBoolItem(FN_PARAM_CRSR_IN_PROTECTED, aViewOpt.IsCursorInProtectedArea()));
+ }
+
+ if( pAppView )
+ {
+ SwWrtShell& rWrtShell = pAppView->GetWrtShell();
+
+ SfxPrinter* pPrt = rWrtShell.getIDocumentDeviceAccess().getPrinter( false );
+ if( pPrt )
+ aRet.Put(SwPtrItem(FN_PARAM_PRINTER, pPrt));
+ aRet.Put(SwPtrItem(FN_PARAM_WRTSHELL, &rWrtShell));
+
+ aRet.Put(rWrtShell.GetDefault(RES_CHRATR_LANGUAGE).CloneSetWhich(SID_ATTR_LANGUAGE));
+ aRet.Put(rWrtShell.GetDefault(RES_CHRATR_CJK_LANGUAGE).CloneSetWhich(SID_ATTR_CHAR_CJK_LANGUAGE));
+ aRet.Put(rWrtShell.GetDefault(RES_CHRATR_CTL_LANGUAGE).CloneSetWhich(SID_ATTR_CHAR_CTL_LANGUAGE));
+ }
+ else
+ {
+ SvtLinguConfig aLinguCfg;
+ css::lang::Locale aLocale;
+ LanguageType nLang;
+
+ using namespace ::com::sun::star::i18n::ScriptType;
+
+ Any aLang = aLinguCfg.GetProperty(u"DefaultLocale");
+ aLang >>= aLocale;
+ nLang = MsLangId::resolveSystemLanguageByScriptType(LanguageTag::convertToLanguageType( aLocale, false), LATIN);
+ aRet.Put(SvxLanguageItem(nLang, SID_ATTR_LANGUAGE));
+
+ aLang = aLinguCfg.GetProperty(u"DefaultLocale_CJK");
+ aLang >>= aLocale;
+ nLang = MsLangId::resolveSystemLanguageByScriptType(LanguageTag::convertToLanguageType( aLocale, false), ASIAN);
+ aRet.Put(SvxLanguageItem(nLang, SID_ATTR_CHAR_CJK_LANGUAGE));
+
+ aLang = aLinguCfg.GetProperty(u"DefaultLocale_CTL");
+ aLang >>= aLocale;
+ nLang = MsLangId::resolveSystemLanguageByScriptType(LanguageTag::convertToLanguageType( aLocale, false), COMPLEX);
+ aRet.Put(SvxLanguageItem(nLang, SID_ATTR_CHAR_CTL_LANGUAGE));
+ }
+ if(bTextDialog)
+ aRet.Put(SwPtrItem(FN_PARAM_STDFONTS, GetStdFontConfig()));
+ if( dynamic_cast<SwPagePreview*>( SfxViewShell::Current())!=nullptr )
+ {
+ SfxBoolItem aBool(SfxBoolItem(SID_PRINTPREVIEW, true));
+ aRet.Put(aBool);
+ }
+
+ FieldUnit eUnit = pPref->GetHScrollMetric();
+ if(pAppView)
+ pAppView->GetHRulerMetric(eUnit);
+ aRet.Put(SfxUInt16Item( FN_HSCROLL_METRIC, static_cast< sal_uInt16 >(eUnit)));
+
+ eUnit = pPref->GetVScrollMetric();
+ if(pAppView)
+ pAppView->GetVRulerMetric(eUnit);
+ aRet.Put(SfxUInt16Item( FN_VSCROLL_METRIC, static_cast< sal_uInt16 >(eUnit) ));
+ aRet.Put(SfxUInt16Item( SID_ATTR_METRIC, static_cast< sal_uInt16 >(pPref->GetMetric()) ));
+ aRet.Put(SfxBoolItem(SID_ATTR_APPLYCHARUNIT, pPref->IsApplyCharUnit()));
+ if(bTextDialog)
+ {
+ if(pAppView)
+ {
+ const SvxTabStopItem& rDefTabs =
+ pAppView->GetWrtShell().GetDefault(RES_PARATR_TABSTOP);
+ aRet.Put( SfxUInt16Item( SID_ATTR_DEFTABSTOP, o3tl::narrowing<sal_uInt16>(::GetTabDist(rDefTabs))));
+ }
+ else
+ aRet.Put(SfxUInt16Item( SID_ATTR_DEFTABSTOP, o3tl::toTwips(pPref->GetDefTabInMm100(), o3tl::Length::mm100)));
+ }
+
+ // Options for GridTabPage
+ SvxGridItem aGridItem( SID_ATTR_GRID_OPTIONS);
+
+ aGridItem.SetUseGridSnap( aViewOpt.IsSnap());
+ aGridItem.SetSynchronize( aViewOpt.IsSynchronize());
+ aGridItem.SetGridVisible( aViewOpt.IsGridVisible());
+
+ const Size& rSnapSize = aViewOpt.GetSnapSize();
+ aGridItem.SetFieldDrawX( o3tl::narrowing<sal_uInt16>(rSnapSize.Width() ));
+ aGridItem.SetFieldDrawY( o3tl::narrowing<sal_uInt16>(rSnapSize.Height()));
+
+ aGridItem.SetFieldDivisionX( aViewOpt.GetDivisionX());
+ aGridItem.SetFieldDivisionY( aViewOpt.GetDivisionY());
+
+ aRet.Put(aGridItem);
+
+ // Options for PrintTabPage
+ const SwPrintData* pOpt = GetPrtOptions(!bTextDialog);
+ SwAddPrinterItem aAddPrinterItem(*pOpt );
+ aRet.Put(aAddPrinterItem);
+
+ // Options for Web
+ if(!bTextDialog)
+ {
+ aRet.Put(SvxBrushItem(aViewOpt.GetRetoucheColor(), RES_BACKGROUND));
+ aRet.Put(SfxUInt16Item(SID_HTML_MODE, HTMLMODE_ON));
+ }
+
+ return aRet;
+}
+
+void SwModule::ApplyItemSet( sal_uInt16 nId, const SfxItemSet& rSet )
+{
+ bool bTextDialog = nId == SID_SW_EDITOPTIONS;
+ SwView* pAppView = GetView();
+ if(pAppView && &pAppView->GetViewFrame() != SfxViewFrame::Current())
+ pAppView = nullptr;
+ if(pAppView)
+ {
+ // the text dialog mustn't apply data to the web view and vice versa
+ bool bWebView = dynamic_cast<SwWebView*>( pAppView ) != nullptr;
+ if(bWebView == bTextDialog)
+ pAppView = nullptr;
+ }
+
+ SwViewOption aViewOpt = *GetUsrPref(!bTextDialog);
+ SwMasterUsrPref* pPref = bTextDialog ? m_pUsrPref.get() : m_pWebUsrPref.get();
+
+ SfxBindings *pBindings = pAppView ? &pAppView->GetViewFrame().GetBindings()
+ : nullptr;
+
+ // Interpret the page Documentview
+ if( const SwDocDisplayItem* pDocDispItem = rSet.GetItemIfSet( FN_PARAM_DOCDISP, false ))
+ {
+ if(!aViewOpt.IsViewMetaChars())
+ {
+ if( (!aViewOpt.IsTab( true ) && pDocDispItem->m_bTab) ||
+ (!aViewOpt.IsBlank( true ) && pDocDispItem->m_bSpace) ||
+ (!aViewOpt.IsShowBookmarks(true) && pDocDispItem->m_bBookmarks) ||
+ (!aViewOpt.IsParagraph( true ) && pDocDispItem->m_bParagraphEnd) ||
+ (!aViewOpt.IsLineBreak( true ) && pDocDispItem->m_bManualBreak) )
+ {
+ aViewOpt.SetViewMetaChars(true);
+ if(pBindings)
+ pBindings->Invalidate(FN_VIEW_META_CHARS);
+ }
+
+ }
+ pDocDispItem->FillViewOptions( aViewOpt );
+ if(pBindings)
+ {
+ pBindings->Invalidate(FN_VIEW_GRAPHIC);
+ pBindings->Invalidate(FN_VIEW_HIDDEN_PARA);
+ }
+ }
+
+ // Elements - interpret Item
+ bool bReFoldOutlineFolding = false;
+ if( const SwElemItem* pElemItem = rSet.GetItemIfSet( FN_PARAM_ELEM, false ) )
+ {
+ pElemItem->FillViewOptions( aViewOpt );
+
+ // Outline-folding options
+ if (SwWrtShell* pWrtShell = GetActiveWrtShell())
+ {
+ bool bIsOutlineFoldingOn = pWrtShell->GetViewOptions()->IsShowOutlineContentVisibilityButton();
+ bool bTreatSubsChanged = aViewOpt.IsTreatSubOutlineLevelsAsContent()
+ != pWrtShell->GetViewOptions()->IsTreatSubOutlineLevelsAsContent();
+ if (bIsOutlineFoldingOn &&
+ (!aViewOpt.IsShowOutlineContentVisibilityButton() || bTreatSubsChanged))
+ {
+ // Outline-folding options have change which require to show all content.
+ // Either outline-folding is being switched off or outline-folding is currently on
+ // and the treat subs option has changed.
+ pWrtShell->GetView().GetViewFrame().GetDispatcher()->Execute(FN_SHOW_OUTLINECONTENTVISIBILITYBUTTON);
+ if (bTreatSubsChanged)
+ bReFoldOutlineFolding = true; // folding method changed, set flag to refold below
+ }
+ else
+ {
+ // Refold needs to be done when outline-folding is being turned on or off
+ bReFoldOutlineFolding =
+ pWrtShell->GetViewOptions()->IsShowOutlineContentVisibilityButton() !=
+ aViewOpt.IsShowOutlineContentVisibilityButton();
+ }
+ }
+ }
+
+ if( const SfxUInt16Item* pMetricItem = rSet.GetItemIfSet(SID_ATTR_METRIC, false ) )
+ {
+ SfxApplication::SetOptions(rSet);
+ PutItem(*pMetricItem);
+ ::SetDfltMetric(static_cast<FieldUnit>(pMetricItem->GetValue()), !bTextDialog);
+ }
+ if( const SfxBoolItem* pCharItem = rSet.GetItemIfSet(SID_ATTR_APPLYCHARUNIT,
+ false ) )
+ {
+ SfxApplication::SetOptions(rSet);
+ ::SetApplyCharUnit(pCharItem->GetValue(), !bTextDialog);
+ }
+
+ if( const SfxUInt16Item* pMetricItem = rSet.GetItemIfSet(FN_HSCROLL_METRIC, false ) )
+ {
+ FieldUnit eUnit = static_cast<FieldUnit>(pMetricItem->GetValue());
+ pPref->SetHScrollMetric(eUnit);
+ if(pAppView)
+ pAppView->ChangeTabMetric(eUnit);
+ }
+
+ if( const SfxUInt16Item* pMetricItem = rSet.GetItemIfSet(FN_VSCROLL_METRIC, false ) )
+ {
+ FieldUnit eUnit = static_cast<FieldUnit>(pMetricItem->GetValue());
+ pPref->SetVScrollMetric(eUnit);
+ if(pAppView)
+ pAppView->ChangeVRulerMetric(eUnit);
+ }
+
+ if( const SfxUInt16Item* pItem = rSet.GetItemIfSet(SID_ATTR_DEFTABSTOP, false ) )
+ {
+ sal_uInt16 nTabDist = pItem->GetValue();
+ pPref->SetDefTabInMm100(convertTwipToMm100(nTabDist));
+ if(pAppView)
+ {
+ SvxTabStopItem aDefTabs( 0, 0, SvxTabAdjust::Default, RES_PARATR_TABSTOP );
+ MakeDefTabs( nTabDist, aDefTabs );
+ pAppView->GetWrtShell().SetDefault( aDefTabs );
+ }
+ }
+
+ // Background only in WebDialog
+ if(SfxItemState::SET == rSet.GetItemState(RES_BACKGROUND))
+ {
+ const SvxBrushItem& rBrushItem = rSet.Get(RES_BACKGROUND);
+ aViewOpt.SetRetoucheColor( rBrushItem.GetColor() );
+ }
+
+ // Interpret page Grid Settings
+ if( const SvxGridItem* pGridItem = rSet.GetItemIfSet( SID_ATTR_GRID_OPTIONS, false ))
+ {
+ aViewOpt.SetSnap( pGridItem->GetUseGridSnap() );
+ aViewOpt.SetSynchronize(pGridItem->GetSynchronize());
+ if( aViewOpt.IsGridVisible() != pGridItem->GetGridVisible() )
+ aViewOpt.SetGridVisible( pGridItem->GetGridVisible());
+ Size aSize( pGridItem->GetFieldDrawX(), pGridItem->GetFieldDrawY() );
+ if( aViewOpt.GetSnapSize() != aSize )
+ aViewOpt.SetSnapSize( aSize );
+ short nDiv = static_cast<short>(pGridItem->GetFieldDivisionX()) ;
+ if( aViewOpt.GetDivisionX() != nDiv )
+ aViewOpt.SetDivisionX( nDiv );
+ nDiv = static_cast<short>(pGridItem->GetFieldDivisionY());
+ if( aViewOpt.GetDivisionY() != nDiv )
+ aViewOpt.SetDivisionY( nDiv );
+
+ if(pBindings)
+ {
+ pBindings->Invalidate(SID_GRID_VISIBLE);
+ pBindings->Invalidate(SID_GRID_USE);
+ }
+ }
+
+ // Interpret Writer Printer Options
+ if( const SwAddPrinterItem* pAddPrinterAttr = rSet.GetItemIfSet( FN_PARAM_ADDPRINTER, false ) )
+ {
+ SwPrintOptions* pOpt = GetPrtOptions(!bTextDialog);
+ if (pOpt)
+ {
+ *pOpt = *pAddPrinterAttr;
+ }
+ }
+
+ if( const SwShadowCursorItem* pItem = rSet.GetItemIfSet( FN_PARAM_SHADOWCURSOR, false ))
+ {
+ pItem->FillViewOptions( aViewOpt );
+ if(pBindings)
+ pBindings->Invalidate(FN_SHADOWCURSOR);
+ }
+
+ if( pAppView )
+ {
+ SwWrtShell &rWrtSh = pAppView->GetWrtShell();
+ const bool bAlignFormulas = rWrtSh.GetDoc()->getIDocumentSettingAccess().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT );
+ pPref->SetAlignMathObjectsToBaseline( bAlignFormulas );
+
+ // don't align formulas in documents that are currently loading
+ if (bAlignFormulas && !rWrtSh.GetDoc()->IsInReading())
+ rWrtSh.AlignAllFormulasToBaseline();
+ }
+
+ if( const SfxBoolItem* pItem = rSet.GetItemIfSet( FN_PARAM_CRSR_IN_PROTECTED, false ))
+ {
+ aViewOpt.SetCursorInProtectedArea(pItem->GetValue());
+ }
+
+ // set elements for the current view and shell
+ ApplyUsrPref( aViewOpt, pAppView, bTextDialog? SvViewOpt::DestText : SvViewOpt::DestWeb);
+
+ // must be done after ApplyUsrPref
+ if (SfxItemState::SET != rSet.GetItemState(FN_PARAM_ELEM, false))
+ return;
+
+ if (bReFoldOutlineFolding)
+ {
+ if (SwWrtShell* pWrtShell = GetActiveWrtShell())
+ {
+ pWrtShell->GetView().GetViewFrame().GetDispatcher()->Execute(FN_SHOW_OUTLINECONTENTVISIBILITYBUTTON);
+ pWrtShell->GetView().GetViewFrame().GetDispatcher()->Execute(FN_SHOW_OUTLINECONTENTVISIBILITYBUTTON);
+ }
+ }
+}
+
+std::unique_ptr<SfxTabPage> SwModule::CreateTabPage( sal_uInt16 nId, weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet )
+{
+ std::unique_ptr<SfxTabPage> xRet;
+ SfxAllItemSet aSet(*(rSet.GetPool()));
+ switch( nId )
+ {
+ case RID_SW_TP_CONTENT_OPT:
+ case RID_SW_TP_HTML_CONTENT_OPT:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( nId );
+ xRet = (*fnCreatePage)( pPage, pController, &rSet );
+ break;
+ }
+ case RID_SW_TP_HTML_OPTGRID_PAGE:
+ case RID_SVXPAGE_GRID:
+ xRet = SvxGridTabPage::Create(pPage, pController, rSet);
+ break;
+
+ case RID_SW_TP_STD_FONT:
+ case RID_SW_TP_STD_FONT_CJK:
+ case RID_SW_TP_STD_FONT_CTL:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( nId );
+ xRet = (*fnCreatePage)( pPage, pController, &rSet );
+ if(RID_SW_TP_STD_FONT != nId)
+ {
+ aSet.Put (SfxUInt16Item(SID_FONTMODE_TYPE, RID_SW_TP_STD_FONT_CJK == nId ? FONT_GROUP_CJK : FONT_GROUP_CTL));
+ xRet->PageCreated(aSet);
+ }
+ }
+ break;
+ case RID_SW_TP_HTML_OPTPRINT_PAGE:
+ case RID_SW_TP_OPTPRINT_PAGE:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( nId );
+ xRet = (*fnCreatePage)( pPage, pController, &rSet );
+ aSet.Put (SfxBoolItem(SID_FAX_LIST, true));
+ xRet->PageCreated(aSet);
+ }
+ break;
+ case RID_SW_TP_HTML_OPTTABLE_PAGE:
+ case RID_SW_TP_OPTTABLE_PAGE:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( nId );
+ xRet = (*fnCreatePage)( pPage, pController, &rSet );
+ SwView* pCurrView = GetView();
+ if(pCurrView)
+ {
+ // if text then not WebView and vice versa
+ bool bWebView = dynamic_cast<SwWebView*>( pCurrView ) != nullptr;
+ if( (bWebView && RID_SW_TP_HTML_OPTTABLE_PAGE == nId) ||
+ (!bWebView && RID_SW_TP_HTML_OPTTABLE_PAGE != nId) )
+ {
+ aSet.Put (SwWrtShellItem(pCurrView->GetWrtShellPtr()));
+ xRet->PageCreated(aSet);
+ }
+ }
+ }
+ break;
+ case RID_SW_TP_OPTSHDWCRSR:
+ case RID_SW_TP_HTML_OPTSHDWCRSR:
+ case RID_SW_TP_REDLINE_OPT:
+ case RID_SW_TP_COMPARISON_OPT:
+ case RID_SW_TP_OPTLOAD_PAGE:
+ case RID_SW_TP_OPTCOMPATIBILITY_PAGE:
+ case RID_SW_TP_MAILCONFIG:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( nId );
+ xRet = (*fnCreatePage)( pPage, pController, &rSet );
+ if (nId == RID_SW_TP_OPTSHDWCRSR || nId == RID_SW_TP_HTML_OPTSHDWCRSR)
+ {
+ SwView* pCurrView = GetView();
+ if(pCurrView)
+ {
+ aSet.Put( SwWrtShellItem( pCurrView->GetWrtShellPtr() ) );
+ xRet->PageCreated(aSet);
+ }
+ }
+ }
+ break;
+ case RID_SW_TP_OPTTEST_PAGE:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( nId );
+ xRet = (*fnCreatePage)( pPage, pController, &rSet );
+ break;
+ }
+ case RID_SW_TP_BACKGROUND:
+ {
+ SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
+ ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( RID_SVXPAGE_BKG );
+ xRet = (*fnCreatePage)( pPage, pController, &rSet );
+ xRet->PageCreated( rSet );
+ break;
+ }
+ case RID_SW_TP_OPTCAPTION_PAGE:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( RID_SW_TP_OPTCAPTION_PAGE );
+ xRet = (*fnCreatePage)( pPage, pController, &rSet );
+ }
+ break;
+ }
+
+ if(!xRet)
+ SAL_WARN( "sw", "SwModule::CreateTabPage(): Unknown tabpage id " << nId );
+ return xRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/app/docsh.cxx b/sw/source/uibase/app/docsh.cxx
new file mode 100644
index 0000000000..1cddf3070b
--- /dev/null
+++ b/sw/source/uibase/app/docsh.cxx
@@ -0,0 +1,1433 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+
+#include <officecfg/Office/Common.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/syswin.hxx>
+#include <vcl/jobset.hxx>
+#include <svl/numformat.hxx>
+#include <svl/whiter.hxx>
+#include <svl/eitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/PasswordHelper.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/notebookbar/SfxNotebookBar.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <editeng/flstitem.hxx>
+#include <comphelper/lok.hxx>
+#include <comphelper/classids.hxx>
+#include <basic/sbmod.hxx>
+#include <osl/diagnose.h>
+#include <node.hxx>
+#include <swwait.hxx>
+#include <printdata.hxx>
+#include <view.hxx>
+#include <edtwin.hxx>
+#include <PostItMgr.hxx>
+#include <wrtsh.hxx>
+#include <docsh.hxx>
+#include <viewopt.hxx>
+#include <wdocsh.hxx>
+#include <swmodule.hxx>
+#include <globdoc.hxx>
+#include <usrpref.hxx>
+#include <shellio.hxx>
+#include <docstyle.hxx>
+#include <doc.hxx>
+#include <docfunc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentLinksAdministration.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <IDocumentStatistics.hxx>
+#include <IDocumentState.hxx>
+#include <pview.hxx>
+#include <srcview.hxx>
+#include <ndindex.hxx>
+#include <ndole.hxx>
+#include <txtftn.hxx>
+#include <ftnidx.hxx>
+#include <fldbas.hxx>
+#include <docary.hxx>
+#include <swerror.h>
+#include <cmdid.h>
+#include <strings.hrc>
+
+#include <unotools/fltrcfg.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/objface.hxx>
+
+#define ShellClass_SwDocShell
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+#include <com/sun/star/document/UpdateDocMode.hpp>
+
+#include <com/sun/star/script/XLibraryContainer.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/sdb/XDocumentDataSource.hpp>
+#include <com/sun/star/uri/UriReferenceFactory.hpp>
+#include <com/sun/star/uri/VndSunStarPkgUrlReferenceFactory.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <ooo/vba/XSinkCaller.hpp>
+
+#include <unotextrange.hxx>
+
+#include <dbmgr.hxx>
+#include <iodetect.hxx>
+
+#include <comphelper/processfactory.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::script;
+using namespace ::com::sun::star::container;
+
+SFX_IMPL_SUPERCLASS_INTERFACE(SwDocShell, SfxObjectShell)
+
+void SwDocShell::InitInterface_Impl()
+{
+}
+
+
+SFX_IMPL_OBJECTFACTORY(SwDocShell, SvGlobalName(SO3_SW_CLASSID), "swriter" )
+
+bool SwDocShell::InsertGeneratedStream(SfxMedium & rMedium,
+ uno::Reference<text::XTextRange> const& xInsertPosition)
+{
+ SwUnoInternalPaM aPam(*GetDoc()); // must have doc since called from SwView
+ if (!::sw::XTextRangeToSwPaM(aPam, xInsertPosition))
+ return false;
+ // similar to SwView::InsertMedium
+ SwReaderPtr pReader;
+ Reader *const pRead = StartConvertFrom(rMedium, pReader, nullptr, &aPam);
+ if (!pRead)
+ return false;
+ ErrCodeMsg const nError = pReader->Read(*pRead);
+ return ERRCODE_NONE == nError;
+}
+
+// Prepare loading
+Reader* SwDocShell::StartConvertFrom(SfxMedium& rMedium, SwReaderPtr& rpRdr,
+ SwCursorShell const *pCursorShell,
+ SwPaM* pPaM )
+{
+ bool bAPICall = false;
+ if( const SfxBoolItem* pApiItem = rMedium.GetItemSet().GetItemIfSet( FN_API_CALL ) )
+ bAPICall = pApiItem->GetValue();
+
+ std::shared_ptr<const SfxFilter> pFlt = rMedium.GetFilter();
+ if( !pFlt )
+ {
+ if(!bAPICall)
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_CANTOPEN)));
+ xInfoBox->run();
+ }
+ return nullptr;
+ }
+ OUString aFileName( rMedium.GetName() );
+ Reader* pRead = SwReaderWriter::GetReader( pFlt->GetUserData() );
+ if( !pRead )
+ return nullptr;
+
+ if( rMedium.IsStorage()
+ ? SwReaderType::Storage & pRead->GetReaderType()
+ : SwReaderType::Stream & pRead->GetReaderType() )
+ {
+ if (pPaM)
+ rpRdr.reset(new SwReader( rMedium, aFileName, *pPaM ));
+ else if (pCursorShell)
+ rpRdr.reset(new SwReader( rMedium, aFileName, *pCursorShell->GetCursor() ));
+ else
+ rpRdr.reset(new SwReader( rMedium, aFileName, m_xDoc.get() ));
+ }
+ else
+ return nullptr;
+
+ // #i30171# set the UpdateDocMode at the SwDocShell
+ const SfxUInt16Item* pUpdateDocItem = rMedium.GetItemSet().GetItem(SID_UPDATEDOCMODE, false);
+ m_nUpdateDocMode = pUpdateDocItem ? pUpdateDocItem->GetValue() : document::UpdateDocMode::NO_UPDATE;
+
+ if (!pFlt->GetDefaultTemplate().isEmpty())
+ pRead->SetTemplateName( pFlt->GetDefaultTemplate() );
+
+ if( pRead == ReadAscii && nullptr != rMedium.GetInStream() &&
+ pFlt->GetUserData() == FILTER_TEXT_DLG )
+ {
+ SwAsciiOptions aOpt;
+ if( const SfxStringItem* pItem = rMedium.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS ) )
+ aOpt.ReadUserData( pItem->GetValue() );
+
+ pRead->GetReaderOpt().SetASCIIOpts( aOpt );
+ }
+
+ return pRead;
+}
+
+// Loading
+bool SwDocShell::ConvertFrom( SfxMedium& rMedium )
+{
+ SwReaderPtr pRdr;
+ Reader* pRead = StartConvertFrom(rMedium, pRdr);
+ if (!pRead)
+ return false; // #129881# return if no reader is found
+ tools::SvRef<SotStorage> pStg=pRead->getSotStorageRef(); // #i45333# save sot storage ref in case of recursive calls
+
+ m_xDoc->setDocAccTitle(OUString());
+ if (const auto pFrame1 = SfxViewFrame::GetFirst(this))
+ {
+ if (auto pSysWin = pFrame1->GetWindow().GetSystemWindow())
+ {
+ pSysWin->SetAccessibleName(OUString());
+ }
+ }
+ SwWait aWait( *this, true );
+
+ // Suppress SfxProgress, when we are Embedded
+ SW_MOD()->SetEmbeddedLoadSave(
+ SfxObjectCreateMode::EMBEDDED == GetCreateMode() );
+
+ pRdr->GetDoc().getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE, dynamic_cast< const SwWebDocShell *>( this ) != nullptr);
+
+ // Restore the pool default if reading a saved document.
+ m_xDoc->RemoveAllFormatLanguageDependencies();
+
+ ErrCodeMsg nErr = pRdr->Read( *pRead );
+
+ // Maybe put away one old Doc
+ if (m_xDoc.get() != &pRdr->GetDoc())
+ {
+ RemoveLink();
+ m_xDoc = &pRdr->GetDoc();
+
+ AddLink();
+
+ if (!m_xBasePool.is())
+ m_xBasePool = new SwDocStyleSheetPool( *m_xDoc, SfxObjectCreateMode::ORGANIZER == GetCreateMode() );
+ }
+
+ UpdateFontList();
+ InitDrawModelAndDocShell(this, m_xDoc ? m_xDoc->getIDocumentDrawModelAccess().GetDrawModel() : nullptr);
+
+ pRdr.reset();
+
+ SW_MOD()->SetEmbeddedLoadSave( false );
+
+ SetError(nErr);
+ bool bOk = !nErr.IsError();
+
+ if (bOk && !m_xDoc->IsInLoadAsynchron())
+ {
+ LoadingFinished();
+ }
+
+ pRead->setSotStorageRef(pStg); // #i45333# save sot storage ref in case of recursive calls
+
+ return bOk;
+}
+
+// Saving the Default-Format, Stg present
+bool SwDocShell::Save()
+{
+ //#i3370# remove quick help to prevent saving of autocorrection suggestions
+ if (m_pView)
+ m_pView->GetEditWin().StopQuickHelp();
+ SwWait aWait( *this, true );
+
+ CalcLayoutForOLEObjects(); // format for OLE objects
+ // #i62875#
+ // reset compatibility flag <DoNotCaptureDrawObjsOnPage>, if possible
+ if (m_pWrtShell && m_xDoc &&
+ m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE) &&
+ docfunc::AllDrawObjsOnPage(*m_xDoc))
+ {
+ m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE, false);
+ }
+
+ ErrCodeMsg nErr = ERR_SWG_WRITE_ERROR;
+ ErrCode nVBWarning = ERRCODE_NONE;
+ if( SfxObjectShell::Save() )
+ {
+ switch( GetCreateMode() )
+ {
+ case SfxObjectCreateMode::INTERNAL:
+ nErr = ERRCODE_NONE;
+ break;
+
+ case SfxObjectCreateMode::ORGANIZER:
+ {
+ WriterRef xWrt;
+ ::GetXMLWriter(std::u16string_view(), GetMedium()->GetBaseURL(true), xWrt);
+ xWrt->SetOrganizerMode( true );
+ SwWriter aWrt( *GetMedium(), *m_xDoc );
+ nErr = aWrt.Write( xWrt );
+ xWrt->SetOrganizerMode( false );
+ }
+ break;
+
+ case SfxObjectCreateMode::EMBEDDED:
+ // Suppress SfxProgress, if we are Embedded
+ SW_MOD()->SetEmbeddedLoadSave( true );
+ [[fallthrough]];
+
+ case SfxObjectCreateMode::STANDARD:
+ default:
+ {
+ if (m_xDoc->ContainsMSVBasic())
+ {
+ if( SvtFilterOptions::Get().IsLoadWordBasicStorage() )
+ nVBWarning = GetSaveWarningOfMSVBAStorage( static_cast<SfxObjectShell&>(*this) );
+ m_xDoc->SetContainsMSVBasic( false );
+ }
+
+ // End TableBox Edit!
+ if (m_pWrtShell)
+ m_pWrtShell->EndAllTableBoxEdit();
+
+ WriterRef xWrt;
+ ::GetXMLWriter(std::u16string_view(), GetMedium()->GetBaseURL(true), xWrt);
+
+ bool bLockedView(false);
+ if (m_pWrtShell)
+ {
+ bLockedView = m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView( true ); //lock visible section
+ }
+
+ SwWriter aWrt( *GetMedium(), *m_xDoc );
+ nErr = aWrt.Write( xWrt );
+
+ if (m_pWrtShell)
+ m_pWrtShell->LockView( bLockedView );
+ }
+ break;
+ }
+ SW_MOD()->SetEmbeddedLoadSave( false );
+ }
+ SetError(nErr ? nErr : nVBWarning);
+
+ SfxViewFrame *const pFrame =
+ m_pWrtShell ? &m_pWrtShell->GetView().GetViewFrame() : nullptr;
+ if( pFrame )
+ {
+ pFrame->GetBindings().SetState(SfxBoolItem(SID_DOC_MODIFIED, false));
+ }
+ return !nErr.IsError();
+}
+
+SwDocShell::LockAllViewsGuard_Impl::LockAllViewsGuard_Impl(SwViewShell* pViewShell)
+{
+ if (!pViewShell)
+ return;
+ for (SwViewShell& rShell : pViewShell->GetRingContainer())
+ {
+ if (!rShell.IsViewLocked())
+ {
+ m_aViewWasUnLocked.push_back(&rShell);
+ rShell.LockView(true);
+ }
+ }
+}
+
+SwDocShell::LockAllViewsGuard_Impl::~LockAllViewsGuard_Impl()
+{
+ for (SwViewShell* pShell : m_aViewWasUnLocked)
+ pShell->LockView(false);
+}
+
+std::unique_ptr<SfxObjectShell::LockAllViewsGuard> SwDocShell::LockAllViews()
+{
+ return std::make_unique<LockAllViewsGuard_Impl>(GetEditShell());
+}
+
+// Save using the Defaultformat
+bool SwDocShell::SaveAs( SfxMedium& rMedium )
+{
+ SwWait aWait( *this, true );
+ //#i3370# remove quick help to prevent saving of autocorrection suggestions
+ if (m_pView)
+ m_pView->GetEditWin().StopQuickHelp();
+
+ //#i91811# mod if we have an active margin window, write back the text
+ if (m_pView &&
+ m_pView->GetPostItMgr() &&
+ m_pView->GetPostItMgr()->HasActiveSidebarWin())
+ {
+ m_pView->GetPostItMgr()->UpdateDataOnActiveSidebarWin();
+ }
+
+ if (m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT) &&
+ !m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT_SAVE_LINKS))
+ RemoveOLEObjects();
+
+ if (GetMedium())
+ {
+ // Task 75666 - is the Document imported by our Microsoft-Filters?
+ std::shared_ptr<const SfxFilter> pOldFilter = GetMedium()->GetFilter();
+ if( pOldFilter &&
+ ( pOldFilter->GetUserData() == FILTER_WW8 ||
+ pOldFilter->GetUserData() == "CWW6" ||
+ pOldFilter->GetUserData() == "WW6" ) )
+ {
+ // when saving it in our own fileformat, then remove the template
+ // name from the docinfo.
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps
+ = xDPS->getDocumentProperties();
+ xDocProps->setTemplateName(OUString());
+ xDocProps->setTemplateURL(OUString());
+ xDocProps->setTemplateDate(::util::DateTime());
+ }
+ }
+
+ CalcLayoutForOLEObjects(); // format for OLE objects
+
+ const bool bURLChanged = GetMedium() && GetMedium()->GetURLObject() != rMedium.GetURLObject();
+ const SwDBManager* const pMgr = m_xDoc->GetDBManager();
+ const bool bHasEmbedded = pMgr && !pMgr->getEmbeddedName().isEmpty();
+ bool bSaveDS = bHasEmbedded && bURLChanged;
+ if (bSaveDS)
+ {
+ // Don't save data source in case a temporary is being saved for preview in MM wizard
+ if (const SfxBoolItem* pNoEmbDS
+ = rMedium.GetItemSet().GetItem(SID_NO_EMBEDDED_DS, false))
+ bSaveDS = !pNoEmbDS->GetValue();
+ }
+ if (bSaveDS)
+ {
+ // We have an embedded data source definition, need to re-store it,
+ // otherwise relative references will break when the new file is in a
+ // different directory.
+
+ OUString aURL(GetMedium()->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::NONE));
+ if (aURL.isEmpty())
+ {
+ // No old URL - is this a new document created from a template with embedded DS?
+ // Try to get the template URL to reconstruct the embedded data source URL
+ const css::beans::PropertyValues& rArgs = GetMedium()->GetArgs();
+ const auto aURLIter = std::find_if(rArgs.begin(), rArgs.end(),
+ [](const auto& v) { return v.Name == "URL"; });
+ if (aURLIter != rArgs.end())
+ aURLIter->Value >>= aURL;
+ }
+
+ if (!aURL.isEmpty())
+ {
+ auto xContext(comphelper::getProcessComponentContext());
+ auto xUri = css::uri::UriReferenceFactory::create(xContext)->parse(aURL);
+ assert(xUri.is());
+ xUri = css::uri::VndSunStarPkgUrlReferenceFactory::create(xContext)
+ ->createVndSunStarPkgUrlReference(xUri);
+ assert(xUri.is());
+ aURL = xUri->getUriReference() + "/"
+ + INetURLObject::encode(pMgr->getEmbeddedName(), INetURLObject::PART_FPATH,
+ INetURLObject::EncodeMechanism::All);
+
+ bool bCopyTo = GetCreateMode() == SfxObjectCreateMode::EMBEDDED;
+ if (!bCopyTo)
+ {
+ if (const SfxBoolItem* pSaveToItem
+ = rMedium.GetItemSet().GetItem(SID_SAVETO, false))
+ bCopyTo = pSaveToItem->GetValue();
+ }
+
+ auto xDatabaseContext = sdb::DatabaseContext::create(xContext);
+ uno::Reference<sdb::XDocumentDataSource> xDataSource(xDatabaseContext->getByName(aURL),
+ uno::UNO_QUERY);
+ if (xDataSource)
+ {
+ uno::Reference<frame::XStorable> xStorable(xDataSource->getDatabaseDocument(),
+ uno::UNO_QUERY);
+ SwDBManager::StoreEmbeddedDataSource(xStorable, rMedium.GetOutputStorage(),
+ pMgr->getEmbeddedName(), rMedium.GetName(),
+ bCopyTo);
+ }
+ }
+ }
+
+ // #i62875#
+ // reset compatibility flag <DoNotCaptureDrawObjsOnPage>, if possible
+ if (m_pWrtShell &&
+ m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE) &&
+ docfunc::AllDrawObjsOnPage(*m_xDoc))
+ {
+ m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE, false);
+ }
+
+ ErrCodeMsg nErr = ERR_SWG_WRITE_ERROR;
+ ErrCode nVBWarning = ERRCODE_NONE;
+ uno::Reference < embed::XStorage > xStor = rMedium.GetOutputStorage();
+ if( SfxObjectShell::SaveAs( rMedium ) )
+ {
+ if( GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT) && dynamic_cast< const SwGlobalDocShell *>( this ) == nullptr )
+ {
+ // The document is closed explicitly, but using SfxObjectShellLock is still more correct here
+ SfxObjectShellLock xDocSh =
+ new SwGlobalDocShell( SfxObjectCreateMode::INTERNAL );
+ // the global document can not be a template
+ xDocSh->SetupStorage( xStor, SotStorage::GetVersion( xStor ), false );
+ xDocSh->DoClose();
+ }
+
+ if (m_xDoc->ContainsMSVBasic())
+ {
+ if( SvtFilterOptions::Get().IsLoadWordBasicStorage() )
+ nVBWarning = GetSaveWarningOfMSVBAStorage( static_cast<SfxObjectShell&>(*this) );
+ m_xDoc->SetContainsMSVBasic( false );
+ }
+
+ if (m_pWrtShell)
+ {
+ // End TableBox Edit!
+ m_pWrtShell->EndAllTableBoxEdit();
+
+ // Remove invalid signatures.
+ m_pWrtShell->ValidateAllParagraphSignatures(false);
+
+ m_pWrtShell->ClassifyDocPerHighestParagraphClass();
+ }
+
+ // Remember and preserve Modified-Flag without calling the Link
+ // (for OLE; after Statement from MM)
+ const bool bIsModified = m_xDoc->getIDocumentState().IsModified();
+ m_xDoc->GetIDocumentUndoRedo().LockUndoNoModifiedPosition();
+ Link<bool,void> aOldOLELnk( m_xDoc->GetOle2Link() );
+ m_xDoc->SetOle2Link( Link<bool,void>() );
+
+ // Suppress SfxProgress when we are Embedded
+ SW_MOD()->SetEmbeddedLoadSave(
+ SfxObjectCreateMode::EMBEDDED == GetCreateMode() );
+
+ WriterRef xWrt;
+ ::GetXMLWriter(std::u16string_view(), rMedium.GetBaseURL(true), xWrt);
+
+ bool bLockedView(false);
+ if (m_pWrtShell)
+ {
+ bLockedView = m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView( true ); //lock visible section
+ }
+
+ SwWriter aWrt( rMedium, *m_xDoc );
+ nErr = aWrt.Write( xWrt );
+
+ if (m_pWrtShell)
+ m_pWrtShell->LockView( bLockedView );
+
+ if( bIsModified )
+ {
+ m_xDoc->getIDocumentState().SetModified();
+ m_xDoc->GetIDocumentUndoRedo().UnLockUndoNoModifiedPosition();
+ }
+ m_xDoc->SetOle2Link( aOldOLELnk );
+
+ SW_MOD()->SetEmbeddedLoadSave( false );
+
+ // Increase RSID
+ m_xDoc->setRsid( m_xDoc->getRsid() );
+
+ m_xDoc->cleanupUnoCursorTable();
+ }
+ SetError(nErr ? nErr : nVBWarning);
+
+ return !nErr.IsError();
+}
+
+// Save all Formats
+static SwSrcView* lcl_GetSourceView( SwDocShell const * pSh )
+{
+ // are we in SourceView?
+ SfxViewFrame* pVFrame = SfxViewFrame::GetFirst( pSh );
+ SfxViewShell* pViewShell = pVFrame ? pVFrame->GetViewShell() : nullptr;
+ return dynamic_cast<SwSrcView*>( pViewShell );
+}
+
+bool SwDocShell::ConvertTo( SfxMedium& rMedium )
+{
+ std::shared_ptr<const SfxFilter> pFlt = rMedium.GetFilter();
+ if( !pFlt )
+ return false;
+
+ WriterRef xWriter;
+ SwReaderWriter::GetWriter( pFlt->GetUserData(), rMedium.GetBaseURL( true ), xWriter );
+ if( !xWriter.is() )
+ { // Filter not available
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_DLLNOTFOUND)));
+ xInfoBox->run();
+ return false;
+ }
+
+ //#i3370# remove quick help to prevent saving of autocorrection suggestions
+ if (m_pView)
+ m_pView->GetEditWin().StopQuickHelp();
+
+ //#i91811# mod if we have an active margin window, write back the text
+ if (m_pView &&
+ m_pView->GetPostItMgr() &&
+ m_pView->GetPostItMgr()->HasActiveSidebarWin())
+ {
+ m_pView->GetPostItMgr()->UpdateDataOnActiveSidebarWin();
+ }
+
+ ErrCode nVBWarning = ERRCODE_NONE;
+
+ if (m_xDoc->ContainsMSVBasic())
+ {
+ bool bSave = pFlt->GetUserData() == "CWW8"
+ && SvtFilterOptions::Get().IsLoadWordBasicStorage();
+
+ if ( bSave )
+ {
+ tools::SvRef<SotStorage> xStg = new SotStorage( rMedium.GetOutStream(), false );
+ OSL_ENSURE( !xStg->GetError(), "No storage available for storing VBA macros!" );
+ if ( !xStg->GetError() )
+ {
+ nVBWarning = SaveOrDelMSVBAStorage( static_cast<SfxObjectShell&>(*this), *xStg, bSave, "Macros" );
+ xStg->Commit();
+ m_xDoc->SetContainsMSVBasic( true );
+ }
+ }
+ }
+
+ // End TableBox Edit!
+ if (m_pWrtShell)
+ m_pWrtShell->EndAllTableBoxEdit();
+
+ if( pFlt->GetUserData() == "HTML" )
+ {
+#if HAVE_FEATURE_SCRIPTING
+ if( !officecfg::Office::Common::Filter::HTML::Export::Basic::get()
+ && officecfg::Office::Common::Filter::HTML::Export::Warning::get()
+ && HasBasic() )
+ {
+ uno::Reference< XLibraryContainer > xLibCont = GetBasicContainer();
+ uno::Reference< XNameAccess > xLib;
+ const Sequence<OUString> aNames = xLibCont->getElementNames();
+ for(const OUString& rName : aNames)
+ {
+ Any aLib = xLibCont->getByName(rName);
+ aLib >>= xLib;
+ if(xLib.is())
+ {
+ Sequence<OUString> aModNames = xLib->getElementNames();
+ if(aModNames.hasElements())
+ {
+ SetError(WARN_SWG_HTML_NO_MACROS);
+ break;
+ }
+ }
+ }
+ }
+#endif
+ }
+
+ // #i76360# Update document statistics
+ if ( !rMedium.IsSkipImages() )
+ m_xDoc->getIDocumentStatistics().UpdateDocStat( false, true );
+
+ CalcLayoutForOLEObjects(); // format for OLE objects
+ // #i62875#
+ // reset compatibility flag <DoNotCaptureDrawObjsOnPage>, if possible
+ if (m_pWrtShell &&
+ m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE) &&
+ docfunc::AllDrawObjsOnPage(*m_xDoc))
+ {
+ m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE, false);
+ }
+
+ if( xWriter->IsStgWriter() &&
+ ( pFlt->GetUserData() == FILTER_XML ||
+ pFlt->GetUserData() == FILTER_XMLV ||
+ pFlt->GetUserData() == FILTER_XMLVW ) )
+ {
+ // determine the own Type
+ sal_uInt8 nMyType = 0;
+ if( dynamic_cast< const SwWebDocShell *>( this ) != nullptr )
+ nMyType = 1;
+ else if( dynamic_cast< const SwGlobalDocShell *>( this ) != nullptr )
+ nMyType = 2;
+
+ // determine the desired Type
+ sal_uInt8 nSaveType = 0;
+ SotClipboardFormatId nSaveClipId = pFlt->GetFormat();
+ if( SotClipboardFormatId::STARWRITERWEB_8 == nSaveClipId ||
+ SotClipboardFormatId::STARWRITERWEB_60 == nSaveClipId ||
+ SotClipboardFormatId::STARWRITERWEB_50 == nSaveClipId ||
+ SotClipboardFormatId::STARWRITERWEB_40 == nSaveClipId )
+ nSaveType = 1;
+ else if( SotClipboardFormatId::STARWRITERGLOB_8 == nSaveClipId ||
+ SotClipboardFormatId::STARWRITERGLOB_8_TEMPLATE == nSaveClipId ||
+ SotClipboardFormatId::STARWRITERGLOB_60 == nSaveClipId ||
+ SotClipboardFormatId::STARWRITERGLOB_50 == nSaveClipId ||
+ SotClipboardFormatId::STARWRITERGLOB_40 == nSaveClipId )
+ nSaveType = 2;
+
+ // Change Flags of the Document accordingly
+ bool bIsHTMLModeSave = GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE);
+ bool bIsGlobalDocSave = GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT);
+ bool bIsGlblDocSaveLinksSave = GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT_SAVE_LINKS);
+ if( nMyType != nSaveType )
+ {
+ GetDoc()->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE, 1 == nSaveType);
+ GetDoc()->getIDocumentSettingAccess().set(DocumentSettingId::GLOBAL_DOCUMENT, 2 == nSaveType);
+ if( 2 != nSaveType )
+ GetDoc()->getIDocumentSettingAccess().set(DocumentSettingId::GLOBAL_DOCUMENT_SAVE_LINKS, false);
+ }
+
+ // if the target format is storage based, then the output storage must be already created
+ if ( rMedium.IsStorage() )
+ {
+ // set MediaType on target storage
+ // (MediaType will be queried during SaveAs)
+ try
+ {
+ // TODO/MBA: testing
+ uno::Reference < beans::XPropertySet > xSet( rMedium.GetStorage(), uno::UNO_QUERY );
+ if ( xSet.is() )
+ xSet->setPropertyValue("MediaType", uno::Any( SotExchange::GetFormatMimeType( nSaveClipId ) ) );
+ }
+ catch (const uno::Exception&)
+ {
+ }
+ }
+
+ // Now normally save the Document
+ bool bRet = SaveAs( rMedium );
+
+ if( nMyType != nSaveType )
+ {
+ GetDoc()->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE, bIsHTMLModeSave );
+ GetDoc()->getIDocumentSettingAccess().set(DocumentSettingId::GLOBAL_DOCUMENT, bIsGlobalDocSave);
+ GetDoc()->getIDocumentSettingAccess().set(DocumentSettingId::GLOBAL_DOCUMENT_SAVE_LINKS, bIsGlblDocSaveLinksSave);
+ }
+
+ return bRet;
+ }
+
+ if( pFlt->GetUserData() == FILTER_TEXT_DLG &&
+ (m_pWrtShell || !::lcl_GetSourceView(this)))
+ {
+ SwAsciiOptions aOpt;
+ OUString sItemOpt;
+ if( const SfxStringItem* pItem = rMedium.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS ) )
+ sItemOpt = pItem->GetValue();
+ if(!sItemOpt.isEmpty())
+ aOpt.ReadUserData( sItemOpt );
+
+ xWriter->SetAsciiOptions( aOpt );
+ }
+
+ // Suppress SfxProgress when we are Embedded
+ SW_MOD()->SetEmbeddedLoadSave(
+ SfxObjectCreateMode::EMBEDDED == GetCreateMode());
+
+ // Span Context in order to suppress the Selection's View
+ ErrCodeMsg nErrno;
+ const OUString aFileName( rMedium.GetName() );
+
+ bool bSelection = false;
+ if (m_pWrtShell)
+ {
+ const SfxBoolItem* pSelectionItem = rMedium.GetItemSet().GetItemIfSet(SID_SELECTION);
+ bSelection = pSelectionItem && pSelectionItem->GetValue();
+ }
+
+ // No View, so the whole Document! (unless SID_SELECTION explicitly set)
+ if (m_pWrtShell && (!Application::IsHeadlessModeEnabled() || bSelection))
+ {
+
+ SwWait aWait( *this, true );
+ // #i106906#
+ const bool bFormerLockView = m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView( true );
+ m_pWrtShell->StartAllAction();
+ m_pWrtShell->Push();
+ SwWriter aWrt( rMedium, *m_pWrtShell, !bSelection );
+ nErrno = aWrt.Write( xWriter, &aFileName );
+ //JP 16.05.97: In case the SFX revokes the View while saving
+ if (m_pWrtShell)
+ {
+ m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
+ m_pWrtShell->EndAllAction();
+ // #i106906#
+ m_pWrtShell->LockView( bFormerLockView );
+ }
+ }
+ else
+ {
+ // are we in SourceView?
+ SwSrcView* pSrcView = ::lcl_GetSourceView( this );
+ if( pSrcView )
+ {
+ pSrcView->SaveContentTo(rMedium);
+ nErrno = ERRCODE_NONE;
+ }
+ else
+ {
+ SwWriter aWrt( rMedium, *m_xDoc );
+ nErrno = aWrt.Write( xWriter, &aFileName );
+ }
+ }
+
+ SW_MOD()->SetEmbeddedLoadSave( false );
+ SetError(nErrno ? nErrno : nVBWarning);
+ if( !rMedium.IsStorage() )
+ rMedium.CloseOutStream();
+
+ return ! nErrno.IsError();
+}
+
+// Hands off
+// do not yet activate, must deliver TRUE
+bool SwDocShell::SaveCompleted( const uno::Reference < embed::XStorage >& xStor )
+{
+ bool bRet = SfxObjectShell::SaveCompleted( xStor );
+ if( bRet )
+ {
+ // Do not decide until here, whether Saving was successful or not
+ if( IsModified() )
+ m_xDoc->getIDocumentState().SetModified();
+ else
+ m_xDoc->getIDocumentState().ResetModified();
+ }
+
+ if (m_pOLEChildList)
+ {
+ bool bResetModified = IsEnableSetModified();
+ if( bResetModified )
+ EnableSetModified( false );
+
+ uno::Sequence < OUString > aNames = m_pOLEChildList->GetObjectNames();
+ for( sal_Int32 n = aNames.getLength(); n; n-- )
+ {
+ if (!m_pOLEChildList->MoveEmbeddedObject(aNames[n-1], GetEmbeddedObjectContainer()))
+ {
+ OSL_FAIL("Copying of objects didn't work!" );
+ }
+ }
+
+ m_pOLEChildList.reset();
+ if( bResetModified )
+ EnableSetModified();
+ }
+ return bRet;
+}
+
+// Draw()-Override for OLE2 (Sfx)
+void SwDocShell::Draw( OutputDevice* pDev, const JobSetup& rSetup,
+ sal_uInt16 nAspect, bool bOutputForScreen )
+{
+ //fix #25341# Draw should not affect the Modified
+ bool bResetModified = IsEnableSetModified();
+ if ( bResetModified )
+ EnableSetModified( false );
+
+ // When there is a JobSetup connected to the Document, we copy it to
+ // reconnect it after PrtOle2. We don't use an empty JobSetup because
+ // that would only lead to questionable results after expensive
+ // reformatting (Preview!)
+ std::unique_ptr<JobSetup> pOrig;
+ if ( !rSetup.GetPrinterName().isEmpty() && ASPECT_THUMBNAIL != nAspect )
+ {
+ const JobSetup* pCurrentJobSetup = m_xDoc->getIDocumentDeviceAccess().getJobsetup();
+ if( pCurrentJobSetup ) // then we copy that
+ pOrig.reset(new JobSetup( *pCurrentJobSetup ));
+ m_xDoc->getIDocumentDeviceAccess().setJobsetup( rSetup );
+ }
+
+ tools::Rectangle aRect( nAspect == ASPECT_THUMBNAIL ?
+ GetVisArea( nAspect ) : GetVisArea( ASPECT_CONTENT ) );
+
+ pDev->Push();
+ pDev->SetFillColor();
+ pDev->SetLineColor();
+ pDev->SetBackground();
+ const bool bWeb = dynamic_cast< const SwWebDocShell *>( this ) != nullptr;
+ SwPrintData aOpts;
+ SwViewShell::PrtOle2(m_xDoc.get(), SW_MOD()->GetUsrPref(bWeb), aOpts, *pDev, aRect, bOutputForScreen);
+ pDev->Pop();
+
+ if( pOrig )
+ {
+ m_xDoc->getIDocumentDeviceAccess().setJobsetup( *pOrig );
+ }
+ if ( bResetModified )
+ EnableSetModified();
+}
+
+void SwDocShell::SetVisArea( const tools::Rectangle &rRect )
+{
+ tools::Rectangle aRect( rRect );
+ if (m_pView)
+ {
+ Size aSz( m_pView->GetDocSz() );
+ aSz.AdjustWidth(DOCUMENTBORDER ); aSz.AdjustHeight(DOCUMENTBORDER );
+ tools::Long nMoveX = 0, nMoveY = 0;
+ if ( aRect.Right() > aSz.Width() )
+ nMoveX = aSz.Width() - aRect.Right();
+ if ( aRect.Bottom() > aSz.Height() )
+ nMoveY = aSz.Height() - aRect.Bottom();
+ aRect.Move( nMoveX, nMoveY );
+ nMoveX = aRect.Left() < 0 ? -aRect.Left() : 0;
+ nMoveY = aRect.Top() < 0 ? -aRect.Top() : 0;
+ aRect.Move( nMoveX, nMoveY );
+
+ // Calls SfxInPlaceObject::SetVisArea()!
+ m_pView->SetVisArea( aRect );
+ }
+ else
+ SfxObjectShell::SetVisArea( aRect );
+}
+
+tools::Rectangle SwDocShell::GetVisArea( sal_uInt16 nAspect ) const
+{
+ if ( nAspect == ASPECT_THUMBNAIL )
+ {
+ // Preview: set VisArea to the first page.
+ SwNodeIndex aIdx( m_xDoc->GetNodes().GetEndOfExtras(), 1 );
+ SwContentNode* pNd = m_xDoc->GetNodes().GoNext( &aIdx );
+
+ const SwRect aPageRect = pNd->FindPageFrameRect();
+ if (aPageRect.IsEmpty())
+ return tools::Rectangle();
+ tools::Rectangle aRect(aPageRect.SVRect());
+
+ // tdf#81219 sanitize - nobody is interested in a thumbnail where's
+ // nothing visible
+ if (aRect.GetHeight() > 2*aRect.GetWidth())
+ aRect.SetSize(Size(aRect.GetWidth(), 2*aRect.GetWidth()));
+ else if (aRect.GetWidth() > 2*aRect.GetHeight())
+ aRect.SetSize(Size(2*aRect.GetHeight(), aRect.GetHeight()));
+
+ return aRect;
+ }
+ return SfxObjectShell::GetVisArea( nAspect );
+}
+
+Printer *SwDocShell::GetDocumentPrinter()
+{
+ return m_xDoc->getIDocumentDeviceAccess().getPrinter( false );
+}
+
+OutputDevice* SwDocShell::GetDocumentRefDev()
+{
+ return m_xDoc->getIDocumentDeviceAccess().getReferenceDevice( false );
+}
+
+void SwDocShell::OnDocumentPrinterChanged( Printer * pNewPrinter )
+{
+ if ( pNewPrinter )
+ GetDoc()->getIDocumentDeviceAccess().setJobsetup( pNewPrinter->GetJobSetup() );
+ else
+ GetDoc()->getIDocumentDeviceAccess().setPrinter( nullptr, true, true );
+}
+
+// #i20883# Digital Signatures and Encryption
+HiddenInformation SwDocShell::GetHiddenInformationState( HiddenInformation nStates )
+{
+ // get global state like HiddenInformation::DOCUMENTVERSIONS
+ HiddenInformation nState = SfxObjectShell::GetHiddenInformationState( nStates );
+
+ if ( nStates & HiddenInformation::RECORDEDCHANGES )
+ {
+ if ( !GetDoc()->getIDocumentRedlineAccess().GetRedlineTable().empty() )
+ nState |= HiddenInformation::RECORDEDCHANGES;
+ }
+ if ( nStates & HiddenInformation::NOTES )
+ {
+ OSL_ENSURE( GetWrtShell(), "No SwWrtShell, no information" );
+ if(GetWrtShell() && GetWrtShell()->GetFieldType(SwFieldIds::Postit, OUString())->HasHiddenInformationNotes())
+ nState |= HiddenInformation::NOTES;
+ }
+
+ return nState;
+}
+
+void SwDocShell::GetState(SfxItemSet& rSet)
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while (nWhich)
+ {
+ switch (nWhich)
+ {
+ case SID_PRINTPREVIEW:
+ {
+ bool bDisable = IsInPlaceActive();
+ // Disable "multiple layout"
+ if ( !bDisable )
+ {
+ SfxViewFrame *pTmpFrame = SfxViewFrame::GetFirst(this);
+ while (pTmpFrame) // Look for Preview
+ {
+ if ( auto pSwView = dynamic_cast<SwView*>( pTmpFrame->GetViewShell() ) )
+ if (pSwView->GetWrtShell().GetViewOptions()->getBrowseMode())
+ {
+ bDisable = true;
+ break;
+ }
+ pTmpFrame = SfxViewFrame::GetNext(*pTmpFrame, this);
+ }
+ }
+ // End of disabled "multiple layout"
+ if ( bDisable )
+ rSet.DisableItem( SID_PRINTPREVIEW );
+ else
+ {
+ SfxBoolItem aBool( SID_PRINTPREVIEW, false );
+ if( dynamic_cast<SwPagePreview*>( SfxViewShell::Current()) )
+ aBool.SetValue( true );
+ rSet.Put( aBool );
+ }
+ }
+ break;
+ case SID_AUTO_CORRECT_DLG:
+ if ( comphelper::LibreOfficeKit::isActive() )
+ rSet.DisableItem( SID_AUTO_CORRECT_DLG );
+ break;
+ case SID_SOURCEVIEW:
+ {
+ SfxViewShell* pCurrView = GetView() ? static_cast<SfxViewShell*>(GetView())
+ : SfxViewShell::Current();
+ bool bSourceView = dynamic_cast<SwSrcView*>( pCurrView ) != nullptr;
+ rSet.Put(SfxBoolItem(SID_SOURCEVIEW, bSourceView));
+ }
+ break;
+ case SID_HTML_MODE:
+ rSet.Put(SfxUInt16Item(SID_HTML_MODE, ::GetHtmlMode(this)));
+ break;
+
+ case FN_ABSTRACT_STARIMPRESS:
+ case FN_OUTLINE_TO_IMPRESS:
+ {
+ SvtModuleOptions aMOpt;
+ if (!aMOpt.IsImpress() || GetObjectShell()->isExportLocked())
+ rSet.DisableItem( nWhich );
+ }
+ [[fallthrough]];
+ case FN_ABSTRACT_NEWDOC:
+ case FN_OUTLINE_TO_CLIPBOARD:
+ {
+ if ( GetDoc()->GetNodes().GetOutLineNds().empty() )
+ rSet.DisableItem( nWhich );
+ }
+ break;
+ case SID_BROWSER_MODE:
+ case FN_PRINT_LAYOUT:
+ {
+ bool bState = GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE);
+ if(FN_PRINT_LAYOUT == nWhich)
+ bState = !bState;
+ rSet.Put( SfxBoolItem( nWhich, bState));
+ }
+ break;
+
+ case FN_NEW_GLOBAL_DOC:
+ if (dynamic_cast<const SwGlobalDocShell*>(this) != nullptr
+ || GetObjectShell()->isExportLocked())
+ rSet.DisableItem( nWhich );
+ break;
+
+ case FN_NEW_HTML_DOC:
+ if (dynamic_cast<const SwWebDocShell*>(this) != nullptr
+ || GetObjectShell()->isExportLocked())
+ rSet.DisableItem( nWhich );
+ break;
+
+ case FN_OPEN_FILE:
+ if( dynamic_cast< const SwWebDocShell *>( this ) != nullptr )
+ rSet.DisableItem( nWhich );
+ break;
+
+ case SID_ATTR_YEAR2000:
+ {
+ const SvNumberFormatter* pFormatr = m_xDoc->GetNumberFormatter(false);
+ rSet.Put( SfxUInt16Item( nWhich,
+ static_cast< sal_uInt16 >(
+ pFormatr ? pFormatr->GetYear2000()
+ : officecfg::Office::Common::DateFormat::TwoDigitYear::get())) );
+ }
+ break;
+ case SID_ATTR_CHAR_FONTLIST:
+ {
+ rSet.Put( SvxFontListItem(m_pFontList.get(), SID_ATTR_CHAR_FONTLIST) );
+ }
+ break;
+ case SID_MAIL_PREPAREEXPORT:
+ {
+ //check if linked content or possibly hidden content is available
+ //m_xDoc->UpdateFields( NULL, false );
+ sfx2::LinkManager& rLnkMgr = m_xDoc->getIDocumentLinksAdministration().GetLinkManager();
+ const ::sfx2::SvBaseLinks& rLnks = rLnkMgr.GetLinks();
+ bool bRet = false;
+ if( !rLnks.empty() )
+ bRet = true;
+ else
+ {
+ //sections with hidden flag, hidden character attribute, hidden paragraph/text or conditional text fields
+ bRet = m_xDoc->HasInvisibleContent();
+ }
+ rSet.Put( SfxBoolItem( nWhich, bRet ) );
+ }
+ break;
+ case SID_NOTEBOOKBAR:
+ {
+ SfxViewShell* pViewShell = GetView()? GetView(): SfxViewShell::Current();
+ bool bVisible = sfx2::SfxNotebookBar::StateMethod(pViewShell->GetViewFrame().GetBindings(),
+ u"modules/swriter/ui/");
+ rSet.Put( SfxBoolItem( SID_NOTEBOOKBAR, bVisible ) );
+ }
+ break;
+ case FN_REDLINE_ACCEPT_ALL:
+ case FN_REDLINE_REJECT_ALL:
+ {
+ if (GetDoc()->getIDocumentRedlineAccess().GetRedlineTable().empty() ||
+ HasChangeRecordProtection()) // tdf#128229 Disable Accept / Reject all if redlines are password protected
+ rSet.DisableItem(nWhich);
+ }
+ break;
+
+ default: OSL_ENSURE(false,"You cannot get here!");
+
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+// OLE-Hdls
+IMPL_LINK( SwDocShell, Ole2ModifiedHdl, bool, bNewStatus, void )
+{
+ if (m_pWrtShell)
+ {
+ SwOLENode* pOLENode = nullptr;
+ if (!m_pWrtShell->IsTableMode())
+ {
+ pOLENode = m_pWrtShell->GetCursor()->GetPointNode().GetOLENode();
+ }
+ if (pOLENode)
+ {
+ if (pOLENode->GetOLEObj().IsProtected())
+ {
+ return;
+ }
+ }
+ }
+
+ if( IsEnableSetModified() )
+ SetModified( bNewStatus );
+}
+
+// return Pool here, because virtual
+SfxStyleSheetBasePool* SwDocShell::GetStyleSheetPool()
+{
+ return m_xBasePool.get();
+}
+
+sfx2::StyleManager* SwDocShell::GetStyleManager()
+{
+ return m_pStyleManager.get();
+}
+
+void SwDocShell::SetView(SwView* pVw)
+{
+ SetViewShell_Impl(pVw);
+ m_pView = pVw;
+ if (m_pView)
+ {
+ m_pWrtShell = &m_pView->GetWrtShell();
+
+ // Set view-specific redline author.
+ const OUString& rRedlineAuthor = m_pView->GetRedlineAuthor();
+ if (!rRedlineAuthor.isEmpty())
+ SW_MOD()->SetRedlineAuthor(m_pView->GetRedlineAuthor());
+ }
+ else
+ m_pWrtShell = nullptr;
+}
+
+// #i59688#
+// linked graphics are now loaded on demand.
+// Thus, loading of linked graphics no longer needed and necessary for
+// the load of document being finished.
+void SwDocShell::LoadingFinished()
+{
+ // #i38810#
+ // Original fix fails after integration of cws xmlsec11:
+ // interface <SfxObjectShell::EnableSetModified(..)> no longer works, because
+ // <SfxObjectShell::FinishedLoading(..)> doesn't care about its status and
+ // enables the document modification again.
+ // Thus, manual modify the document, if it's modified and its links are updated
+ // before <FinishedLoading(..)> is called.
+ const bool bHasDocToStayModified( m_xDoc->getIDocumentState().IsModified() && m_xDoc->getIDocumentLinksAdministration().LinksUpdated() );
+
+ FinishedLoading();
+ SfxViewFrame* pVFrame = SfxViewFrame::GetFirst(this);
+ if(pVFrame)
+ {
+ SfxViewShell* pShell = pVFrame->GetViewShell();
+ if(auto pSrcView = dynamic_cast<SwSrcView*>( pShell) )
+ pSrcView->Load(this);
+ }
+
+ // #i38810#
+ if ( bHasDocToStayModified && !m_xDoc->getIDocumentState().IsModified() )
+ {
+ m_xDoc->getIDocumentState().SetModified();
+ }
+}
+
+// a Transfer is cancelled (is called from SFX)
+void SwDocShell::CancelTransfers()
+{
+ // Cancel all links from LinkManager
+ m_xDoc->getIDocumentLinksAdministration().GetLinkManager().CancelTransfers();
+ SfxObjectShell::CancelTransfers();
+}
+
+SwEditShell * SwDocShell::GetEditShell()
+{
+ return m_pWrtShell;
+}
+
+SwFEShell* SwDocShell::GetFEShell()
+{
+ return m_pWrtShell;
+}
+
+void SwDocShell::RemoveOLEObjects()
+{
+ SwIterator<SwContentNode,SwFormatColl> aIter( *m_xDoc->GetDfltGrfFormatColl() );
+ for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() )
+ {
+ SwOLENode* pOLENd = pNd->GetOLENode();
+ if( pOLENd && ( pOLENd->IsOLEObjectDeleted() ||
+ pOLENd->IsInGlobalDocSection() ) )
+ {
+ if (!m_pOLEChildList)
+ m_pOLEChildList.reset( new comphelper::EmbeddedObjectContainer );
+
+ OUString aObjName = pOLENd->GetOLEObj().GetCurrentPersistName();
+ GetEmbeddedObjectContainer().MoveEmbeddedObject( aObjName, *m_pOLEChildList );
+ }
+ }
+}
+
+// When a document is loaded, SwDoc::PrtOLENotify is called to update
+// the sizes of math objects. However, for objects that do not have a
+// SwFrame at this time, only a flag is set (bIsOLESizeInvalid) and the
+// size change takes place later, while calculating the layout in the
+// idle handler. If this document is saved now, it is saved with invalid
+// sizes. For this reason, the layout has to be calculated before a document is
+// saved, but of course only id there are OLE objects with bOLESizeInvalid set.
+void SwDocShell::CalcLayoutForOLEObjects()
+{
+ if (!m_pWrtShell)
+ return;
+
+ if (m_pView && m_pView->GetIPClient())
+ {
+ // We have an active OLE edit: allow link updates, so an up to date replacement graphic can
+ // be created.
+ comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = getEmbeddedObjectContainer();
+ rEmbeddedObjectContainer.setUserAllowsLinkUpdate(true);
+ }
+
+ SwIterator<SwContentNode,SwFormatColl> aIter( *m_xDoc->GetDfltGrfFormatColl() );
+ for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() )
+ {
+ SwOLENode* pOLENd = pNd->GetOLENode();
+ if( pOLENd && pOLENd->IsOLESizeInvalid() )
+ {
+ m_pWrtShell->CalcLayout();
+ break;
+ }
+ }
+}
+
+// #i42634# Overwrites SfxObjectShell::UpdateLinks
+// This new function is necessary to trigger update of links in docs
+// read by the binary filter:
+void SwDocShell::UpdateLinks()
+{
+ GetDoc()->getIDocumentLinksAdministration().UpdateLinks();
+ // #i50703# Update footnote numbers
+ SwTextFootnote::SetUniqueSeqRefNo( *GetDoc() );
+ SwNodeIndex aTmp( GetDoc()->GetNodes() );
+ GetDoc()->GetFootnoteIdxs().UpdateFootnote( aTmp.GetNode() );
+}
+
+uno::Reference< frame::XController >
+ SwDocShell::GetController()
+{
+ css::uno::Reference< css::frame::XController > aRet;
+ // #i82346# No view in page preview
+ if ( GetView() )
+ aRet = GetView()->GetController();
+ return aRet;
+}
+
+static const char* s_EventNames[] =
+{
+ "OnPageCountChange",
+ "OnMailMerge",
+ "OnMailMergeFinished",
+ "OnFieldMerge",
+ "OnFieldMergeFinished",
+ "OnLayoutFinished"
+};
+sal_Int32 const s_nEvents(SAL_N_ELEMENTS(s_EventNames));
+
+Sequence< OUString > SwDocShell::GetEventNames()
+{
+ Sequence< OUString > aRet = SfxObjectShell::GetEventNames();
+ sal_Int32 nLen = aRet.getLength();
+ aRet.realloc(nLen + 6);
+ OUString* pNames = aRet.getArray();
+ pNames[nLen++] = GetEventName(0);
+ pNames[nLen++] = GetEventName(1);
+ pNames[nLen++] = GetEventName(2);
+ pNames[nLen++] = GetEventName(3);
+ pNames[nLen++] = GetEventName(4);
+ pNames[nLen] = GetEventName(5);
+
+ return aRet;
+}
+
+OUString SwDocShell::GetEventName( sal_Int32 nIndex )
+{
+ if (nIndex < s_nEvents)
+ {
+ return OUString::createFromAscii(s_EventNames[nIndex]);
+ }
+ return OUString();
+}
+
+const ::sfx2::IXmlIdRegistry* SwDocShell::GetXmlIdRegistry() const
+{
+ return m_xDoc ? &m_xDoc->GetXmlIdRegistry() : nullptr;
+}
+
+bool SwDocShell::IsChangeRecording() const
+{
+ if (!m_pWrtShell)
+ return false;
+ return bool(m_pWrtShell->GetRedlineFlags() & RedlineFlags::On);
+}
+
+bool SwDocShell::HasChangeRecordProtection() const
+{
+ if (!m_pWrtShell)
+ return false;
+ return m_pWrtShell->getIDocumentRedlineAccess().GetRedlinePassword().hasElements();
+}
+
+void SwDocShell::SetChangeRecording( bool bActivate, bool bLockAllViews )
+{
+ RedlineFlags nOn = bActivate ? RedlineFlags::On : RedlineFlags::NONE;
+ RedlineFlags nMode = m_pWrtShell->GetRedlineFlags();
+ if (bLockAllViews)
+ {
+ // tdf#107870: prevent jumping to cursor
+ auto aViewGuard(LockAllViews());
+ m_pWrtShell->SetRedlineFlagsAndCheckInsMode( (nMode & ~RedlineFlags::On) | nOn );
+ }
+ else
+ {
+ m_pWrtShell->SetRedlineFlagsAndCheckInsMode( (nMode & ~RedlineFlags::On) | nOn );
+ }
+}
+
+void SwDocShell::SetProtectionPassword( const OUString &rNewPassword )
+{
+ const SfxAllItemSet aSet( GetPool() );
+
+ IDocumentRedlineAccess& rIDRA = m_pWrtShell->getIDocumentRedlineAccess();
+ Sequence< sal_Int8 > aPasswd = rIDRA.GetRedlinePassword();
+ const SfxBoolItem* pRedlineProtectItem = aSet.GetItemIfSet(FN_REDLINE_PROTECT, false);
+ if (pRedlineProtectItem
+ && pRedlineProtectItem->GetValue() == aPasswd.hasElements())
+ return;
+
+ if (!rNewPassword.isEmpty())
+ {
+ // when password protection is applied change tracking must always be active
+ SetChangeRecording( true );
+
+ Sequence< sal_Int8 > aNewPasswd;
+ SvPasswordHelper::GetHashPassword( aNewPasswd, rNewPassword );
+ rIDRA.SetRedlinePassword( aNewPasswd );
+ }
+ else
+ {
+ rIDRA.SetRedlinePassword( Sequence< sal_Int8 >() );
+ }
+}
+
+bool SwDocShell::GetProtectionHash( /*out*/ css::uno::Sequence< sal_Int8 > &rPasswordHash )
+{
+ bool bRes = false;
+
+ const SfxAllItemSet aSet( GetPool() );
+
+ IDocumentRedlineAccess& rIDRA = m_pWrtShell->getIDocumentRedlineAccess();
+ const Sequence< sal_Int8 >& aPasswdHash( rIDRA.GetRedlinePassword() );
+ const SfxBoolItem* pRedlineProtectItem = aSet.GetItemIfSet(FN_REDLINE_PROTECT, false);
+ if (pRedlineProtectItem
+ && pRedlineProtectItem->GetValue() == aPasswdHash.hasElements())
+ return false;
+ rPasswordHash = aPasswdHash;
+ bRes = true;
+
+ return bRes;
+}
+
+void SwDocShell::RegisterAutomationDocumentEventsCaller(css::uno::Reference< ooo::vba::XSinkCaller > const& xCaller)
+{
+ mxAutomationDocumentEventsCaller = xCaller;
+}
+
+void SwDocShell::CallAutomationDocumentEventSinks(const OUString& Method, css::uno::Sequence< css::uno::Any >& Arguments)
+{
+ if (mxAutomationDocumentEventsCaller.is())
+ mxAutomationDocumentEventsCaller->CallSinks(Method, Arguments);
+}
+
+void SwDocShell::RegisterAutomationDocumentObject(css::uno::Reference< ooo::vba::word::XDocument > const& xDocument)
+{
+ mxAutomationDocumentObject = xDocument;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/app/docsh2.cxx b/sw/source/uibase/app/docsh2.cxx
new file mode 100644
index 0000000000..47c8a3ec65
--- /dev/null
+++ b/sw/source/uibase/app/docsh2.cxx
@@ -0,0 +1,1805 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+
+#include <osl/diagnose.h>
+#include <com/sun/star/drawing/ModuleDispatcher.hpp>
+#include <com/sun/star/frame/DispatchHelper.hpp>
+#include <ooo/vba/word/XDocument.hpp>
+#include <comphelper/fileformat.h>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/string.hxx>
+
+#include <sal/log.hxx>
+#include <edtwin.hxx>
+#include <tools/urlobj.hxx>
+#include <unotools/tempfile.hxx>
+#include <unotools/configmgr.hxx>
+#include <vcl/errinf.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <svl/eitem.hxx>
+#include <svl/macitem.hxx>
+#include <unotools/pathoptions.hxx>
+#include <vcl/transfer.hxx>
+#include <sfx2/dinfdlg.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/new.hxx>
+#include <sfx2/notebookbar/SfxNotebookBar.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/evntconf.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <svx/dialogs.hrc>
+#include <svx/drawitem.hxx>
+#include <editeng/svxacorr.hxx>
+#include <svx/fmshell.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <sfx2/classificationhelper.hxx>
+#include <sfx2/watermarkitem.hxx>
+
+#include <svx/ofaitem.hxx>
+#include <SwSmartTagMgr.hxx>
+#include <sfx2/app.hxx>
+#include <basic/sbstar.hxx>
+#include <basic/basmgr.hxx>
+#include <comphelper/classids.hxx>
+#include <fmtcol.hxx>
+#include <istype.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <docary.hxx>
+#include <wrtsh.hxx>
+#include <rootfrm.hxx>
+#include <fldbas.hxx>
+#include <viewopt.hxx>
+#include <globdoc.hxx>
+#include <fldwrap.hxx>
+#include <redlndlg.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentLinksAdministration.hxx>
+#include <IDocumentFieldsAccess.hxx>
+#include <IDocumentStatistics.hxx>
+#include <IDocumentLayoutAccess.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <IDocumentState.hxx>
+#include <shellio.hxx>
+#include <pview.hxx>
+#include <srcview.hxx>
+#include <wdocsh.hxx>
+#include <unotxdoc.hxx>
+#include <acmplwrd.hxx>
+#include <swmodule.hxx>
+#include <unobaseclass.hxx>
+#include <swwait.hxx>
+#include <swcli.hxx>
+
+#include <cmdid.h>
+#include <helpids.h>
+#include <strings.hrc>
+#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
+#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
+#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
+#include <com/sun/star/ui/dialogs/ListboxControlActions.hpp>
+#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
+#include <com/sun/star/script/vba/VBAEventId.hpp>
+#include <editeng/acorrcfg.hxx>
+#include <officecfg/Office/Security.hxx>
+#include <officecfg/Office/Common.hxx>
+
+#include <sfx2/fcontnr.hxx>
+#include <svx/ClassificationDialog.hxx>
+#include <svtools/embedhlp.hxx>
+
+#include <swabstdlg.hxx>
+#include <watermarkdialog.hxx>
+
+#include <ndtxt.hxx>
+#include <iodetect.hxx>
+
+#include <memory>
+
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::sfx2;
+
+// create DocInfo (virtual)
+std::shared_ptr<SfxDocumentInfoDialog> SwDocShell::CreateDocumentInfoDialog(weld::Window* pParent, const SfxItemSet &rSet)
+{
+ std::shared_ptr<SfxDocumentInfoDialog> xDlg = std::make_shared<SfxDocumentInfoDialog>(pParent, rSet);
+ //only with statistics, when this document is being shown, not
+ //from within the Doc-Manager
+ SwDocShell* pDocSh = static_cast<SwDocShell*>( SfxObjectShell::Current());
+ if( pDocSh == this )
+ {
+ //Not for SourceView.
+ SfxViewShell *pVSh = SfxViewShell::Current();
+ if ( pVSh && dynamic_cast< const SwSrcView *>( pVSh ) == nullptr )
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ xDlg->AddFontTabPage();
+ xDlg->AddTabPage("writerstats", SwResId(STR_DOC_STAT), pFact->GetTabPageCreatorFunc(RID_SW_TP_DOC_STAT));
+ }
+ }
+ return xDlg;
+}
+
+void SwDocShell::ToggleLayoutMode(SwView* pView)
+{
+ OSL_ENSURE( pView, "SwDocShell::ToggleLayoutMode, pView is null." );
+
+ const SwViewOption& rViewOptions = *pView->GetWrtShell().GetViewOptions();
+
+ //TODO: Should HideWhitespace flag be saved in the document settings?
+ GetDoc()->getIDocumentSettingAccess().set(DocumentSettingId::BROWSE_MODE, rViewOptions.getBrowseMode());
+ UpdateFontList(); // Why is this necessary here?
+
+ pView->GetViewFrame().GetBindings().Invalidate(FN_SHADOWCURSOR);
+ if( !GetDoc()->getIDocumentDeviceAccess().getPrinter( false ) )
+ pView->SetPrinter( GetDoc()->getIDocumentDeviceAccess().getPrinter( false ), SfxPrinterChangeFlags::PRINTER | SfxPrinterChangeFlags::JOBSETUP );
+ GetDoc()->CheckDefaultPageFormat();
+ SfxViewFrame *pTmpFrame = SfxViewFrame::GetFirst(this, false);
+ while (pTmpFrame)
+ {
+ if( pTmpFrame != &pView->GetViewFrame() )
+ {
+ pTmpFrame->DoClose();
+ pTmpFrame = SfxViewFrame::GetFirst(this, false);
+ }
+ else
+ pTmpFrame = SfxViewFrame::GetNext(*pTmpFrame, this, false);
+ }
+
+ pView->GetWrtShell().InvalidateLayout(true);
+
+ pView->RecheckBrowseMode();
+
+ pView->SetNewWindowAllowed(!rViewOptions.getBrowseMode());
+}
+
+// update text fields on document properties changes
+void SwDocShell::DoFlushDocInfo()
+{
+ if (!m_xDoc)
+ return;
+
+ bool bUnlockView(true);
+ if (m_pWrtShell)
+ {
+ bUnlockView = !m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView( true ); // lock visible section
+ m_pWrtShell->StartAllAction();
+ }
+
+ m_xDoc->getIDocumentStatistics().DocInfoChgd(IsEnableSetModified());
+
+ if (m_pWrtShell)
+ {
+ m_pWrtShell->EndAllAction();
+ if (bUnlockView)
+ {
+ m_pWrtShell->LockView( false );
+ }
+ }
+}
+
+static void lcl_processCompatibleSfxHint( const uno::Reference< script::vba::XVBAEventProcessor >& xVbaEvents, const SfxHint& rHint )
+{
+ using namespace com::sun::star::script::vba::VBAEventId;
+ if (rHint.GetId() != SfxHintId::ThisIsAnSfxEventHint)
+ return;
+
+ uno::Sequence< uno::Any > aArgs;
+ switch (static_cast<const SfxEventHint&>(rHint).GetEventId())
+ {
+ case SfxEventHintId::CreateDoc:
+ xVbaEvents->processVbaEvent(AUTO_NEW, aArgs);
+ xVbaEvents->processVbaEvent(DOCUMENT_NEW, aArgs);
+ break;
+ case SfxEventHintId::OpenDoc:
+ xVbaEvents->processVbaEvent(AUTO_OPEN, aArgs);
+ xVbaEvents->processVbaEvent(DOCUMENT_OPEN, aArgs);
+ break;
+ default: break;
+ }
+}
+
+// Notification on DocInfo changes
+void SwDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ if (!m_xDoc)
+ {
+ return ;
+ }
+
+ uno::Reference< script::vba::XVBAEventProcessor > const xVbaEvents =
+ m_xDoc->GetVbaEventProcessor();
+ if( xVbaEvents.is() )
+ lcl_processCompatibleSfxHint( xVbaEvents, rHint );
+
+ if (rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint)
+ {
+ switch (static_cast<const SfxEventHint&>(rHint).GetEventId())
+ {
+ case SfxEventHintId::ActivateDoc:
+ case SfxEventHintId::CreateDoc:
+ case SfxEventHintId::OpenDoc:
+ {
+ uno::Sequence< css::uno::Any > aArgs;
+ SW_MOD()->CallAutomationApplicationEventSinks( "DocumentChange", aArgs );
+ break;
+ }
+ default:
+ break;
+ }
+
+ switch (static_cast<const SfxEventHint&>(rHint).GetEventId())
+ {
+ case SfxEventHintId::CreateDoc:
+ {
+ uno::Any aDocument;
+ aDocument <<= mxAutomationDocumentObject;
+ uno::Sequence< uno::Any > aArgs{ aDocument };
+ SW_MOD()->CallAutomationApplicationEventSinks( "NewDocument", aArgs );
+ }
+ break;
+ case SfxEventHintId::OpenDoc:
+ {
+ uno::Any aDocument;
+ aDocument <<= mxAutomationDocumentObject;
+ uno::Sequence< uno::Any > aArgs{ aDocument };
+ SW_MOD()->CallAutomationApplicationEventSinks( "DocumentOpen", aArgs );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ sal_uInt16 nAction = 0;
+ if (rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint &&
+ static_cast<const SfxEventHint&>(rHint).GetEventId() == SfxEventHintId::LoadFinished)
+ {
+ // #i38126# - own action id
+ nAction = 3;
+ }
+ else
+ {
+ // switch for more actions
+ if( rHint.GetId() == SfxHintId::TitleChanged)
+ {
+ if( GetMedium() )
+ nAction = 2;
+ }
+ }
+
+ if( !nAction )
+ return;
+
+ bool bUnlockView = true; //initializing prevents warning
+ if (m_pWrtShell)
+ {
+ bUnlockView = !m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView( true ); //lock visible section
+ m_pWrtShell->StartAllAction();
+ }
+ switch( nAction )
+ {
+ case 2:
+ m_xDoc->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Filename )->UpdateFields();
+ break;
+ // #i38126# - own action for event LOADFINISHED
+ // in order to avoid a modified document.
+ // #i41679# - Also for the instance of <SwDoc>
+ // it has to be assured, that it's not modified.
+ // Perform the same as for action id 1, but disable <SetModified>.
+ case 3:
+ {
+ const bool bResetModified = IsEnableSetModified();
+ if ( bResetModified )
+ EnableSetModified( false );
+ // #i41679#
+ const bool bIsDocModified = m_xDoc->getIDocumentState().IsModified();
+ // TODO: is the ResetModified() below because of only the direct call from DocInfoChgd, or does UpdateFields() set it too?
+
+ m_xDoc->getIDocumentStatistics().DocInfoChgd(false);
+
+ // #i41679#
+ if ( !bIsDocModified )
+ m_xDoc->getIDocumentState().ResetModified();
+ if ( bResetModified )
+ EnableSetModified();
+ }
+ break;
+ }
+
+ if (m_pWrtShell)
+ {
+ m_pWrtShell->EndAllAction();
+ if( bUnlockView )
+ m_pWrtShell->LockView( false );
+ }
+}
+
+// Notification Close Doc
+bool SwDocShell::PrepareClose( bool bUI )
+{
+ bool bRet = SfxObjectShell::PrepareClose( bUI );
+
+ // If we are going to close it at this point, let potential DocumentBeforeClose event handlers
+ // in Automation clients veto it.
+ if (bRet && m_xDoc && IsInPrepareClose())
+ {
+ uno::Any aDocument;
+ aDocument <<= mxAutomationDocumentObject;
+
+ uno::Sequence<uno::Any> aArgs{ // Arg 0: Document
+ aDocument,
+ // Arg 1: Cancel
+ uno::Any(false)
+ };
+
+ SW_MOD()->CallAutomationApplicationEventSinks( "DocumentBeforeClose", aArgs );
+
+ // If the Cancel argument was set to True by an event handler, return false.
+ bool bCancel(false);
+ aArgs[1] >>= bCancel;
+ if (bCancel)
+ bRet = false;
+ }
+
+ if( bRet )
+ EndListening( *this );
+
+ if (m_xDoc && IsInPrepareClose())
+ {
+ uno::Reference< script::vba::XVBAEventProcessor > const xVbaEvents =
+ m_xDoc->GetVbaEventProcessor();
+ if( xVbaEvents.is() )
+ {
+ using namespace com::sun::star::script::vba::VBAEventId;
+ uno::Sequence< uno::Any > aNoArgs;
+ xVbaEvents->processVbaEvent(AUTO_CLOSE, aNoArgs);
+ xVbaEvents->processVbaEvent(DOCUMENT_CLOSE, aNoArgs);
+ }
+ }
+ return bRet;
+}
+
+void SwDocShell::Execute(SfxRequest& rReq)
+{
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem;
+ sal_uInt16 nWhich = rReq.GetSlot();
+ bool bDone = false;
+ switch ( nWhich )
+ {
+ case SID_AUTO_CORRECT_DLG:
+ {
+ SvxSwAutoFormatFlags* pAFlags = &SvxAutoCorrCfg::Get().GetAutoCorrect()->GetSwFlags();
+ SwAutoCompleteWord& rACW = SwDoc::GetAutoCompleteWords();
+
+ bool bOldLocked = rACW.IsLockWordLstLocked(),
+ bOldAutoCmpltCollectWords = pAFlags->bAutoCmpltCollectWords;
+
+ rACW.SetLockWordLstLocked( true );
+
+ editeng::SortedAutoCompleteStrings aTmpLst( rACW.GetWordList().createNonOwningCopy() );
+ pAFlags->m_pAutoCompleteList = &aTmpLst;
+
+ SfxApplication* pApp = SfxGetpApp();
+ SfxRequest aAppReq(SID_AUTO_CORRECT_DLG, SfxCallMode::SYNCHRON, pApp->GetPool());
+ SfxBoolItem aSwOptions( SID_AUTO_CORRECT_DLG, true );
+ aAppReq.AppendItem(aSwOptions);
+
+ pAFlags->pSmartTagMgr = &SwSmartTagMgr::Get();
+
+ SfxItemSetFixed<SID_AUTO_CORRECT_DLG, SID_AUTO_CORRECT_DLG, SID_OPEN_SMARTTAGOPTIONS, SID_OPEN_SMARTTAGOPTIONS> aSet( pApp->GetPool() );
+ aSet.Put( aSwOptions );
+
+ const SfxBoolItem* pOpenSmartTagOptionsItem = nullptr;
+ if( pArgs && (pOpenSmartTagOptionsItem = pArgs->GetItemIfSet( SID_OPEN_SMARTTAGOPTIONS, false )) )
+ aSet.Put( *pOpenSmartTagOptionsItem );
+
+ SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
+ VclPtr<SfxAbstractTabDialog> pDlg = pFact->CreateAutoCorrTabDialog(GetView()->GetFrameWeld(), &aSet);
+ pDlg->Execute();
+ pDlg.disposeAndClear();
+
+
+ rACW.SetLockWordLstLocked( bOldLocked );
+
+ SwEditShell::SetAutoFormatFlags( pAFlags );
+ rACW.SetMinWordLen( pAFlags->nAutoCmpltWordLen );
+ rACW.SetMaxCount( pAFlags->nAutoCmpltListLen );
+ if (pAFlags->m_pAutoCompleteList) // any changes?
+ {
+ rACW.CheckChangedList( aTmpLst );
+ // clear the temp WordList pointer
+ pAFlags->m_pAutoCompleteList = nullptr;
+ }
+
+ if( !bOldAutoCmpltCollectWords && bOldAutoCmpltCollectWords !=
+ pAFlags->bAutoCmpltCollectWords )
+ {
+ // call on all Docs the idle formatter to start
+ // the collection of Words
+ for( SwDocShell *pDocSh = static_cast<SwDocShell*>(SfxObjectShell::GetFirst(checkSfxObjectShell<SwDocShell>));
+ pDocSh;
+ pDocSh = static_cast<SwDocShell*>(SfxObjectShell::GetNext( *pDocSh, checkSfxObjectShell<SwDocShell> )) )
+ {
+ SwDoc* pTmp = pDocSh->GetDoc();
+ if ( pTmp->getIDocumentLayoutAccess().GetCurrentViewShell() )
+ pTmp->InvalidateAutoCompleteFlag();
+ }
+ }
+ }
+ break;
+
+ case SID_PRINTPREVIEW:
+ {
+ bool bSet = false;
+ bool bFound = false, bOnly = true;
+ SfxViewFrame *pTmpFrame = SfxViewFrame::GetFirst(this);
+ SfxViewShell* pViewShell = SfxViewShell::Current();
+ SwView* pCurrView = dynamic_cast< SwView *> ( pViewShell );
+ bool bCurrent = isType<SwPagePreview>( pViewShell );
+
+ while( pTmpFrame ) // search Preview
+ {
+ if( isType<SwView>( pTmpFrame->GetViewShell()) )
+ bOnly = false;
+ else if( isType<SwPagePreview>( pTmpFrame->GetViewShell()))
+ {
+ pTmpFrame->GetFrame().Appear();
+ bFound = true;
+ }
+ if( bFound && !bOnly )
+ break;
+ pTmpFrame = SfxViewFrame::GetNext(*pTmpFrame, this);
+ }
+
+ if( pArgs && SfxItemState::SET ==
+ pArgs->GetItemState( SID_PRINTPREVIEW, false, &pItem ))
+ bSet = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ else
+ bSet = !bCurrent;
+
+ sal_uInt16 nSlotId = 0;
+ if( bSet && !bFound ) // Nothing found, so create new Preview
+ nSlotId = SID_VIEWSHELL1;
+ else if( bFound && !bSet )
+ nSlotId = bOnly ? SID_VIEWSHELL0 : SID_VIEWSHELL1;
+
+ if( nSlotId )
+ {
+ // PagePreview in the WebDocShell
+ // is found under Id VIEWSHELL2.
+ if( dynamic_cast< const SwWebDocShell *>( this ) != nullptr && SID_VIEWSHELL1 == nSlotId )
+ nSlotId = SID_VIEWSHELL2;
+
+ if( pCurrView && pCurrView->GetDocShell() == this )
+ pTmpFrame = &pCurrView->GetViewFrame();
+ else
+ pTmpFrame = SfxViewFrame::GetFirst( this );
+
+ if (pTmpFrame)
+ pTmpFrame->GetDispatcher()->Execute( nSlotId, SfxCallMode::ASYNCHRON );
+ }
+
+ rReq.SetReturnValue(SfxBoolItem(SID_PRINTPREVIEW, bSet ));
+ }
+ break;
+ case SID_TEMPLATE_LOAD:
+ {
+ OUString aFileName;
+ static bool bText = true;
+ static bool bFrame = false;
+ static bool bPage = false;
+ static bool bNum = false;
+ static bool bMerge = false;
+
+ SfxTemplateFlags nFlags = bFrame ? SfxTemplateFlags::LOAD_FRAME_STYLES : SfxTemplateFlags::NONE;
+ if(bPage)
+ nFlags |= SfxTemplateFlags::LOAD_PAGE_STYLES;
+ if(bNum)
+ nFlags |= SfxTemplateFlags::LOAD_NUM_STYLES;
+ if(nFlags == SfxTemplateFlags::NONE || bText)
+ nFlags |= SfxTemplateFlags::LOAD_TEXT_STYLES;
+ if(bMerge)
+ nFlags |= SfxTemplateFlags::MERGE_STYLES;
+
+ if ( pArgs )
+ {
+ const SfxStringItem* pTemplateItem = rReq.GetArg<SfxStringItem>(SID_TEMPLATE_NAME);
+ if ( pTemplateItem )
+ {
+ aFileName = pTemplateItem->GetValue();
+ const SfxInt32Item* pFlagsItem = rReq.GetArg<SfxInt32Item>(SID_TEMPLATE_LOAD);
+ if ( pFlagsItem )
+ nFlags = static_cast<SfxTemplateFlags>(o3tl::narrowing<sal_uInt16>(pFlagsItem->GetValue()));
+ }
+ }
+
+ if ( aFileName.isEmpty() )
+ {
+ SfxNewFileDialog aNewFileDlg(GetView()->GetFrameWeld(), SfxNewFileDialogMode::LoadTemplate);
+ aNewFileDlg.SetTemplateFlags(nFlags);
+
+ sal_uInt16 nRet = aNewFileDlg.run();
+ if(RET_TEMPLATE_LOAD == nRet)
+ {
+ FileDialogHelper aDlgHelper(TemplateDescription::FILEOPEN_SIMPLE,
+ FileDialogFlags::NONE, GetView()->GetFrameWeld());
+ aDlgHelper.SetContext(FileDialogHelper::WriterLoadTemplate);
+ uno::Reference < XFilePicker3 > xFP = aDlgHelper.GetFilePicker();
+
+ SfxObjectFactory &rFact = GetFactory();
+ SfxFilterMatcher aMatcher( rFact.GetFactoryName() );
+ SfxFilterMatcherIter aIter( aMatcher );
+ std::shared_ptr<const SfxFilter> pFlt = aIter.First();
+ while( pFlt )
+ {
+ // --> OD #i117339#
+ if( pFlt && pFlt->IsAllowedAsTemplate() &&
+ ( pFlt->GetUserData() == "CXML" ||
+ pFlt->GetUserData() == "CXMLV" ) )
+ {
+ const OUString sWild = pFlt->GetWildcard().getGlob();
+ xFP->appendFilter( pFlt->GetUIName(), sWild );
+ }
+ pFlt = aIter.Next();
+ }
+ bool bWeb = dynamic_cast< SwWebDocShell *>( this ) != nullptr;
+ std::shared_ptr<const SfxFilter> pOwnFlt =
+ SwDocShell::Factory().GetFilterContainer()->
+ GetFilter4FilterName("writer8");
+
+ // make sure the default file format is also available
+ if(bWeb)
+ {
+ const OUString sWild = pOwnFlt->GetWildcard().getGlob();
+ xFP->appendFilter( pOwnFlt->GetUIName(), sWild );
+ }
+
+ bool bError = false;
+ // catch exception if wrong filter is selected - should not happen anymore
+ try
+ {
+ xFP->setCurrentFilter( pOwnFlt->GetUIName() );
+ }
+ catch (const uno::Exception&)
+ {
+ bError = true;
+ }
+
+ if( !bError && ERRCODE_NONE == aDlgHelper.Execute() )
+ {
+ aFileName = xFP->getSelectedFiles().getConstArray()[0];
+ }
+ }
+ else if( RET_OK == nRet)
+ {
+ aFileName = aNewFileDlg.GetTemplateFileName();
+ }
+
+ nFlags = aNewFileDlg.GetTemplateFlags();
+ rReq.AppendItem( SfxStringItem( SID_TEMPLATE_NAME, aFileName ) );
+ rReq.AppendItem( SfxInt32Item( SID_TEMPLATE_LOAD, static_cast<tools::Long>(nFlags) ) );
+ }
+
+ if( !aFileName.isEmpty() )
+ {
+ SwgReaderOption aOpt;
+ bText = bool(nFlags & SfxTemplateFlags::LOAD_TEXT_STYLES );
+ aOpt.SetTextFormats(bText);
+ bFrame = bool(nFlags & SfxTemplateFlags::LOAD_FRAME_STYLES);
+ aOpt.SetFrameFormats(bFrame);
+ bPage = bool(nFlags & SfxTemplateFlags::LOAD_PAGE_STYLES );
+ aOpt.SetPageDescs(bPage);
+ bNum = bool(nFlags & SfxTemplateFlags::LOAD_NUM_STYLES );
+ aOpt.SetNumRules(bNum);
+ //different meaning between SFX_MERGE_STYLES and aOpt.SetMerge!
+ bMerge = bool(nFlags & SfxTemplateFlags::MERGE_STYLES);
+ aOpt.SetMerge( !bMerge );
+
+ SetError(LoadStylesFromFile(aFileName, aOpt, false));
+ if ( !GetErrorIgnoreWarning() )
+ rReq.Done();
+ }
+ }
+ break;
+ case SID_SOURCEVIEW:
+ {
+ SfxViewShell* pViewShell = GetView()
+ ? static_cast<SfxViewShell*>(GetView())
+ : SfxViewShell::Current();
+ SfxViewFrame& rViewFrame = pViewShell->GetViewFrame();
+ SwSrcView* pSrcView = dynamic_cast< SwSrcView *>( pViewShell );
+ if(!pSrcView)
+ {
+ // 3 possible state:
+ // 1 - file unsaved -> save as HTML
+ // 2 - file modified and HTML filter active -> save
+ // 3 - file saved in non-HTML -> QueryBox to save as HTML
+ std::shared_ptr<const SfxFilter> pHtmlFlt =
+ SwIoSystem::GetFilterOfFormat(
+ u"HTML",
+ SwWebDocShell::Factory().GetFilterContainer() );
+ bool bLocalHasName = HasName();
+ if(bLocalHasName)
+ {
+ //check for filter type
+ std::shared_ptr<const SfxFilter> pFlt = GetMedium()->GetFilter();
+ if(!pFlt || pFlt->GetUserData() != pHtmlFlt->GetUserData())
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(rViewFrame.GetFrameWeld(), "modules/swriter/ui/saveashtmldialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("SaveAsHTMLDialog"));
+ if (RET_YES == xQuery->run())
+ bLocalHasName = false;
+ else
+ break;
+ }
+ }
+ if(!bLocalHasName)
+ {
+ FileDialogHelper aDlgHelper(TemplateDescription::FILESAVE_AUTOEXTENSION,
+ FileDialogFlags::NONE,
+ GetView()->GetFrameWeld());
+ aDlgHelper.SetContext(FileDialogHelper::WriterSaveHTML);
+ aDlgHelper.AddFilter( pHtmlFlt->GetFilterName(), pHtmlFlt->GetDefaultExtension() );
+ aDlgHelper.SetCurrentFilter( pHtmlFlt->GetFilterName() );
+ if( ERRCODE_NONE != aDlgHelper.Execute())
+ {
+ break;
+ }
+ OUString sPath = aDlgHelper.GetPath();
+ SfxStringItem aName(SID_FILE_NAME, sPath);
+ SfxStringItem aFilter(SID_FILTER_NAME, pHtmlFlt->GetName());
+ const SfxPoolItemHolder aResult(
+ rViewFrame.GetDispatcher()->ExecuteList(
+ SID_SAVEASDOC, SfxCallMode::SYNCHRON,
+ { &aName, &aFilter }));
+ const SfxBoolItem* pBool(static_cast<const SfxBoolItem*>(aResult.getItem()));
+ if(!pBool || !pBool->GetValue())
+ break;
+ }
+ }
+
+ assert(dynamic_cast<SwWebDocShell*>(this) && "SourceView only in WebDocShell");
+
+ // the SourceView is not the 1 for SwWebDocShell
+ sal_uInt16 nSlot = SID_VIEWSHELL1;
+ bool bSetModified = false;
+ VclPtr<SfxPrinter> pSavePrinter;
+ if( nullptr != pSrcView)
+ {
+ SfxPrinter* pTemp = GetDoc()->getIDocumentDeviceAccess().getPrinter( false );
+ if(pTemp)
+ pSavePrinter = VclPtr<SfxPrinter>::Create(*pTemp);
+ bSetModified = IsModified() || pSrcView->IsModified();
+ if(pSrcView->IsModified()||pSrcView->HasSourceSaved())
+ {
+ utl::TempFileNamed aTempFile;
+ aTempFile.EnableKillingFile();
+ pSrcView->SaveContent(aTempFile.GetURL());
+ bDone = true;
+ SvxMacro aMac(OUString(), OUString(), STARBASIC);
+ SfxEventConfiguration::ConfigureEvent(GlobalEventConfig::GetEventName( GlobalEventId::OPENDOC ), aMac, this);
+ SfxEventConfiguration::ConfigureEvent(GlobalEventConfig::GetEventName( GlobalEventId::PREPARECLOSEDOC ), aMac, this);
+ SfxEventConfiguration::ConfigureEvent(GlobalEventConfig::GetEventName( GlobalEventId::ACTIVATEDOC ), aMac, this);
+ SfxEventConfiguration::ConfigureEvent(GlobalEventConfig::GetEventName( GlobalEventId::DEACTIVATEDOC ), aMac, this);
+ ReloadFromHtml(aTempFile.GetURL(), pSrcView);
+ nSlot = 0;
+ }
+ else
+ {
+ nSlot = SID_VIEWSHELL0;
+ }
+ }
+ if (nSlot)
+ rViewFrame.GetDispatcher()->Execute(nSlot, SfxCallMode::SYNCHRON);
+ if(bSetModified)
+ GetDoc()->getIDocumentState().SetModified();
+ if(pSavePrinter)
+ {
+ GetDoc()->getIDocumentDeviceAccess().setPrinter( pSavePrinter, true, true);
+ //pSavePrinter must not be deleted again
+ }
+ rViewFrame.GetBindings().SetState(SfxBoolItem(SID_SOURCEVIEW, false)); // not SID_VIEWSHELL2
+ rViewFrame.GetBindings().Invalidate( SID_NEWWINDOW );
+ rViewFrame.GetBindings().Invalidate( SID_BROWSER_MODE );
+ rViewFrame.GetBindings().Invalidate( FN_PRINT_LAYOUT );
+ }
+ break;
+ case SID_GET_COLORLIST:
+ {
+ const SvxColorListItem* pColItem = GetItem(SID_COLOR_TABLE);
+ const XColorListRef& pList = pColItem->GetColorList();
+ rReq.SetReturnValue(OfaXColorListItem(SID_GET_COLORLIST, pList));
+ }
+ break;
+ case FN_ABSTRACT_STARIMPRESS:
+ case FN_ABSTRACT_NEWDOC:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractSwInsertAbstractDlg> pDlg(pFact->CreateSwInsertAbstractDlg(GetView()->GetFrameWeld()));
+ if(RET_OK == pDlg->Execute())
+ {
+ sal_uInt8 nLevel = pDlg->GetLevel();
+ sal_uInt8 nPara = pDlg->GetPara();
+ SwDoc* pSmryDoc = new SwDoc();
+ SfxObjectShellLock xDocSh(new SwDocShell(*pSmryDoc, SfxObjectCreateMode::STANDARD));
+ xDocSh->DoInitNew();
+
+ bool bImpress = FN_ABSTRACT_STARIMPRESS == nWhich;
+ m_xDoc->Summary(*pSmryDoc, nLevel, nPara, bImpress);
+ if( bImpress )
+ {
+ WriterRef xWrt;
+ // mba: looks as if relative URLs don't make sense here
+ ::GetRTFWriter(std::u16string_view(), OUString(), xWrt);
+ SvMemoryStream *pStrm = new SvMemoryStream();
+ pStrm->SetBufferSize( 16348 );
+ SwWriter aWrt( *pStrm, *pSmryDoc );
+ ErrCodeMsg eErr = aWrt.Write( xWrt );
+ if( !eErr.IgnoreWarning() )
+ {
+ uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
+ uno::Reference< frame::XDispatchProvider > xProv = drawing::ModuleDispatcher::create( xContext );
+
+ uno::Reference< frame::XDispatchHelper > xHelper( frame::DispatchHelper::create(xContext) );
+ pStrm->Seek( STREAM_SEEK_TO_END );
+ pStrm->WriteChar( '\0' );
+ pStrm->Seek( STREAM_SEEK_TO_BEGIN );
+
+ // Transfer ownership of stream to a lockbytes object
+ SvLockBytes aLockBytes( pStrm, true );
+ SvLockBytesStat aStat;
+ if ( aLockBytes.Stat( &aStat ) == ERRCODE_NONE )
+ {
+ sal_uInt32 nLen = aStat.nSize;
+ std::size_t nRead = 0;
+ uno::Sequence< sal_Int8 > aSeq( nLen );
+ aLockBytes.ReadAt( 0, aSeq.getArray(), nLen, &nRead );
+
+ uno::Sequence< beans::PropertyValue > aArgs{
+ comphelper::makePropertyValue("RtfOutline", aSeq)
+ };
+ xHelper->executeDispatch( xProv, "SendOutlineToImpress", OUString(), 0, aArgs );
+ }
+ }
+ else
+ ErrorHandler::HandleError( eErr );
+ }
+ else
+ {
+ // Create new document
+ SfxViewFrame *pFrame = SfxViewFrame::LoadDocument( *xDocSh, SFX_INTERFACE_NONE );
+ SwView *pCurrView = static_cast<SwView*>( pFrame->GetViewShell());
+
+ // Set document's title
+ OUString aTmp = SwResId(STR_ABSTRACT_TITLE) + GetTitle();
+ xDocSh->SetTitle( aTmp );
+ pCurrView->GetWrtShell().SetNewDoc();
+ pFrame->Show();
+ pSmryDoc->getIDocumentState().SetModified();
+ }
+
+ }
+ }
+ break;
+ case FN_OUTLINE_TO_CLIPBOARD:
+ case FN_OUTLINE_TO_IMPRESS:
+ {
+ bool bEnable = IsEnableSetModified();
+ EnableSetModified( false );
+ WriterRef xWrt;
+ // mba: looks as if relative URLs don't make sense here
+ ::GetRTFWriter( u"O", OUString(), xWrt );
+ std::unique_ptr<SvMemoryStream> pStrm (new SvMemoryStream());
+ pStrm->SetBufferSize( 16348 );
+ SwWriter aWrt( *pStrm, *GetDoc() );
+ ErrCodeMsg eErr = aWrt.Write( xWrt );
+ EnableSetModified( bEnable );
+ if( !eErr.IgnoreWarning() )
+ {
+ pStrm->Seek( STREAM_SEEK_TO_END );
+ pStrm->WriteChar( '\0' );
+ pStrm->Seek( STREAM_SEEK_TO_BEGIN );
+ if ( nWhich == FN_OUTLINE_TO_IMPRESS )
+ {
+ uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
+ uno::Reference< frame::XDispatchProvider > xProv = drawing::ModuleDispatcher::create( xContext );
+
+ uno::Reference< frame::XDispatchHelper > xHelper( frame::DispatchHelper::create(xContext) );
+ pStrm->Seek( STREAM_SEEK_TO_END );
+ pStrm->WriteChar( '\0' );
+ pStrm->Seek( STREAM_SEEK_TO_BEGIN );
+
+ // Transfer ownership of stream to a lockbytes object
+ SvLockBytes aLockBytes( pStrm.release(), true );
+ SvLockBytesStat aStat;
+ if ( aLockBytes.Stat( &aStat ) == ERRCODE_NONE )
+ {
+ sal_uInt32 nLen = aStat.nSize;
+ std::size_t nRead = 0;
+ uno::Sequence< sal_Int8 > aSeq( nLen );
+ aLockBytes.ReadAt( 0, aSeq.getArray(), nLen, &nRead );
+
+ uno::Sequence< beans::PropertyValue > aArgs{
+ comphelper::makePropertyValue("RtfOutline", aSeq)
+ };
+ xHelper->executeDispatch( xProv, "SendOutlineToImpress", OUString(), 0, aArgs );
+ }
+ }
+ else
+ {
+ rtl::Reference<TransferDataContainer> pClipCntnr = new TransferDataContainer;
+
+ pClipCntnr->CopyAnyData( SotClipboardFormatId::RTF, static_cast<char const *>(
+ pStrm->GetData()), pStrm->GetEndOfData() );
+ pClipCntnr->CopyToClipboard(
+ GetView()? &GetView()->GetEditWin() : nullptr );
+ }
+ }
+ else
+ ErrorHandler::HandleError( eErr );
+ }
+ break;
+ case SID_SPELLCHECKER_CHANGED:
+ {
+ //! false, true, true is on the save side but a probably overdone
+ SwModule::CheckSpellChanges(false, true, true, false );
+ Broadcast(SfxHint(SfxHintId::LanguageChanged));
+ }
+ break;
+
+ case SID_MAIL_PREPAREEXPORT:
+ {
+ const SfxBoolItem* pNoUpdate = pArgs ?
+ pArgs->GetItem<SfxBoolItem>(FN_NOUPDATE, false) :
+ nullptr;
+
+ //pWrtShell is not set in page preview
+ if (m_pWrtShell)
+ m_pWrtShell->StartAllAction();
+
+ if (!pNoUpdate || !pNoUpdate->GetValue())
+ {
+ m_xDoc->getIDocumentFieldsAccess().UpdateFields( false );
+ m_xDoc->getIDocumentLinksAdministration().EmbedAllLinks();
+ }
+
+ m_IsRemovedInvisibleContent
+ = officecfg::Office::Security::HiddenContent::RemoveHiddenContent::get();
+ if (m_IsRemovedInvisibleContent)
+ m_xDoc->RemoveInvisibleContent();
+ if (m_pWrtShell)
+ m_pWrtShell->EndAllAction();
+ }
+ break;
+
+ case SID_MAIL_EXPORT_FINISHED:
+ {
+ if (m_pWrtShell)
+ m_pWrtShell->StartAllAction();
+ //try to undo the removal of invisible content
+ if (m_IsRemovedInvisibleContent)
+ m_xDoc->RestoreInvisibleContent();
+ if (m_pWrtShell)
+ m_pWrtShell->EndAllAction();
+ }
+ break;
+ case FN_NEW_HTML_DOC:
+ case FN_NEW_GLOBAL_DOC:
+ {
+ bDone = false;
+ bool bCreateHtml = FN_NEW_HTML_DOC == nWhich;
+
+ bool bCreateByOutlineLevel = false;
+ sal_Int32 nTemplateOutlineLevel = 0;
+
+ OUString aFileName, aTemplateName;
+ if( pArgs && SfxItemState::SET == pArgs->GetItemState( nWhich, false, &pItem ) )
+ {
+ aFileName = static_cast<const SfxStringItem*>(pItem)->GetValue();
+ const SfxStringItem* pTemplItem = SfxItemSet::GetItem<SfxStringItem>(pArgs, SID_TEMPLATE_NAME, false);
+ if ( pTemplItem )
+ aTemplateName = pTemplItem->GetValue();
+ }
+ if ( aFileName.isEmpty() )
+ {
+ bool bError = false;
+
+ FileDialogHelper aDlgHelper(TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE, FileDialogFlags::NONE,
+ GetView()->GetFrameWeld());
+ aDlgHelper.SetContext(FileDialogHelper::WriterNewHTMLGlobalDoc);
+
+ const sal_Int16 nControlIds[] = {
+ CommonFilePickerElementIds::PUSHBUTTON_OK,
+ CommonFilePickerElementIds::PUSHBUTTON_CANCEL,
+ CommonFilePickerElementIds::LISTBOX_FILTER,
+ CommonFilePickerElementIds::CONTROL_FILEVIEW,
+ CommonFilePickerElementIds::EDIT_FILEURL,
+ ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION,
+ ExtendedFilePickerElementIds::LISTBOX_TEMPLATE,
+ 0
+ };
+
+ if (bCreateHtml)
+ {
+ const char* aHTMLHelpIds[] =
+ {
+ HID_SEND_HTML_CTRL_PUSHBUTTON_OK,
+ HID_SEND_HTML_CTRL_PUSHBUTTON_CANCEL,
+ HID_SEND_HTML_CTRL_LISTBOX_FILTER,
+ HID_SEND_HTML_CTRL_CONTROL_FILEVIEW,
+ HID_SEND_HTML_CTRL_EDIT_FILEURL,
+ HID_SEND_HTML_CTRL_CHECKBOX_AUTOEXTENSION,
+ HID_SEND_HTML_CTRL_LISTBOX_TEMPLATE,
+ ""
+ };
+ aDlgHelper.SetControlHelpIds( nControlIds, aHTMLHelpIds );
+ }
+ else
+ {
+ const char* aMasterHelpIds[] =
+ {
+ HID_SEND_MASTER_CTRL_PUSHBUTTON_OK,
+ HID_SEND_MASTER_CTRL_PUSHBUTTON_CANCEL,
+ HID_SEND_MASTER_CTRL_LISTBOX_FILTER,
+ HID_SEND_MASTER_CTRL_CONTROL_FILEVIEW,
+ HID_SEND_MASTER_CTRL_EDIT_FILEURL,
+ HID_SEND_MASTER_CTRL_CHECKBOX_AUTOEXTENSION,
+ HID_SEND_MASTER_CTRL_LISTBOX_TEMPLATE,
+ ""
+ };
+ aDlgHelper.SetControlHelpIds( nControlIds, aMasterHelpIds );
+ }
+ uno::Reference < XFilePicker3 > xFP = aDlgHelper.GetFilePicker();
+
+ std::shared_ptr<const SfxFilter> pFlt;
+ TranslateId pStrId;
+
+ if( bCreateHtml )
+ {
+ // for HTML there is only one filter!!
+ pFlt = SwIoSystem::GetFilterOfFormat(
+ u"HTML",
+ SwWebDocShell::Factory().GetFilterContainer() );
+ pStrId = STR_LOAD_HTML_DOC;
+ }
+ else
+ {
+ // for Global-documents we now only offer the current one.
+ pFlt = SwGlobalDocShell::Factory().GetFilterContainer()->
+ GetFilter4Extension( "odm" );
+ pStrId = STR_LOAD_GLOBAL_DOC;
+ }
+
+ if( pFlt )
+ {
+ const OUString sWild = pFlt->GetWildcard().getGlob();
+ xFP->appendFilter( pFlt->GetUIName(), sWild );
+ try
+ {
+ xFP->setCurrentFilter( pFlt->GetUIName() ) ;
+ }
+ catch (const uno::Exception&)
+ {
+ bError = true;
+ }
+ }
+ if(!bError)
+ {
+ uno::Reference<XFilePickerControlAccess> xCtrlAcc(xFP, UNO_QUERY);
+
+ bool bOutline[MAXLEVEL] = {false};
+ const SwOutlineNodes& rOutlNds = m_xDoc->GetNodes().GetOutLineNds();
+ for( size_t n = 0; n < rOutlNds.size(); ++n )
+ {
+ const int nLevel = rOutlNds[n]->GetTextNode()->GetAttrOutlineLevel();
+ if( nLevel > 0 && ! bOutline[nLevel-1] )
+ {
+ bOutline[nLevel-1] = true;
+ }
+ }
+
+ const sal_uInt16 nStyleCount = m_xDoc->GetTextFormatColls()->size();
+ Sequence<OUString> aListBoxEntries( MAXLEVEL + nStyleCount);
+ OUString* pEntries = aListBoxEntries.getArray();
+ sal_Int32 nIdx = 0 ;
+
+ OUString sOutline( SwResId(STR_FDLG_OUTLINE_LEVEL) );
+ for( sal_uInt16 i = 0; i < MAXLEVEL; ++i )
+ {
+ if( bOutline[i] )
+ pEntries[nIdx++] = sOutline + OUString::number( i+1 );
+ }
+
+ OUString sStyle( SwResId(STR_FDLG_STYLE) );
+ for(sal_uInt16 i = 0; i < nStyleCount; ++i)
+ {
+ SwTextFormatColl &rTextColl = *(*m_xDoc->GetTextFormatColls())[ i ];
+ if( !rTextColl.IsDefault() && rTextColl.IsAtDocNodeSet() )
+ {
+ pEntries[nIdx++] = sStyle + rTextColl.GetName();
+ }
+ }
+
+ aListBoxEntries.realloc(nIdx);
+ sal_Int16 nSelect = 0;
+
+ try
+ {
+ Any aTemplates(&aListBoxEntries, cppu::UnoType<decltype(aListBoxEntries)>::get());
+
+ xCtrlAcc->setValue( ExtendedFilePickerElementIds::LISTBOX_TEMPLATE,
+ ListboxControlActions::ADD_ITEMS , aTemplates );
+ Any aSelectPos(&nSelect, cppu::UnoType<decltype(nSelect)>::get());
+ xCtrlAcc->setValue( ExtendedFilePickerElementIds::LISTBOX_TEMPLATE,
+ ListboxControlActions::SET_SELECT_ITEM, aSelectPos );
+ xCtrlAcc->setLabel( ExtendedFilePickerElementIds::LISTBOX_TEMPLATE,
+ SwResId( STR_FDLG_TEMPLATE_NAME ));
+ }
+ catch (const Exception&)
+ {
+ OSL_FAIL("control access failed");
+ }
+
+ xFP->setTitle(SwResId(pStrId));
+ SvtPathOptions aPathOpt;
+ xFP->setDisplayDirectory( aPathOpt.GetWorkPath() );
+ if( ERRCODE_NONE == aDlgHelper.Execute())
+ {
+ aFileName = xFP->getSelectedFiles().getConstArray()[0];
+ Any aTemplateValue = xCtrlAcc->getValue(
+ ExtendedFilePickerElementIds::LISTBOX_TEMPLATE,
+ ListboxControlActions::GET_SELECTED_ITEM );
+ OUString sTmpl;
+ aTemplateValue >>= sTmpl;
+
+ OUString aStyle(SwResId(STR_FDLG_STYLE));
+ OUString aOutline(SwResId(STR_FDLG_OUTLINE_LEVEL));
+
+ if ( sTmpl.startsWith(aStyle) )
+ {
+ aTemplateName = sTmpl.copy( aStyle.getLength() ); //get string behind "Style: "
+ }
+ else if ( sTmpl.startsWith(aOutline) )
+ {
+ nTemplateOutlineLevel = o3tl::toInt32(sTmpl.subView(aOutline.getLength())); //get string behind "Outline: Level ";
+ bCreateByOutlineLevel = true;
+ }
+
+ if ( !aFileName.isEmpty() )
+ {
+ rReq.AppendItem( SfxStringItem( nWhich, aFileName ) );
+ if( !aTemplateName.isEmpty() )
+ rReq.AppendItem( SfxStringItem( SID_TEMPLATE_NAME, aTemplateName ) );
+ }
+ }
+ }
+ }
+
+ if( !aFileName.isEmpty() )
+ {
+ if( PrepareClose( false ) )
+ {
+ SwWait aWait( *this, true );
+
+ if ( bCreateByOutlineLevel )
+ {
+ bDone = bCreateHtml
+ ? m_xDoc->GenerateHTMLDoc( aFileName, nTemplateOutlineLevel )
+ : m_xDoc->GenerateGlobalDoc( aFileName, nTemplateOutlineLevel );
+ }
+ else
+ {
+ const SwTextFormatColl* pSplitColl = nullptr;
+ if ( !aTemplateName.isEmpty() )
+ pSplitColl = m_xDoc->FindTextFormatCollByName(aTemplateName);
+ bDone = bCreateHtml
+ ? m_xDoc->GenerateHTMLDoc( aFileName, pSplitColl )
+ : m_xDoc->GenerateGlobalDoc( aFileName, pSplitColl );
+ }
+ if( bDone )
+ {
+ SfxStringItem aName( SID_FILE_NAME, aFileName );
+ SfxStringItem aReferer(SID_REFERER, OUString());
+ SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+ while(pViewShell)
+ {
+ //search for the view that created the call
+ if(pViewShell->GetObjectShell() == this && pViewShell->GetDispatcher())
+ {
+ SfxFrameItem aFrameItem(SID_DOCFRAME, &pViewShell->GetViewFrame());
+ SfxDispatcher* pDispatch = pViewShell->GetDispatcher();
+ pDispatch->ExecuteList(SID_OPENDOC,
+ SfxCallMode::ASYNCHRON,
+ { &aName, &aReferer, &aFrameItem });
+ break;
+ }
+ pViewShell = SfxViewShell::GetNext(*pViewShell);
+ }
+ }
+ }
+ if( !bDone && !rReq.IsAPI() )
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_CANTCREATE)));
+ xInfoBox->run();
+ }
+ }
+ }
+ rReq.SetReturnValue(SfxBoolItem( nWhich, bDone ));
+ if (bDone)
+ rReq.Done();
+ else
+ rReq.Ignore();
+ break;
+
+ case SID_ATTR_YEAR2000:
+ if ( pArgs && SfxItemState::SET == pArgs->GetItemState( nWhich , false, &pItem ))
+ {
+ assert(dynamic_cast< const SfxUInt16Item *>( pItem ) && "wrong Item");
+ sal_uInt16 nYear2K = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
+ // iterate over Views and put the State to FormShells
+
+ SfxViewFrame* pVFrame = SfxViewFrame::GetFirst( this );
+ SfxViewShell* pViewShell = pVFrame ? pVFrame->GetViewShell() : nullptr;
+ SwView* pCurrView = dynamic_cast< SwView* >( pViewShell );
+ while(pCurrView)
+ {
+ FmFormShell* pFormShell = pCurrView->GetFormShell();
+ if(pFormShell)
+ pFormShell->SetY2KState(nYear2K);
+ pVFrame = SfxViewFrame::GetNext( *pVFrame, this );
+ pViewShell = pVFrame ? pVFrame->GetViewShell() : nullptr;
+ pCurrView = dynamic_cast<SwView*>( pViewShell );
+ }
+ m_xDoc->GetNumberFormatter()->SetYear2000(nYear2K);
+ }
+ break;
+ case FN_OPEN_FILE:
+ {
+ SfxViewShell* pViewShell = GetView();
+ if (!pViewShell)
+ pViewShell = SfxViewShell::Current();
+
+ if (!pViewShell)
+ // Ok. I did my best.
+ break;
+
+ if (SfxDispatcher* pDispatch = pViewShell->GetDispatcher())
+ {
+ SfxStringItem aApp(SID_DOC_SERVICE, "com.sun.star.text.TextDocument");
+ SfxStringItem aTarget(SID_TARGETNAME, "_blank");
+ pDispatch->ExecuteList(SID_OPENDOC, SfxCallMode::API|SfxCallMode::SYNCHRON, { &aApp, &aTarget });
+ }
+ }
+ break;
+ case SID_CLASSIFICATION_APPLY:
+ {
+ if (pArgs && pArgs->GetItemState(nWhich, false, &pItem) == SfxItemState::SET)
+ {
+ SwWrtShell* pSh = GetWrtShell();
+ const OUString& rValue = static_cast<const SfxStringItem*>(pItem)->GetValue();
+ auto eType = SfxClassificationPolicyType::IntellectualProperty;
+ if (const SfxStringItem* pTypeNameItem = pArgs->GetItemIfSet(SID_TYPE_NAME, false))
+ {
+ const OUString& rType = pTypeNameItem->GetValue();
+ eType = SfxClassificationHelper::stringToPolicyType(rType);
+ }
+ pSh->SetClassification(rValue, eType);
+ }
+ else
+ SAL_WARN("sw.ui", "missing parameter for SID_CLASSIFICATION_APPLY");
+ }
+ break;
+ case SID_CLASSIFICATION_DIALOG:
+ if (SfxObjectShell* pObjSh = SfxObjectShell::Current())
+ {
+ auto xDialog = std::make_shared<svx::ClassificationDialog>(GetView()->GetFrameWeld(), pObjSh->getDocProperties(), false);
+
+ SwWrtShell* pShell = GetWrtShell();
+ std::vector<svx::ClassificationResult> aInput = pShell->CollectAdvancedClassification();
+ xDialog->setupValues(std::move(aInput));
+
+ weld::DialogController::runAsync(xDialog, [xDialog, pShell](sal_Int32 nResult){
+ if (RET_OK == nResult)
+ pShell->ApplyAdvancedClassification(xDialog->getResult());
+ });
+ }
+ break;
+ case SID_PARAGRAPH_SIGN_CLASSIFY_DLG:
+ if (SfxObjectShell* pObjSh = SfxObjectShell::Current())
+ {
+ SwWrtShell* pShell = GetWrtShell();
+ auto xDialog = std::make_shared<svx::ClassificationDialog>(GetView()->GetFrameWeld(), pObjSh->getDocProperties(), true, [pShell]()
+ {
+ pShell->SignParagraph();
+ });
+
+ std::vector<svx::ClassificationResult> aInput = pShell->CollectParagraphClassification();
+ xDialog->setupValues(std::move(aInput));
+
+ weld::DialogController::runAsync(xDialog, [xDialog, pShell](sal_Int32 nResult){
+ if (RET_OK == nResult)
+ pShell->ApplyParagraphClassification(xDialog->getResult());
+ });
+ }
+ break;
+ case SID_WATERMARK:
+ {
+ SwWrtShell* pSh = GetWrtShell();
+ if ( pSh )
+ {
+ if (pArgs && pArgs->GetItemState( SID_WATERMARK, false, &pItem ) == SfxItemState::SET)
+ {
+ SfxWatermarkItem aItem;
+ aItem.SetText( static_cast<const SfxStringItem*>( pItem )->GetValue() );
+
+ if ( const SfxStringItem* pFontItem = pArgs->GetItemIfSet( SID_WATERMARK_FONT, false ) )
+ aItem.SetFont( pFontItem->GetValue() );
+ if ( const SfxInt16Item* pAngleItem = pArgs->GetItemIfSet( SID_WATERMARK_ANGLE, false ) )
+ aItem.SetAngle( pAngleItem->GetValue() );
+ if ( const SfxInt16Item* pTransItem = pArgs->GetItemIfSet( SID_WATERMARK_TRANSPARENCY, false ) )
+ aItem.SetTransparency( pTransItem->GetValue() );
+ if ( const SfxUInt32Item* pColorItem = pArgs->GetItemIfSet( SID_WATERMARK_COLOR, false ) )
+ aItem.SetColor( Color(ColorTransparency, pColorItem->GetValue()) );
+
+ pSh->SetWatermark( aItem );
+ }
+ else
+ {
+ SfxViewShell* pViewShell = GetView() ? GetView() : SfxViewShell::Current();
+ SfxBindings& rBindings( pViewShell->GetViewFrame().GetBindings() );
+ auto xDlg = std::make_shared<SwWatermarkDialog>(pViewShell->GetViewFrame().GetFrameWeld(),
+ rBindings);
+ weld::DialogController::runAsync(xDlg, [](sal_Int32 /*nResult*/){});
+ }
+ }
+ }
+ break;
+ case SID_NOTEBOOKBAR:
+ {
+ const SfxStringItem* pFile = rReq.GetArg<SfxStringItem>( SID_NOTEBOOKBAR );
+ SfxViewShell* pViewShell = GetView()? GetView(): SfxViewShell::Current();
+ SfxBindings& rBindings( pViewShell->GetViewFrame().GetBindings() );
+
+ if ( SfxNotebookBar::IsActive() )
+ sfx2::SfxNotebookBar::ExecMethod( rBindings, pFile ? pFile->GetValue() : "" );
+ else
+ {
+ sfx2::SfxNotebookBar::CloseMethod( rBindings );
+ }
+ }
+ break;
+ case FN_REDLINE_ACCEPT_ALL:
+ case FN_REDLINE_REJECT_ALL:
+ {
+ IDocumentRedlineAccess& rRedlineAccess = GetDoc()->getIDocumentRedlineAccess();
+ SwWrtShell *pWrtShell = dynamic_cast<SwWrtShell*>(GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell());
+
+ if (rRedlineAccess.GetRedlineTable().empty())
+ {
+ break;
+ }
+
+ // tables with tracked deletion need Show Changes
+ bool bHideChanges = pWrtShell && pWrtShell->GetLayout() &&
+ pWrtShell->GetLayout()->IsHideRedlines();
+ bool bChangedHideChanges = false;
+ if ( bHideChanges )
+ {
+ SwTableNode* pOldTableNd = nullptr;
+ const SwRedlineTable& aRedlineTable = rRedlineAccess.GetRedlineTable();
+ for (SwRedlineTable::size_type n = 0; n < aRedlineTable.size(); ++n)
+ {
+ const SwRangeRedline* pRedline = aRedlineTable[n];
+ if ( pRedline->GetType() == RedlineType::Delete )
+ {
+ SwTableNode* pTableNd =
+ pRedline->GetPoint()->GetNode().FindTableNode();
+ if ( pTableNd && pTableNd !=
+ pOldTableNd && pTableNd->GetTable().HasDeletedRowOrCell() )
+ {
+ SfxBoolItem aShow(FN_REDLINE_SHOW, true);
+ SfxViewShell* pViewShell = GetView()
+ ? GetView()
+ : SfxViewShell::Current();
+ pViewShell->GetViewFrame().GetDispatcher()->ExecuteList(
+ FN_REDLINE_SHOW, SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
+ { &aShow });
+ bChangedHideChanges = true;
+ break;
+ }
+ pOldTableNd = pTableNd;
+ }
+ }
+ }
+
+ if (pWrtShell)
+ {
+ pWrtShell->StartAllAction();
+ }
+
+ rRedlineAccess.AcceptAllRedline(nWhich == FN_REDLINE_ACCEPT_ALL);
+
+ if (pWrtShell)
+ {
+ pWrtShell->EndAllAction();
+ }
+
+ if ( bChangedHideChanges )
+ {
+ SfxBoolItem aShow(FN_REDLINE_SHOW, false);
+ SfxViewShell* pViewShell = GetView()? GetView(): SfxViewShell::Current();
+ pViewShell->GetViewFrame().GetDispatcher()->ExecuteList(
+ FN_REDLINE_SHOW, SfxCallMode::SYNCHRON|SfxCallMode::RECORD, { &aShow });
+ }
+
+ Broadcast(SfxHint(SfxHintId::RedlineChanged));
+ rReq.Done();
+ }
+ break;
+
+ default: OSL_FAIL("wrong Dispatcher");
+ }
+}
+
+#if defined(_WIN32)
+bool SwDocShell::DdeGetData( const OUString& rItem, const OUString& rMimeType,
+ uno::Any & rValue )
+{
+ return m_xDoc->getIDocumentLinksAdministration().GetData( rItem, rMimeType, rValue );
+}
+
+bool SwDocShell::DdeSetData( const OUString& rItem, const OUString& /*rMimeType*/,
+ const uno::Any & /*rValue*/ )
+{
+ m_xDoc->getIDocumentLinksAdministration().SetData( rItem );
+ return false;
+}
+
+#endif
+
+::sfx2::SvLinkSource* SwDocShell::DdeCreateLinkSource( const OUString& rItem )
+{
+ if(officecfg::Office::Common::Security::Scripting::DisableActiveContent::get())
+ return nullptr;
+ return m_xDoc->getIDocumentLinksAdministration().CreateLinkSource( rItem );
+}
+
+void SwDocShell::ReconnectDdeLink(SfxObjectShell& rServer)
+{
+ if (m_xDoc)
+ {
+ ::sfx2::LinkManager& rLinkManager = m_xDoc->getIDocumentLinksAdministration().GetLinkManager();
+ rLinkManager.ReconnectDdeLink(rServer);
+ }
+}
+
+void SwDocShell::FillClass( SvGlobalName * pClassName,
+ SotClipboardFormatId * pClipFormat,
+ OUString * pLongUserName,
+ sal_Int32 nVersion,
+ bool bTemplate /* = false */) const
+{
+ if (nVersion == SOFFICE_FILEFORMAT_60)
+ {
+ *pClassName = SvGlobalName( SO3_SW_CLASSID_60 );
+ *pClipFormat = SotClipboardFormatId::STARWRITER_60;
+ *pLongUserName = SwResId(STR_WRITER_DOCUMENT_FULLTYPE);
+ }
+ else if (nVersion == SOFFICE_FILEFORMAT_8)
+ {
+ *pClassName = SvGlobalName( SO3_SW_CLASSID_60 );
+ *pClipFormat = bTemplate ? SotClipboardFormatId::STARWRITER_8_TEMPLATE : SotClipboardFormatId::STARWRITER_8;
+ *pLongUserName = SwResId(STR_WRITER_DOCUMENT_FULLTYPE);
+ }
+// #FIXME check with new Event handling
+#if 0
+ uno::Reference< document::XVbaEventsHelper > xVbaEventsHelper = m_xDoc->GetVbaEventsHelper();
+ if( xVbaEventsHelper.is() )
+ lcl_processCompatibleSfxHint( xVbaEventsHelper, rHint );
+#endif
+}
+
+void SwDocShell::SetModified( bool bSet )
+{
+ if (utl::ConfigManager::IsFuzzing())
+ return;
+ SfxObjectShell::SetModified( bSet );
+ if( !IsEnableSetModified())
+ return;
+
+ if (!m_xDoc->getIDocumentState().IsInCallModified())
+ {
+ EnableSetModified( false );
+ if( bSet )
+ {
+ bool const bOld = m_xDoc->getIDocumentState().IsModified();
+ m_xDoc->getIDocumentState().SetModified();
+ if( !bOld )
+ {
+ m_xDoc->GetIDocumentUndoRedo().SetUndoNoResetModified();
+ }
+ }
+ else
+ m_xDoc->getIDocumentState().ResetModified();
+
+ EnableSetModified();
+ }
+
+ UpdateChildWindows();
+ Broadcast(SfxHint(SfxHintId::DocChanged));
+}
+
+void SwDocShell::UpdateChildWindows()
+{
+ // if necessary newly initialize Fielddlg (i.e. for TYP_SETVAR)
+ if(!GetView())
+ return;
+ SfxViewFrame& rVFrame = GetView()->GetViewFrame();
+ SwFieldDlgWrapper *pWrp = static_cast<SwFieldDlgWrapper*>(rVFrame.
+ GetChildWindow( SwFieldDlgWrapper::GetChildWindowId() ));
+ if( pWrp )
+ pWrp->ReInitDlg( this );
+
+ // if necessary newly initialize RedlineDlg
+ SwRedlineAcceptChild *pRed = static_cast<SwRedlineAcceptChild*>(rVFrame.
+ GetChildWindow( SwRedlineAcceptChild::GetChildWindowId() ));
+ if( pRed )
+ pRed->ReInitDlg( this );
+}
+
+namespace {
+
+// #i48748#
+class SwReloadFromHtmlReader : public SwReader
+{
+ public:
+ SwReloadFromHtmlReader( SfxMedium& _rTmpMedium,
+ const OUString& _rFilename,
+ SwDoc* _pDoc )
+ : SwReader( _rTmpMedium, _rFilename, _pDoc )
+ {
+ SetBaseURL( _rFilename );
+ }
+};
+
+}
+
+void SwDocShell::ReloadFromHtml( const OUString& rStreamName, SwSrcView* pSrcView )
+{
+ bool bModified = IsModified();
+
+ // The HTTP-Header fields have to be removed, otherwise
+ // there are some from Meta-Tags duplicated or triplicated afterwards.
+ ClearHeaderAttributesForSourceViewHack();
+
+#if HAVE_FEATURE_SCRIPTING
+ // The Document-Basic also bites the dust ...
+ // A EnterBasicCall is not needed here, because nothing is called and
+ // there can't be any Dok-Basic, that has not yet been loaded inside
+ // of an HTML document.
+ //#59620# HasBasic() shows, that there already is a BasicManager at the DocShell.
+ // That was always generated in HTML-Import, when there are
+ // Macros in the source code.
+ if( officecfg::Office::Common::Filter::HTML::Export::Basic::get() && HasBasic())
+ {
+ BasicManager *pBasicMan = GetBasicManager();
+ if( pBasicMan && (pBasicMan != SfxApplication::GetBasicManager()) )
+ {
+ sal_uInt16 nLibCount = pBasicMan->GetLibCount();
+ while( nLibCount )
+ {
+ StarBASIC *pBasic = pBasicMan->GetLib( --nLibCount );
+ if( pBasic )
+ {
+ // Notify the IDE
+ SfxUnoAnyItem aShellItem( SID_BASICIDE_ARG_DOCUMENT_MODEL, Any( GetModel() ) );
+ OUString aLibName( pBasic->GetName() );
+ SfxStringItem aLibNameItem( SID_BASICIDE_ARG_LIBNAME, aLibName );
+ pSrcView->GetViewFrame().GetDispatcher()->ExecuteList(
+ SID_BASICIDE_LIBREMOVED,
+ SfxCallMode::SYNCHRON,
+ { &aShellItem, &aLibNameItem });
+
+ // Only the modules are deleted from the standard-lib
+ if( nLibCount )
+ pBasicMan->RemoveLib( nLibCount, true );
+ else
+ pBasic->Clear();
+ }
+ }
+
+ OSL_ENSURE( pBasicMan->GetLibCount() <= 1,
+ "Deleting Basics didn't work" );
+ }
+ }
+#endif
+ bool bWasBrowseMode = m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE);
+ RemoveLink();
+
+ // now also the UNO-Model has to be informed about the new Doc #51535#
+ uno::Reference<text::XTextDocument> xDoc(GetBaseModel(), uno::UNO_QUERY);
+ text::XTextDocument* pxDoc = xDoc.get();
+ static_cast<SwXTextDocument*>(pxDoc)->InitNewDoc();
+
+ AddLink();
+ //#116402# update font list when new document is created
+ UpdateFontList();
+ m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::BROWSE_MODE, bWasBrowseMode);
+ pSrcView->SetPool(&GetPool());
+
+ const OUString& rMedname = GetMedium()->GetName();
+
+ // The HTML template still has to be set
+ SetHTMLTemplate( *GetDoc() ); //Styles from HTML.vor
+
+ SfxViewShell* pViewShell = GetView() ? static_cast<SfxViewShell*>(GetView())
+ : SfxViewShell::Current();
+ SfxViewFrame& rViewFrame = pViewShell->GetViewFrame();
+ rViewFrame.GetDispatcher()->Execute( SID_VIEWSHELL0, SfxCallMode::SYNCHRON );
+
+ SubInitNew();
+
+ SfxMedium aMed( rStreamName, StreamMode::READ );
+ // #i48748# - use class <SwReloadFromHtmlReader>, because
+ // the base URL has to be set to the filename of the document <rMedname>
+ // and not to the base URL of the temporary file <aMed> in order to get
+ // the URLs of the linked graphics correctly resolved.
+ SwReloadFromHtmlReader aReader( aMed, rMedname, m_xDoc.get() );
+
+ aReader.Read( *ReadHTML );
+
+ const SwView* pCurrView = GetView();
+ //in print layout the first page(s) may have been formatted as a mix of browse
+ //and print layout
+ if(!bWasBrowseMode && pCurrView)
+ {
+ SwWrtShell& rWrtSh = pCurrView->GetWrtShell();
+ if( rWrtSh.GetLayout())
+ rWrtSh.InvalidateLayout( true );
+ }
+
+ // Take HTTP-Header-Attributes over into the DocInfo again.
+ // The Base-URL doesn't matter here because TLX uses the one from the document
+ // for absolutization.
+ SetHeaderAttributesForSourceViewHack();
+
+ if(bModified && !IsReadOnly())
+ SetModified();
+ else
+ m_xDoc->getIDocumentState().ResetModified();
+}
+
+ErrCodeMsg SwDocShell::LoadStylesFromFile(const OUString& rURL, SwgReaderOption& rOpt, bool bUnoCall)
+{
+ ErrCodeMsg nErr = ERRCODE_NONE;
+
+ // Set filter:
+ SfxFilterMatcher aMatcher( SwDocShell::Factory().GetFactoryName() );
+
+ // search for filter in WebDocShell, too
+ SfxMedium aMed( rURL, StreamMode::STD_READ );
+ if (rURL == "private:stream")
+ aMed.setStreamToLoadFrom(rOpt.GetInputStream(), true);
+ std::shared_ptr<const SfxFilter> pFlt;
+ aMatcher.DetectFilter( aMed, pFlt );
+ if(!pFlt)
+ {
+ SfxFilterMatcher aWebMatcher( SwWebDocShell::Factory().GetFactoryName() );
+ aWebMatcher.DetectFilter( aMed, pFlt );
+ }
+ // --> OD #i117339# - trigger import only for own formats
+ bool bImport( false );
+ if ( aMed.IsStorage() )
+ {
+ // As <SfxMedium.GetFilter().IsOwnFormat() resp. IsOwnTemplateFormat()
+ // does not work correct (e.g., MS Word 2007 XML Template),
+ // use workaround provided by MAV.
+ uno::Reference< embed::XStorage > xStorage = aMed.GetStorage();
+ if ( xStorage.is() )
+ {
+ // use <try-catch> on retrieving <MediaType> in order to check,
+ // if the storage is one of our own ones.
+ try
+ {
+ uno::Reference< beans::XPropertySet > xProps( xStorage, uno::UNO_QUERY_THROW );
+ xProps->getPropertyValue( "MediaType" );
+ bImport = true;
+ }
+ catch (const uno::Exception&)
+ {
+ bImport = false;
+ }
+ }
+ }
+ if ( bImport )
+ {
+ Reader* pRead = ReadXML;
+ SwReaderPtr pReader;
+ std::optional<SwPaM> pPam;
+ // the SW3IO - Reader need the pam/wrtshell, because only then he
+ // insert the styles!
+ if( bUnoCall )
+ {
+ SwNodeIndex aIdx( m_xDoc->GetNodes().GetEndOfContent(), -1 );
+ pPam.emplace( aIdx );
+ pReader.reset(new SwReader( aMed, rURL, *pPam ));
+ }
+ else
+ {
+ pReader.reset(new SwReader( aMed, rURL, *m_pWrtShell->GetCursor() ));
+ }
+
+ pRead->GetReaderOpt().SetTextFormats( rOpt.IsTextFormats() );
+ pRead->GetReaderOpt().SetFrameFormats( rOpt.IsFrameFormats() );
+ pRead->GetReaderOpt().SetPageDescs( rOpt.IsPageDescs() );
+ pRead->GetReaderOpt().SetNumRules( rOpt.IsNumRules() );
+ pRead->GetReaderOpt().SetMerge( rOpt.IsMerge() );
+
+ if( bUnoCall )
+ {
+ UnoActionContext aAction( m_xDoc.get() );
+ nErr = pReader->Read( *pRead );
+ }
+ else
+ {
+ m_pWrtShell->StartAllAction();
+ nErr = pReader->Read( *pRead );
+ m_pWrtShell->EndAllAction();
+ }
+ }
+
+ return nErr;
+}
+
+// Get a client for an embedded object if possible.
+SfxInPlaceClient* SwDocShell::GetIPClient( const ::svt::EmbeddedObjectRef& xObjRef )
+{
+ SfxInPlaceClient* pResult = nullptr;
+
+ SwWrtShell* pShell = GetWrtShell();
+ if ( pShell )
+ {
+ pResult = pShell->GetView().FindIPClient( xObjRef.GetObject(), &pShell->GetView().GetEditWin() );
+ if ( !pResult )
+ pResult = new SwOleClient( &pShell->GetView(), &pShell->GetView().GetEditWin(), xObjRef );
+ }
+
+ return pResult;
+}
+
+int SwFindDocShell( SfxObjectShellRef& xDocSh,
+ SfxObjectShellLock& xLockRef,
+ std::u16string_view rFileName,
+ const OUString& rPasswd,
+ const OUString& rFilter,
+ sal_Int16 nVersion,
+ SwDocShell* pDestSh )
+{
+ if ( rFileName.empty() )
+ return 0;
+
+ // 1. Does the file already exist in the list of all Documents?
+ INetURLObject aTmpObj( rFileName );
+ aTmpObj.SetMark( u"" );
+
+ // Iterate over the DocShell and get the ones with the name
+
+ SfxObjectShell* pShell = pDestSh;
+ bool bFirst = nullptr != pShell;
+
+ if( !bFirst )
+ // No DocShell passed, starting with the first from the DocShell list
+ pShell = SfxObjectShell::GetFirst( checkSfxObjectShell<SwDocShell> );
+
+ while( pShell )
+ {
+ // We want this one
+ SfxMedium* pMed = pShell->GetMedium();
+ if( pMed && pMed->GetURLObject() == aTmpObj )
+ {
+ const SfxPoolItem* pItem;
+ if( ( SfxItemState::SET == pMed->GetItemSet().GetItemState(
+ SID_VERSION, false, &pItem ) )
+ ? (nVersion == static_cast<const SfxInt16Item*>(pItem)->GetValue())
+ : !nVersion )
+ {
+ // Found, thus return
+ xDocSh = pShell;
+ return 1;
+ }
+ }
+
+ if( bFirst )
+ {
+ bFirst = false;
+ pShell = SfxObjectShell::GetFirst( checkSfxObjectShell<SwDocShell> );
+ }
+ else
+ pShell = SfxObjectShell::GetNext( *pShell, checkSfxObjectShell<SwDocShell> );
+ }
+
+ // 2. Open the file ourselves
+ std::unique_ptr<SfxMedium> xMed(new SfxMedium( aTmpObj.GetMainURL(
+ INetURLObject::DecodeMechanism::NONE ), StreamMode::READ ));
+ if( INetProtocol::File == aTmpObj.GetProtocol() )
+ xMed->Download(); // Touch the medium (download it)
+
+ std::shared_ptr<const SfxFilter> pSfxFlt;
+ if (!xMed->GetErrorIgnoreWarning())
+ {
+ SfxFilterMatcher aMatcher( rFilter == "writerglobal8"
+ ? SwGlobalDocShell::Factory().GetFactoryName()
+ : SwDocShell::Factory().GetFactoryName() );
+
+ // No Filter, so search for it. Else test if the one passed is a valid one
+ if( !rFilter.isEmpty() )
+ {
+ pSfxFlt = aMatcher.GetFilter4FilterName( rFilter );
+ }
+
+ if( nVersion )
+ xMed->GetItemSet().Put( SfxInt16Item( SID_VERSION, nVersion ));
+
+ if( !rPasswd.isEmpty() )
+ xMed->GetItemSet().Put( SfxStringItem( SID_PASSWORD, rPasswd ));
+
+ if( !pSfxFlt )
+ aMatcher.DetectFilter( *xMed, pSfxFlt );
+
+ if( pSfxFlt )
+ {
+ // We cannot do anything without a Filter
+ xMed->SetFilter( pSfxFlt );
+
+ // If the new shell is created, SfxObjectShellLock should be used to let it be closed later for sure
+ SwDocShell *const pNew(new SwDocShell(SfxObjectCreateMode::INTERNAL));
+ xLockRef = pNew;
+ xDocSh = static_cast<SfxObjectShell*>(xLockRef);
+ if (xDocSh->DoLoad(xMed.release()))
+ {
+ return 2;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/app/docshdrw.cxx b/sw/source/uibase/app/docshdrw.cxx
new file mode 100644
index 0000000000..f767191fbd
--- /dev/null
+++ b/sw/source/uibase/app/docshdrw.cxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svxids.hrc>
+#include <svx/drawitem.hxx>
+#include <svx/svdoutl.hxx>
+#include <svx/xtable.hxx>
+#include <unotools/configmgr.hxx>
+#include <docsh.hxx>
+#include <drawdoc.hxx>
+#include <swtypes.hxx>
+
+using namespace ::com::sun::star;
+
+// Load Document
+void InitDrawModelAndDocShell(SwDocShell* pSwDocShell, SwDrawModel* pSwDrawDocument)
+{
+ if(pSwDrawDocument)
+ {
+ if(pSwDocShell == pSwDrawDocument->GetObjectShell())
+ {
+ // association already done, nothing to do
+ }
+ else
+ {
+ // set object shell (mainly for FormControl stuff), maybe zero
+ pSwDrawDocument->SetObjectShell(pSwDocShell);
+
+ // set persist, maybe zero
+ pSwDrawDocument->SetPersist(pSwDocShell);
+
+ // get and decide on the color table to use
+ if(pSwDocShell)
+ {
+ const SvxColorListItem* pColItemFromDocShell = pSwDocShell->GetItem(SID_COLOR_TABLE);
+
+ if(pColItemFromDocShell)
+ {
+ // the DocShell has a ColorTable, use it also in DrawingLayer
+ const XColorListRef& xCol(pColItemFromDocShell->GetColorList());
+ pSwDrawDocument->SetPropertyList(static_cast<XPropertyList*>(xCol.get()));
+ }
+ else
+ {
+ // Use the ColorTable which is used at the DrawingLayer's SdrModel
+ XColorListRef xColorList = pSwDrawDocument->GetColorList();
+ if (xColorList.is())
+ {
+ pSwDocShell->PutItem(SvxColorListItem(xColorList, SID_COLOR_TABLE));
+ }
+ else if (!utl::ConfigManager::IsFuzzing())
+ {
+ // there wasn't one, get the standard and set to the
+ // docshell and then to the drawdocument
+ xColorList = XColorList::GetStdColorList();
+ pSwDocShell->PutItem(SvxColorListItem(xColorList, SID_COLOR_TABLE));
+ pSwDrawDocument->SetPropertyList(xColorList);
+ }
+ }
+
+ // add other tables in SfxItemSet of the DocShell
+ pSwDocShell->PutItem(SvxGradientListItem(pSwDrawDocument->GetGradientList(), SID_GRADIENT_LIST));
+ pSwDocShell->PutItem(SvxHatchListItem(pSwDrawDocument->GetHatchList(), SID_HATCH_LIST));
+ pSwDocShell->PutItem(SvxBitmapListItem(pSwDrawDocument->GetBitmapList(), SID_BITMAP_LIST));
+ pSwDocShell->PutItem(SvxPatternListItem(pSwDrawDocument->GetPatternList(), SID_PATTERN_LIST));
+ pSwDocShell->PutItem(SvxDashListItem(pSwDrawDocument->GetDashList(), SID_DASH_LIST));
+ pSwDocShell->PutItem(SvxLineEndListItem(pSwDrawDocument->GetLineEndList(), SID_LINEEND_LIST));
+ }
+
+ // init hyphenator for DrawingLayer outliner
+ uno::Reference<linguistic2::XHyphenator> xHyphenator(::GetHyphenator());
+ Outliner& rOutliner = pSwDrawDocument->GetDrawOutliner();
+
+ rOutliner.SetHyphenator(xHyphenator);
+ }
+ }
+ else if(pSwDocShell)
+ {
+ // fallback: add the default color list to have one when someone requests it from the DocShell
+ pSwDocShell->PutItem(SvxColorListItem(XColorList::GetStdColorList(), SID_COLOR_TABLE));
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/app/docshini.cxx b/sw/source/uibase/app/docshini.cxx
new file mode 100644
index 0000000000..5acee759db
--- /dev/null
+++ b/sw/source/uibase/app/docshini.cxx
@@ -0,0 +1,711 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <i18nlangtag/mslangid.hxx>
+#include <svtools/ctrltool.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/lingucfg.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/sfxmodelfactory.hxx>
+#include <sfx2/printer.hxx>
+#include <svl/asiancfg.hxx>
+#include <svl/intitem.hxx>
+#include <editeng/adjustitem.hxx>
+#include <editeng/autokernitem.hxx>
+#include <com/sun/star/document/UpdateDocMode.hpp>
+#include <com/sun/star/i18n/ScriptType.hpp>
+#include <svx/compatflags.hxx>
+#include <svx/svxids.hrc>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/flstitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/orphitem.hxx>
+#include <editeng/widwitem.hxx>
+#include <editeng/hyphenzoneitem.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <prtopt.hxx>
+#include <fmtcol.hxx>
+#include <docsh.hxx>
+#include <wdocsh.hxx>
+#include <swmodule.hxx>
+#include <doc.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentStylePoolAccess.hxx>
+#include <IDocumentChartDataProviderAccess.hxx>
+#include <IDocumentState.hxx>
+#include <docfac.hxx>
+#include <docstyle.hxx>
+#include <shellio.hxx>
+#include <swdtflvr.hxx>
+#include <usrpref.hxx>
+#include <fontcfg.hxx>
+#include <poolfmt.hxx>
+#include <globdoc.hxx>
+#include <unotxdoc.hxx>
+#include <linkenum.hxx>
+#include <swwait.hxx>
+#include <swerror.h>
+#include <unochart.hxx>
+#include <drawdoc.hxx>
+
+#include <svx/CommonStyleManager.hxx>
+
+#include <memory>
+
+#include <officecfg/Office/Common.hxx>
+
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+
+// Load Document
+bool SwDocShell::InitNew( const uno::Reference < embed::XStorage >& xStor )
+{
+ bool bRet = SfxObjectShell::InitNew( xStor );
+ OSL_ENSURE( GetMapUnit() == MapUnit::MapTwip, "map unit is not twip!" );
+ bool bHTMLTemplSet = false;
+ if( bRet )
+ {
+ AddLink(); // create m_xDoc / pIo if applicable
+
+ bool bWeb = dynamic_cast< const SwWebDocShell *>( this ) != nullptr;
+ if ( bWeb )
+ bHTMLTemplSet = SetHTMLTemplate( *GetDoc() );// Styles from HTML.vor
+ else if( dynamic_cast< const SwGlobalDocShell *>( this ) != nullptr )
+ GetDoc()->getIDocumentSettingAccess().set(DocumentSettingId::GLOBAL_DOCUMENT, true); // Globaldokument
+
+ if ( GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
+ SwTransferable::InitOle( this );
+
+ // set forbidden characters if necessary
+ const bool bFuzzing = utl::ConfigManager::IsFuzzing();
+ if (!bFuzzing)
+ {
+ SvxAsianConfig aAsian;
+ const Sequence<lang::Locale> aLocales = aAsian.GetStartEndCharLocales();
+ for(const lang::Locale& rLocale : aLocales)
+ {
+ ForbiddenCharacters aForbidden;
+ aAsian.GetStartEndChars( rLocale, aForbidden.beginLine, aForbidden.endLine);
+ LanguageType eLang = LanguageTag::convertToLanguageType(rLocale);
+ m_xDoc->getIDocumentSettingAccess().setForbiddenCharacters( eLang, aForbidden);
+ }
+ m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::KERN_ASIAN_PUNCTUATION,
+ !aAsian.IsKerningWesternTextOnly());
+ m_xDoc->getIDocumentSettingAccess().setCharacterCompressionType(aAsian.GetCharDistanceCompression());
+ m_xDoc->getIDocumentDeviceAccess().setPrintData(*SW_MOD()->GetPrtOptions(bWeb));
+ }
+
+ SubInitNew();
+
+ // for all
+
+ SwStdFontConfig* pStdFont = SW_MOD()->GetStdFontConfig();
+ SfxPrinter* pPrt = m_xDoc->getIDocumentDeviceAccess().getPrinter( false );
+
+ OUString sEntry;
+ static const sal_uInt16 aFontWhich[] =
+ { RES_CHRATR_FONT,
+ RES_CHRATR_CJK_FONT,
+ RES_CHRATR_CTL_FONT
+ };
+ static const sal_uInt16 aFontHeightWhich[] =
+ {
+ RES_CHRATR_FONTSIZE,
+ RES_CHRATR_CJK_FONTSIZE,
+ RES_CHRATR_CTL_FONTSIZE
+ };
+ static const sal_uInt16 aFontIds[] =
+ {
+ FONT_STANDARD,
+ FONT_STANDARD_CJK,
+ FONT_STANDARD_CTL
+ };
+ static const DefaultFontType nFontTypes[] =
+ {
+ DefaultFontType::LATIN_TEXT,
+ DefaultFontType::CJK_TEXT,
+ DefaultFontType::CTL_TEXT
+ };
+ static const sal_uInt16 aLangTypes[] =
+ {
+ RES_CHRATR_LANGUAGE,
+ RES_CHRATR_CJK_LANGUAGE,
+ RES_CHRATR_CTL_LANGUAGE
+ };
+
+ for(sal_uInt8 i = 0; i < 3; i++)
+ {
+ sal_uInt16 nFontWhich = aFontWhich[i];
+ sal_uInt16 nFontId = aFontIds[i];
+ std::unique_ptr<SvxFontItem> pFontItem;
+ const SvxLanguageItem& rLang = static_cast<const SvxLanguageItem&>(m_xDoc->GetDefault( aLangTypes[i] ));
+ LanguageType eLanguage = rLang.GetLanguage();
+ if(!pStdFont->IsFontDefault(nFontId))
+ {
+ sEntry = pStdFont->GetFontFor(nFontId);
+
+ vcl::Font aFont( sEntry, Size( 0, 10 ) );
+ if( pPrt )
+ {
+ aFont = pPrt->GetFontMetric( aFont );
+ }
+
+ pFontItem.reset(new SvxFontItem(aFont.GetFamilyType(), aFont.GetFamilyName(),
+ OUString(), aFont.GetPitch(), aFont.GetCharSet(), nFontWhich));
+ }
+ else
+ {
+ // #107782# OJ use korean language if latin was used
+ if ( i == 0 )
+ {
+ LanguageType eUiLanguage = Application::GetSettings().GetUILanguageTag().getLanguageType();
+ if (MsLangId::isKorean(eUiLanguage))
+ eLanguage = eUiLanguage;
+ }
+
+ vcl::Font aLangDefFont = OutputDevice::GetDefaultFont(
+ nFontTypes[i],
+ eLanguage,
+ GetDefaultFontFlags::OnlyOne );
+ pFontItem.reset(new SvxFontItem(aLangDefFont.GetFamilyType(), aLangDefFont.GetFamilyName(),
+ OUString(), aLangDefFont.GetPitch(), aLangDefFont.GetCharSet(), nFontWhich));
+ }
+ m_xDoc->SetDefault(*pFontItem);
+ if( !bHTMLTemplSet )
+ {
+ SwTextFormatColl *pColl = m_xDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_STANDARD);
+ pColl->ResetFormatAttr(nFontWhich);
+ }
+ pFontItem.reset();
+ sal_Int32 nFontHeight = pStdFont->GetFontHeight( FONT_STANDARD, i, eLanguage );
+ if(nFontHeight <= 0)
+ nFontHeight = SwStdFontConfig::GetDefaultHeightFor( nFontId, eLanguage );
+ m_xDoc->SetDefault(SvxFontHeightItem( nFontHeight, 100, aFontHeightWhich[i] ));
+ if( !bHTMLTemplSet )
+ {
+ SwTextFormatColl *pColl = m_xDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_STANDARD);
+ pColl->ResetFormatAttr(aFontHeightWhich[i]);
+ }
+
+ }
+ sal_uInt16 aFontIdPoolId[] =
+ {
+ FONT_OUTLINE, RES_POOLCOLL_HEADLINE_BASE,
+ FONT_LIST, RES_POOLCOLL_NUMBER_BULLET_BASE,
+ FONT_CAPTION, RES_POOLCOLL_LABEL,
+ FONT_INDEX, RES_POOLCOLL_REGISTER_BASE,
+ FONT_OUTLINE_CJK, RES_POOLCOLL_HEADLINE_BASE,
+ FONT_LIST_CJK, RES_POOLCOLL_NUMBER_BULLET_BASE,
+ FONT_CAPTION_CJK, RES_POOLCOLL_LABEL,
+ FONT_INDEX_CJK, RES_POOLCOLL_REGISTER_BASE,
+ FONT_OUTLINE_CTL, RES_POOLCOLL_HEADLINE_BASE,
+ FONT_LIST_CTL, RES_POOLCOLL_NUMBER_BULLET_BASE,
+ FONT_CAPTION_CTL, RES_POOLCOLL_LABEL,
+ FONT_INDEX_CTL, RES_POOLCOLL_REGISTER_BASE
+ };
+
+ TypedWhichId<SvxFontItem> nFontWhich = RES_CHRATR_FONT;
+ TypedWhichId<SvxFontHeightItem> nFontHeightWhich = RES_CHRATR_FONTSIZE;
+ LanguageType eLanguage = m_xDoc->GetDefault( RES_CHRATR_LANGUAGE ).GetLanguage();
+ bool bDisableBuiltinStyles = !bFuzzing && officecfg::Office::Common::Load::DisableBuiltinStyles::get();
+ sal_uInt8 nLimit = bDisableBuiltinStyles ? 0 : 24;
+ for(sal_uInt8 nIdx = 0; nIdx < nLimit; nIdx += 2)
+ {
+ if(nIdx == 8)
+ {
+ nFontWhich = RES_CHRATR_CJK_FONT;
+ nFontHeightWhich = RES_CHRATR_CJK_FONTSIZE;
+ eLanguage = m_xDoc->GetDefault( RES_CHRATR_CJK_LANGUAGE ).GetLanguage();
+ }
+ else if(nIdx == 16)
+ {
+ nFontWhich = RES_CHRATR_CTL_FONT;
+ nFontHeightWhich = RES_CHRATR_CTL_FONTSIZE;
+ eLanguage = m_xDoc->GetDefault( RES_CHRATR_CTL_LANGUAGE ).GetLanguage();
+ }
+ SwTextFormatColl *pColl = nullptr;
+ if(!pStdFont->IsFontDefault(aFontIdPoolId[nIdx]))
+ {
+ sEntry = pStdFont->GetFontFor(aFontIdPoolId[nIdx]);
+
+ vcl::Font aFont( sEntry, Size( 0, 10 ) );
+ if( pPrt )
+ aFont = pPrt->GetFontMetric( aFont );
+
+ pColl = m_xDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(aFontIdPoolId[nIdx + 1]);
+ if( !bHTMLTemplSet ||
+ SfxItemState::SET != pColl->GetAttrSet().GetItemState(
+ nFontWhich, false ) )
+ {
+ pColl->SetFormatAttr(SvxFontItem(aFont.GetFamilyType(), aFont.GetFamilyName(),
+ OUString(), aFont.GetPitch(), aFont.GetCharSet(), nFontWhich));
+ }
+ }
+ sal_Int32 nFontHeight = pStdFont->GetFontHeight( static_cast< sal_Int8 >(aFontIdPoolId[nIdx]), 0, eLanguage );
+ if(nFontHeight <= 0)
+ nFontHeight = SwStdFontConfig::GetDefaultHeightFor( aFontIdPoolId[nIdx], eLanguage );
+ if(!pColl)
+ pColl = m_xDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(aFontIdPoolId[nIdx + 1]);
+ SvxFontHeightItem aFontHeight( pColl->GetFormatAttr( nFontHeightWhich ) );
+ if(aFontHeight.GetHeight() != sal::static_int_cast<sal_uInt32, sal_Int32>(nFontHeight))
+ {
+ aFontHeight.SetHeight(nFontHeight);
+ pColl->SetFormatAttr( aFontHeight );
+ }
+ }
+
+ // the default for documents created via 'File/New' should be 'on'
+ // (old documents, where this property was not yet implemented, will get the
+ // value 'false' in the SwDoc c-tor)
+ m_xDoc->getIDocumentSettingAccess().set( DocumentSettingId::MATH_BASELINE_ALIGNMENT,
+ SW_MOD()->GetUsrPref( bWeb )->IsAlignMathObjectsToBaseline() );
+ m_xDoc->getIDocumentSettingAccess().set( DocumentSettingId::FOOTNOTE_IN_COLUMN_TO_PAGEEND, true);
+ }
+
+ /* #106748# If the default frame direction of a document is RTL
+ the default adjustment is to the right. */
+ if( !bHTMLTemplSet &&
+ SvxFrameDirection::Horizontal_RL_TB == GetDefaultFrameDirection(GetAppLanguage()) )
+ {
+ m_xDoc->SetDefault( SvxAdjustItem(SvxAdjust::Right, RES_PARATR_ADJUST ) );
+ }
+
+// #i29550#
+ m_xDoc->SetDefault( SfxBoolItem( RES_COLLAPSING_BORDERS, true ) );
+// <-- collapsing
+
+ //#i16874# AutoKerning as default for new documents
+ m_xDoc->SetDefault( SvxAutoKernItem( true, RES_CHRATR_AUTOKERN ) );
+
+ // #i42080# - Due to the several calls of method <SetDefault(..)>
+ // at the document instance, the document is modified. Thus, reset this
+ // status here. Note: In method <SubInitNew()> this is also done.
+ m_xDoc->getIDocumentState().ResetModified();
+
+ return bRet;
+}
+
+// Ctor with SfxCreateMode ?????
+SwDocShell::SwDocShell( SfxObjectCreateMode const eMode )
+ : SfxObjectShell(eMode)
+ , m_IsInUpdateFontList(false)
+ , m_pStyleManager(new svx::CommonStyleManager(*this))
+ , m_pView(nullptr)
+ , m_pWrtShell(nullptr)
+ , m_nUpdateDocMode(document::UpdateDocMode::ACCORDING_TO_CONFIG)
+ , m_IsATemplate(false)
+ , m_IsRemovedInvisibleContent(false)
+{
+ Init_Impl();
+}
+
+// Ctor / Dtor
+SwDocShell::SwDocShell( const SfxModelFlags i_nSfxCreationFlags )
+ : SfxObjectShell ( i_nSfxCreationFlags )
+ , m_IsInUpdateFontList(false)
+ , m_pStyleManager(new svx::CommonStyleManager(*this))
+ , m_pView(nullptr)
+ , m_pWrtShell(nullptr)
+ , m_nUpdateDocMode(document::UpdateDocMode::ACCORDING_TO_CONFIG)
+ , m_IsATemplate(false)
+ , m_IsRemovedInvisibleContent(false)
+{
+ Init_Impl();
+}
+
+// Ctor / Dtor
+SwDocShell::SwDocShell( SwDoc& rD, SfxObjectCreateMode const eMode )
+ : SfxObjectShell(eMode)
+ , m_xDoc(&rD)
+ , m_IsInUpdateFontList(false)
+ , m_pStyleManager(new svx::CommonStyleManager(*this))
+ , m_pView(nullptr)
+ , m_pWrtShell(nullptr)
+ , m_nUpdateDocMode(document::UpdateDocMode::ACCORDING_TO_CONFIG)
+ , m_IsATemplate(false)
+ , m_IsRemovedInvisibleContent(false)
+{
+ Init_Impl();
+}
+
+// Dtor
+SwDocShell::~SwDocShell()
+{
+ // disable chart related objects now because in ~SwDoc it may be too late for this
+ if (m_xDoc)
+ {
+ m_xDoc->getIDocumentChartDataProviderAccess().GetChartControllerHelper().Disconnect();
+ SwChartDataProvider *pPCD = m_xDoc->getIDocumentChartDataProviderAccess().GetChartDataProvider();
+ if (pPCD)
+ pPCD->dispose();
+ }
+
+ RemoveLink();
+ m_pFontList.reset();
+
+ // we, as BroadCaster also become our own Listener
+ // (for DocInfo/FileNames/...)
+ EndListening( *this );
+
+ m_pOLEChildList.reset();
+}
+
+void SwDocShell::Init_Impl()
+{
+ SetPool(&SW_MOD()->GetPool());
+ SetBaseModel(new SwXTextDocument(this));
+ // we, as BroadCaster also become our own Listener
+ // (for DocInfo/FileNames/...)
+ StartListening( *this );
+ //position of the "Automatic" style filter for the stylist (app.src)
+ SetAutoStyleFilterIndex(3);
+
+ // set map unit to twip
+ SetMapUnit( MapUnit::MapTwip );
+}
+
+void SwDocShell::AddLink()
+{
+ if (!m_xDoc)
+ {
+ SwDocFac aFactory;
+ m_xDoc = &aFactory.GetDoc();
+ m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE, dynamic_cast< const SwWebDocShell *>( this ) != nullptr );
+ }
+ m_xDoc->SetDocShell( this ); // set the DocShell-Pointer for Doc
+ uno::Reference< text::XTextDocument > xDoc(GetBaseModel(), uno::UNO_QUERY);
+ static_cast<SwXTextDocument*>(xDoc.get())->Reactivate(this);
+
+ SetPool(&m_xDoc->GetAttrPool());
+
+ // most suitably not until a sdbcx::View is created!!!
+ m_xDoc->SetOle2Link(LINK(this, SwDocShell, Ole2ModifiedHdl));
+}
+
+// create new FontList Change Printer
+void SwDocShell::UpdateFontList()
+{
+ if (!m_IsInUpdateFontList)
+ {
+ m_IsInUpdateFontList = true;
+ OSL_ENSURE(m_xDoc, "No Doc no FontList");
+ if (m_xDoc)
+ {
+ m_pFontList.reset( new FontList( m_xDoc->getIDocumentDeviceAccess().getReferenceDevice(true) ) );
+ PutItem( SvxFontListItem( m_pFontList.get(), SID_ATTR_CHAR_FONTLIST ) );
+ }
+ m_IsInUpdateFontList = false;
+ }
+}
+
+void SwDocShell::RemoveLink()
+{
+ // disconnect Uno-Object
+ uno::Reference< text::XTextDocument > xDoc(GetBaseModel(), uno::UNO_QUERY);
+ static_cast<SwXTextDocument*>(xDoc.get())->Invalidate();
+ if (m_xDoc)
+ {
+ if (m_xBasePool.is())
+ {
+ m_xBasePool->dispose();
+ m_xBasePool.clear();
+ }
+ m_xDoc->SetOle2Link(Link<bool,void>());
+ m_xDoc->SetDocShell( nullptr );
+ m_xDoc.clear(); // we don't have the Doc anymore!!
+ }
+}
+void SwDocShell::InvalidateModel()
+{
+ // disconnect Uno-Object
+ uno::Reference< text::XTextDocument > xDoc(GetBaseModel(), uno::UNO_QUERY);
+ static_cast<SwXTextDocument*>(xDoc.get())->Invalidate();
+}
+void SwDocShell::ReactivateModel()
+{
+ // disconnect Uno-Object
+ uno::Reference< text::XTextDocument > xDoc(GetBaseModel(), uno::UNO_QUERY);
+ static_cast<SwXTextDocument*>(xDoc.get())->Reactivate(this);
+}
+
+// Load, Default-Format
+bool SwDocShell::Load( SfxMedium& rMedium )
+{
+ bool bRet = false;
+
+ if (SfxObjectShell::Load(rMedium))
+ {
+ comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = getEmbeddedObjectContainer();
+ rEmbeddedObjectContainer.setUserAllowsLinkUpdate(false);
+
+ SAL_INFO( "sw.ui", "after SfxInPlaceObject::Load" );
+ if (m_xDoc) // for last version!!
+ RemoveLink(); // release the existing
+
+ AddLink(); // set Link and update Data!!
+
+ // Define some settings for legacy ODF files that have different default values now
+ // (if required, they will be overridden later when settings will be read)
+ if (IsOwnStorageFormat(rMedium))
+ {
+ SwDrawModel* pDrawModel = m_xDoc->getIDocumentDrawModelAccess().GetDrawModel();
+ if (pDrawModel)
+ {
+ pDrawModel->SetCompatibilityFlag(SdrCompatibilityFlag::AnchoredTextOverflowLegacy,
+ true); // legacy processing for tdf#99729
+ pDrawModel->SetCompatibilityFlag(SdrCompatibilityFlag::LegacyFontwork,
+ true); // legacy processing for tdf#148000
+ }
+ }
+
+ // Loading
+ // for MD
+ OSL_ENSURE( !m_xBasePool.is(), "who hasn't destroyed their Pool?" );
+ m_xBasePool = new SwDocStyleSheetPool( *m_xDoc, SfxObjectCreateMode::ORGANIZER == GetCreateMode() );
+ if(GetCreateMode() != SfxObjectCreateMode::ORGANIZER)
+ {
+ const SfxUInt16Item* pUpdateDocItem = rMedium.GetItemSet().GetItem(SID_UPDATEDOCMODE, false);
+ m_nUpdateDocMode = pUpdateDocItem ? pUpdateDocItem->GetValue() : document::UpdateDocMode::NO_UPDATE;
+ }
+
+ SwWait aWait( *this, true );
+ ErrCodeMsg nErr = ERR_SWG_READ_ERROR;
+ switch( GetCreateMode() )
+ {
+ case SfxObjectCreateMode::ORGANIZER:
+ {
+ if( ReadXML )
+ {
+ ReadXML->SetOrganizerMode( true );
+ SwReader aRdr(rMedium, OUString(), m_xDoc.get());
+ nErr = aRdr.Read( *ReadXML );
+ ReadXML->SetOrganizerMode( false );
+ }
+ }
+ break;
+
+ case SfxObjectCreateMode::INTERNAL:
+ case SfxObjectCreateMode::EMBEDDED:
+ {
+ SwTransferable::InitOle( this );
+ }
+ // suppress SfxProgress, when we are Embedded
+ SW_MOD()->SetEmbeddedLoadSave( true );
+ [[fallthrough]];
+
+ case SfxObjectCreateMode::STANDARD:
+ {
+ Reader *pReader = ReadXML;
+ if( pReader )
+ {
+ // set Doc's DocInfo at DocShell-Medium
+ SAL_INFO( "sw.ui", "before ReadDocInfo" );
+ SwReader aRdr(rMedium, OUString(), m_xDoc.get());
+ SAL_INFO( "sw.ui", "before Read" );
+ nErr = aRdr.Read( *pReader );
+ SAL_INFO( "sw.ui", "after Read" );
+ // If a XML document is loaded, the global doc/web doc
+ // flags have to be set, because they aren't loaded
+ // by this formats.
+ if( dynamic_cast< const SwWebDocShell *>( this ) != nullptr )
+ {
+ if (!m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE))
+ m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE, true);
+ }
+ if( dynamic_cast< const SwGlobalDocShell *>( this ) != nullptr )
+ {
+ if (!m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT))
+ m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::GLOBAL_DOCUMENT, true);
+ }
+ }
+ }
+ break;
+
+ default:
+ OSL_ENSURE( false, "Load: new CreateMode?" );
+ }
+
+ UpdateFontList();
+ InitDrawModelAndDocShell(this, m_xDoc ? m_xDoc->getIDocumentDrawModelAccess().GetDrawModel()
+ : nullptr);
+
+ SetError(nErr);
+ bRet = !nErr.IsError();
+
+ if (bRet && !m_xDoc->IsInLoadAsynchron() &&
+ GetCreateMode() == SfxObjectCreateMode::STANDARD)
+ {
+ LoadingFinished();
+ }
+
+ // suppress SfxProgress, when we are Embedded
+ SW_MOD()->SetEmbeddedLoadSave( false );
+ }
+
+ return bRet;
+}
+
+bool SwDocShell::LoadFrom( SfxMedium& rMedium )
+{
+ bool bRet = false;
+ if (m_xDoc)
+ RemoveLink();
+
+ AddLink(); // set Link and update Data!!
+
+ do { // middle check loop
+ ErrCodeMsg nErr = ERR_SWG_READ_ERROR;
+ OUString aStreamName = "styles.xml";
+ uno::Reference < container::XNameAccess > xAccess = rMedium.GetStorage();
+ if ( xAccess->hasByName( aStreamName ) && rMedium.GetStorage()->isStreamElement( aStreamName ) )
+ {
+ // Loading
+ SwWait aWait( *this, true );
+ {
+ OSL_ENSURE( !m_xBasePool.is(), "who hasn't destroyed their Pool?" );
+ m_xBasePool = new SwDocStyleSheetPool( *m_xDoc, SfxObjectCreateMode::ORGANIZER == GetCreateMode() );
+ if( ReadXML )
+ {
+ ReadXML->SetOrganizerMode( true );
+ SwReader aRdr(rMedium, OUString(), m_xDoc.get());
+ nErr = aRdr.Read( *ReadXML );
+ ReadXML->SetOrganizerMode( false );
+ }
+ }
+ }
+ else
+ {
+ OSL_FAIL("Code removed!");
+ }
+
+ SetError(nErr);
+ bRet = !nErr.IsError();
+
+ } while( false );
+
+ SfxObjectShell::LoadFrom( rMedium );
+ m_xDoc->getIDocumentState().ResetModified();
+ return bRet;
+}
+
+void SwDocShell::SubInitNew()
+{
+ OSL_ENSURE( !m_xBasePool.is(), "who hasn't destroyed their Pool?" );
+ m_xBasePool = new SwDocStyleSheetPool( *m_xDoc, SfxObjectCreateMode::ORGANIZER == GetCreateMode() );
+ UpdateFontList();
+ InitDrawModelAndDocShell(this, m_xDoc ? m_xDoc->getIDocumentDrawModelAccess().GetDrawModel() : nullptr);
+
+ m_xDoc->getIDocumentSettingAccess().setLinkUpdateMode( GLOBALSETTING );
+ m_xDoc->getIDocumentSettingAccess().setFieldUpdateFlags( AUTOUPD_GLOBALSETTING );
+
+ bool bWeb = dynamic_cast< const SwWebDocShell *>( this ) != nullptr;
+
+ static const WhichRangesContainer nRange1(svl::Items<
+ RES_CHRATR_COLOR, RES_CHRATR_COLOR,
+ RES_CHRATR_LANGUAGE, RES_CHRATR_LANGUAGE,
+ RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_LANGUAGE,
+ RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_LANGUAGE,
+ RES_PARATR_ADJUST, RES_PARATR_ADJUST
+ >);
+ static const WhichRangesContainer nRange2(svl::Items<
+ RES_CHRATR_COLOR, RES_CHRATR_COLOR,
+ RES_CHRATR_LANGUAGE, RES_CHRATR_LANGUAGE,
+ RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_LANGUAGE,
+ RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_LANGUAGE,
+ RES_PARATR_ADJUST, RES_PARATR_ADJUST,
+ RES_PARATR_TABSTOP, RES_PARATR_HYPHENZONE
+ >);
+ SfxItemSet aDfltSet( m_xDoc->GetAttrPool(), bWeb ? nRange1 : nRange2 );
+
+ //! get lingu options without loading lingu DLL
+ SvtLinguOptions aLinguOpt;
+
+ const bool bFuzzing = utl::ConfigManager::IsFuzzing();
+ if (!bFuzzing)
+ SvtLinguConfig().GetOptions(aLinguOpt);
+
+ LanguageType nVal = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage, css::i18n::ScriptType::LATIN),
+ eCJK = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage_CJK, css::i18n::ScriptType::ASIAN),
+ eCTL = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage_CTL, css::i18n::ScriptType::COMPLEX);
+ aDfltSet.Put( SvxLanguageItem( nVal, RES_CHRATR_LANGUAGE ) );
+ aDfltSet.Put( SvxLanguageItem( eCJK, RES_CHRATR_CJK_LANGUAGE ) );
+ aDfltSet.Put( SvxLanguageItem( eCTL, RES_CHRATR_CTL_LANGUAGE ) );
+
+ if(!bWeb)
+ {
+ SvxHyphenZoneItem aHyp( m_xDoc->GetDefault(RES_PARATR_HYPHENZONE) );
+ aHyp.GetMinLead() = static_cast< sal_uInt8 >(aLinguOpt.nHyphMinLeading);
+ aHyp.GetMinTrail() = static_cast< sal_uInt8 >(aLinguOpt.nHyphMinTrailing);
+ aHyp.GetMinWordLength() = static_cast< sal_uInt8 >(aLinguOpt.nHyphMinWordLength);
+
+ aDfltSet.Put( aHyp );
+
+ sal_uInt16 nNewPos = o3tl::toTwips(SW_MOD()->GetUsrPref(false)->GetDefTabInMm100(), o3tl::Length::mm100);
+ if( nNewPos )
+ aDfltSet.Put( SvxTabStopItem( 1, nNewPos,
+ SvxTabAdjust::Default, RES_PARATR_TABSTOP ) );
+ }
+ aDfltSet.Put( SvxColorItem( COL_AUTO, RES_CHRATR_COLOR ) );
+
+ m_xDoc->SetDefault( aDfltSet );
+
+ //default page mode for text grid
+ if(!bWeb)
+ {
+ bool bSquaredPageMode = SW_MOD()->GetUsrPref(false)->IsSquaredPageMode();
+ m_xDoc->SetDefaultPageMode( bSquaredPageMode );
+
+ // only set Widow/Orphan defaults on a new, non-web document - not an opened one
+ if (GetMedium() && GetMedium()->GetOrigURL().isEmpty() && !bFuzzing)
+ {
+ m_xDoc->SetDefault( SvxWidowsItem( sal_uInt8(2), RES_PARATR_WIDOWS) );
+ m_xDoc->SetDefault( SvxOrphansItem( sal_uInt8(2), RES_PARATR_ORPHANS) );
+ }
+ }
+
+ m_xDoc->getIDocumentState().ResetModified();
+}
+
+/*
+ * Document Interface Access
+ */
+IDocumentDeviceAccess& SwDocShell::getIDocumentDeviceAccess()
+{
+ return m_xDoc->getIDocumentDeviceAccess();
+}
+
+IDocumentChartDataProviderAccess& SwDocShell::getIDocumentChartDataProviderAccess()
+{
+ return m_xDoc->getIDocumentChartDataProviderAccess();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/app/docst.cxx b/sw/source/uibase/app/docst.cxx
new file mode 100644
index 0000000000..ba6c850a86
--- /dev/null
+++ b/sw/source/uibase/app/docst.cxx
@@ -0,0 +1,1693 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_wasm_strip.h>
+
+#include <memory>
+
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <comphelper/flagguard.hxx>
+#include <o3tl/any.hxx>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <hintids.hxx>
+#include <sfx2/styledlg.hxx>
+#include <svl/whiter.hxx>
+#include <sfx2/tplpitem.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/newstyle.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/stritem.hxx>
+#include <svl/ctloptions.hxx>
+#include <sfx2/htmlmode.hxx>
+#include <swmodule.hxx>
+#include <fchrfmt.hxx>
+#include <svx/xdef.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <SwRewriter.hxx>
+#include <numrule.hxx>
+#include <swundo.hxx>
+#include <svx/drawitem.hxx>
+#include <utility>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <docsh.hxx>
+#include <uitool.hxx>
+#include <cmdid.h>
+#include <viewopt.hxx>
+#include <doc.hxx>
+#include <drawdoc.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentFieldsAccess.hxx>
+#include <IDocumentState.hxx>
+#include <frmfmt.hxx>
+#include <charfmt.hxx>
+#include <poolfmt.hxx>
+#include <pagedesc.hxx>
+#include <docstyle.hxx>
+#include <uiitems.hxx>
+#include <fmtcol.hxx>
+#include <edtwin.hxx>
+#include <unochart.hxx>
+#include <swabstdlg.hxx>
+#include <tblafmt.hxx>
+#include <sfx2/watermarkitem.hxx>
+#include <svl/grabbagitem.hxx>
+#include <PostItMgr.hxx>
+#include <AnnotationWin.hxx>
+#include <SwUndoFmt.hxx>
+#include <strings.hrc>
+#include <AccessibilityCheck.hxx>
+#include <docmodel/theme/Theme.hxx>
+#include <svx/svdpage.hxx>
+#include <officecfg/Office/Common.hxx>
+
+using namespace ::com::sun::star;
+
+void SwDocShell::StateStyleSheet(SfxItemSet& rSet, SwWrtShell* pSh)
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ SfxStyleFamily nActualFamily = SfxStyleFamily(USHRT_MAX);
+
+ SwWrtShell* pShell = pSh ? pSh : GetWrtShell();
+ if(!pShell)
+ {
+ while (nWhich)
+ {
+ rSet.DisableItem(nWhich);
+ nWhich = aIter.NextWhich();
+ }
+ return;
+ }
+ else
+ {
+ SfxViewFrame& rFrame = pShell->GetView().GetViewFrame();
+ std::unique_ptr<SfxUInt16Item> pFamilyItem;
+ rFrame.GetBindings().QueryState(SID_STYLE_FAMILY, pFamilyItem);
+ if (pFamilyItem)
+ {
+ nActualFamily = static_cast<SfxStyleFamily>(pFamilyItem->GetValue());
+ }
+ }
+
+ while (nWhich)
+ {
+ // determine current template to every family
+ OUString aName;
+ SwTableAutoFormat aTableAutoFormat("dummy"); // needed to check if can take a table auto format at current cursor position
+ switch (nWhich)
+ {
+ case SID_STYLE_APPLY:
+ {// here the template and its family are passed to the StyleBox
+ // so that this family is being showed
+ if(pShell->IsFrameSelected())
+ {
+ SwFrameFormat* pFormat = pShell->GetSelectedFrameFormat();
+ if( pFormat )
+ aName = pFormat->GetName();
+ }
+ else if (pShell->GetSelectionType() == SelectionType::PostIt)
+ {
+ auto pStyle = pShell->GetPostItMgr()->GetActiveSidebarWin()->GetOutlinerView()->GetStyleSheet();
+ if (pStyle)
+ aName = pStyle->GetName();
+ }
+ else
+ {
+ SwTextFormatColl* pColl = pShell->GetCurTextFormatColl();
+ if(pColl)
+ aName = pColl->GetName();
+ }
+ rSet.Put(SfxTemplateItem(nWhich, aName));
+ }
+ break;
+ case SID_STYLE_FAMILY1:
+ if( !pShell->IsFrameSelected() )
+ {
+ SwCharFormat* pFormat = pShell->GetCurCharFormat();
+ if(pFormat)
+ aName = pFormat->GetName();
+ else
+ aName = SwResId(STR_POOLCHR_STANDARD);
+ rSet.Put(SfxTemplateItem(nWhich, aName));
+ }
+ break;
+
+ case SID_STYLE_FAMILY2:
+ if(!pShell->IsFrameSelected())
+ {
+ OUString aProgName;
+ if (pShell->GetSelectionType() == SelectionType::PostIt)
+ {
+ if (auto pStyle = pShell->GetPostItMgr()->GetActiveSidebarWin()->GetOutlinerView()->GetStyleSheet())
+ {
+ aName = pStyle->GetName();
+ aProgName = SwStyleNameMapper::GetProgName(aName, SwGetPoolIdFromName::TxtColl);
+ }
+ }
+ else if (auto pColl = pShell->GetCurTextFormatColl())
+ {
+ aName = pColl->GetName();
+ sal_uInt16 nId = pColl->GetPoolFormatId();
+ SwStyleNameMapper::FillProgName(nId, aProgName);
+ }
+
+ SfxTemplateItem aItem(nWhich, aName, aProgName);
+
+ SfxStyleSearchBits nMask = SfxStyleSearchBits::Auto;
+ if (m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE))
+ nMask = SfxStyleSearchBits::SwHtml;
+ else
+ {
+ const FrameTypeFlags nSelection = pShell->GetFrameType(nullptr,true);
+ if(pShell->GetCurTOX())
+ nMask = SfxStyleSearchBits::SwIndex ;
+ else if(nSelection & FrameTypeFlags::HEADER ||
+ nSelection & FrameTypeFlags::FOOTER ||
+ nSelection & FrameTypeFlags::TABLE ||
+ nSelection & FrameTypeFlags::FLY_ANY ||
+ nSelection & FrameTypeFlags::FOOTNOTE ||
+ nSelection & FrameTypeFlags::FTNPAGE)
+ nMask = SfxStyleSearchBits::SwExtra;
+ else
+ nMask = SfxStyleSearchBits::SwText;
+ }
+
+ aItem.SetValue(nMask);
+ rSet.Put(aItem);
+ }
+
+ break;
+
+ case SID_STYLE_FAMILY3:
+
+ if (m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE))
+ rSet.DisableItem( nWhich );
+ else
+ {
+ SwFrameFormat* pFormat = pShell->GetSelectedFrameFormat();
+ if(pFormat && pShell->IsFrameSelected())
+ {
+ aName = pFormat->GetName();
+ rSet.Put(SfxTemplateItem(nWhich, aName));
+ }
+ }
+ break;
+
+ case SID_STYLE_FAMILY4:
+ {
+ if (m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) && !officecfg::Office::Common::Filter::HTML::Export::PrintLayout::get())
+ rSet.DisableItem( nWhich );
+ else
+ {
+ size_t n = pShell->GetCurPageDesc( false );
+ if( n < pShell->GetPageDescCnt() )
+ aName = pShell->GetPageDesc( n ).GetName();
+
+ rSet.Put(SfxTemplateItem(nWhich, aName));
+ }
+ }
+ break;
+ case SID_STYLE_FAMILY5:
+ {
+ const SwNumRule* pRule = pShell->GetNumRuleAtCurrCursorPos();
+ if( pRule )
+ aName = pRule->GetName();
+
+ rSet.Put(SfxTemplateItem(nWhich, aName));
+ }
+ break;
+ case SID_STYLE_FAMILY6:
+ {
+ const SwTableNode *pTableNd = pShell->IsCursorInTable();
+ if( pTableNd )
+ aName = pTableNd->GetTable().GetTableStyleName();
+
+ rSet.Put(SfxTemplateItem(nWhich, aName));
+ }
+ break;
+
+ case SID_STYLE_WATERCAN:
+ {
+ SwEditWin& rEdtWin = pShell->GetView().GetEditWin();
+ SwApplyTemplate* pApply = rEdtWin.GetApplyTemplate();
+ rSet.Put(SfxBoolItem(nWhich, pApply && pApply->eType != SfxStyleFamily(0)));
+ }
+ break;
+ case SID_STYLE_UPDATE_BY_EXAMPLE:
+ if( pShell->IsFrameSelected()
+ ? SfxStyleFamily::Frame != nActualFamily
+ : ( SfxStyleFamily::Frame == nActualFamily ||
+ SfxStyleFamily::Page == nActualFamily ||
+ (SfxStyleFamily::Pseudo == nActualFamily && !pShell->GetNumRuleAtCurrCursorPos()) ||
+ (SfxStyleFamily::Table == nActualFamily && !pShell->GetTableAutoFormat(aTableAutoFormat))) )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case SID_STYLE_NEW_BY_EXAMPLE:
+ if( (pShell->IsFrameSelected()
+ ? SfxStyleFamily::Frame != nActualFamily
+ : SfxStyleFamily::Frame == nActualFamily) ||
+ (SfxStyleFamily::Pseudo == nActualFamily && !pShell->GetNumRuleAtCurrCursorPos()) ||
+ (SfxStyleFamily::Table == nActualFamily && !pShell->GetTableAutoFormat(aTableAutoFormat)) )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case SID_CLASSIFICATION_APPLY:
+ // Just trigger ClassificationCategoriesController::statusChanged().
+ rSet.InvalidateItem(nWhich);
+ break;
+ case SID_CLASSIFICATION_DIALOG:
+ rSet.InvalidateItem(nWhich);
+ break;
+ case SID_STYLE_EDIT:
+ break;
+ case SID_WATERMARK:
+ if (pSh)
+ {
+ SfxWatermarkItem aItem = pSh->GetWatermark();
+ rSet.Put(aItem);
+ }
+ break;
+ default:
+ OSL_FAIL("Invalid SlotId");
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+// evaluate StyleSheet-Requests
+void SwDocShell::ExecStyleSheet( SfxRequest& rReq )
+{
+ sal_uInt16 nSlot = rReq.GetSlot();
+
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem;
+ switch (nSlot)
+ {
+ case SID_STYLE_NEW:
+ if( pArgs && SfxItemState::SET == pArgs->GetItemState( SID_STYLE_FAMILY,
+ false, &pItem ))
+ {
+ const SfxStyleFamily nFamily = static_cast<SfxStyleFamily>(static_cast<const SfxUInt16Item*>(pItem)->GetValue());
+
+ OUString sName;
+ SfxStyleSearchBits nMask = SfxStyleSearchBits::Auto;
+ if( SfxItemState::SET == pArgs->GetItemState( SID_STYLE_NEW,
+ false, &pItem ))
+ sName = static_cast<const SfxStringItem*>(pItem)->GetValue();
+ if( SfxItemState::SET == pArgs->GetItemState( SID_STYLE_MASK,
+ false, &pItem ))
+ nMask = static_cast<SfxStyleSearchBits>(static_cast<const SfxUInt16Item*>(pItem)->GetValue());
+ OUString sParent;
+ if( SfxItemState::SET == pArgs->GetItemState( SID_STYLE_REFERENCE,
+ false, &pItem ))
+ sParent = static_cast<const SfxStringItem*>(pItem)->GetValue();
+
+ if (sName.isEmpty() && m_xBasePool)
+ sName = SfxStyleDialogController::GenerateUnusedName(*m_xBasePool, nFamily);
+
+ Edit(rReq.GetFrameWeld(), sName, sParent, nFamily, nMask, true, {}, nullptr, &rReq, nSlot);
+ }
+ break;
+
+ case SID_STYLE_APPLY:
+ if( !pArgs )
+ {
+ GetView()->GetViewFrame().GetDispatcher()->Execute(SID_STYLE_DESIGNER);
+ break;
+ }
+ else
+ {
+ // convert internal StyleName to DisplayName (slot implementation uses the latter)
+ const SfxStringItem* pNameItem = rReq.GetArg<SfxStringItem>(SID_APPLY_STYLE);
+ const SfxStringItem* pFamilyItem = rReq.GetArg<SfxStringItem>(SID_STYLE_FAMILYNAME);
+ if ( pFamilyItem && pNameItem )
+ {
+ uno::Reference< style::XStyleFamiliesSupplier > xModel(GetModel(), uno::UNO_QUERY);
+ try
+ {
+ uno::Reference< container::XNameAccess > xStyles;
+ uno::Reference< container::XNameAccess > xCont = xModel->getStyleFamilies();
+ xCont->getByName(pFamilyItem->GetValue()) >>= xStyles;
+ uno::Reference< beans::XPropertySet > xInfo;
+ xStyles->getByName( pNameItem->GetValue() ) >>= xInfo;
+ OUString aUIName;
+ xInfo->getPropertyValue("DisplayName") >>= aUIName;
+ if ( !aUIName.isEmpty() )
+ rReq.AppendItem( SfxStringItem( SID_STYLE_APPLY, aUIName ) );
+ }
+ catch (const uno::Exception&)
+ {
+ }
+ }
+ }
+
+ [[fallthrough]];
+
+ case SID_STYLE_EDIT:
+ case SID_STYLE_FONT:
+ case SID_STYLE_DELETE:
+ case SID_STYLE_HIDE:
+ case SID_STYLE_SHOW:
+ case SID_STYLE_WATERCAN:
+ case SID_STYLE_FAMILY:
+ case SID_STYLE_UPDATE_BY_EXAMPLE:
+ case SID_STYLE_NEW_BY_EXAMPLE:
+ {
+ OUString aParam;
+ SfxStyleFamily nFamily = SfxStyleFamily::Para;
+ SfxStyleSearchBits nMask = SfxStyleSearchBits::Auto;
+ SwWrtShell* pActShell = nullptr;
+
+ if( !pArgs )
+ {
+ switch (nSlot)
+ {
+ case SID_STYLE_NEW_BY_EXAMPLE:
+ {
+ SfxStyleSheetBasePool& rPool = *GetStyleSheetPool();
+ SfxNewStyleDlg aDlg(GetView()->GetFrameWeld(), rPool, nFamily);
+ if (aDlg.run() == RET_OK)
+ {
+ aParam = aDlg.GetName();
+ rReq.AppendItem(SfxStringItem(nSlot, aParam));
+ }
+ }
+ break;
+
+ case SID_STYLE_UPDATE_BY_EXAMPLE:
+ case SID_STYLE_EDIT:
+ {
+ if (GetWrtShell()->GetSelectionType() == SelectionType::PostIt)
+ {
+ auto pOLV = GetWrtShell()->GetPostItMgr()->GetActiveSidebarWin()->GetOutlinerView();
+ if (auto pStyle = pOLV->GetStyleSheet())
+ aParam = pStyle->GetName();
+ }
+ else if (auto pColl = GetWrtShell()->GetCurTextFormatColl())
+ aParam = pColl->GetName();
+
+ if (!aParam.isEmpty())
+ rReq.AppendItem(SfxStringItem(nSlot, aParam));
+ }
+ break;
+ }
+ }
+ else
+ {
+ SAL_WARN_IF( !pArgs->Count(), "sw.ui", "SfxBug ItemSet is empty" );
+
+ SwWrtShell* pShell = GetWrtShell();
+ if( SfxItemState::SET == pArgs->GetItemState(nSlot, false, &pItem ))
+ aParam = static_cast<const SfxStringItem*>(pItem)->GetValue();
+
+ if( SfxItemState::SET == pArgs->GetItemState(SID_STYLE_FAMILY,
+ false, &pItem ))
+ nFamily = static_cast<SfxStyleFamily>(static_cast<const SfxUInt16Item*>(pItem)->GetValue());
+
+ if( SfxItemState::SET == pArgs->GetItemState(SID_STYLE_FAMILYNAME, false, &pItem ))
+ {
+ OUString aFamily = static_cast<const SfxStringItem*>(pItem)->GetValue();
+ if(aFamily == "CharacterStyles")
+ nFamily = SfxStyleFamily::Char;
+ else
+ if(aFamily == "ParagraphStyles")
+ nFamily = SfxStyleFamily::Para;
+ else
+ if(aFamily == "PageStyles")
+ nFamily = SfxStyleFamily::Page;
+ else
+ if(aFamily == "FrameStyles")
+ nFamily = SfxStyleFamily::Frame;
+ else
+ if(aFamily == "NumberingStyles")
+ nFamily = SfxStyleFamily::Pseudo;
+ else
+ if(aFamily == "TableStyles")
+ nFamily = SfxStyleFamily::Table;
+ }
+
+ if( SfxItemState::SET == pArgs->GetItemState(SID_STYLE_MASK,
+ false, &pItem ))
+ nMask = static_cast<SfxStyleSearchBits>(static_cast<const SfxUInt16Item*>(pItem)->GetValue());
+ if( const SwPtrItem* pShellItem = pArgs->GetItemIfSet(FN_PARAM_WRTSHELL, false ))
+ pActShell = pShell = static_cast<SwWrtShell*>(pShellItem->GetValue());
+
+ if( nSlot == SID_STYLE_UPDATE_BY_EXAMPLE && aParam.isEmpty() )
+ {
+ switch( nFamily )
+ {
+ case SfxStyleFamily::Para:
+ {
+ SwTextFormatColl* pColl = pShell->GetCurTextFormatColl();
+ if(pColl)
+ aParam = pColl->GetName();
+ }
+ break;
+ case SfxStyleFamily::Frame:
+ {
+ SwFrameFormat* pFrame = m_pWrtShell->GetSelectedFrameFormat();
+ if( pFrame )
+ aParam = pFrame->GetName();
+ }
+ break;
+ case SfxStyleFamily::Char:
+ {
+ SwCharFormat* pChar = m_pWrtShell->GetCurCharFormat();
+ if( pChar )
+ aParam = pChar->GetName();
+ }
+ break;
+ case SfxStyleFamily::Pseudo:
+ if(const SfxStringItem* pExName = pArgs->GetItemIfSet(SID_STYLE_UPD_BY_EX_NAME, false))
+ {
+ aParam = pExName->GetValue();
+ }
+ break;
+ case SfxStyleFamily::Table:
+ if(const SfxStringItem* pExName = pArgs->GetItemIfSet(SID_STYLE_UPD_BY_EX_NAME, false))
+ {
+ aParam = pExName->GetValue();
+ }
+ break;
+ default: break;
+ }
+ rReq.AppendItem(SfxStringItem(nSlot, aParam));
+ }
+ }
+ if (!aParam.isEmpty() || nSlot == SID_STYLE_WATERCAN )
+ {
+ sal_uInt16 nRet = 0xffff;
+ bool bReturns = false;
+
+ switch(nSlot)
+ {
+ case SID_STYLE_EDIT:
+ case SID_STYLE_FONT:
+ Edit(rReq.GetFrameWeld(), aParam, {}, nFamily, nMask, false, (nSlot == SID_STYLE_FONT) ? "font" : OUString(), pActShell);
+ break;
+ case SID_STYLE_DELETE:
+ Delete(aParam, nFamily);
+ break;
+ case SID_STYLE_HIDE:
+ case SID_STYLE_SHOW:
+ Hide(aParam, nFamily, nSlot == SID_STYLE_HIDE);
+ break;
+ case SID_STYLE_APPLY:
+ // Shell-switch in ApplyStyles
+ nRet = static_cast<sal_uInt16>(ApplyStyles(aParam, nFamily, pActShell, rReq.GetModifier() ));
+ bReturns = true;
+ break;
+ case SID_STYLE_WATERCAN:
+ nRet = static_cast<sal_uInt16>(DoWaterCan(aParam, nFamily));
+ bReturns = true;
+ break;
+ case SID_STYLE_UPDATE_BY_EXAMPLE:
+ UpdateStyle(aParam, nFamily, pActShell);
+ break;
+ case SID_STYLE_NEW_BY_EXAMPLE:
+ MakeByExample(aParam, nFamily, nMask, pActShell);
+ break;
+
+ default:
+ OSL_FAIL("Invalid SlotId");
+ }
+
+ // Update formatting toolbar buttons status
+ if (GetWrtShell()->GetSelectionType() == SelectionType::PostIt)
+ GetView()->GetViewFrame().GetBindings().InvalidateAll(false);
+
+ if (bReturns)
+ {
+ if(rReq.IsAPI()) // Basic only gets TRUE or FALSE
+ rReq.SetReturnValue(SfxUInt16Item(nSlot, sal_uInt16(nRet !=0)));
+ else
+ rReq.SetReturnValue(SfxUInt16Item(nSlot, nRet));
+ }
+
+ rReq.Done();
+ }
+
+ break;
+ }
+ }
+}
+
+namespace {
+
+class ApplyStyle
+{
+public:
+ ApplyStyle(SwDocShell &rDocSh, bool bNew,
+ rtl::Reference< SwDocStyleSheet > xTmp,
+ SfxStyleFamily nFamily, SfxAbstractApplyTabDialog *pDlg,
+ rtl::Reference< SfxStyleSheetBasePool > xBasePool,
+ bool bModified)
+ : m_pDlg(pDlg)
+ , m_rDocSh(rDocSh)
+ , m_bNew(bNew)
+ , m_xTmp(std::move(xTmp))
+ , m_nFamily(nFamily)
+ , m_xBasePool(std::move(xBasePool))
+ , m_bModified(bModified)
+ {
+ }
+ DECL_LINK( ApplyHdl, LinkParamNone*, void );
+ void apply()
+ {
+ ApplyHdl(nullptr);
+ }
+ VclPtr<SfxAbstractApplyTabDialog> m_pDlg;
+ // true if the document was initially modified before ApplyStyle was created
+ // or if ApplyStyle:::apply was called
+ bool DocIsModified() const
+ {
+ return m_bModified;
+ }
+private:
+ SwDocShell &m_rDocSh;
+ bool m_bNew;
+ rtl::Reference< SwDocStyleSheet > m_xTmp;
+ SfxStyleFamily m_nFamily;
+ rtl::Reference< SfxStyleSheetBasePool > m_xBasePool;
+ bool m_bModified;
+};
+
+}
+
+IMPL_LINK_NOARG(ApplyStyle, ApplyHdl, LinkParamNone*, void)
+{
+ SwWrtShell* pWrtShell = m_rDocSh.GetWrtShell();
+ SwDoc* pDoc = m_rDocSh.GetDoc();
+ SwView* pView = m_rDocSh.GetView();
+
+ pWrtShell->StartAllAction();
+
+ if( SfxStyleFamily::Para == m_nFamily )
+ {
+ SfxItemSet aSet( *m_pDlg->GetOutputItemSet() );
+ ::ConvertAttrGenToChar(aSet, m_xTmp->GetItemSet(), /*bIsPara=*/true);
+ ::SfxToSwPageDescAttr( *pWrtShell, aSet );
+ // reset indent attributes at paragraph style, if a list style
+ // will be applied and no indent attributes will be applied.
+ m_xTmp->SetItemSet( aSet, false, true );
+ }
+ else
+ {
+ if(SfxStyleFamily::Page == m_nFamily || SfxStyleFamily::Frame == m_nFamily)
+ {
+ static const sal_uInt16 aInval[] = {
+ SID_IMAGE_ORIENTATION,
+ SID_ATTR_CHAR_FONT,
+ FN_INSERT_CTRL, FN_INSERT_OBJ_CTRL,
+ FN_TABLE_INSERT_COL_BEFORE,
+ FN_TABLE_INSERT_COL_AFTER, 0};
+ pView->GetViewFrame().GetBindings().Invalidate(aInval);
+ }
+ SfxItemSet aTmpSet( *m_pDlg->GetOutputItemSet() );
+ if( SfxStyleFamily::Char == m_nFamily )
+ {
+ ::ConvertAttrGenToChar(aTmpSet, m_xTmp->GetItemSet());
+ }
+
+ m_xTmp->SetItemSet( aTmpSet, false );
+
+ if( SfxStyleFamily::Page == m_nFamily && SvtCTLOptions::IsCTLFontEnabled() )
+ {
+ const SfxPoolItem *pItem = nullptr;
+ if( aTmpSet.GetItemState( m_rDocSh.GetPool().GetTrueWhich( SID_ATTR_FRAMEDIRECTION, false ) , true, &pItem ) == SfxItemState::SET )
+ SwChartHelper::DoUpdateAllCharts( pDoc );
+ }
+
+ if (m_nFamily == SfxStyleFamily::Page)
+ {
+ if (const SfxGrabBagItem* pGrabBagItem = aTmpSet.GetItemIfSet(SID_ATTR_CHAR_GRABBAG))
+ {
+ bool bGutterAtTop{};
+ auto it = pGrabBagItem->GetGrabBag().find("GutterAtTop");
+ if (it != pGrabBagItem->GetGrabBag().end())
+ {
+ it->second >>= bGutterAtTop;
+ }
+ bool bOldGutterAtTop
+ = pDoc->getIDocumentSettingAccess().get(DocumentSettingId::GUTTER_AT_TOP);
+ if (bOldGutterAtTop != bGutterAtTop)
+ {
+ pDoc->getIDocumentSettingAccess().set(DocumentSettingId::GUTTER_AT_TOP,
+ bGutterAtTop);
+ pWrtShell->InvalidateLayout(/*bSizeChanged=*/true);
+ }
+ }
+ }
+
+ if (m_nFamily == SfxStyleFamily::Frame)
+ {
+ if (const SfxBoolItem* pBoolItem = aTmpSet.GetItemIfSet(FN_KEEP_ASPECT_RATIO))
+ {
+ const SwViewOption* pVOpt = pWrtShell->GetViewOptions();
+ SwViewOption aUsrPref(*pVOpt);
+ aUsrPref.SetKeepRatio(pBoolItem->GetValue());
+ if (pBoolItem->GetValue() != pVOpt->IsKeepRatio())
+ {
+ SW_MOD()->ApplyUsrPref(aUsrPref, &pWrtShell->GetView());
+ }
+ }
+ }
+ }
+
+ if(m_bNew)
+ {
+ if(SfxStyleFamily::Frame == m_nFamily || SfxStyleFamily::Para == m_nFamily)
+ {
+ // clear FillStyle so that it works as a derived attribute
+ SfxItemSet aTmpSet(*m_pDlg->GetOutputItemSet());
+
+ aTmpSet.ClearItem(XATTR_FILLSTYLE);
+ m_xTmp->SetItemSet(aTmpSet, false);
+ }
+ }
+
+ if(SfxStyleFamily::Page == m_nFamily)
+ pView->InvalidateRulerPos();
+
+ if( m_bNew )
+ m_xBasePool->Broadcast(SfxStyleSheetHint(SfxHintId::StyleSheetCreated, *m_xTmp));
+ else
+ m_xBasePool->Broadcast(SfxStyleSheetHint(SfxHintId::StyleSheetModified, *m_xTmp));
+
+ pDoc->getIDocumentState().SetModified();
+ if( !m_bModified )
+ {
+ pDoc->GetIDocumentUndoRedo().SetUndoNoResetModified();
+ m_bModified = true;
+ }
+
+ pWrtShell->EndAllAction();
+}
+
+namespace
+{
+/// Checks if there is an Endnote page style in use, and makes sure it has the same orientation
+/// with the Default (Standard) page style.
+void syncEndnoteOrientation(const uno::Reference< style::XStyleFamiliesSupplier >& xStyleFamSupp)
+{
+ if (!xStyleFamSupp.is())
+ {
+ SAL_WARN("sw.ui", "Ref to XStyleFamiliesSupplier is null.");
+ return;
+ }
+ uno::Reference<container::XNameAccess> xStyleFamilies = xStyleFamSupp->getStyleFamilies();
+
+ if (!xStyleFamilies.is())
+ return;
+
+ uno::Reference<container::XNameAccess> xPageStyles(xStyleFamilies->getByName("PageStyles"),
+ uno::UNO_QUERY);
+
+ if (!xPageStyles.is())
+ return;
+
+ uno::Reference<css::style::XStyle> xEndnotePageStyle(xPageStyles->getByName("Endnote"),
+ uno::UNO_QUERY);
+
+ if (!xEndnotePageStyle.is())
+ return;
+
+ // Language-independent name of the "Default Style" is "Standard"
+ uno::Reference<css::style::XStyle> xDefaultPageStyle(xPageStyles->getByName("Standard"),
+ uno::UNO_QUERY);
+ if (!xDefaultPageStyle.is())
+ return;
+
+ if (xEndnotePageStyle->isUserDefined() || !xEndnotePageStyle->isInUse())
+ return;
+
+ uno::Reference<beans::XPropertySet> xEndnotePagePropSet(xPageStyles->getByName("Endnote"), uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xDefaultPagePropSet(xPageStyles->getByName("Standard"), uno::UNO_QUERY);
+
+ if (!xEndnotePagePropSet.is() || !xDefaultPagePropSet.is())
+ {
+ SAL_WARN("sw.ui", "xEndnotePagePropSet or xDefaultPagePropSet is null.");
+ return;
+ }
+
+ auto const bIsDefLandScape = *o3tl::doAccess<bool>(
+ xDefaultPagePropSet->getPropertyValue("IsLandscape"));
+ auto const bIsEndLandScape = *o3tl::doAccess<bool>(
+ xEndnotePagePropSet->getPropertyValue("IsLandscape"));
+
+ if (bIsDefLandScape == bIsEndLandScape)
+ return;
+
+ auto const nWidth = xEndnotePagePropSet->getPropertyValue("Width");
+ auto const nHeight = xEndnotePagePropSet->getPropertyValue("Height");
+
+ xEndnotePagePropSet->setPropertyValue("IsLandscape", css::uno::toAny(bIsDefLandScape));
+ xEndnotePagePropSet->setPropertyValue("Width", nHeight);
+ xEndnotePagePropSet->setPropertyValue("Height", nWidth);
+}
+}
+
+void SwDocShell::Edit(
+ weld::Window* pDialogParent,
+ const OUString &rName,
+ const OUString &rParent,
+ const SfxStyleFamily nFamily,
+ SfxStyleSearchBits nMask,
+ const bool bNew,
+ const OUString& sPage,
+ SwWrtShell* pActShell,
+ SfxRequest* pReq,
+ sal_uInt16 nSlot)
+{
+ assert( GetWrtShell() );
+ const bool bBasic = pReq && pReq->IsAPI();
+ SfxStyleSheetBase *pStyle = nullptr;
+
+ bool bModified = m_xDoc->getIDocumentState().IsModified();
+
+ SwUndoId nNewStyleUndoId(SwUndoId::EMPTY);
+
+ if( bNew )
+ {
+ if (!bBasic)
+ {
+ // start undo action in order to get only one undo action for the
+ // UI new style + change style operations
+ m_pWrtShell->StartUndo();
+ }
+
+ if( SfxStyleSearchBits::All != nMask && SfxStyleSearchBits::AllVisible != nMask && SfxStyleSearchBits::Used != nMask )
+ nMask |= SfxStyleSearchBits::UserDefined;
+ else
+ nMask = SfxStyleSearchBits::UserDefined;
+
+ if ( nFamily == SfxStyleFamily::Para || nFamily == SfxStyleFamily::Char || nFamily == SfxStyleFamily::Frame )
+ {
+ // Prevent undo append from being done during paragraph, character, and frame style Make
+ // Do it after ok return from style dialog when derived from style is known
+ ::sw::UndoGuard const undoGuard(GetDoc()->GetIDocumentUndoRedo());
+ pStyle = &m_xBasePool->Make( rName, nFamily, nMask );
+ }
+ else
+ {
+ pStyle = &m_xBasePool->Make( rName, nFamily, nMask );
+ }
+
+ // set the current one as Parent
+ SwDocStyleSheet* pDStyle = static_cast<SwDocStyleSheet*>(pStyle);
+ switch( nFamily )
+ {
+ case SfxStyleFamily::Para:
+ {
+ if(!rParent.isEmpty())
+ {
+ SwTextFormatColl* pColl = m_pWrtShell->FindTextFormatCollByName( rParent );
+ if(!pColl)
+ {
+ sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(rParent, SwGetPoolIdFromName::TxtColl);
+ if(USHRT_MAX != nId)
+ pColl = m_pWrtShell->GetTextCollFromPool( nId );
+ }
+ pDStyle->GetCollection()->SetDerivedFrom( pColl );
+ pDStyle->PresetParent( rParent );
+ }
+ else
+ {
+ SwTextFormatColl* pColl = m_pWrtShell->GetCurTextFormatColl();
+ pDStyle->GetCollection()->SetDerivedFrom( pColl );
+ if( pColl )
+ pDStyle->PresetParent( pColl->GetName() );
+ }
+ }
+ break;
+ case SfxStyleFamily::Char:
+ {
+ if(!rParent.isEmpty())
+ {
+ SwCharFormat* pCFormat = m_pWrtShell->FindCharFormatByName(rParent);
+ if(!pCFormat)
+ {
+ sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(rParent, SwGetPoolIdFromName::ChrFmt);
+ if(USHRT_MAX != nId)
+ pCFormat = m_pWrtShell->GetCharFormatFromPool( nId );
+ }
+
+ pDStyle->GetCharFormat()->SetDerivedFrom( pCFormat );
+ pDStyle->PresetParent( rParent );
+ }
+ else
+ {
+ SwCharFormat* pCFormat = m_pWrtShell->GetCurCharFormat();
+ pDStyle->GetCharFormat()->SetDerivedFrom( pCFormat );
+ if( pCFormat )
+ pDStyle->PresetParent( pCFormat->GetName() );
+ }
+ }
+ break;
+ case SfxStyleFamily::Frame :
+ {
+ if(!rParent.isEmpty())
+ {
+ SwFrameFormat* pFFormat = m_pWrtShell->GetDoc()->FindFrameFormatByName( rParent );
+ if(!pFFormat)
+ {
+ sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(rParent, SwGetPoolIdFromName::FrmFmt);
+ if(USHRT_MAX != nId)
+ pFFormat = m_pWrtShell->GetFrameFormatFromPool( nId );
+ }
+ pDStyle->GetFrameFormat()->SetDerivedFrom( pFFormat );
+ pDStyle->PresetParent( rParent );
+ }
+ }
+ break;
+ default: break;
+ }
+
+ if (!bBasic)
+ {
+ //Get the undo id for the type of style that was created in order to re-use that comment for the grouped
+ //create style + change style operations
+ m_pWrtShell->GetLastUndoInfo(nullptr, &nNewStyleUndoId);
+ }
+ }
+ else
+ {
+ pStyle = m_xBasePool->Find( rName, nFamily );
+ SAL_WARN_IF( !pStyle, "sw.ui", "Style not found" );
+ }
+
+ if(!pStyle)
+ return;
+
+ // put dialogues together
+ rtl::Reference< SwDocStyleSheet > xTmp( new SwDocStyleSheet( *static_cast<SwDocStyleSheet*>(pStyle) ) );
+ if( SfxStyleFamily::Para == nFamily )
+ {
+ SfxItemSet& rSet = xTmp->GetItemSet();
+ ::SwToSfxPageDescAttr( rSet );
+ // merge list level indent attributes into the item set if needed
+ xTmp->MergeIndentAttrsOfListStyle( rSet );
+
+ ::ConvertAttrCharToGen(xTmp->GetItemSet(), /*bIsPara=*/true);
+ }
+ else if( SfxStyleFamily::Char == nFamily )
+ {
+ ::ConvertAttrCharToGen(xTmp->GetItemSet());
+ }
+
+ if(SfxStyleFamily::Page == nFamily || SfxStyleFamily::Para == nFamily)
+ {
+ // create needed items for XPropertyList entries from the DrawModel so that
+ // the Area TabPage can access them
+ SfxItemSet& rSet = xTmp->GetItemSet();
+ const SwDrawModel* pDrawModel = GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
+
+ rSet.Put(SvxColorListItem(pDrawModel->GetColorList(), SID_COLOR_TABLE));
+ rSet.Put(SvxGradientListItem(pDrawModel->GetGradientList(), SID_GRADIENT_LIST));
+ rSet.Put(SvxHatchListItem(pDrawModel->GetHatchList(), SID_HATCH_LIST));
+ rSet.Put(SvxBitmapListItem(pDrawModel->GetBitmapList(), SID_BITMAP_LIST));
+ rSet.Put(SvxPatternListItem(pDrawModel->GetPatternList(), SID_PATTERN_LIST));
+
+ std::optional<SfxGrabBagItem> oGrabBag;
+ if (SfxGrabBagItem const* pItem = rSet.GetItemIfSet(SID_ATTR_CHAR_GRABBAG))
+ {
+ oGrabBag.emplace(*pItem);
+ }
+ else
+ {
+ oGrabBag.emplace(SID_ATTR_CHAR_GRABBAG);
+ }
+ bool bGutterAtTop
+ = GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::GUTTER_AT_TOP);
+ oGrabBag->GetGrabBag()["GutterAtTop"] <<= bGutterAtTop;
+ rSet.Put(*oGrabBag);
+ }
+
+ SwWrtShell* pCurrShell = pActShell ? pActShell : m_pWrtShell;
+ if (nFamily == SfxStyleFamily::Frame)
+ {
+ SfxItemSet& rSet = xTmp->GetItemSet();
+ const SwViewOption* pVOpt = pCurrShell->GetViewOptions();
+ rSet.Put(SfxBoolItem(FN_KEEP_ASPECT_RATIO, pVOpt->IsKeepRatio()));
+ }
+
+ if (!bBasic)
+ {
+ // prior to the dialog the HtmlMode at the DocShell is being sunk
+ sal_uInt16 nHtmlMode = ::GetHtmlMode(this);
+
+ // In HTML mode, we do not always have a printer. In order to show
+ // the correct page size in the Format - Page dialog, we have to
+ // get one here.
+ if( ( HTMLMODE_ON & nHtmlMode ) &&
+ !pCurrShell->getIDocumentDeviceAccess().getPrinter( false ) )
+ pCurrShell->InitPrt( pCurrShell->getIDocumentDeviceAccess().getPrinter( true ) );
+
+ PutItem(SfxUInt16Item(SID_HTML_MODE, nHtmlMode));
+ FieldUnit eMetric = ::GetDfltMetric(0 != (HTMLMODE_ON&nHtmlMode));
+ SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)));
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ if (!pDialogParent)
+ {
+ SAL_WARN("sw.ui", "no parent for dialog supplied, assuming document frame is good enough");
+ pDialogParent = GetView()->GetFrameWeld();
+ }
+ VclPtr<SfxAbstractApplyTabDialog> pDlg(pFact->CreateTemplateDialog(pDialogParent,
+ *xTmp, nFamily, sPage, pCurrShell, bNew));
+ auto pApplyStyleHelper = std::make_shared<ApplyStyle>(*this, bNew, xTmp, nFamily, pDlg.get(), m_xBasePool, bModified);
+ pDlg->SetApplyHdl(LINK(pApplyStyleHelper.get(), ApplyStyle, ApplyHdl));
+
+ std::shared_ptr<SfxRequest> pRequest;
+ if (pReq)
+ {
+ pRequest = std::make_shared<SfxRequest>(*pReq);
+ pReq->Ignore(); // the 'old' request is not relevant any more
+ }
+
+ bool bIsDefaultPage = nFamily == SfxStyleFamily::Page
+ && rName == SwResId(STR_POOLPAGE_STANDARD)
+ && pStyle->IsUsed()
+ && !pStyle->IsUserDefined();
+
+ pDlg->StartExecuteAsync([bIsDefaultPage, bNew, nFamily, nSlot, nNewStyleUndoId, pApplyStyleHelper, pRequest, xTmp, this](sal_Int32 nResult){
+ if (RET_OK == nResult)
+ pApplyStyleHelper->apply();
+
+ if (bNew)
+ {
+ switch( nFamily )
+ {
+ case SfxStyleFamily::Para:
+ {
+ if(!xTmp->GetParent().isEmpty())
+ {
+ SwTextFormatColl* pColl = m_pWrtShell->FindTextFormatCollByName(xTmp->GetParent());
+ if (GetDoc()->GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetDoc()->GetIDocumentUndoRedo().AppendUndo(
+ std::make_unique<SwUndoTextFormatCollCreate>(xTmp->GetCollection(), pColl, *GetDoc()));
+ }
+ }
+ }
+ break;
+ case SfxStyleFamily::Char:
+ {
+ if(!xTmp->GetParent().isEmpty())
+ {
+ SwCharFormat* pCFormat = m_pWrtShell->FindCharFormatByName(xTmp->GetParent());
+ if (GetDoc()->GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetDoc()->GetIDocumentUndoRedo().AppendUndo(
+ std::make_unique<SwUndoCharFormatCreate>(xTmp->GetCharFormat(), pCFormat, *GetDoc()));
+ }
+ }
+ }
+ break;
+ case SfxStyleFamily::Frame:
+ {
+ if(!xTmp->GetParent().isEmpty())
+ {
+ SwFrameFormat* pFFormat = m_pWrtShell->GetDoc()->FindFrameFormatByName(xTmp->GetParent());
+ if (GetDoc()->GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetDoc()->GetIDocumentUndoRedo().AppendUndo(
+ std::make_unique<SwUndoFrameFormatCreate>(xTmp->GetFrameFormat(), pFFormat, *GetDoc()));
+ }
+ }
+ }
+ break;
+ default: break;
+ }
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, xTmp->GetName());
+ //Group the create style and change style operations together under the
+ //one "create style" comment
+ m_pWrtShell->EndUndo(nNewStyleUndoId, &aRewriter);
+ }
+
+ bool bDocModified = pApplyStyleHelper->DocIsModified();
+
+ if (RET_OK != nResult)
+ {
+ if (bNew)
+ {
+ GetWrtShell()->Undo();
+ m_xDoc->GetIDocumentUndoRedo().ClearRedo();
+ }
+
+ if (!bDocModified)
+ m_xDoc->getIDocumentState().ResetModified();
+ }
+
+ // Update Watermark if new page style was created
+ if (nSlot == SID_STYLE_NEW && nFamily == SfxStyleFamily::Page)
+ {
+ SwWrtShell* pShell = GetWrtShell();
+ const SfxWatermarkItem aWatermark = pShell->GetWatermark();
+ pShell->SetWatermark(aWatermark);
+ }
+
+ pApplyStyleHelper->m_pDlg.disposeAndClear();
+ if (pRequest)
+ pRequest->Done();
+
+ if (bIsDefaultPage && bDocModified)
+ {
+ uno::Reference< style::XStyleFamiliesSupplier > xStyleFamSupp(GetModel(), uno::UNO_QUERY);
+
+ if (!xStyleFamSupp.is())
+ {
+ SAL_WARN("sw.ui", "Ref to XStyleFamiliesSupplier is null.");
+ return;
+ }
+
+ syncEndnoteOrientation(xStyleFamSupp);
+ }
+ });
+ }
+ else
+ {
+ // prior to the dialog the HtmlMode at the DocShell is being sunk
+ PutItem(SfxUInt16Item(SID_HTML_MODE, ::GetHtmlMode(this)));
+
+ GetWrtShell()->StartAllAction();
+
+ if( SfxStyleFamily::Para == nFamily )
+ {
+ ::SfxToSwPageDescAttr( *GetWrtShell(), xTmp->GetItemSet() );
+ ::ConvertAttrGenToChar(xTmp->GetItemSet(), xTmp->GetItemSet(), /*bIsPara=*/true);
+ }
+ else
+ {
+ ::ConvertAttrGenToChar(xTmp->GetItemSet(), xTmp->GetItemSet());
+ }
+ if(SfxStyleFamily::Page == nFamily)
+ m_pView->InvalidateRulerPos();
+
+ if( bNew )
+ m_xBasePool->Broadcast(SfxStyleSheetHint(SfxHintId::StyleSheetCreated, *xTmp));
+
+ m_xDoc->getIDocumentState().SetModified();
+ if( !bModified ) // Bug 57028
+ {
+ m_xDoc->GetIDocumentUndoRedo().SetUndoNoResetModified();
+ }
+ GetWrtShell()->EndAllAction();
+ }
+}
+
+void SwDocShell::Delete(const OUString &rName, SfxStyleFamily nFamily)
+{
+ SfxStyleSheetBase *pStyle = m_xBasePool->Find(rName, nFamily);
+
+ if(pStyle)
+ {
+ assert( GetWrtShell() );
+
+ GetWrtShell()->StartAllAction();
+ m_xBasePool->Remove(pStyle);
+ GetWrtShell()->EndAllAction();
+ }
+}
+
+void SwDocShell::Hide(const OUString &rName, SfxStyleFamily nFamily, bool bHidden)
+{
+ SfxStyleSheetBase *pStyle = m_xBasePool->Find(rName, nFamily);
+
+ if(pStyle)
+ {
+ assert( GetWrtShell() );
+
+ GetWrtShell()->StartAllAction();
+ rtl::Reference< SwDocStyleSheet > xTmp( new SwDocStyleSheet( *static_cast<SwDocStyleSheet*>(pStyle) ) );
+ xTmp->SetHidden( bHidden );
+ GetWrtShell()->EndAllAction();
+ }
+}
+
+// apply template
+SfxStyleFamily SwDocShell::ApplyStyles(const OUString &rName, SfxStyleFamily nFamily,
+ SwWrtShell* pShell, const sal_uInt16 nMode )
+{
+ SwDocStyleSheet* pStyle = static_cast<SwDocStyleSheet*>( m_xBasePool->Find( rName, nFamily ) );
+
+ SAL_WARN_IF( !pStyle, "sw.ui", "Style not found" );
+
+ if(!pStyle)
+ return SfxStyleFamily::None;
+
+ SwWrtShell *pSh = pShell ? pShell : GetWrtShell();
+
+ assert( pSh );
+
+ pSh->StartAllAction();
+
+ switch (nFamily)
+ {
+ case SfxStyleFamily::Char:
+ {
+ SwFormatCharFormat aFormat(pStyle->GetCharFormat());
+ pSh->SetAttrItem( aFormat, (nMode & KEY_SHIFT) ?
+ SetAttrMode::DONTREPLACE : SetAttrMode::DEFAULT );
+ break;
+ }
+ case SfxStyleFamily::Para:
+ {
+ if (pSh->GetPostItMgr() && pSh->GetPostItMgr()->HasActiveSidebarWin())
+ {
+ pSh->GetPostItMgr()->GetActiveSidebarWin()->GetOutlinerView()->SetStyleSheet(rName);
+ }
+ else
+ {
+ // When outline-folding is enabled, MakeAllOutlineContentTemporarilyVisible makes
+ // application of a paragraph style that has an outline-level greater than the previous
+ // outline node become folded content of the previous outline node if the previous
+ // outline node's content is folded.
+ MakeAllOutlineContentTemporarilyVisible a(GetDoc());
+ // #i62675#
+ // clear also list attributes at affected text nodes, if paragraph
+ // style has the list style attribute set.
+ pSh->SetTextFormatColl( pStyle->GetCollection(), true );
+ }
+ break;
+ }
+ case SfxStyleFamily::Frame:
+ {
+ if ( pSh->IsFrameSelected() )
+ pSh->SetFrameFormat( pStyle->GetFrameFormat() );
+ break;
+ }
+ case SfxStyleFamily::Page:
+ {
+ pSh->SetPageStyle(pStyle->GetPageDesc()->GetName());
+ break;
+ }
+ case SfxStyleFamily::Pseudo:
+ {
+ // reset indent attribute on applying list style
+ // continue list of list style
+ const SwNumRule* pNumRule = pStyle->GetNumRule();
+ if (pNumRule->GetName() == SwResId(STR_POOLNUMRULE_NOLIST))
+ {
+ if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
+ pViewFrm->GetDispatcher()->Execute(FN_NUM_BULLET_OFF);
+ break;
+ }
+ const OUString sListIdForStyle =pNumRule->GetDefaultListId();
+ pSh->SetCurNumRule( *pNumRule, false, sListIdForStyle, true );
+ break;
+ }
+ case SfxStyleFamily::Table:
+ {
+ pSh->SetTableStyle(pStyle->GetName());
+ break;
+ }
+ default:
+ OSL_FAIL("Unknown family");
+ }
+ pSh->EndAllAction();
+
+ return nFamily;
+}
+
+// start watering-can
+SfxStyleFamily SwDocShell::DoWaterCan(const OUString &rName, SfxStyleFamily nFamily)
+{
+ assert( GetWrtShell() );
+
+ SwEditWin& rEdtWin = m_pView->GetEditWin();
+ SwApplyTemplate* pApply = rEdtWin.GetApplyTemplate();
+ bool bWaterCan = !(pApply && pApply->eType != SfxStyleFamily(0));
+
+ if( rName.isEmpty() )
+ bWaterCan = false;
+
+ SwApplyTemplate aTemplate;
+ aTemplate.eType = nFamily;
+
+ if(bWaterCan)
+ {
+ SwDocStyleSheet* pStyle =
+ static_cast<SwDocStyleSheet*>( m_xBasePool->Find(rName, nFamily) );
+
+ SAL_WARN_IF( !pStyle, "sw.ui", "Where's the StyleSheet" );
+
+ if(!pStyle) return nFamily;
+
+ switch(nFamily)
+ {
+ case SfxStyleFamily::Char:
+ aTemplate.aColl.pCharFormat = pStyle->GetCharFormat();
+ break;
+ case SfxStyleFamily::Para:
+ aTemplate.aColl.pTextColl = pStyle->GetCollection();
+ break;
+ case SfxStyleFamily::Frame:
+ aTemplate.aColl.pFrameFormat = pStyle->GetFrameFormat();
+ break;
+ case SfxStyleFamily::Page:
+ aTemplate.aColl.pPageDesc = const_cast<SwPageDesc*>(pStyle->GetPageDesc());
+ break;
+ case SfxStyleFamily::Pseudo:
+ aTemplate.aColl.pNumRule = const_cast<SwNumRule*>(pStyle->GetNumRule());
+ break;
+
+ default:
+ OSL_FAIL("Unknown family");
+ }
+ }
+ else
+ aTemplate.eType = SfxStyleFamily(0);
+
+ m_pView->GetEditWin().SetApplyTemplate(aTemplate);
+
+ return nFamily;
+}
+
+// update template
+void SwDocShell::UpdateStyle(const OUString &rName, SfxStyleFamily nFamily, SwWrtShell* pShell)
+{
+ SwWrtShell* pCurrWrtShell = pShell ? pShell : GetWrtShell();
+ assert( pCurrWrtShell );
+
+ SwDocStyleSheet* pStyle =
+ static_cast<SwDocStyleSheet*>( m_xBasePool->Find(rName, nFamily) );
+
+ if (!pStyle)
+ return;
+
+ switch(nFamily)
+ {
+ case SfxStyleFamily::Para:
+ {
+ SwTextFormatColl* pColl = pStyle->GetCollection();
+ if(pColl && !pColl->IsDefault())
+ {
+ GetWrtShell()->StartAllAction();
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, pColl->GetName());
+
+ GetWrtShell()->StartUndo(SwUndoId::INSFMTATTR, &aRewriter);
+ GetWrtShell()->FillByEx(pColl);
+ // also apply template to remove hard set attributes
+ GetWrtShell()->SetTextFormatColl( pColl );
+ GetWrtShell()->EndUndo();
+ GetWrtShell()->EndAllAction();
+ }
+ break;
+ }
+ case SfxStyleFamily::Frame:
+ {
+ SwFrameFormat* pFrame = pStyle->GetFrameFormat();
+ if( pCurrWrtShell->IsFrameSelected() && pFrame && !pFrame->IsDefault() )
+ {
+ SfxItemSet aSet( GetPool(), aFrameFormatSetRange );
+ pCurrWrtShell->StartAllAction();
+ pCurrWrtShell->GetFlyFrameAttr( aSet );
+
+ // #i105535#
+ // no update of anchor attribute
+ aSet.ClearItem( RES_ANCHOR );
+
+ pFrame->SetFormatAttr( aSet );
+
+ // also apply template to remove hard set attributes
+ pCurrWrtShell->SetFrameFormat( pFrame, true );
+ pCurrWrtShell->EndAllAction();
+ }
+ }
+ break;
+ case SfxStyleFamily::Char:
+ {
+ SwCharFormat* pChar = pStyle->GetCharFormat();
+ if( pChar && !pChar->IsDefault() )
+ {
+ pCurrWrtShell->StartAllAction();
+ pCurrWrtShell->FillByEx(pChar);
+ // also apply template to remove hard set attributes
+ pCurrWrtShell->EndAllAction();
+ }
+
+ }
+ break;
+ case SfxStyleFamily::Pseudo:
+ {
+ const SwNumRule* pCurRule;
+ if( pStyle->GetNumRule() &&
+ nullptr != ( pCurRule = pCurrWrtShell->GetNumRuleAtCurrCursorPos() ))
+ {
+ SwNumRule aRule( *pCurRule );
+ // #i91400#
+ aRule.SetName( pStyle->GetNumRule()->GetName(),
+ pCurrWrtShell->GetDoc()->getIDocumentListsAccess() );
+ pCurrWrtShell->ChgNumRuleFormats( aRule );
+ }
+ }
+ break;
+ case SfxStyleFamily::Table:
+ {
+ if (SwFEShell* pFEShell = GetFEShell())
+ {
+ if(pFEShell->IsTableMode())
+ {
+ pFEShell->TableCursorToCursor();
+ }
+ }
+ SwTableAutoFormat aFormat(rName);
+ if (pCurrWrtShell->GetTableAutoFormat(aFormat))
+ {
+ pCurrWrtShell->StartAllAction();
+ pCurrWrtShell->GetDoc()->ChgTableStyle(rName, aFormat);
+ pCurrWrtShell->EndAllAction();
+ }
+
+ }
+ break;
+ default: break;
+ }
+
+ m_xDoc->BroadcastStyleOperation(rName, nFamily, SfxHintId::StyleSheetModified);
+}
+
+// NewByExample
+void SwDocShell::MakeByExample( const OUString &rName, SfxStyleFamily nFamily,
+ SfxStyleSearchBits nMask, SwWrtShell* pShell )
+{
+ SwWrtShell* pCurrWrtShell = pShell ? pShell : GetWrtShell();
+ SwDocStyleSheet* pStyle = static_cast<SwDocStyleSheet*>( m_xBasePool->Find(
+ rName, nFamily ) );
+ if(!pStyle)
+ {
+ // preserve the current mask of PI, then the new one is
+ // immediately merged with the viewable area
+ if( SfxStyleSearchBits::All == nMask || SfxStyleSearchBits::Used == nMask )
+ nMask = SfxStyleSearchBits::UserDefined;
+ else
+ nMask |= SfxStyleSearchBits::UserDefined;
+
+ if (nFamily == SfxStyleFamily::Para || nFamily == SfxStyleFamily::Char || nFamily == SfxStyleFamily::Frame)
+ {
+ // Prevent undo append from being done during paragraph, character, and frame style Make. Do it later
+ ::sw::UndoGuard const undoGuard(GetDoc()->GetIDocumentUndoRedo());
+ pStyle = static_cast<SwDocStyleSheet*>(&m_xBasePool->Make(rName, nFamily, nMask));
+ }
+ else
+ {
+ pStyle = static_cast<SwDocStyleSheet*>(&m_xBasePool->Make(rName, nFamily, nMask));
+ }
+ }
+
+ switch(nFamily)
+ {
+ case SfxStyleFamily::Para:
+ {
+ SwTextFormatColl* pColl = pStyle->GetCollection();
+ if(pColl && !pColl->IsDefault())
+ {
+ pCurrWrtShell->StartAllAction();
+ pCurrWrtShell->FillByEx(pColl);
+ // also apply template to remove hard set attributes
+ SwTextFormatColl * pDerivedFrom = pCurrWrtShell->GetCurTextFormatColl();
+ pColl->SetDerivedFrom(pDerivedFrom);
+
+ // set the mask at the Collection:
+ sal_uInt16 nId = pColl->GetPoolFormatId() & 0x87ff;
+ switch( nMask & static_cast<SfxStyleSearchBits>(0x0fff) )
+ {
+ case SfxStyleSearchBits::SwText:
+ nId |= COLL_TEXT_BITS;
+ break;
+ case SfxStyleSearchBits::SwChapter:
+ nId |= COLL_DOC_BITS;
+ break;
+ case SfxStyleSearchBits::SwList:
+ nId |= COLL_LISTS_BITS;
+ break;
+ case SfxStyleSearchBits::SwIndex:
+ nId |= COLL_REGISTER_BITS;
+ break;
+ case SfxStyleSearchBits::SwExtra:
+ nId |= COLL_EXTRA_BITS;
+ break;
+ case SfxStyleSearchBits::SwHtml:
+ nId |= COLL_HTML_BITS;
+ break;
+ default: break;
+ }
+ pColl->SetPoolFormatId(nId);
+
+ if (GetDoc()->GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetDoc()->GetIDocumentUndoRedo().AppendUndo(
+ std::make_unique<SwUndoTextFormatCollCreate>(pColl, pDerivedFrom, *GetDoc()));
+ }
+ pCurrWrtShell->SetTextFormatColl(pColl);
+ pCurrWrtShell->EndAllAction();
+ }
+ }
+ break;
+ case SfxStyleFamily::Frame:
+ {
+ SwFrameFormat* pFrame = pStyle->GetFrameFormat();
+ if(pCurrWrtShell->IsFrameSelected() && pFrame && !pFrame->IsDefault())
+ {
+ pCurrWrtShell->StartAllAction();
+
+ SfxItemSet aSet(GetPool(), aFrameFormatSetRange );
+ pCurrWrtShell->GetFlyFrameAttr( aSet );
+ aSet.ClearItem(RES_ANCHOR); // tdf#112574 no anchor in styles
+
+ SwFrameFormat* pFFormat = pCurrWrtShell->GetSelectedFrameFormat();
+ pFrame->SetDerivedFrom( pFFormat );
+ pFrame->SetFormatAttr( aSet );
+ if (GetDoc()->GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetDoc()->GetIDocumentUndoRedo().AppendUndo(
+ std::make_unique<SwUndoFrameFormatCreate>(pFrame, pFFormat, *GetDoc()));
+ }
+ // also apply template to remove hard set attributes
+ pCurrWrtShell->SetFrameFormat(pFrame);
+ pCurrWrtShell->EndAllAction();
+ }
+ }
+ break;
+ case SfxStyleFamily::Char:
+ {
+ SwCharFormat* pChar = pStyle->GetCharFormat();
+ if(pChar && !pChar->IsDefault())
+ {
+ pCurrWrtShell->StartAllAction();
+ pCurrWrtShell->FillByEx( pChar );
+ SwCharFormat * pDerivedFrom = pCurrWrtShell->GetCurCharFormat();
+ pChar->SetDerivedFrom( pDerivedFrom );
+ SwFormatCharFormat aFormat( pChar );
+
+ if (GetDoc()->GetIDocumentUndoRedo().DoesUndo())
+ {
+ // Looks like sometimes pDerivedFrom can be null and this is not supported by redo code
+ // So use default format as a derived from in such situations
+ GetDoc()->GetIDocumentUndoRedo().AppendUndo(
+ std::make_unique<SwUndoCharFormatCreate>(
+ pChar, pDerivedFrom ? pDerivedFrom : GetDoc()->GetDfltCharFormat(),
+ *GetDoc()));
+ }
+ pCurrWrtShell->SetAttrItem(aFormat);
+ pCurrWrtShell->EndAllAction();
+ }
+ }
+ break;
+
+ case SfxStyleFamily::Page:
+ {
+ pCurrWrtShell->StartAllAction();
+ size_t nPgDsc = pCurrWrtShell->GetCurPageDesc();
+ SwPageDesc& rSrc = const_cast<SwPageDesc&>(pCurrWrtShell->GetPageDesc( nPgDsc ));
+ SwPageDesc& rDest = *const_cast<SwPageDesc*>(pStyle->GetPageDesc());
+
+ sal_uInt16 nPoolId = rDest.GetPoolFormatId();
+ sal_uInt16 nHId = rDest.GetPoolHelpId();
+ sal_uInt8 nHFId = rDest.GetPoolHlpFileId();
+
+ pCurrWrtShell->GetDoc()->CopyPageDesc( rSrc, rDest );
+
+ // PoolId must NEVER be copied!
+ rDest.SetPoolFormatId( nPoolId );
+ rDest.SetPoolHelpId( nHId );
+ rDest.SetPoolHlpFileId( nHFId );
+
+ // when Headers/Footers are created, there is no Undo anymore!
+ pCurrWrtShell->GetDoc()->GetIDocumentUndoRedo().DelAllUndoObj();
+
+ pCurrWrtShell->EndAllAction();
+ }
+ break;
+
+ case SfxStyleFamily::Pseudo:
+ {
+ const SwNumRule* pCurRule = pCurrWrtShell->GetNumRuleAtCurrCursorPos();
+
+ if (pCurRule)
+ {
+ pCurrWrtShell->StartAllAction();
+
+ SwNumRule aRule( *pCurRule );
+ OUString sOrigRule( aRule.GetName() );
+ // #i91400#
+ aRule.SetName( pStyle->GetNumRule()->GetName(),
+ pCurrWrtShell->GetDoc()->getIDocumentListsAccess() );
+ pCurrWrtShell->ChgNumRuleFormats( aRule );
+
+ pCurrWrtShell->ReplaceNumRule( sOrigRule, aRule.GetName() );
+
+ pCurrWrtShell->EndAllAction();
+ }
+ }
+ break;
+
+ case SfxStyleFamily::Table:
+ {
+ SwTableAutoFormat* pFormat = pStyle->GetTableFormat();
+ if (pCurrWrtShell->GetTableAutoFormat(*pFormat))
+ {
+ pCurrWrtShell->StartAllAction();
+
+ pCurrWrtShell->SetTableStyle(rName);
+
+ pCurrWrtShell->EndAllAction();
+ }
+ }
+ break;
+
+ default: break;
+ }
+
+ m_xDoc->BroadcastStyleOperation(rName, nFamily, SfxHintId::StyleSheetCreated);
+}
+
+sfx::AccessibilityIssueCollection SwDocShell::runAccessibilityCheck()
+{
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ sw::AccessibilityCheck aCheck(m_xDoc.get());
+ aCheck.check();
+ return aCheck.getIssueCollection();
+#else
+ return sfx::AccessibilityIssueCollection();
+#endif
+}
+
+std::set<Color> SwDocShell::GetDocColors()
+{
+ return m_xDoc->GetDocColors();
+}
+
+std::shared_ptr<model::ColorSet> SwDocShell::GetThemeColors()
+{
+ SdrModel* pModel = m_xDoc->getIDocumentDrawModelAccess().GetDrawModel();
+ if (!pModel)
+ return {};
+ auto const& pTheme = pModel->getTheme();
+ if (!pTheme)
+ return {};
+ return pTheme->getColorSet();
+}
+
+void SwDocShell::LoadStyles( SfxObjectShell& rSource )
+{
+ LoadStyles_(rSource, false);
+}
+
+// bPreserveCurrentDocument determines whether SetFixFields() is called
+// This call modifies the source document. This mustn't happen when the source
+// is a document the user is working on.
+// Calls of ::LoadStyles() normally use files especially loaded for the purpose
+// of importing styles.
+void SwDocShell::LoadStyles_( SfxObjectShell& rSource, bool bPreserveCurrentDocument )
+{
+/* [Description]
+
+ This method is called by SFx if Styles have to be reloaded from a
+ document-template. Existing Styles should be overwritten by that.
+ That's why the document has to be reformatted. Therefore applications
+ will usually override this method and call the baseclass' implementation
+ in their implementation.
+*/
+ // When the source is our document, we do the checking ourselves
+ // (much quicker and doesn't use the crutch StxStylePool).
+ if( dynamic_cast<const SwDocShell*>( &rSource) != nullptr)
+ {
+ // in order for the Headers/Footers not to get the fixed content
+ // of the template, update all the Source's
+ // FixFields once.
+ if(!bPreserveCurrentDocument)
+ static_cast<SwDocShell&>(rSource).m_xDoc->getIDocumentFieldsAccess().SetFixFields(nullptr);
+ if (m_pWrtShell)
+ {
+ // rhbz#818557, fdo#58893: EndAllAction will call SelectShell(),
+ // which pushes a bunch of SfxShells that are not cleared
+ // (for unknown reasons) when closing the document, causing crash;
+ // setting g_bNoInterrupt appears to avoid the problem.
+ ::comphelper::FlagRestorationGuard g(g_bNoInterrupt, true);
+ m_pWrtShell->StartAllAction();
+ m_xDoc->ReplaceStyles( *static_cast<SwDocShell&>(rSource).m_xDoc );
+ m_pWrtShell->EndAllAction();
+ }
+ else
+ {
+ bool bModified = m_xDoc->getIDocumentState().IsModified();
+ m_xDoc->ReplaceStyles( *static_cast<SwDocShell&>(rSource).m_xDoc );
+ if (!bModified && m_xDoc->getIDocumentState().IsModified() && !m_pView)
+ {
+ // the View is created later, but overwrites the Modify-Flag.
+ // Undo doesn't work anymore anyways.
+ m_xDoc->GetIDocumentUndoRedo().SetUndoNoResetModified();
+ }
+ }
+ }
+ else
+ SfxObjectShell::LoadStyles( rSource );
+}
+
+void SwDocShell::FormatPage(
+ weld::Window* pDialogParent,
+ const OUString& rPage,
+ const OUString& rPageId,
+ SwWrtShell& rActShell,
+ SfxRequest* pRequest)
+{
+ Edit(pDialogParent, rPage, OUString(), SfxStyleFamily::Page, SfxStyleSearchBits::Auto, false, rPageId, &rActShell, pRequest);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/app/docstyle.cxx b/sw/source/uibase/app/docstyle.cxx
new file mode 100644
index 0000000000..a715bef70d
--- /dev/null
+++ b/sw/source/uibase/app/docstyle.cxx
@@ -0,0 +1,3380 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <sal/config.h>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+
+#include <cstdlib>
+
+#include <hintids.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <svl/itemiter.hxx>
+#include <svl/eitem.hxx>
+#include <unotools/syslocale.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/numitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <drawdoc.hxx>
+#include <fmtcol.hxx>
+#include <uitool.hxx>
+#include <wrtsh.hxx>
+#include <docsh.hxx>
+#include <frmfmt.hxx>
+#include <charfmt.hxx>
+#include <tblafmt.hxx>
+#include <poolfmt.hxx>
+#include <pagedesc.hxx>
+#include <docstyle.hxx>
+#include <docary.hxx>
+#include <ccoll.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IDocumentStylePoolAccess.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentState.hxx>
+#include <cmdid.h>
+#include <strings.hrc>
+#include <paratr.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <svl/cjkoptions.hxx>
+#include <svl/ctloptions.hxx>
+#include <unotools/intlwrapper.hxx>
+#include <numrule.hxx>
+#include <svx/xdef.hxx>
+#include <SwRewriter.hxx>
+#include <hints.hxx>
+#include <frameformats.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/eeitem.hxx>
+#include <svx/xfillit0.hxx>
+#include <svx/xflftrit.hxx>
+#include <svx/drawitem.hxx>
+
+using namespace com::sun::star;
+
+// At the names' publication, this character is removed again and the
+// family is newly generated.
+
+// In addition now there is the Bit bPhysical. In case this Bit is
+// TRUE, the Pool-Formatnames are not being submitted.
+
+namespace {
+
+class EEStyleSheet : public SfxStyleSheet
+{
+public:
+ using SfxStyleSheet::SfxStyleSheet;
+ bool IsUsed() const override
+ {
+ bool bResult = false;
+ ForAllListeners(
+ [&bResult] (SfxListener* pListener)
+ {
+ auto pUser(dynamic_cast<svl::StyleSheetUser*>(pListener));
+ bResult = pUser && pUser->isUsedByModel();
+ return bResult;
+ });
+ return bResult;
+ }
+ void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override
+ {
+ if (rHint.GetId() == SfxHintId::DataChanged)
+ Broadcast(rHint);
+ else
+ SfxStyleSheet::Notify(rBC, rHint);
+ }
+ bool SetParent(const OUString& rName) override
+ {
+ if (SfxStyleSheet::SetParent(rName))
+ {
+ auto pStyle = m_pPool->Find(rName, nFamily);
+ pSet->SetParent(pStyle ? &pStyle->GetItemSet() : nullptr);
+ return true;
+ }
+ return false;
+ }
+};
+
+class EEStyleSheetPool : public SfxStyleSheetPool, public SfxListener
+{
+ SfxStyleSheetBasePool* m_pOwner;
+
+public:
+ explicit EEStyleSheetPool(SfxStyleSheetBasePool* pOwner)
+ : SfxStyleSheetPool(pOwner->GetPool())
+ , m_pOwner(pOwner)
+ {
+ StartListening(*m_pOwner);
+ }
+
+ using SfxStyleSheetPool::Create;
+ rtl::Reference<SfxStyleSheetBase> Create(const OUString& rName, SfxStyleFamily eFamily,
+ SfxStyleSearchBits nMask) override
+ {
+ return new EEStyleSheet(rName, *this, eFamily, nMask);
+ }
+
+ void Notify(SfxBroadcaster&, const SfxHint& rHint) override
+ {
+ auto pHint = dynamic_cast<const SfxStyleSheetHint*>(&rHint);
+ if (!pHint)
+ return;
+
+ auto nId = pHint->GetId();
+ auto pDocStyleSheet = pHint->GetStyleSheet();
+ auto pExtendedHint = dynamic_cast<const SfxStyleSheetModifiedHint*>(&rHint);
+ const OUString aName = pExtendedHint ? pExtendedHint->GetOldName() : pDocStyleSheet->GetName();
+ auto pStyleSheet = SfxStyleSheetPool::Find(aName, pDocStyleSheet->GetFamily());
+ if (!pStyleSheet)
+ return;
+
+ if (nId == SfxHintId::StyleSheetModified)
+ {
+ pStyleSheet->SetName(pDocStyleSheet->GetName());
+ UpdateStyleHierarchyFrom(pStyleSheet, pDocStyleSheet);
+ static_cast<SfxStyleSheet*>(pStyleSheet)->Broadcast(SfxHint(SfxHintId::DataChanged));
+ }
+ else if (nId == SfxHintId::StyleSheetErased)
+ Remove(pStyleSheet);
+ }
+
+ SfxStyleSheetBase* Find(const OUString& rName, SfxStyleFamily eFamily,
+ SfxStyleSearchBits = SfxStyleSearchBits::All) override
+ {
+ auto pStyleSheet = SfxStyleSheetPool::Find(rName, eFamily);
+
+ if (auto pDocStyleSheet = pStyleSheet ? nullptr : m_pOwner->Find(rName, eFamily))
+ {
+ pStyleSheet = &Make(pDocStyleSheet->GetName(), pDocStyleSheet->GetFamily());
+ UpdateStyleHierarchyFrom(pStyleSheet, pDocStyleSheet);
+ }
+
+ return pStyleSheet;
+ }
+
+ void UpdateStyleHierarchyFrom(SfxStyleSheetBase* pStyleSheet, SfxStyleSheetBase* pDocStyleSheet)
+ {
+ FillItemSet(pStyleSheet, pDocStyleSheet);
+
+ // Remember now, as the next calls will invalidate pDocStyleSheet.
+ const OUString aParent = pDocStyleSheet->GetParent();
+ const OUString aFollow = pDocStyleSheet->GetFollow();
+
+ if (pStyleSheet->GetParent() != aParent)
+ pStyleSheet->SetParent(aParent);
+
+ if (pStyleSheet->GetFollow() != aFollow)
+ pStyleSheet->SetFollow(aFollow);
+ }
+
+ void FillItemSet(SfxStyleSheetBase* pDestSheet, SfxStyleSheetBase* pSourceSheet)
+ {
+ auto& rItemSet = pDestSheet->GetItemSet();
+ rItemSet.ClearItem();
+
+ auto pCol = static_cast<SwDocStyleSheet*>(pSourceSheet)->GetCollection();
+ SfxItemIter aIter(pCol->GetAttrSet());
+ std::optional<SvxLRSpaceItem> oLRSpaceItem;
+
+ for (auto pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
+ {
+ if (aIter.GetItemState(false) != SfxItemState::SET)
+ continue;
+
+ auto nWhich = pItem->Which();
+ auto nSlotId = rPool.GetSlotId(nWhich);
+ auto nNewWhich = rPool.GetSecondaryPool()->GetWhich(nSlotId);
+ if (nNewWhich != nSlotId)
+ rItemSet.Put(pItem->CloneSetWhich(nNewWhich));
+ else if (nWhich == RES_MARGIN_FIRSTLINE)
+ {
+ if (!oLRSpaceItem)
+ oLRSpaceItem.emplace(EE_PARA_LRSPACE);
+ auto pFirstLineItem = static_cast<const SvxFirstLineIndentItem*>(pItem);
+ (*oLRSpaceItem).SetTextFirstLineOffsetValue(pFirstLineItem->GetTextFirstLineOffset());
+ (*oLRSpaceItem).SetAutoFirst(pFirstLineItem->IsAutoFirst());
+ }
+ else if (nWhich == RES_MARGIN_TEXTLEFT)
+ {
+ if (!oLRSpaceItem)
+ oLRSpaceItem.emplace(EE_PARA_LRSPACE);
+ (*oLRSpaceItem).SetTextLeft(static_cast<const SvxTextLeftMarginItem*>(pItem)->GetTextLeft());
+ }
+ else if (nWhich == RES_MARGIN_RIGHT)
+ {
+ if (!oLRSpaceItem)
+ oLRSpaceItem.emplace(EE_PARA_LRSPACE);
+ (*oLRSpaceItem).SetRight(static_cast<const SvxRightMarginItem*>(pItem)->GetRight());
+ }
+ else if (nWhich == RES_CHRATR_BACKGROUND)
+ {
+ auto pBrushItem = static_cast<const SvxBrushItem*>(pItem);
+ rItemSet.Put(SvxColorItem(pBrushItem->GetColor(), EE_CHAR_BKGCOLOR));
+ }
+ }
+ if (oLRSpaceItem)
+ rItemSet.Put(*oLRSpaceItem);
+ }
+};
+
+class SwImplShellAction
+{
+ SwWrtShell* m_pSh;
+ std::unique_ptr<CurrShell> m_pCurrSh;
+public:
+ explicit SwImplShellAction( SwDoc& rDoc );
+ ~SwImplShellAction() COVERITY_NOEXCEPT_FALSE;
+ SwImplShellAction(const SwImplShellAction&) = delete;
+ SwImplShellAction& operator=(const SwImplShellAction&) = delete;
+};
+
+}
+
+SwImplShellAction::SwImplShellAction( SwDoc& rDoc )
+{
+ if( rDoc.GetDocShell() )
+ m_pSh = rDoc.GetDocShell()->GetWrtShell();
+ else
+ m_pSh = nullptr;
+
+ if( m_pSh )
+ {
+ m_pCurrSh.reset( new CurrShell( m_pSh ) );
+ m_pSh->StartAllAction();
+ }
+}
+
+SwImplShellAction::~SwImplShellAction() COVERITY_NOEXCEPT_FALSE
+{
+ if( m_pCurrSh )
+ {
+ m_pSh->EndAllAction();
+ m_pCurrSh.reset();
+ }
+}
+
+// find/create SwCharFormate
+// possibly fill Style
+static SwCharFormat* lcl_FindCharFormat( SwDoc& rDoc,
+ const OUString& rName,
+ SwDocStyleSheet* pStyle = nullptr,
+ bool bCreate = true )
+{
+ SwCharFormat* pFormat = nullptr;
+ if (!rName.isEmpty())
+ {
+ pFormat = rDoc.FindCharFormatByName( rName );
+ if( !pFormat && rName == SwResId(STR_POOLCHR_STANDARD))
+ {
+ // Standard-Character template
+ pFormat = rDoc.GetDfltCharFormat();
+ }
+
+ if( !pFormat && bCreate )
+ { // explore Pool
+ const sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(rName, SwGetPoolIdFromName::ChrFmt);
+ if(nId != USHRT_MAX)
+ pFormat = rDoc.getIDocumentStylePoolAccess().GetCharFormatFromPool(nId);
+ }
+ }
+ if(pStyle)
+ {
+ if(pFormat)
+ {
+ pStyle->SetPhysical(true);
+ SwFormat* p = pFormat->DerivedFrom();
+ if( p && !p->IsDefault() )
+ pStyle->PresetParent( p->GetName() );
+ else
+ pStyle->PresetParent( OUString() );
+ }
+ else
+ pStyle->SetPhysical(false);
+ }
+ return pFormat;
+}
+
+// find/create ParaFormats
+// fill Style
+static SwTextFormatColl* lcl_FindParaFormat( SwDoc& rDoc,
+ const OUString& rName,
+ SwDocStyleSheet* pStyle = nullptr,
+ bool bCreate = true )
+{
+ SwTextFormatColl* pColl = nullptr;
+
+ if (!rName.isEmpty())
+ {
+ pColl = rDoc.FindTextFormatCollByName( rName );
+ if( !pColl && bCreate )
+ { // explore Pool
+ const sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(rName, SwGetPoolIdFromName::TxtColl);
+ if(nId != USHRT_MAX)
+ pColl = rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool(nId);
+ }
+ }
+
+ if(pStyle)
+ {
+ if(pColl)
+ {
+ pStyle->SetPhysical(true);
+ if( pColl->DerivedFrom() && !pColl->DerivedFrom()->IsDefault() )
+ pStyle->PresetParent( pColl->DerivedFrom()->GetName() );
+ else
+ pStyle->PresetParent( OUString() );
+
+ SwTextFormatColl& rNext = pColl->GetNextTextFormatColl();
+ pStyle->PresetFollow(rNext.GetName());
+ }
+ else
+ pStyle->SetPhysical(false);
+ }
+ return pColl;
+}
+
+// Border formats
+static SwFrameFormat* lcl_FindFrameFormat( SwDoc& rDoc,
+ const OUString& rName,
+ SwDocStyleSheet* pStyle = nullptr,
+ bool bCreate = true )
+{
+ SwFrameFormat* pFormat = nullptr;
+ if( !rName.isEmpty() )
+ {
+ pFormat = rDoc.FindFrameFormatByName( rName );
+ if( !pFormat && bCreate )
+ { // explore Pool
+ const sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(rName, SwGetPoolIdFromName::FrmFmt);
+ if(nId != USHRT_MAX)
+ pFormat = rDoc.getIDocumentStylePoolAccess().GetFrameFormatFromPool(nId);
+ }
+ }
+
+ if(pStyle)
+ {
+ if(pFormat)
+ {
+ pStyle->SetPhysical(true);
+ if( pFormat->DerivedFrom() && !pFormat->DerivedFrom()->IsDefault() )
+ pStyle->PresetParent( pFormat->DerivedFrom()->GetName() );
+ else
+ pStyle->PresetParent( OUString() );
+ }
+ else
+ pStyle->SetPhysical(false);
+ }
+ return pFormat;
+}
+
+// Page descriptors
+static const SwPageDesc* lcl_FindPageDesc( SwDoc& rDoc,
+ const OUString& rName,
+ SwDocStyleSheet* pStyle = nullptr,
+ bool bCreate = true )
+{
+ const SwPageDesc* pDesc = nullptr;
+
+ if (!rName.isEmpty())
+ {
+ pDesc = rDoc.FindPageDesc(rName);
+ if( !pDesc && bCreate )
+ {
+ sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(rName, SwGetPoolIdFromName::PageDesc);
+ if(nId != USHRT_MAX)
+ pDesc = rDoc.getIDocumentStylePoolAccess().GetPageDescFromPool(nId);
+ }
+ }
+
+ if(pStyle)
+ {
+ if(pDesc)
+ {
+ pStyle->SetPhysical(true);
+ if(pDesc->GetFollow())
+ pStyle->PresetFollow(pDesc->GetFollow()->GetName());
+ else
+ pStyle->PresetParent( OUString() );
+ }
+ else
+ pStyle->SetPhysical(false);
+ }
+ return pDesc;
+}
+
+static const SwNumRule* lcl_FindNumRule( SwDoc& rDoc,
+ const OUString& rName,
+ SwDocStyleSheet* pStyle = nullptr,
+ bool bCreate = true )
+{
+ const SwNumRule* pRule = nullptr;
+
+ if (!rName.isEmpty())
+ {
+ pRule = rDoc.FindNumRulePtr( rName );
+ if( !pRule && bCreate )
+ {
+ sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(rName, SwGetPoolIdFromName::NumRule);
+ if(nId != USHRT_MAX)
+ pRule = rDoc.getIDocumentStylePoolAccess().GetNumRuleFromPool(nId);
+ }
+ }
+
+ if(pStyle)
+ {
+ if(pRule)
+ {
+ pStyle->SetPhysical(true);
+ pStyle->PresetParent( OUString() );
+ }
+ else
+ pStyle->SetPhysical(false);
+ }
+ return pRule;
+}
+
+static SwTableAutoFormat* lcl_FindTableStyle(SwDoc& rDoc, const OUString& rName, SwDocStyleSheet *pStyle = nullptr, bool bCreate = true)
+{
+ SwTableAutoFormat* pFormat = nullptr;
+
+ if (!rName.isEmpty())
+ {
+ pFormat = rDoc.GetTableStyles().FindAutoFormat(rName);
+ if (!pFormat && bCreate)
+ {
+ SwTableAutoFormat aNew(rName);
+ rDoc.GetTableStyles().AddAutoFormat(aNew);
+ }
+ }
+
+ if(pStyle)
+ {
+ if(pFormat)
+ {
+ pStyle->SetPhysical(true);
+ pStyle->PresetParent(OUString());
+ }
+ else
+ pStyle->SetPhysical(false);
+ }
+ return pFormat;
+}
+
+static const SwBoxAutoFormat* lcl_FindCellStyle(SwDoc& rDoc, std::u16string_view rName, SwDocStyleSheet *pStyle)
+{
+ const SwBoxAutoFormat* pFormat = rDoc.GetCellStyles().GetBoxFormat(rName);
+
+ if (!pFormat)
+ {
+ const auto& aTableTemplateMap = SwTableAutoFormat::GetTableTemplateMap();
+ SwTableAutoFormatTable& rTableStyles = rDoc.GetTableStyles();
+ for (size_t i=0; i < rTableStyles.size() && !pFormat; ++i)
+ {
+ const SwTableAutoFormat& rTableStyle = rTableStyles[i];
+ for (size_t nBoxFormat=0; nBoxFormat < aTableTemplateMap.size() && !pFormat; ++nBoxFormat)
+ {
+ const sal_uInt32 nBoxIndex = aTableTemplateMap[nBoxFormat];
+ const SwBoxAutoFormat& rBoxFormat = rTableStyle.GetBoxFormat(nBoxIndex);
+ OUString sBoxFormatName;
+ SwStyleNameMapper::FillProgName(rTableStyle.GetName(), sBoxFormatName, SwGetPoolIdFromName::TabStyle);
+ sBoxFormatName += rTableStyle.GetTableTemplateCellSubName(rBoxFormat);
+ if (rName == sBoxFormatName)
+ pFormat = &rBoxFormat;
+ }
+ }
+ }
+
+ if(pStyle)
+ {
+ if(pFormat)
+ {
+ pStyle->SetPhysical(true);
+ pStyle->PresetParent(OUString());
+ }
+ else
+ pStyle->SetPhysical(false);
+ }
+ return pFormat;
+}
+
+sal_uInt32 SwStyleSheetIterator::SwPoolFormatList::FindName(SfxStyleFamily eFam,
+ const OUString& rName)
+{
+ if(!maImpl.empty())
+ {
+ UniqueHash::const_iterator it = maUnique.find(std::pair<SfxStyleFamily,OUString>{eFam, rName});
+ if (it != maUnique.end())
+ {
+ sal_uInt32 nIdx = it->second;
+ assert (nIdx < maImpl.size());
+ assert (maImpl.size() == maUnique.size());
+ return nIdx;
+ }
+ }
+ return SAL_MAX_UINT32;
+}
+
+void SwStyleSheetIterator::SwPoolFormatList::rehash()
+{
+ maUnique.clear();
+ for (size_t i = 0; i < maImpl.size(); i++)
+ maUnique[maImpl[i]] = i;
+ assert (maImpl.size() == maUnique.size());
+}
+
+void SwStyleSheetIterator::SwPoolFormatList::RemoveName(SfxStyleFamily eFam,
+ const OUString& rName)
+{
+ sal_uInt32 nTmpPos = FindName( eFam, rName );
+ if (nTmpPos != SAL_MAX_UINT32)
+ maImpl.erase(maImpl.begin() + nTmpPos);
+
+ // assumption: this seldom occurs, the iterator is built, then emptied.
+ rehash();
+ assert (maImpl.size() == maUnique.size());
+}
+
+// Add Strings to the list of templates
+void SwStyleSheetIterator::SwPoolFormatList::Append( SfxStyleFamily eFam, const OUString& rStr )
+{
+ UniqueHash::const_iterator it = maUnique.find(std::pair<SfxStyleFamily,OUString>{eFam, rStr});
+ if (it != maUnique.end())
+ return;
+
+ maUnique.emplace(std::pair<SfxStyleFamily,OUString>{eFam, rStr}, static_cast<sal_uInt32>(maImpl.size()));
+ maImpl.push_back(std::pair<SfxStyleFamily,OUString>{eFam, rStr});
+}
+
+// UI-sided implementation of StyleSheets
+// uses the Core-Engine
+SwDocStyleSheet::SwDocStyleSheet( SwDoc& rDocument,
+ SwDocStyleSheetPool& rPool) :
+
+ SfxStyleSheetBase( OUString(), &rPool, SfxStyleFamily::Char, SfxStyleSearchBits::Auto ),
+ m_pCharFormat(nullptr),
+ m_pColl(nullptr),
+ m_pFrameFormat(nullptr),
+ m_pDesc(nullptr),
+ m_pNumRule(nullptr),
+ m_pTableFormat(nullptr),
+ m_pBoxFormat(nullptr),
+ m_rDoc(rDocument),
+ m_aCoreSet(
+ rPool.GetPool(),
+ svl::Items<
+ RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
+ RES_PARATR_BEGIN, RES_FRMATR_END - 1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END - 1,
+ // FillAttribute support:
+ XATTR_FILL_FIRST, XATTR_FILL_LAST,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
+ SID_ATTR_PAGE, SID_ATTR_PAGE_EXT1,
+ SID_ATTR_PAGE_HEADERSET, SID_ATTR_PAGE_FOOTERSET,
+ SID_ATTR_PARA_MODEL, SID_ATTR_PARA_MODEL,
+ // Items to hand over XPropertyList things like XColorList,
+ // XHatchList, XGradientList, and XBitmapList to the Area TabPage:
+ SID_COLOR_TABLE, SID_PATTERN_LIST,
+ SID_SWREGISTER_COLLECTION, SID_SWREGISTER_COLLECTION,
+ SID_ATTR_PARA_PAGENUM, SID_ATTR_PARA_PAGENUM,
+ SID_SWREGISTER_MODE, SID_SWREGISTER_MODE,
+ SID_ATTR_BRUSH_CHAR, SID_ATTR_BRUSH_CHAR,
+ SID_ATTR_NUMBERING_RULE, SID_ATTR_NUMBERING_RULE,
+ SID_ATTR_CHAR_GRABBAG, SID_ATTR_CHAR_GRABBAG,
+ SID_ATTR_AUTO_STYLE_UPDATE, SID_ATTR_AUTO_STYLE_UPDATE,
+ FN_PARAM_FTN_INFO, FN_PARAM_FTN_INFO,
+ FN_KEEP_ASPECT_RATIO, FN_KEEP_ASPECT_RATIO,
+ FN_COND_COLL, FN_COND_COLL>),
+ m_bPhysical(false)
+{
+ nHelpId = UCHAR_MAX;
+}
+
+SwDocStyleSheet::SwDocStyleSheet( const SwDocStyleSheet& ) = default;
+
+SwDocStyleSheet::~SwDocStyleSheet() = default;
+
+void SwDocStyleSheet::Reset()
+{
+ aName.clear();
+ aFollow.clear();
+ aParent.clear();
+ SetPhysical(false);
+}
+
+void SwDocStyleSheet::SetGrabBagItem(const uno::Any& rVal)
+{
+ bool bChg = false;
+ if (!m_bPhysical)
+ FillStyleSheet(FillPhysical);
+
+ SwFormat* pFormat = nullptr;
+ switch (nFamily)
+ {
+ case SfxStyleFamily::Char:
+ pFormat = m_rDoc.FindCharFormatByName(aName);
+ if (pFormat)
+ {
+ pFormat->SetGrabBagItem(rVal);
+ bChg = true;
+ }
+ break;
+ case SfxStyleFamily::Para:
+ pFormat = m_rDoc.FindTextFormatCollByName(aName);
+ if (pFormat)
+ {
+ pFormat->SetGrabBagItem(rVal);
+ bChg = true;
+ }
+ break;
+ case SfxStyleFamily::Pseudo:
+ {
+ SwNumRule* pRule = m_rDoc.FindNumRulePtr(aName);
+ if (pRule)
+ {
+ pRule->SetGrabBagItem(rVal);
+ bChg = true;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (bChg)
+ {
+ dynamic_cast<SwDocStyleSheetPool&>(*m_pPool).InvalidateIterator();
+ m_pPool->Broadcast(SfxStyleSheetHint(SfxHintId::StyleSheetModified, *this));
+ if (SwEditShell* pSh = m_rDoc.GetEditShell())
+ pSh->CallChgLnk();
+ }
+}
+
+void SwDocStyleSheet::GetGrabBagItem(uno::Any& rVal) const
+{
+ SwFormat* pFormat = nullptr;
+ switch (nFamily)
+ {
+ case SfxStyleFamily::Char:
+ pFormat = m_rDoc.FindCharFormatByName(aName);
+ if (pFormat)
+ pFormat->GetGrabBagItem(rVal);
+ break;
+ case SfxStyleFamily::Para:
+ pFormat = m_rDoc.FindTextFormatCollByName(aName);
+ if (pFormat)
+ pFormat->GetGrabBagItem(rVal);
+ break;
+ case SfxStyleFamily::Pseudo:
+ {
+ SwNumRule* pRule = m_rDoc.FindNumRulePtr(aName);
+ if (pRule)
+ pRule->GetGrabBagItem(rVal);
+ }
+ break;
+ default:
+ break;
+ }
+}
+// virtual methods
+void SwDocStyleSheet::SetHidden( bool bValue )
+{
+ bool bChg = false;
+ if(!m_bPhysical)
+ FillStyleSheet( FillPhysical );
+
+ SwFormat* pFormat = nullptr;
+ switch(nFamily)
+ {
+ case SfxStyleFamily::Char:
+ pFormat = m_rDoc.FindCharFormatByName( aName );
+ if ( pFormat )
+ {
+ pFormat->SetHidden( bValue );
+ bChg = true;
+ }
+ break;
+
+ case SfxStyleFamily::Para:
+ pFormat = m_rDoc.FindTextFormatCollByName( aName );
+ if ( pFormat )
+ {
+ pFormat->SetHidden( bValue );
+ bChg = true;
+ }
+ break;
+
+ case SfxStyleFamily::Frame:
+ pFormat = m_rDoc.FindFrameFormatByName( aName );
+ if ( pFormat )
+ {
+ pFormat->SetHidden( bValue );
+ bChg = true;
+ }
+ break;
+
+ case SfxStyleFamily::Page:
+ {
+ SwPageDesc* pPgDesc = m_rDoc.FindPageDesc(aName);
+ if ( pPgDesc )
+ {
+ pPgDesc->SetHidden( bValue );
+ bChg = true;
+ }
+ }
+ break;
+
+ case SfxStyleFamily::Pseudo:
+ {
+ SwNumRule* pRule = m_rDoc.FindNumRulePtr( aName );
+ if ( pRule )
+ {
+ pRule->SetHidden( bValue );
+ bChg = true;
+ }
+ }
+ break;
+
+ case SfxStyleFamily::Table:
+ {
+ SwTableAutoFormat* pTableAutoFormat = m_rDoc.GetTableStyles().FindAutoFormat( aName );
+ if ( pTableAutoFormat )
+ {
+ pTableAutoFormat->SetHidden( bValue );
+ bChg = true;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if( bChg )
+ {
+ // calling pPool->First() here would be quite slow...
+ dynamic_cast<SwDocStyleSheetPool&>(*m_pPool).InvalidateIterator(); // internal list has to be updated
+ m_pPool->Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetModified, *this ) );
+ if (SwEditShell* pSh = m_rDoc.GetEditShell())
+ pSh->CallChgLnk();
+ }
+}
+
+bool SwDocStyleSheet::IsHidden( ) const
+{
+ bool bRet = false;
+
+ SwFormat* pFormat = nullptr;
+ switch(nFamily)
+ {
+ case SfxStyleFamily::Char:
+ pFormat = m_rDoc.FindCharFormatByName( aName );
+ bRet = pFormat && pFormat->IsHidden( );
+ break;
+
+ case SfxStyleFamily::Para:
+ pFormat = m_rDoc.FindTextFormatCollByName( aName );
+ bRet = pFormat && pFormat->IsHidden( );
+ break;
+
+ case SfxStyleFamily::Frame:
+ pFormat = m_rDoc.FindFrameFormatByName( aName );
+ bRet = pFormat && pFormat->IsHidden( );
+ break;
+
+ case SfxStyleFamily::Page:
+ {
+ SwPageDesc* pPgDesc = m_rDoc.FindPageDesc(aName);
+ bRet = pPgDesc && pPgDesc->IsHidden( );
+ }
+ break;
+ case SfxStyleFamily::Pseudo:
+ {
+ SwNumRule* pRule = m_rDoc.FindNumRulePtr( aName );
+ bRet = pRule && pRule->IsHidden( );
+ }
+ break;
+ case SfxStyleFamily::Table:
+ {
+ SwTableAutoFormat* pTableAutoFormat = m_rDoc.GetTableStyles().FindAutoFormat( aName );
+ bRet = pTableAutoFormat && pTableAutoFormat->IsHidden( );
+ }
+ break;
+ default:
+ break;
+ }
+
+ return bRet;
+}
+
+const OUString& SwDocStyleSheet::GetParent() const
+{
+ if( !m_bPhysical )
+ {
+ // check if it's already in document
+ SwFormat* pFormat = nullptr;
+ SwGetPoolIdFromName eGetType;
+ switch(nFamily)
+ {
+ case SfxStyleFamily::Char:
+ pFormat = m_rDoc.FindCharFormatByName( aName );
+ eGetType = SwGetPoolIdFromName::ChrFmt;
+ break;
+
+ case SfxStyleFamily::Para:
+ pFormat = m_rDoc.FindTextFormatCollByName( aName );
+ eGetType = SwGetPoolIdFromName::TxtColl;
+ break;
+
+ case SfxStyleFamily::Frame:
+ pFormat = m_rDoc.FindFrameFormatByName( aName );
+ eGetType = SwGetPoolIdFromName::FrmFmt;
+ break;
+
+ case SfxStyleFamily::Page:
+ case SfxStyleFamily::Pseudo:
+ default:
+ {
+ static const OUString sEmpty;
+ return sEmpty; // there's no parent
+ }
+ }
+
+ OUString sTmp;
+ if( !pFormat ) // not yet there, so default Parent
+ {
+ sal_uInt16 i = SwStyleNameMapper::GetPoolIdFromUIName( aName, eGetType );
+ i = ::GetPoolParent( i );
+ if( i && USHRT_MAX != i )
+ SwStyleNameMapper::FillUIName( i, sTmp );
+ }
+ else
+ {
+ SwFormat* p = pFormat->DerivedFrom();
+ if( p && !p->IsDefault() )
+ sTmp = p->GetName();
+ }
+ SwDocStyleSheet* pThis = const_cast<SwDocStyleSheet*>(this);
+ pThis->aParent = sTmp;
+ }
+ return aParent;
+}
+
+// Follower
+const OUString& SwDocStyleSheet::GetFollow() const
+{
+ if( !m_bPhysical )
+ {
+ SwDocStyleSheet* pThis = const_cast<SwDocStyleSheet*>(this);
+ pThis->FillStyleSheet( FillAllInfo );
+ }
+ return aFollow;
+}
+
+void SwDocStyleSheet::SetLink(const OUString& rStr)
+{
+ SwImplShellAction aTmpSh(m_rDoc);
+ switch (nFamily)
+ {
+ case SfxStyleFamily::Para:
+ {
+ if (m_pColl)
+ {
+ SwCharFormat* pLink = lcl_FindCharFormat(m_rDoc, rStr);
+ if (pLink)
+ {
+ m_pColl->SetLinkedCharFormat(pLink);
+ }
+ }
+ break;
+ }
+ case SfxStyleFamily::Char:
+ {
+ if (m_pCharFormat)
+ {
+ SwTextFormatColl* pLink = lcl_FindParaFormat(m_rDoc, rStr);
+ if (pLink)
+ {
+ m_pCharFormat->SetLinkedParaFormat(pLink);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+const OUString& SwDocStyleSheet::GetLink() const
+{
+ if (!m_bPhysical)
+ {
+ SwDocStyleSheet* pThis = const_cast<SwDocStyleSheet*>(this);
+ pThis->FillStyleSheet(FillAllInfo);
+ }
+
+ return m_aLink;
+}
+
+// What Linkage is possible
+bool SwDocStyleSheet::HasFollowSupport() const
+{
+ switch(nFamily)
+ {
+ case SfxStyleFamily::Para :
+ case SfxStyleFamily::Page : return true;
+ case SfxStyleFamily::Frame:
+ case SfxStyleFamily::Char :
+ case SfxStyleFamily::Pseudo: return false;
+ default:
+ OSL_ENSURE(false, "unknown style family");
+ }
+ return false;
+}
+
+// Parent ?
+bool SwDocStyleSheet::HasParentSupport() const
+{
+ bool bRet = false;
+ switch(nFamily)
+ {
+ case SfxStyleFamily::Char :
+ case SfxStyleFamily::Para :
+ case SfxStyleFamily::Frame: bRet = true;
+ break;
+ default:; //prevent warning
+ }
+ return bRet;
+}
+
+bool SwDocStyleSheet::HasClearParentSupport() const
+{
+ bool bRet = false;
+ switch(nFamily)
+ {
+ case SfxStyleFamily::Para :
+ case SfxStyleFamily::Char :
+ case SfxStyleFamily::Frame: bRet = true;
+ break;
+ default:; //prevent warning
+ }
+ return bRet;
+}
+
+// determine textual description
+OUString SwDocStyleSheet::GetDescription(MapUnit eUnit)
+{
+ IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
+
+ static constexpr OUString sPlus(u" + "_ustr);
+ if ( SfxStyleFamily::Page == nFamily )
+ {
+ if( !pSet )
+ GetItemSet();
+
+ SfxItemIter aIter( *pSet );
+ OUStringBuffer aDesc;
+
+ for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
+ {
+ if(!IsInvalidItem(pItem))
+ {
+ switch ( pItem->Which() )
+ {
+ case RES_LR_SPACE:
+ case SID_ATTR_PAGE_SIZE:
+ case SID_ATTR_PAGE_MAXSIZE:
+ case SID_ATTR_PAGE_PAPERBIN:
+ case SID_ATTR_BORDER_INNER:
+ break;
+ default:
+ {
+ OUString aItemPresentation;
+ if ( !IsInvalidItem( pItem ) &&
+ m_pPool->GetPool().GetPresentation(
+ *pItem, eUnit, aItemPresentation, aIntlWrapper ) )
+ {
+ if ( !aDesc.isEmpty() && !aItemPresentation.isEmpty() )
+ aDesc.append(sPlus);
+ aDesc.append(aItemPresentation);
+ }
+ }
+ }
+ }
+ }
+ return aDesc.makeStringAndClear();
+ }
+
+ if ( SfxStyleFamily::Frame == nFamily || SfxStyleFamily::Para == nFamily || SfxStyleFamily::Char == nFamily )
+ {
+ if( !pSet )
+ GetItemSet();
+
+ SfxItemIter aIter( *pSet );
+ OUStringBuffer aDesc;
+ OUString sPageNum;
+ OUString sModel;
+ OUString sBreak;
+ bool bHasWesternFontPrefix = false;
+ bool bHasCJKFontPrefix = false;
+ bool bHasCTLFontPrefix = false;
+ SvtCTLOptions aCTLOptions;
+
+ // Get currently used FillStyle and remember, also need the XFillFloatTransparenceItem
+ // to decide if gradient transparence is used
+ const drawing::FillStyle eFillStyle(pSet->Get(XATTR_FILLSTYLE).GetValue());
+ const bool bUseFloatTransparence(pSet->Get(XATTR_FILLFLOATTRANSPARENCE).IsEnabled());
+
+ for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
+ {
+ if(!IsInvalidItem(pItem))
+ {
+ switch ( pItem->Which() )
+ {
+ case SID_ATTR_AUTO_STYLE_UPDATE:
+ case RES_PAGEDESC:
+ break;
+ default:
+ {
+ OUString aItemPresentation;
+ if ( !IsInvalidItem( pItem ) &&
+ m_pPool->GetPool().GetPresentation(
+ *pItem, eUnit, aItemPresentation, aIntlWrapper ) )
+ {
+ bool bIsDefault = false;
+ switch ( pItem->Which() )
+ {
+ case XATTR_FILLCOLOR:
+ {
+ // only use active FillStyle information
+ bIsDefault = (drawing::FillStyle_SOLID == eFillStyle);
+ break;
+ }
+ case XATTR_FILLGRADIENT:
+ {
+ // only use active FillStyle information
+ bIsDefault = (drawing::FillStyle_GRADIENT == eFillStyle);
+ break;
+ }
+ case XATTR_FILLHATCH:
+ {
+ // only use active FillStyle information
+ bIsDefault = (drawing::FillStyle_HATCH == eFillStyle);
+ break;
+ }
+ case XATTR_FILLBITMAP:
+ {
+ // only use active FillStyle information
+ bIsDefault = (drawing::FillStyle_BITMAP == eFillStyle);
+ break;
+ }
+ case XATTR_FILLTRANSPARENCE:
+ {
+ // only active when not FloatTransparence
+ bIsDefault = !bUseFloatTransparence;
+ break;
+ }
+ case XATTR_FILLFLOATTRANSPARENCE:
+ {
+ // only active when FloatTransparence
+ bIsDefault = bUseFloatTransparence;
+ break;
+ }
+
+ case SID_ATTR_PARA_PAGENUM:
+ sPageNum = aItemPresentation;
+ break;
+ case SID_ATTR_PARA_MODEL:
+ sModel = aItemPresentation;
+ break;
+ case RES_BREAK:
+ sBreak = aItemPresentation;
+ break;
+ case RES_CHRATR_CJK_FONT:
+ case RES_CHRATR_CJK_FONTSIZE:
+ case RES_CHRATR_CJK_LANGUAGE:
+ case RES_CHRATR_CJK_POSTURE:
+ case RES_CHRATR_CJK_WEIGHT:
+ if(SvtCJKOptions::IsCJKFontEnabled())
+ bIsDefault = true;
+ if(!bHasCJKFontPrefix)
+ {
+ aItemPresentation = SwResId(STR_CJK_FONT) + aItemPresentation;
+ bHasCJKFontPrefix = true;
+ }
+ break;
+ case RES_CHRATR_CTL_FONT:
+ case RES_CHRATR_CTL_FONTSIZE:
+ case RES_CHRATR_CTL_LANGUAGE:
+ case RES_CHRATR_CTL_POSTURE:
+ case RES_CHRATR_CTL_WEIGHT:
+ if(SvtCTLOptions::IsCTLFontEnabled())
+ bIsDefault = true;
+ if(!bHasCTLFontPrefix)
+ {
+ aItemPresentation = SwResId(STR_CTL_FONT) + aItemPresentation;
+ bHasCTLFontPrefix = true;
+ }
+ break;
+ case RES_CHRATR_FONT:
+ case RES_CHRATR_FONTSIZE:
+ case RES_CHRATR_LANGUAGE:
+ case RES_CHRATR_POSTURE:
+ case RES_CHRATR_WEIGHT:
+ if(!bHasWesternFontPrefix)
+ {
+ aItemPresentation = SwResId(STR_WESTERN_FONT) + aItemPresentation;
+ bHasWesternFontPrefix = true;
+ }
+ [[fallthrough]];
+ default:
+ bIsDefault = true;
+ }
+ if(bIsDefault)
+ {
+ if ( !aDesc.isEmpty() && !aItemPresentation.isEmpty() )
+ aDesc.append(sPlus);
+ aDesc.append(aItemPresentation);
+ }
+ }
+ }
+ }
+ }
+ }
+ // Special treatment for Break, Page template and Site offset
+ if (!sModel.isEmpty())
+ {
+ if (!aDesc.isEmpty())
+ aDesc.append(sPlus);
+ aDesc.append(SwResId(STR_PAGEBREAK) + sPlus + sModel);
+ if (sPageNum != "0")
+ {
+ aDesc.append(sPlus + SwResId(STR_PAGEOFFSET) + sPageNum);
+ }
+ }
+ else if (!sBreak.isEmpty()) // Break can be valid only when NO Model
+ {
+ if (!aDesc.isEmpty())
+ aDesc.append(sPlus);
+ aDesc.append(sBreak);
+ }
+ return aDesc.makeStringAndClear();
+ }
+
+ if( SfxStyleFamily::Pseudo == nFamily )
+ {
+ return OUString();
+ }
+
+ return SfxStyleSheetBase::GetDescription(eUnit);
+}
+
+// Set names
+bool SwDocStyleSheet::SetName(const OUString& rStr, bool bReindexNow)
+{
+ if( rStr.isEmpty() )
+ return false;
+
+ if( aName != rStr )
+ {
+ if( !SfxStyleSheetBase::SetName(rStr, bReindexNow))
+ return false;
+ }
+ else if(!m_bPhysical)
+ FillStyleSheet( FillPhysical );
+
+ bool bChg = false;
+ switch(nFamily)
+ {
+ case SfxStyleFamily::Char :
+ {
+ OSL_ENSURE(m_pCharFormat, "SwCharFormat missing!");
+ if( m_pCharFormat && m_pCharFormat->GetName() != rStr )
+ {
+ if (!m_pCharFormat->GetName().isEmpty())
+ m_rDoc.RenameFormat(*m_pCharFormat, rStr);
+ else
+ m_pCharFormat->SetFormatName(rStr);
+
+ bChg = true;
+ }
+ break;
+ }
+ case SfxStyleFamily::Para :
+ {
+ OSL_ENSURE(m_pColl, "Collection missing!");
+ if( m_pColl && m_pColl->GetName() != rStr )
+ {
+ if (!m_pColl->GetName().isEmpty())
+ m_rDoc.RenameFormat(*m_pColl, rStr);
+ else
+ m_pColl->SetFormatName(rStr);
+
+ bChg = true;
+ }
+ break;
+ }
+ case SfxStyleFamily::Frame:
+ {
+ OSL_ENSURE(m_pFrameFormat, "FrameFormat missing!");
+ if( m_pFrameFormat && m_pFrameFormat->GetName() != rStr )
+ {
+ if (!m_pFrameFormat->GetName().isEmpty())
+ m_rDoc.RenameFormat(*m_pFrameFormat, rStr);
+ else
+ m_pFrameFormat->SetFormatName( rStr );
+
+ bChg = true;
+ }
+ break;
+ }
+ case SfxStyleFamily::Page :
+ OSL_ENSURE(m_pDesc, "PageDesc missing!");
+ if( m_pDesc && m_pDesc->GetName() != rStr )
+ {
+ // Set PageDesc - copy with earlier one - probably not
+ // necessary for setting the name. So here we allow a
+ // cast.
+ SwPageDesc aPageDesc(*const_cast<SwPageDesc*>(m_pDesc));
+ const OUString aOldName(aPageDesc.GetName());
+
+ aPageDesc.SetName( rStr );
+ bool const bDoesUndo = m_rDoc.GetIDocumentUndoRedo().DoesUndo();
+
+ m_rDoc.GetIDocumentUndoRedo().DoUndo(!aOldName.isEmpty());
+ m_rDoc.ChgPageDesc(aOldName, aPageDesc);
+ m_rDoc.GetIDocumentUndoRedo().DoUndo(bDoesUndo);
+
+ m_rDoc.getIDocumentState().SetModified();
+ bChg = true;
+ }
+ break;
+ case SfxStyleFamily::Pseudo:
+ OSL_ENSURE(m_pNumRule, "NumRule missing!");
+
+ if (m_pNumRule)
+ {
+ OUString aOldName = m_pNumRule->GetName();
+
+ if (!aOldName.isEmpty())
+ {
+ if ( aOldName != rStr &&
+ m_rDoc.RenameNumRule(aOldName, rStr))
+ {
+ m_pNumRule = m_rDoc.FindNumRulePtr(rStr);
+ m_rDoc.getIDocumentState().SetModified();
+
+ bChg = true;
+ }
+ }
+ else
+ {
+ // #i91400#
+ const_cast<SwNumRule*>(m_pNumRule)->SetName( rStr, m_rDoc.getIDocumentListsAccess() );
+ m_rDoc.getIDocumentState().SetModified();
+
+ bChg = true;
+ }
+ }
+
+ break;
+
+ default:
+ OSL_ENSURE(false, "unknown style family");
+ }
+
+ if( bChg )
+ {
+ m_pPool->First(nFamily); // internal list has to be updated
+ m_pPool->Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetModified, *this ) );
+ if (SwEditShell* pSh = m_rDoc.GetEditShell())
+ pSh->CallChgLnk();
+ }
+ return true;
+}
+
+// hierarchy of deduction
+bool SwDocStyleSheet::SetParent( const OUString& rStr)
+{
+ SwFormat* pFormat = nullptr, *pParent = nullptr;
+ switch(nFamily)
+ {
+ case SfxStyleFamily::Char :
+ OSL_ENSURE( m_pCharFormat, "SwCharFormat missing!" );
+ if( nullptr != ( pFormat = m_pCharFormat ) && !rStr.isEmpty() )
+ pParent = lcl_FindCharFormat(m_rDoc, rStr);
+ break;
+
+ case SfxStyleFamily::Para :
+ OSL_ENSURE( m_pColl, "Collection missing!");
+ if( nullptr != ( pFormat = m_pColl ) && !rStr.isEmpty() )
+ pParent = lcl_FindParaFormat( m_rDoc, rStr );
+ break;
+
+ case SfxStyleFamily::Frame:
+ OSL_ENSURE(m_pFrameFormat, "FrameFormat missing!");
+ if( nullptr != ( pFormat = m_pFrameFormat ) && !rStr.isEmpty() )
+ pParent = lcl_FindFrameFormat( m_rDoc, rStr );
+ break;
+
+ case SfxStyleFamily::Page:
+ case SfxStyleFamily::Pseudo:
+ break;
+ default:
+ OSL_ENSURE(false, "unknown style family");
+ }
+
+ bool bRet = false;
+ if( pFormat && pFormat->DerivedFrom() &&
+ pFormat->DerivedFrom()->GetName() != rStr )
+ {
+ {
+ SwImplShellAction aTmp( m_rDoc );
+ bRet = pFormat->SetDerivedFrom( pParent );
+ }
+
+ if( bRet )
+ {
+ aParent = rStr;
+ m_pPool->Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetModified,
+ *this ) );
+ }
+ }
+
+ return bRet;
+}
+
+// Set Follower
+bool SwDocStyleSheet::SetFollow( const OUString& rStr)
+{
+ if( !rStr.isEmpty() && !SfxStyleSheetBase::SetFollow( rStr ))
+ return false;
+
+ SwImplShellAction aTmpSh( m_rDoc );
+ switch(nFamily)
+ {
+ case SfxStyleFamily::Para :
+ {
+ OSL_ENSURE(m_pColl, "Collection missing!");
+ if( m_pColl )
+ {
+ SwTextFormatColl* pFollow = m_pColl;
+ if( !rStr.isEmpty() && nullptr == (pFollow = lcl_FindParaFormat(m_rDoc, rStr) ))
+ pFollow = m_pColl;
+
+ m_pColl->SetNextTextFormatColl(*pFollow);
+ }
+ break;
+ }
+ case SfxStyleFamily::Page :
+ {
+ OSL_ENSURE(m_pDesc, "PageDesc missing!");
+ if( m_pDesc )
+ {
+ const SwPageDesc* pFollowDesc = !rStr.isEmpty()
+ ? lcl_FindPageDesc(m_rDoc, rStr)
+ : nullptr;
+ size_t nId = 0;
+ if (pFollowDesc != m_pDesc->GetFollow() && m_rDoc.FindPageDesc(m_pDesc->GetName(), &nId))
+ {
+ SwPageDesc aDesc( *m_pDesc );
+ aDesc.SetFollow( pFollowDesc );
+ m_rDoc.ChgPageDesc( nId, aDesc );
+ m_pDesc = &m_rDoc.GetPageDesc( nId );
+ }
+ }
+ break;
+ }
+ case SfxStyleFamily::Char:
+ case SfxStyleFamily::Frame:
+ case SfxStyleFamily::Pseudo:
+ break;
+ default:
+ OSL_ENSURE(false, "unknown style family");
+ }
+
+ return true;
+}
+
+static
+void lcl_SwFormatToFlatItemSet(SwFormat const *const pFormat, std::optional<SfxItemSet>& pRet)
+{
+ // note: we don't add the odd items that GetItemSet() would add
+ // because they don't seem relevant for preview
+ std::vector<SfxItemSet const*> sets;
+ sets.push_back(&pFormat->GetAttrSet());
+ while (SfxItemSet const*const pParent = sets.back()->GetParent())
+ {
+ sets.push_back(pParent);
+ }
+ // start by copying top-level parent set
+ pRet.emplace(*sets.back());
+ sets.pop_back();
+ for (auto iter = sets.rbegin(); iter != sets.rend(); ++iter)
+ { // in reverse so child overrides parent
+ pRet->Put(**iter);
+ }
+}
+
+std::optional<SfxItemSet> SwDocStyleSheet::GetItemSetForPreview()
+{
+ if (SfxStyleFamily::Page == nFamily || SfxStyleFamily::Pseudo == nFamily || SfxStyleFamily::Table == nFamily)
+ {
+ SAL_WARN("sw.ui", "GetItemSetForPreview not implemented for page or number or table style");
+ return std::optional<SfxItemSet>();
+ }
+ if (!m_bPhysical)
+ {
+ // because not only this style, but also any number of its parents
+ // (or follow style) may not actually exist in the document at this
+ // time, return one "flattened" item set that contains all items from
+ // all parents.
+ std::optional<SfxItemSet> pRet;
+
+ bool bModifiedEnabled = m_rDoc.getIDocumentState().IsEnableSetModified();
+ m_rDoc.getIDocumentState().SetEnableSetModified(false);
+
+ FillStyleSheet(FillPreview, &pRet);
+
+ m_rDoc.getIDocumentState().SetEnableSetModified(bModifiedEnabled);
+
+ assert(pRet);
+ return pRet;
+ }
+ else
+ {
+ std::optional<SfxItemSet> pRet;
+ switch (nFamily)
+ {
+ case SfxStyleFamily::Char:
+ lcl_SwFormatToFlatItemSet(m_pCharFormat, pRet);
+ break;
+ case SfxStyleFamily::Para:
+ lcl_SwFormatToFlatItemSet(m_pColl, pRet);
+ break;
+ case SfxStyleFamily::Frame:
+ lcl_SwFormatToFlatItemSet(m_pFrameFormat, pRet);
+ break;
+ default:
+ std::abort();
+ }
+ return pRet;
+ }
+}
+
+// extract ItemSet to Name and Family, Mask
+
+SfxItemSet& SwDocStyleSheet::GetItemSet()
+{
+ if(!m_bPhysical)
+ FillStyleSheet( FillPhysical );
+
+ switch(nFamily)
+ {
+ case SfxStyleFamily::Char:
+ case SfxStyleFamily::Para:
+ case SfxStyleFamily::Frame:
+ {
+ SvxBoxInfoItem aBoxInfo( SID_ATTR_BORDER_INNER );
+ aBoxInfo.SetTable( false );
+ aBoxInfo.SetDist( true ); // always show gap field
+ aBoxInfo.SetMinDist( true );// set minimum size in tables and paragraphs
+ aBoxInfo.SetDefDist( MIN_BORDER_DIST );// always set Default-Gap
+ // Single lines can only have DontCare-Status in tables
+ aBoxInfo.SetValid( SvxBoxInfoItemValidFlags::DISABLE );
+
+ if( nFamily == SfxStyleFamily::Char )
+ {
+ SAL_WARN_IF(!m_pCharFormat, "sw.ui", "Where's SwCharFormat");
+ m_aCoreSet.Put(m_pCharFormat->GetAttrSet());
+ m_aCoreSet.Put( aBoxInfo );
+
+ if(m_pCharFormat->DerivedFrom())
+ m_aCoreSet.SetParent(&m_pCharFormat->DerivedFrom()->GetAttrSet());
+ }
+ else if ( nFamily == SfxStyleFamily::Para )
+ {
+ OSL_ENSURE(m_pColl, "Where's Collection");
+ m_aCoreSet.Put(m_pColl->GetAttrSet());
+ m_aCoreSet.Put( aBoxInfo );
+ m_aCoreSet.Put(SfxBoolItem(SID_ATTR_AUTO_STYLE_UPDATE, m_pColl->IsAutoUpdateOnDirectFormat()));
+
+ if(m_pColl->DerivedFrom())
+ m_aCoreSet.SetParent(&m_pColl->DerivedFrom()->GetAttrSet());
+ }
+ else
+ {
+ OSL_ENSURE(m_pFrameFormat, "Where's FrameFormat");
+ m_aCoreSet.Put(m_pFrameFormat->GetAttrSet());
+ m_aCoreSet.Put( aBoxInfo );
+ m_aCoreSet.Put(SfxBoolItem(SID_ATTR_AUTO_STYLE_UPDATE, m_pFrameFormat->IsAutoUpdateOnDirectFormat()));
+
+ if(m_pFrameFormat->DerivedFrom())
+ m_aCoreSet.SetParent(&m_pFrameFormat->DerivedFrom()->GetAttrSet());
+
+ // create needed items for XPropertyList entries from the DrawModel so that
+ // the Area TabPage can access them
+ const SwDrawModel* pDrawModel = m_rDoc.getIDocumentDrawModelAccess().GetDrawModel();
+
+ m_aCoreSet.Put(SvxColorListItem(pDrawModel->GetColorList(), SID_COLOR_TABLE));
+ m_aCoreSet.Put(SvxGradientListItem(pDrawModel->GetGradientList(), SID_GRADIENT_LIST));
+ m_aCoreSet.Put(SvxHatchListItem(pDrawModel->GetHatchList(), SID_HATCH_LIST));
+ m_aCoreSet.Put(SvxBitmapListItem(pDrawModel->GetBitmapList(), SID_BITMAP_LIST));
+ m_aCoreSet.Put(SvxPatternListItem(pDrawModel->GetPatternList(), SID_PATTERN_LIST));
+ }
+ }
+ break;
+
+ case SfxStyleFamily::Page :
+ {
+ // set correct parent to get the drawing::FillStyle_NONE FillStyle as needed
+ if(!m_aCoreSet.GetParent())
+ {
+ m_aCoreSet.SetParent(&m_rDoc.GetDfltFrameFormat()->GetAttrSet());
+ }
+
+ OSL_ENSURE(m_pDesc, "No PageDescriptor");
+ ::PageDescToItemSet(*const_cast<SwPageDesc*>(m_pDesc), m_aCoreSet);
+ }
+ break;
+
+ case SfxStyleFamily::Pseudo:
+ {
+ OSL_ENSURE(m_pNumRule, "No NumRule");
+ SvxNumRule aRule = m_pNumRule->MakeSvxNumRule();
+ m_aCoreSet.Put(SvxNumBulletItem(std::move(aRule)));
+ }
+ break;
+
+ default:
+ OSL_ENSURE(false, "unknown style family");
+ }
+ // Member of Baseclass
+ pSet = &m_aCoreSet;
+
+ return m_aCoreSet;
+}
+
+void SwDocStyleSheet::MergeIndentAttrsOfListStyle( SfxItemSet& rSet )
+{
+ if ( nFamily != SfxStyleFamily::Para )
+ {
+ return;
+ }
+
+ OSL_ENSURE( m_pColl, "<SwDocStyleSheet::MergeIndentAttrsOfListStyle(..)> - missing paragraph style");
+ ::sw::ListLevelIndents const indents(m_pColl->AreListLevelIndentsApplicable());
+ if (indents == ::sw::ListLevelIndents::No)
+ return;
+
+ OSL_ENSURE( m_pColl->GetItemState( RES_PARATR_NUMRULE ) == SfxItemState::SET,
+ "<SwDocStyleSheet::MergeIndentAttrsOfListStyle(..)> - list level indents are applicable at paragraph style, but no list style found. Serious defect." );
+ const OUString sNumRule = m_pColl->GetNumRule().GetValue();
+ if (sNumRule.isEmpty())
+ return;
+
+ const SwNumRule* pRule = m_rDoc.FindNumRulePtr( sNumRule );
+ if( pRule )
+ {
+ const SwNumFormat& rFormat = pRule->Get( 0 );
+ if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ if (indents & ::sw::ListLevelIndents::FirstLine)
+ {
+ SvxFirstLineIndentItem const firstLine(static_cast<short>(rFormat.GetFirstLineIndent()), RES_MARGIN_FIRSTLINE);
+ rSet.Put(firstLine);
+ }
+ if (indents & ::sw::ListLevelIndents::LeftMargin)
+ {
+ SvxTextLeftMarginItem const leftMargin(rFormat.GetIndentAt(), RES_MARGIN_TEXTLEFT);
+ rSet.Put(leftMargin);
+ }
+ }
+ }
+}
+
+// handling of parameter <bResetIndentAttrsAtParagraphStyle>
+void SwDocStyleSheet::SetItemSet( const SfxItemSet& rSet, const bool bBroadcast,
+ const bool bResetIndentAttrsAtParagraphStyle )
+{
+ // if applicable determine format first
+ if(!m_bPhysical)
+ FillStyleSheet( FillPhysical );
+
+ SwImplShellAction aTmpSh( m_rDoc );
+
+ OSL_ENSURE( &rSet != &m_aCoreSet, "SetItemSet with own Set is not allowed" );
+
+ if (m_rDoc.GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwRewriter aRewriter;
+ aRewriter.AddRule( UndoArg1, GetName() );
+ m_rDoc.GetIDocumentUndoRedo().StartUndo( SwUndoId::INSFMTATTR, &aRewriter );
+ }
+
+ SwFormat* pFormat = nullptr;
+ std::vector<sal_uInt16> aWhichIdsToReset;
+ std::unique_ptr<SwPageDesc> pNewDsc;
+ size_t nPgDscPos = 0;
+
+ switch(nFamily)
+ {
+ case SfxStyleFamily::Char :
+ {
+ OSL_ENSURE(m_pCharFormat, "Where's CharFormat");
+ pFormat = m_pCharFormat;
+ }
+ break;
+
+ case SfxStyleFamily::Para :
+ {
+ OSL_ENSURE(m_pColl, "Where's Collection");
+ if(const SfxBoolItem* pAutoUpdate = rSet.GetItemIfSet(SID_ATTR_AUTO_STYLE_UPDATE,false))
+ {
+ m_pColl->SetAutoUpdateOnDirectFormat(pAutoUpdate->GetValue());
+ }
+
+ const SwCondCollItem* pCondItem = rSet.GetItemIfSet( FN_COND_COLL, false );
+
+ if( RES_CONDTXTFMTCOLL == m_pColl->Which() && pCondItem )
+ {
+ const CommandStruct* pCmds = SwCondCollItem::GetCmds();
+ for(sal_uInt16 i = 0; i < COND_COMMAND_COUNT; i++)
+ {
+ SwCollCondition aCond( nullptr, pCmds[ i ].nCnd, pCmds[ i ].nSubCond );
+ static_cast<SwConditionTextFormatColl*>(m_pColl)->RemoveCondition( aCond );
+ const OUString sStyle = pCondItem->GetStyle( i );
+ if (sStyle.isEmpty())
+ continue;
+ SwFormat *const pFindFormat = lcl_FindParaFormat( m_rDoc, sStyle );
+ if (pFindFormat)
+ {
+ aCond.RegisterToFormat( *pFindFormat );
+ static_cast<SwConditionTextFormatColl*>(m_pColl)->InsertCondition( aCond );
+ }
+ }
+
+ m_pColl->GetNotifier().Broadcast(sw::CondCollCondChg(*m_pColl));
+ }
+ else if( pCondItem && !m_pColl->HasWriterListeners() )
+ {
+ // no conditional template, then first create and adopt
+ // all important values
+ SwConditionTextFormatColl* pCColl = m_rDoc.MakeCondTextFormatColl(
+ m_pColl->GetName(), static_cast<SwTextFormatColl*>(m_pColl->DerivedFrom()) );
+ if( m_pColl != &m_pColl->GetNextTextFormatColl() )
+ pCColl->SetNextTextFormatColl( m_pColl->GetNextTextFormatColl() );
+
+ if( m_pColl->IsAssignedToListLevelOfOutlineStyle())
+ pCColl->AssignToListLevelOfOutlineStyle(m_pColl->GetAssignedOutlineStyleLevel());
+ else
+ pCColl->DeleteAssignmentToListLevelOfOutlineStyle();
+
+ const CommandStruct* pCmds = SwCondCollItem::GetCmds();
+ for( sal_uInt16 i = 0; i < COND_COMMAND_COUNT; ++i )
+ {
+ const OUString sStyle = pCondItem->GetStyle( i );
+ if (sStyle.isEmpty())
+ continue;
+ SwTextFormatColl *const pFindFormat = lcl_FindParaFormat( m_rDoc, sStyle );
+ if (pFindFormat)
+ {
+ pCColl->InsertCondition( SwCollCondition( pFindFormat,
+ pCmds[ i ].nCnd, pCmds[ i ].nSubCond ) );
+ }
+ }
+
+ m_rDoc.DelTextFormatColl( m_pColl );
+ m_pColl = pCColl;
+ }
+ if ( bResetIndentAttrsAtParagraphStyle &&
+ rSet.GetItemState( RES_PARATR_NUMRULE, false ) == SfxItemState::SET &&
+ rSet.GetItemState(RES_MARGIN_FIRSTLINE, false) != SfxItemState::SET &&
+ m_pColl->GetItemState(RES_MARGIN_FIRSTLINE, false) == SfxItemState::SET)
+ {
+ aWhichIdsToReset.emplace_back(RES_MARGIN_FIRSTLINE);
+ }
+ if ( bResetIndentAttrsAtParagraphStyle &&
+ rSet.GetItemState( RES_PARATR_NUMRULE, false ) == SfxItemState::SET &&
+ rSet.GetItemState(RES_MARGIN_TEXTLEFT, false) != SfxItemState::SET &&
+ m_pColl->GetItemState(RES_MARGIN_TEXTLEFT, false) == SfxItemState::SET)
+ {
+ aWhichIdsToReset.emplace_back(RES_MARGIN_TEXTLEFT);
+ }
+
+ // #i56252: If a standard numbering style is assigned to a standard paragraph style
+ // we have to create a physical instance of the numbering style. If we do not and
+ // neither the paragraph style nor the numbering style is used in the document
+ // the numbering style will not be saved with the document and the assignment got lost.
+ if( const SfxPoolItem* pNumRuleItem = rSet.GetItemIfSet( RES_PARATR_NUMRULE, false ) )
+ { // Setting a numbering rule?
+ const OUString sNumRule = static_cast<const SwNumRuleItem*>(pNumRuleItem)->GetValue();
+ if (!sNumRule.isEmpty())
+ {
+ SwNumRule* pRule = m_rDoc.FindNumRulePtr( sNumRule );
+ if( !pRule )
+ { // Numbering rule not in use yet.
+ sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( sNumRule, SwGetPoolIdFromName::NumRule );
+ if( USHRT_MAX != nPoolId ) // It's a standard numbering rule
+ {
+ m_rDoc.getIDocumentStylePoolAccess().GetNumRuleFromPool( nPoolId ); // Create numbering rule (physical)
+ }
+ }
+ }
+ }
+
+ pFormat = m_pColl;
+
+ sal_uInt16 nId = m_pColl->GetPoolFormatId() &
+ ~ ( COLL_GET_RANGE_BITS | POOLGRP_NOCOLLID );
+ switch( GetMask() & ( static_cast<SfxStyleSearchBits>(0x0fff) & ~SfxStyleSearchBits::SwCondColl ) )
+ {
+ case SfxStyleSearchBits::SwText:
+ nId |= COLL_TEXT_BITS;
+ break;
+ case SfxStyleSearchBits::SwChapter:
+ nId |= COLL_DOC_BITS;
+ break;
+ case SfxStyleSearchBits::SwList:
+ nId |= COLL_LISTS_BITS;
+ break;
+ case SfxStyleSearchBits::SwIndex:
+ nId |= COLL_REGISTER_BITS;
+ break;
+ case SfxStyleSearchBits::SwExtra:
+ nId |= COLL_EXTRA_BITS;
+ break;
+ case SfxStyleSearchBits::SwHtml:
+ nId |= COLL_HTML_BITS;
+ break;
+ default: break;
+ }
+ m_pColl->SetPoolFormatId( nId );
+ break;
+ }
+ case SfxStyleFamily::Frame:
+ {
+ OSL_ENSURE(m_pFrameFormat, "Where's FrameFormat");
+
+ if(const SfxPoolItem* pAutoUpdate = rSet.GetItemIfSet(SID_ATTR_AUTO_STYLE_UPDATE,false))
+ {
+ m_pFrameFormat->SetAutoUpdateOnDirectFormat(static_cast<const SfxBoolItem*>(pAutoUpdate)->GetValue());
+ }
+ pFormat = m_pFrameFormat;
+ }
+ break;
+
+ case SfxStyleFamily::Page :
+ {
+ OSL_ENSURE(m_pDesc, "Where's PageDescriptor");
+
+ if (m_rDoc.FindPageDesc(m_pDesc->GetName(), &nPgDscPos))
+ {
+ pNewDsc.reset( new SwPageDesc( *m_pDesc ) );
+ // #i48949# - no undo actions for the
+ // copy of the page style
+ ::sw::UndoGuard const ug(m_rDoc.GetIDocumentUndoRedo());
+ m_rDoc.CopyPageDesc(*m_pDesc, *pNewDsc); // #i7983#
+
+ pFormat = &pNewDsc->GetMaster();
+ }
+ }
+ break;
+
+ case SfxStyleFamily::Pseudo:
+ {
+ OSL_ENSURE(m_pNumRule, "Where's NumRule");
+
+ if (!m_pNumRule)
+ break;
+
+ const SfxPoolItem* pItem;
+ switch( rSet.GetItemState( SID_ATTR_NUMBERING_RULE, false, &pItem ))
+ {
+ case SfxItemState::SET:
+ {
+ SvxNumRule& rSetRule = const_cast<SvxNumRule&>(static_cast<const SvxNumBulletItem*>(pItem)->GetNumRule());
+ rSetRule.UnLinkGraphics();
+ SwNumRule aSetRule(*m_pNumRule);
+ aSetRule.SetSvxRule(rSetRule, &m_rDoc);
+ m_rDoc.ChgNumRuleFormats( aSetRule );
+ }
+ break;
+ case SfxItemState::DONTCARE:
+ // set NumRule to default values
+ // what are the default values?
+ {
+ SwNumRule aRule( m_pNumRule->GetName(),
+ // #i89178#
+ numfunc::GetDefaultPositionAndSpaceMode() );
+ m_rDoc.ChgNumRuleFormats( aRule );
+ }
+ break;
+ default: break;
+ }
+ }
+ break;
+
+ default:
+ OSL_ENSURE(false, "unknown style family");
+ }
+
+ if( pFormat && rSet.Count())
+ {
+ SfxItemIter aIter( rSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ do
+ {
+ if( IsInvalidItem( pItem ) ) // Clear
+ {
+ // use method <SwDoc::ResetAttrAtFormat(..)> in order to
+ // create an Undo object for the attribute reset.
+ aWhichIdsToReset.emplace_back(rSet.GetWhichByOffset(aIter.GetCurPos()));
+ }
+
+ pItem = aIter.NextItem();
+ } while (pItem);
+
+ m_rDoc.ResetAttrAtFormat(aWhichIdsToReset, *pFormat);
+
+ SfxItemSet aSet(rSet);
+ aSet.ClearInvalidItems();
+
+ if(SfxStyleFamily::Frame == nFamily)
+ {
+ // Need to check for unique item for DrawingLayer items of type NameOrIndex
+ // and evtl. correct that item to ensure unique names for that type. This call may
+ // modify/correct entries inside of the given SfxItemSet
+ m_rDoc.CheckForUniqueItemForLineFillNameOrIndex(aSet);
+ }
+
+ m_aCoreSet.ClearItem();
+
+ if( pNewDsc )
+ {
+ ::ItemSetToPageDesc( aSet, *pNewDsc );
+ m_rDoc.ChgPageDesc( nPgDscPos, *pNewDsc );
+ m_pDesc = &m_rDoc.GetPageDesc( nPgDscPos );
+ m_rDoc.PreDelPageDesc(pNewDsc.get()); // #i7983#
+ pNewDsc.reset();
+ }
+ else
+ {
+ m_rDoc.ChgFormat(*pFormat, aSet); // put all that is set
+ if (bBroadcast)
+ m_pPool->Broadcast(SfxStyleSheetHint(SfxHintId::StyleSheetModified, *this));
+ }
+ }
+ else
+ {
+ m_aCoreSet.ClearItem();
+ if( pNewDsc ) // we still need to delete it
+ {
+ m_rDoc.PreDelPageDesc(pNewDsc.get()); // #i7983#
+ pNewDsc.reset();
+ }
+ }
+
+ if (m_rDoc.GetIDocumentUndoRedo().DoesUndo())
+ {
+ m_rDoc.GetIDocumentUndoRedo().EndUndo(SwUndoId::END, nullptr);
+ }
+}
+
+static void lcl_SaveStyles( SfxStyleFamily nFamily, std::vector<void*>& rArr, SwDoc& rDoc )
+{
+ switch( nFamily )
+ {
+ case SfxStyleFamily::Char:
+ {
+ const SwCharFormats& rTable = *rDoc.GetCharFormats();
+ for(auto const& rChar: rTable)
+ {
+ rArr.push_back(rChar);
+ }
+ }
+ break;
+ case SfxStyleFamily::Para:
+ {
+ const SwTextFormatColls& rTable = *rDoc.GetTextFormatColls();
+ for(auto const& rPara : rTable)
+ {
+ rArr.push_back(rPara);
+ }
+ }
+ break;
+ case SfxStyleFamily::Frame:
+ {
+ for(auto const& rFrame: *rDoc.GetFrameFormats())
+ {
+ rArr.push_back(rFrame);
+ }
+ }
+ break;
+
+ case SfxStyleFamily::Page:
+ {
+ for( size_t n = 0, nCnt = rDoc.GetPageDescCnt(); n < nCnt; ++n )
+ {
+ rArr.push_back( &rDoc.GetPageDesc( n ) );
+ }
+ }
+ break;
+
+ case SfxStyleFamily::Pseudo:
+ {
+ const SwNumRuleTable& rTable = rDoc.GetNumRuleTable();
+ for(auto const& rPseudo: rTable)
+ {
+ rArr.push_back(rPseudo);
+ }
+ }
+ break;
+ default: break;
+ }
+}
+
+static bool lcl_Contains(const std::vector<void*>& rArr, const void* p)
+{
+ return std::find( rArr.begin(), rArr.end(), p ) != rArr.end();
+}
+
+static void lcl_DeleteInfoStyles( SfxStyleFamily nFamily, std::vector<void*> const & rArr, SwDoc& rDoc )
+{
+ size_t n, nCnt;
+ switch( nFamily )
+ {
+ case SfxStyleFamily::Char:
+ {
+ std::deque<sal_uInt16> aDelArr;
+ const SwCharFormats& rTable = *rDoc.GetCharFormats();
+ for( n = 0, nCnt = rTable.size(); n < nCnt; ++n )
+ {
+ if( !lcl_Contains( rArr, rTable[ n ] ))
+ aDelArr.push_front( n );
+ }
+ for(auto const& rDelArr: aDelArr)
+ rDoc.DelCharFormat( rDelArr );
+ }
+ break;
+
+ case SfxStyleFamily::Para :
+ {
+ std::deque<sal_uInt16> aDelArr;
+ const SwTextFormatColls& rTable = *rDoc.GetTextFormatColls();
+ for( n = 0, nCnt = rTable.size(); n < nCnt; ++n )
+ {
+ if( !lcl_Contains( rArr, rTable[ n ] ))
+ aDelArr.push_front( n );
+ }
+ for(auto const& rDelArr: aDelArr)
+ rDoc.DelTextFormatColl( rDelArr );
+ }
+ break;
+
+ case SfxStyleFamily::Frame:
+ {
+ std::deque<SwFrameFormat*> aDelArr;
+ for(auto const& rFrame: *rDoc.GetFrameFormats())
+ {
+ if( !lcl_Contains( rArr, rFrame ))
+ aDelArr.push_front( rFrame );
+ }
+ for( auto const& rDelArr: aDelArr)
+ rDoc.DelFrameFormat( rDelArr );
+ }
+ break;
+
+ case SfxStyleFamily::Page:
+ {
+ std::deque<size_t> aDelArr;
+ for( n = 0, nCnt = rDoc.GetPageDescCnt(); n < nCnt; ++n )
+ {
+ if( !lcl_Contains( rArr, &rDoc.GetPageDesc( n ) ))
+ aDelArr.push_front( n );
+ }
+ for( auto const& rDelArr: aDelArr )
+ rDoc.DelPageDesc( rDelArr);
+ }
+ break;
+
+ case SfxStyleFamily::Pseudo:
+ {
+ std::deque<SwNumRule*> aDelArr;
+ const SwNumRuleTable& rTable = rDoc.GetNumRuleTable();
+ for( auto const& rPseudo: rTable)
+ {
+ if( !lcl_Contains( rArr, rPseudo ))
+ aDelArr.push_front( rPseudo );
+ }
+ for( auto const& rDelArr: aDelArr)
+ rDoc.DelNumRule( rDelArr->GetName() );
+ }
+ break;
+ default: break;
+ }
+}
+
+// determine the format
+bool SwDocStyleSheet::FillStyleSheet(
+ FillStyleType const eFType, std::optional<SfxItemSet> *const o_ppFlatSet)
+{
+ bool bRet = false;
+ sal_uInt16 nPoolId = USHRT_MAX;
+ SwFormat* pFormat = nullptr;
+
+ bool bCreate = FillPhysical == eFType;
+ bool bDeleteInfo = false;
+ bool bFillOnlyInfo = FillAllInfo == eFType || FillPreview == eFType;
+ std::vector<void*> aDelArr;
+ bool const isModified(m_rDoc.getIDocumentState().IsModified());
+
+ switch(nFamily)
+ {
+ case SfxStyleFamily::Char:
+ m_pCharFormat = lcl_FindCharFormat(m_rDoc, aName, this, bCreate );
+ m_bPhysical = nullptr != m_pCharFormat;
+ if( bFillOnlyInfo && !m_bPhysical )
+ {
+ // create style (plus all needed parents) and clean it up
+ // later - without affecting the undo/redo stack
+ ::sw::UndoGuard const ug(m_rDoc.GetIDocumentUndoRedo());
+ bDeleteInfo = true;
+ ::lcl_SaveStyles( nFamily, aDelArr, m_rDoc );
+ m_pCharFormat = lcl_FindCharFormat(m_rDoc, aName, this );
+ }
+
+ pFormat = m_pCharFormat;
+ m_aLink.clear();
+ if( !bCreate && !pFormat )
+ {
+ if( aName == SwResId(STR_POOLCHR_STANDARD))
+ nPoolId = 0;
+ else
+ nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::ChrFmt );
+ }
+
+ if (m_pCharFormat)
+ {
+ const SwTextFormatColl* pParaFormat = m_pCharFormat->GetLinkedParaFormat();
+ if (pParaFormat)
+ {
+ m_aLink = pParaFormat->GetName();
+ }
+ }
+
+ bRet = nullptr != m_pCharFormat || USHRT_MAX != nPoolId;
+
+ if( bDeleteInfo )
+ m_pCharFormat = nullptr;
+ break;
+
+ case SfxStyleFamily::Para:
+ {
+ m_pColl = lcl_FindParaFormat(m_rDoc, aName, this, bCreate);
+ m_bPhysical = nullptr != m_pColl;
+ if( bFillOnlyInfo && !m_bPhysical )
+ {
+ ::sw::UndoGuard const ug(m_rDoc.GetIDocumentUndoRedo());
+ bDeleteInfo = true;
+ ::lcl_SaveStyles( nFamily, aDelArr, m_rDoc );
+ m_pColl = lcl_FindParaFormat(m_rDoc, aName, this );
+ }
+
+ pFormat = m_pColl;
+ m_aLink.clear();
+ if( m_pColl )
+ {
+ PresetFollow( m_pColl->GetNextTextFormatColl().GetName() );
+ const SwCharFormat* pCharFormat = m_pColl->GetLinkedCharFormat();
+ if (pCharFormat)
+ {
+ m_aLink = pCharFormat->GetName();
+ }
+ }
+ else if( !bCreate )
+ nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::TxtColl );
+
+ bRet = nullptr != m_pColl || USHRT_MAX != nPoolId;
+
+ if( bDeleteInfo )
+ m_pColl = nullptr;
+ }
+ break;
+
+ case SfxStyleFamily::Frame:
+ m_pFrameFormat = lcl_FindFrameFormat(m_rDoc, aName, this, bCreate);
+ m_bPhysical = nullptr != m_pFrameFormat;
+ if (bFillOnlyInfo && !m_bPhysical)
+ {
+ ::sw::UndoGuard const ug(m_rDoc.GetIDocumentUndoRedo());
+ bDeleteInfo = true;
+ ::lcl_SaveStyles( nFamily, aDelArr, m_rDoc );
+ m_pFrameFormat = lcl_FindFrameFormat(m_rDoc, aName, this );
+ }
+ pFormat = m_pFrameFormat;
+ if( !bCreate && !pFormat )
+ nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::FrmFmt );
+
+ bRet = nullptr != m_pFrameFormat || USHRT_MAX != nPoolId;
+
+ if( bDeleteInfo )
+ m_pFrameFormat = nullptr;
+ break;
+
+ case SfxStyleFamily::Page:
+ m_pDesc = lcl_FindPageDesc(m_rDoc, aName, this, bCreate);
+ m_bPhysical = nullptr != m_pDesc;
+ if( bFillOnlyInfo && !m_pDesc )
+ {
+ ::sw::UndoGuard const ug(m_rDoc.GetIDocumentUndoRedo());
+ bDeleteInfo = true;
+ ::lcl_SaveStyles( nFamily, aDelArr, m_rDoc );
+ m_pDesc = lcl_FindPageDesc( m_rDoc, aName, this );
+ }
+
+ if( m_pDesc )
+ {
+ nPoolId = m_pDesc->GetPoolFormatId();
+ nHelpId = m_pDesc->GetPoolHelpId();
+ if (const OUString* pattern = m_pDesc->GetPoolHlpFileId() != UCHAR_MAX
+ ? m_rDoc.GetDocPattern(m_pDesc->GetPoolHlpFileId())
+ : nullptr)
+ aHelpFile = *pattern;
+ else
+ aHelpFile.clear();
+ }
+ else if( !bCreate )
+ nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::PageDesc );
+ SetMask( (USER_FMT & nPoolId) ? SfxStyleSearchBits::UserDefined : SfxStyleSearchBits::Auto );
+
+ bRet = nullptr != m_pDesc || USHRT_MAX != nPoolId;
+ if( bDeleteInfo )
+ m_pDesc = nullptr;
+ break;
+
+ case SfxStyleFamily::Pseudo:
+ m_pNumRule = lcl_FindNumRule(m_rDoc, aName, this, bCreate);
+ m_bPhysical = nullptr != m_pNumRule;
+ if( bFillOnlyInfo && !m_pNumRule )
+ {
+ ::sw::UndoGuard const ug(m_rDoc.GetIDocumentUndoRedo());
+ bDeleteInfo = true;
+ ::lcl_SaveStyles( nFamily, aDelArr, m_rDoc );
+ m_pNumRule = lcl_FindNumRule( m_rDoc, aName, this );
+ }
+
+ if( m_pNumRule )
+ {
+ nPoolId = m_pNumRule->GetPoolFormatId();
+ nHelpId = m_pNumRule->GetPoolHelpId();
+ if (const OUString* pattern = m_pNumRule->GetPoolHlpFileId() != UCHAR_MAX
+ ? m_rDoc.GetDocPattern(m_pNumRule->GetPoolHlpFileId())
+ : nullptr)
+ aHelpFile = *pattern;
+ else
+ aHelpFile.clear();
+ }
+ else if( !bCreate )
+ nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::NumRule );
+ SetMask( (USER_FMT & nPoolId) ? SfxStyleSearchBits::UserDefined : SfxStyleSearchBits::Auto );
+
+ bRet = nullptr != m_pNumRule || USHRT_MAX != nPoolId;
+
+ if( bDeleteInfo )
+ m_pNumRule = nullptr;
+ break;
+
+ case SfxStyleFamily::Table:
+ m_pTableFormat = lcl_FindTableStyle(m_rDoc, aName, this, bCreate);
+ SetMask((m_pTableFormat && m_pTableFormat->IsUserDefined()) ? SfxStyleSearchBits::UserDefined : SfxStyleSearchBits::Auto);
+ bRet = m_bPhysical = (nullptr != m_pTableFormat);
+ break;
+
+ case SfxStyleFamily::Cell:
+ m_pBoxFormat = lcl_FindCellStyle(m_rDoc, aName, this);
+ bRet = m_bPhysical = (nullptr != m_pBoxFormat);
+ break;
+ default:; //prevent warning
+ }
+
+ if( SfxStyleFamily::Char == nFamily ||
+ SfxStyleFamily::Para == nFamily ||
+ SfxStyleFamily::Frame == nFamily )
+ {
+ if( pFormat )
+ nPoolId = pFormat->GetPoolFormatId();
+
+ SfxStyleSearchBits _nMask = SfxStyleSearchBits::Auto;
+ if( pFormat == m_rDoc.GetDfltCharFormat() )
+ _nMask |= SfxStyleSearchBits::ReadOnly;
+ else if( USER_FMT & nPoolId )
+ _nMask |= SfxStyleSearchBits::UserDefined;
+
+ switch ( COLL_GET_RANGE_BITS & nPoolId )
+ {
+ case COLL_TEXT_BITS: _nMask |= SfxStyleSearchBits::SwText; break;
+ case COLL_DOC_BITS : _nMask |= SfxStyleSearchBits::SwChapter; break;
+ case COLL_LISTS_BITS: _nMask |= SfxStyleSearchBits::SwList; break;
+ case COLL_REGISTER_BITS: _nMask |= SfxStyleSearchBits::SwIndex; break;
+ case COLL_EXTRA_BITS: _nMask |= SfxStyleSearchBits::SwExtra; break;
+ case COLL_HTML_BITS: _nMask |= SfxStyleSearchBits::SwHtml; break;
+ }
+
+ if( pFormat )
+ {
+ OSL_ENSURE( m_bPhysical, "Format not found" );
+
+ nHelpId = pFormat->GetPoolHelpId();
+ if (const OUString* pattern = pFormat->GetPoolHlpFileId() != UCHAR_MAX
+ ? m_rDoc.GetDocPattern(pFormat->GetPoolHlpFileId())
+ : nullptr)
+ aHelpFile = *pattern;
+ else
+ aHelpFile.clear();
+
+ if( RES_CONDTXTFMTCOLL == pFormat->Which() )
+ _nMask |= SfxStyleSearchBits::SwCondColl;
+
+ if (FillPreview == eFType)
+ {
+ assert(o_ppFlatSet);
+ lcl_SwFormatToFlatItemSet(pFormat, *o_ppFlatSet);
+ }
+ }
+
+ SetMask( _nMask );
+ }
+ if( bDeleteInfo && bFillOnlyInfo )
+ {
+ ::sw::UndoGuard const ug(m_rDoc.GetIDocumentUndoRedo());
+ ::lcl_DeleteInfoStyles( nFamily, aDelArr, m_rDoc );
+ if (!isModified)
+ {
+ m_rDoc.getIDocumentState().ResetModified();
+ }
+ }
+ return bRet;
+}
+
+// Create new format in Core
+void SwDocStyleSheet::Create()
+{
+ switch(nFamily)
+ {
+ case SfxStyleFamily::Char :
+ m_pCharFormat = lcl_FindCharFormat( m_rDoc, aName );
+ if( !m_pCharFormat )
+ m_pCharFormat = m_rDoc.MakeCharFormat(aName,
+ m_rDoc.GetDfltCharFormat());
+ m_pCharFormat->SetAuto(false);
+ break;
+
+ case SfxStyleFamily::Para :
+ m_pColl = lcl_FindParaFormat( m_rDoc, aName );
+ if( !m_pColl )
+ {
+ SwTextFormatColl *pPar = (*m_rDoc.GetTextFormatColls())[0];
+ if( nMask & SfxStyleSearchBits::SwCondColl )
+ m_pColl = m_rDoc.MakeCondTextFormatColl( aName, pPar );
+ else
+ m_pColl = m_rDoc.MakeTextFormatColl( aName, pPar );
+ }
+ break;
+
+ case SfxStyleFamily::Frame:
+ m_pFrameFormat = lcl_FindFrameFormat( m_rDoc, aName );
+ if( !m_pFrameFormat )
+ m_pFrameFormat = m_rDoc.MakeFrameFormat(aName, m_rDoc.GetDfltFrameFormat(), false, false);
+
+ break;
+
+ case SfxStyleFamily::Page :
+ m_pDesc = lcl_FindPageDesc( m_rDoc, aName );
+ if( !m_pDesc )
+ {
+ m_pDesc = m_rDoc.MakePageDesc(aName);
+ }
+ break;
+
+ case SfxStyleFamily::Pseudo:
+ m_pNumRule = lcl_FindNumRule( m_rDoc, aName );
+ if( !m_pNumRule )
+ {
+ const OUString sTmpNm( aName.isEmpty() ? m_rDoc.GetUniqueNumRuleName() : aName );
+ SwNumRule* pRule = m_rDoc.GetNumRuleTable()[
+ m_rDoc.MakeNumRule( sTmpNm, nullptr, false,
+ // #i89178#
+ numfunc::GetDefaultPositionAndSpaceMode() ) ];
+ pRule->SetAutoRule( false );
+ if( aName.isEmpty() )
+ {
+ // #i91400#
+ pRule->SetName( aName, m_rDoc.getIDocumentListsAccess() );
+ }
+ m_pNumRule = pRule;
+ }
+ break;
+
+ case SfxStyleFamily::Table:
+ if (aName.isEmpty())
+ return;
+ m_pTableFormat = lcl_FindTableStyle(m_rDoc, aName);
+ if (!m_pTableFormat)
+ {
+ m_rDoc.MakeTableStyle(aName);
+ m_pTableFormat = m_rDoc.GetTableStyles().FindAutoFormat(aName);
+ SAL_WARN_IF(!m_pTableFormat, "sw.ui", "Recently added auto format not found");
+ }
+ break;
+ default:; //prevent warning
+ }
+ m_bPhysical = true;
+ m_aCoreSet.ClearItem();
+}
+
+SwCharFormat* SwDocStyleSheet::GetCharFormat()
+{
+ if(!m_bPhysical)
+ FillStyleSheet( FillPhysical );
+ return m_pCharFormat;
+}
+
+SwTextFormatColl* SwDocStyleSheet::GetCollection()
+{
+ if(!m_bPhysical)
+ FillStyleSheet( FillPhysical );
+ return m_pColl;
+}
+
+const SwPageDesc* SwDocStyleSheet::GetPageDesc()
+{
+ if(!m_bPhysical)
+ FillStyleSheet( FillPhysical );
+ return m_pDesc;
+}
+
+const SwNumRule * SwDocStyleSheet::GetNumRule()
+{
+ if(!m_bPhysical)
+ FillStyleSheet( FillPhysical );
+ return m_pNumRule;
+}
+
+
+void SwDocStyleSheet::SetNumRule(const SwNumRule& rRule)
+{
+ OSL_ENSURE(m_pNumRule, "Where is the NumRule");
+ m_rDoc.ChgNumRuleFormats( rRule );
+}
+
+SwTableAutoFormat* SwDocStyleSheet::GetTableFormat()
+{
+ if(!m_bPhysical)
+ FillStyleSheet( FillPhysical );
+ assert(m_pTableFormat && "SwDocStyleSheet table style, SwTableAutoFormat not found");
+ return m_pTableFormat;
+}
+
+// re-generate Name AND Family from String
+// First() and Next() (see below) insert an identification letter at Pos.1
+
+void SwDocStyleSheet::PresetNameAndFamily(SfxStyleFamily eFamily, const OUString& rName)
+{
+ this->nFamily = eFamily;
+ this->aName = rName;
+}
+
+// Is the format physically present yet
+void SwDocStyleSheet::SetPhysical(bool bPhys)
+{
+ m_bPhysical = bPhys;
+
+ if(!bPhys)
+ {
+ m_pCharFormat = nullptr;
+ m_pColl = nullptr;
+ m_pFrameFormat = nullptr;
+ m_pDesc = nullptr;
+ }
+}
+
+SwFrameFormat* SwDocStyleSheet::GetFrameFormat()
+{
+ if(!m_bPhysical)
+ FillStyleSheet( FillPhysical );
+ return m_pFrameFormat;
+}
+
+bool SwDocStyleSheet::IsUsed() const
+{
+ if( !m_bPhysical )
+ {
+ SwDocStyleSheet* pThis = const_cast<SwDocStyleSheet*>(this);
+ pThis->FillStyleSheet( FillOnlyName );
+ }
+
+ if( !m_bPhysical )
+ return false;
+
+ const sw::BroadcastingModify* pMod;
+ switch( nFamily )
+ {
+ case SfxStyleFamily::Char : pMod = m_pCharFormat; break;
+ case SfxStyleFamily::Para : pMod = m_pColl; break;
+ case SfxStyleFamily::Frame: pMod = m_pFrameFormat; break;
+ case SfxStyleFamily::Page : pMod = m_pDesc; break;
+
+ case SfxStyleFamily::Pseudo:
+ return m_pNumRule && m_rDoc.IsUsed(*m_pNumRule);
+
+ case SfxStyleFamily::Table:
+ return m_pTableFormat && m_rDoc.IsUsed( *m_pTableFormat );
+
+ default:
+ OSL_ENSURE(false, "unknown style family");
+ return false;
+ }
+
+ if (m_rDoc.IsUsed(*pMod))
+ return true;
+
+ SfxStyleSheetIterator aIter(static_cast<SwDocStyleSheetPool*>(m_pPool)->GetEEStyleSheetPool(), nFamily,
+ SfxStyleSearchBits::Used);
+ return aIter.Find(GetName()) != nullptr;
+}
+
+OUString SwDocStyleSheet::GetUsedBy()
+{
+ return m_pNumRule ? m_pNumRule->MakeParagraphStyleListString() : OUString();
+}
+
+sal_uLong SwDocStyleSheet::GetHelpId( OUString& rFile )
+{
+ sal_uInt16 nId = 0;
+ sal_uInt16 nPoolId = 0;
+ unsigned char nFileId = UCHAR_MAX;
+
+ rFile = "swrhlppi.hlp";
+
+ const SwFormat* pTmpFormat = nullptr;
+ switch( nFamily )
+ {
+ case SfxStyleFamily::Char :
+ if( !m_pCharFormat &&
+ nullptr == (m_pCharFormat = lcl_FindCharFormat( m_rDoc, aName, nullptr, false )) )
+ {
+ nId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::ChrFmt );
+ return USHRT_MAX == nId ? 0 : nId;
+ }
+ pTmpFormat = m_pCharFormat;
+ break;
+
+ case SfxStyleFamily::Para:
+ if( !m_pColl &&
+ nullptr == ( m_pColl = lcl_FindParaFormat( m_rDoc, aName, nullptr, false )) )
+ {
+ nId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::TxtColl );
+ return USHRT_MAX == nId ? 0 : nId;
+ }
+ pTmpFormat = m_pColl;
+ break;
+
+ case SfxStyleFamily::Frame:
+ if( !m_pFrameFormat &&
+ nullptr == ( m_pFrameFormat = lcl_FindFrameFormat( m_rDoc, aName, nullptr, false ) ) )
+ {
+ nId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::FrmFmt );
+ return USHRT_MAX == nId ? 0 : nId;
+ }
+ pTmpFormat = m_pFrameFormat;
+ break;
+
+ case SfxStyleFamily::Page:
+ if( !m_pDesc &&
+ nullptr == ( m_pDesc = lcl_FindPageDesc( m_rDoc, aName, nullptr, false ) ) )
+ {
+ nId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::PageDesc );
+ return USHRT_MAX == nId ? 0 : nId;
+ }
+
+ nId = m_pDesc->GetPoolHelpId();
+ nFileId = m_pDesc->GetPoolHlpFileId();
+ nPoolId = m_pDesc->GetPoolFormatId();
+ break;
+
+ case SfxStyleFamily::Pseudo:
+ if( !m_pNumRule &&
+ nullptr == ( m_pNumRule = lcl_FindNumRule( m_rDoc, aName, nullptr, false ) ) )
+ {
+ nId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::NumRule );
+ return USHRT_MAX == nId ? 0 : nId;
+ }
+
+ nId = m_pNumRule->GetPoolHelpId();
+ nFileId = m_pNumRule->GetPoolHlpFileId();
+ nPoolId = m_pNumRule->GetPoolFormatId();
+ break;
+
+ default:
+ OSL_ENSURE(false, "unknown style family");
+ return 0;
+ }
+
+ if( pTmpFormat )
+ {
+ nId = pTmpFormat->GetPoolHelpId();
+ nFileId = pTmpFormat->GetPoolHlpFileId();
+ nPoolId = pTmpFormat->GetPoolFormatId();
+ }
+
+ if( UCHAR_MAX != nFileId )
+ {
+ const OUString *pTemplate = m_rDoc.GetDocPattern( nFileId );
+ if( pTemplate )
+ {
+ rFile = *pTemplate;
+ }
+ }
+ else if( !IsPoolUserFormat( nPoolId ) )
+ {
+ nId = nPoolId;
+ }
+
+ // because SFX acts like that, with HelpId:
+ if( USHRT_MAX == nId )
+ nId = 0; // don't show Help accordingly
+
+ return nId;
+}
+
+void SwDocStyleSheet::SetHelpId( const OUString& r, sal_uLong nId )
+{
+ sal_uInt8 nFileId = static_cast< sal_uInt8 >(m_rDoc.SetDocPattern( r ));
+ sal_uInt16 nHId = static_cast< sal_uInt16 >(nId); //!! SFX changed over to ULONG arbitrarily!
+
+ SwFormat* pTmpFormat = nullptr;
+ switch( nFamily )
+ {
+ case SfxStyleFamily::Char : pTmpFormat = m_pCharFormat; break;
+ case SfxStyleFamily::Para : pTmpFormat = m_pColl; break;
+ case SfxStyleFamily::Frame: pTmpFormat = m_pFrameFormat; break;
+ case SfxStyleFamily::Page :
+ const_cast<SwPageDesc*>(m_pDesc)->SetPoolHelpId( nHId );
+ const_cast<SwPageDesc*>(m_pDesc)->SetPoolHlpFileId( nFileId );
+ break;
+
+ case SfxStyleFamily::Pseudo:
+ const_cast<SwNumRule*>(m_pNumRule)->SetPoolHelpId( nHId );
+ const_cast<SwNumRule*>(m_pNumRule)->SetPoolHlpFileId( nFileId );
+ break;
+
+ default:
+ OSL_ENSURE(false, "unknown style family");
+ return ;
+ }
+ if( pTmpFormat )
+ {
+ pTmpFormat->SetPoolHelpId( nHId );
+ pTmpFormat->SetPoolHlpFileId( nFileId );
+ }
+}
+
+// methods for DocStyleSheetPool
+SwDocStyleSheetPool::SwDocStyleSheetPool( SwDoc& rDocument, bool bOrg )
+ : SfxStyleSheetBasePool(rDocument.GetAttrPool())
+ , mxStyleSheet(new SwDocStyleSheet(rDocument, *this))
+ , mxEEStyleSheetPool(new EEStyleSheetPool(this))
+ , m_rDoc(rDocument)
+{
+ m_bOrganizer = bOrg;
+}
+
+SwDocStyleSheetPool::~SwDocStyleSheetPool()
+{
+}
+
+SfxStyleSheetBase& SwDocStyleSheetPool::Make( const OUString& rName,
+ SfxStyleFamily eFam,
+ SfxStyleSearchBits _nMask)
+{
+ mxStyleSheet->PresetName(rName);
+ mxStyleSheet->PresetParent(OUString());
+ mxStyleSheet->PresetFollow(OUString());
+ mxStyleSheet->SetMask(_nMask) ;
+ mxStyleSheet->SetFamily(eFam);
+ mxStyleSheet->SetPhysical(true);
+ mxStyleSheet->Create();
+
+ return *mxStyleSheet;
+}
+
+rtl::Reference<SfxStyleSheetBase> SwDocStyleSheetPool::Create( const SfxStyleSheetBase& /*rOrg*/)
+{
+ OSL_ENSURE(false , "Create in SW-Stylesheet-Pool not possible" );
+ return nullptr;
+}
+
+rtl::Reference<SfxStyleSheetBase> SwDocStyleSheetPool::Create( const OUString &,
+ SfxStyleFamily, SfxStyleSearchBits )
+{
+ OSL_ENSURE( false, "Create in SW-Stylesheet-Pool not possible" );
+ return nullptr;
+}
+
+std::unique_ptr<SfxStyleSheetIterator> SwDocStyleSheetPool::CreateIterator( SfxStyleFamily eFam, SfxStyleSearchBits _nMask )
+{
+ return std::make_unique<SwStyleSheetIterator>(*this, eFam, _nMask);
+}
+
+void SwDocStyleSheetPool::dispose()
+{
+ mxStyleSheet.clear();
+ mxEEStyleSheetPool.clear();
+}
+
+void SwDocStyleSheetPool::Remove( SfxStyleSheetBase* pStyle)
+{
+ if( !pStyle )
+ return;
+
+ bool bBroadcast = true;
+ SwImplShellAction aTmpSh( m_rDoc );
+ const OUString sName = pStyle->GetName();
+ switch( pStyle->GetFamily() )
+ {
+ case SfxStyleFamily::Char:
+ {
+ SwCharFormat* pFormat = lcl_FindCharFormat(m_rDoc, sName, nullptr, false );
+ if(pFormat)
+ m_rDoc.DelCharFormat(pFormat);
+ }
+ break;
+ case SfxStyleFamily::Para:
+ {
+ SwTextFormatColl* pColl = lcl_FindParaFormat(m_rDoc, sName, nullptr, false );
+ if(pColl)
+ m_rDoc.DelTextFormatColl(pColl);
+ }
+ break;
+ case SfxStyleFamily::Frame:
+ {
+ SwFrameFormat* pFormat = lcl_FindFrameFormat(m_rDoc, sName, nullptr, false );
+ if(pFormat)
+ m_rDoc.DelFrameFormat(pFormat);
+ }
+ break;
+ case SfxStyleFamily::Page :
+ {
+ m_rDoc.DelPageDesc(sName);
+ }
+ break;
+
+ case SfxStyleFamily::Pseudo:
+ {
+ if( !m_rDoc.DelNumRule( sName ) )
+ // Only send Broadcast, when something was deleted
+ bBroadcast = false;
+ }
+ break;
+
+ case SfxStyleFamily::Table:
+ {
+ m_rDoc.DelTableStyle(sName);
+ }
+ break;
+
+ default:
+ OSL_ENSURE(false, "unknown style family");
+ bBroadcast = false;
+ }
+
+ if( bBroadcast )
+ Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetErased, *pStyle ) );
+}
+
+SfxStyleSheetBase* SwDocStyleSheetPool::Find(const OUString& rName,
+ SfxStyleFamily eFam, SfxStyleSearchBits n)
+{
+ SfxStyleSearchBits nSMask = n;
+ if( SfxStyleFamily::Para == eFam && m_rDoc.getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) )
+ {
+ // then only HTML-Templates are of interest
+ if( SfxStyleSearchBits::All == nSMask )
+ nSMask = SfxStyleSearchBits::SwHtml | SfxStyleSearchBits::UserDefined | SfxStyleSearchBits::Used;
+ else
+ nSMask &= SfxStyleSearchBits::Used | SfxStyleSearchBits::UserDefined |
+ SfxStyleSearchBits::SwCondColl | SfxStyleSearchBits::SwHtml;
+ if( nSMask == SfxStyleSearchBits::Auto )
+ nSMask = SfxStyleSearchBits::SwHtml;
+ }
+
+ const bool bSearchUsed = ( n != SfxStyleSearchBits::All && n & SfxStyleSearchBits::Used );
+ const sw::BroadcastingModify* pMod = nullptr;
+
+ mxStyleSheet->SetPhysical( false );
+ mxStyleSheet->PresetName( rName );
+ mxStyleSheet->SetFamily( eFam );
+ bool bFnd = mxStyleSheet->FillStyleSheet( SwDocStyleSheet::FillOnlyName );
+
+ if( mxStyleSheet->IsPhysical() )
+ {
+ switch( eFam )
+ {
+ case SfxStyleFamily::Char:
+ pMod = mxStyleSheet->GetCharFormat();
+ break;
+
+ case SfxStyleFamily::Para:
+ pMod = mxStyleSheet->GetCollection();
+ break;
+
+ case SfxStyleFamily::Frame:
+ pMod = mxStyleSheet->GetFrameFormat();
+ break;
+
+ case SfxStyleFamily::Page:
+ pMod = mxStyleSheet->GetPageDesc();
+ break;
+
+ case SfxStyleFamily::Pseudo:
+ {
+ const SwNumRule* pRule = mxStyleSheet->GetNumRule();
+ if( pRule &&
+ !bSearchUsed &&
+ (( nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::UserDefined
+ ? !(pRule->GetPoolFormatId() & USER_FMT)
+ // searched for used and found none
+ : bSearchUsed ))
+ bFnd = false;
+ }
+ break;
+
+ case SfxStyleFamily::Table:
+ case SfxStyleFamily::Cell:
+ break;
+ default:
+ OSL_ENSURE(false, "unknown style family");
+ }
+ }
+
+ // then evaluate the mask:
+ if( pMod && !bSearchUsed )
+ {
+ const sal_uInt16 nId = SfxStyleFamily::Page == eFam
+ ? static_cast<const SwPageDesc*>(pMod)->GetPoolFormatId()
+ : static_cast<const SwFormat*>(pMod)->GetPoolFormatId();
+
+ if( ( nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::UserDefined
+ && !(nId & USER_FMT) )
+ // searched for used and found none
+ bFnd = false;
+ }
+ return bFnd ? mxStyleSheet.get() : nullptr;
+}
+
+SwStyleSheetIterator::SwStyleSheetIterator(SwDocStyleSheetPool& rBase,
+ SfxStyleFamily eFam, SfxStyleSearchBits n )
+ : SfxStyleSheetIterator(&rBase, eFam, n)
+ , mxIterSheet(new SwDocStyleSheet(rBase.GetDoc(), rBase))
+ , mxStyleSheet(new SwDocStyleSheet(rBase.GetDoc(), rBase))
+{
+ m_bFirstCalled = false;
+ m_nLastPos = 0;
+ StartListening(rBase);
+}
+
+SwStyleSheetIterator::~SwStyleSheetIterator()
+{
+ EndListening( *mxIterSheet->GetPool() );
+}
+
+sal_Int32 SwStyleSheetIterator::Count()
+{
+ // let the list fill correctly!!
+ if( !m_bFirstCalled )
+ First();
+ return m_aLst.size();
+}
+
+SfxStyleSheetBase* SwStyleSheetIterator::operator[]( sal_Int32 nIdx )
+{
+ // found
+ if( !m_bFirstCalled )
+ First();
+ auto const & rEntry = m_aLst[ nIdx ];
+ mxStyleSheet->PresetNameAndFamily( rEntry.first, rEntry.second );
+ mxStyleSheet->SetPhysical( false );
+ mxStyleSheet->FillStyleSheet( SwDocStyleSheet::FillOnlyName );
+
+ return mxStyleSheet.get();
+}
+
+SfxStyleSheetBase* SwStyleSheetIterator::First()
+{
+ // Delete old list
+ m_bFirstCalled = true;
+ m_nLastPos = 0;
+ m_aLst.clear();
+
+ // Delete current
+ mxIterSheet->Reset();
+
+ const SwDoc& rDoc = static_cast<const SwDocStyleSheetPool*>(pBasePool)->GetDoc();
+ const SfxStyleSearchBits nSrchMask = nMask;
+ const bool bIsSearchUsed = SearchUsed();
+
+ bool bSearchHidden( nMask & SfxStyleSearchBits::Hidden );
+ bool bOnlyHidden = nMask == SfxStyleSearchBits::Hidden;
+
+ const bool bOrganizer = static_cast<const SwDocStyleSheetPool*>(pBasePool)->IsOrganizerMode();
+ bool bAll = ( nSrchMask & SfxStyleSearchBits::AllVisible ) == SfxStyleSearchBits::AllVisible;
+
+ if( nSearchFamily == SfxStyleFamily::Char
+ || nSearchFamily == SfxStyleFamily::All )
+ {
+ const size_t nArrLen = rDoc.GetCharFormats()->size();
+ for( size_t i = 0; i < nArrLen; i++ )
+ {
+ SwCharFormat* pFormat = (*rDoc.GetCharFormats())[ i ];
+
+ const bool bUsed = bIsSearchUsed && (bOrganizer || rDoc.IsUsed(*pFormat));
+ if( ( !bSearchHidden && pFormat->IsHidden() && !bUsed ) || ( pFormat->IsDefault() && pFormat != rDoc.GetDfltCharFormat() ) )
+ continue;
+
+ if ( nSrchMask == SfxStyleSearchBits::Hidden && !pFormat->IsHidden( ) )
+ continue;
+
+ if( !bUsed )
+ {
+ // Standard is no User template
+ const sal_uInt16 nId = rDoc.GetDfltCharFormat() == pFormat ?
+ sal_uInt16( RES_POOLCHR_INET_NORMAL ):
+ pFormat->GetPoolFormatId();
+ if( (nSrchMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::UserDefined
+ ? !(nId & USER_FMT)
+ // searched for used and found none
+ : bIsSearchUsed )
+ {
+ continue;
+ }
+
+ if( rDoc.getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) && !(nId & USER_FMT) &&
+ ( RES_POOLCHR_HTML_BEGIN > nId || nId >= RES_POOLCHR_HTML_END ) &&
+ RES_POOLCHR_INET_NORMAL != nId &&
+ RES_POOLCHR_INET_VISIT != nId &&
+ RES_POOLCHR_FOOTNOTE != nId &&
+ RES_POOLCHR_ENDNOTE != nId )
+ continue;
+ }
+
+ m_aLst.Append( SfxStyleFamily::Char, pFormat == rDoc.GetDfltCharFormat()
+ ? SwResId(STR_POOLCHR_STANDARD)
+ : pFormat->GetName() );
+ }
+
+ // PoolFormat
+ if( bAll )
+ {
+ if( ! rDoc.getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) )
+ AppendStyleList(SwStyleNameMapper::GetChrFormatUINameArray(),
+ bIsSearchUsed, bSearchHidden, bOnlyHidden,
+ SwGetPoolIdFromName::ChrFmt, SfxStyleFamily::Char);
+ else
+ {
+ m_aLst.Append( SfxStyleFamily::Char, SwStyleNameMapper::GetChrFormatUINameArray()[
+ RES_POOLCHR_INET_NORMAL - RES_POOLCHR_BEGIN ] );
+ m_aLst.Append( SfxStyleFamily::Char, SwStyleNameMapper::GetChrFormatUINameArray()[
+ RES_POOLCHR_INET_VISIT - RES_POOLCHR_BEGIN ] );
+ m_aLst.Append( SfxStyleFamily::Char, SwStyleNameMapper::GetChrFormatUINameArray()[
+ RES_POOLCHR_ENDNOTE - RES_POOLCHR_BEGIN ] );
+ m_aLst.Append( SfxStyleFamily::Char, SwStyleNameMapper::GetChrFormatUINameArray()[
+ RES_POOLCHR_FOOTNOTE - RES_POOLCHR_BEGIN ] );
+ }
+ AppendStyleList(SwStyleNameMapper::GetHTMLChrFormatUINameArray(),
+ bIsSearchUsed, bSearchHidden, bOnlyHidden,
+ SwGetPoolIdFromName::ChrFmt, SfxStyleFamily::Char);
+ }
+ }
+
+ if( nSearchFamily == SfxStyleFamily::Para ||
+ nSearchFamily == SfxStyleFamily::All )
+ {
+ SfxStyleSearchBits nSMask = nSrchMask;
+ if( rDoc.getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) )
+ {
+ // then only HTML-Template are of interest
+ if( SfxStyleSearchBits::AllVisible == ( nSMask & SfxStyleSearchBits::AllVisible ) )
+ nSMask = SfxStyleSearchBits::SwHtml | SfxStyleSearchBits::UserDefined |
+ SfxStyleSearchBits::Used;
+ else
+ nSMask &= SfxStyleSearchBits::Used | SfxStyleSearchBits::UserDefined |
+ SfxStyleSearchBits::SwCondColl | SfxStyleSearchBits::SwHtml;
+ if( nSMask == SfxStyleSearchBits::Auto )
+ nSMask = SfxStyleSearchBits::SwHtml;
+ }
+
+ const size_t nArrLen = rDoc.GetTextFormatColls()->size();
+ for( size_t i = 0; i < nArrLen; i++ )
+ {
+ SwTextFormatColl* pColl = (*rDoc.GetTextFormatColls())[ i ];
+
+ const bool bUsed = bOrganizer || rDoc.IsUsed(*pColl) || IsUsedInComments(pColl->GetName());
+ if ( ( !bSearchHidden && pColl->IsHidden( ) && !bUsed ) || pColl->IsDefault() )
+ continue;
+
+ if ( nSMask == SfxStyleSearchBits::Hidden && !pColl->IsHidden( ) )
+ continue;
+
+ if( !(bIsSearchUsed && bUsed ))
+ {
+ const sal_uInt16 nId = pColl->GetPoolFormatId();
+ auto tmpMask = nSMask & ~SfxStyleSearchBits::Used;
+ if (tmpMask == SfxStyleSearchBits::UserDefined)
+ {
+ if(!IsPoolUserFormat(nId)) continue;
+ }
+ else if (tmpMask == SfxStyleSearchBits::SwText)
+ {
+ if((nId & COLL_GET_RANGE_BITS) != COLL_TEXT_BITS) continue;
+ }
+ else if (tmpMask == SfxStyleSearchBits::SwChapter)
+ {
+ if((nId & COLL_GET_RANGE_BITS) != COLL_DOC_BITS) continue;
+ }
+ else if (tmpMask == SfxStyleSearchBits::SwList)
+ {
+ if((nId & COLL_GET_RANGE_BITS) != COLL_LISTS_BITS) continue;
+ }
+ else if (tmpMask == SfxStyleSearchBits::SwIndex)
+ {
+ if((nId & COLL_GET_RANGE_BITS) != COLL_REGISTER_BITS) continue;
+ }
+ else if (tmpMask == SfxStyleSearchBits::SwExtra)
+ {
+ if((nId & COLL_GET_RANGE_BITS) != COLL_EXTRA_BITS) continue;
+ }
+ else if (tmpMask == (SfxStyleSearchBits::SwHtml | SfxStyleSearchBits::UserDefined)
+ || tmpMask == SfxStyleSearchBits::SwHtml)
+ {
+ if((tmpMask & SfxStyleSearchBits::UserDefined) && IsPoolUserFormat(nId))
+ ; // do nothing
+ else if( (nId & COLL_GET_RANGE_BITS) != COLL_HTML_BITS)
+ {
+ // but some we also want to see in this section
+ bool bContinue = true;
+ switch( nId )
+ {
+ case RES_POOLCOLL_SEND_ADDRESS: // --> ADDRESS
+ case RES_POOLCOLL_TABLE_HDLN: // --> TH
+ case RES_POOLCOLL_TABLE: // --> TD
+ case RES_POOLCOLL_TEXT: // --> P
+ case RES_POOLCOLL_HEADLINE_BASE:// --> H
+ case RES_POOLCOLL_HEADLINE1: // --> H1
+ case RES_POOLCOLL_HEADLINE2: // --> H2
+ case RES_POOLCOLL_HEADLINE3: // --> H3
+ case RES_POOLCOLL_HEADLINE4: // --> H4
+ case RES_POOLCOLL_HEADLINE5: // --> H5
+ case RES_POOLCOLL_HEADLINE6: // --> H6
+ case RES_POOLCOLL_STANDARD: // --> P
+ case RES_POOLCOLL_FOOTNOTE:
+ case RES_POOLCOLL_ENDNOTE:
+ bContinue = false;
+ break;
+ }
+ if( bContinue )
+ continue;
+ }
+ }
+ else if (tmpMask == SfxStyleSearchBits::SwCondColl)
+ {
+ if( RES_CONDTXTFMTCOLL != pColl->Which() ) continue;
+ }
+ else
+ {
+ // searched for used and found none
+ if( bIsSearchUsed )
+ continue;
+ }
+ }
+ m_aLst.Append( SfxStyleFamily::Para, pColl->GetName() );
+ }
+
+ bAll = ( nSMask & SfxStyleSearchBits::AllVisible ) == SfxStyleSearchBits::AllVisible;
+ if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwText )
+ AppendStyleList(SwStyleNameMapper::GetTextUINameArray(),
+ bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::TxtColl, SfxStyleFamily::Para );
+ if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwChapter )
+ AppendStyleList(SwStyleNameMapper::GetDocUINameArray(),
+ bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::TxtColl, SfxStyleFamily::Para ) ;
+ if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwList )
+ AppendStyleList(SwStyleNameMapper::GetListsUINameArray(),
+ bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::TxtColl, SfxStyleFamily::Para ) ;
+ if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwIndex )
+ AppendStyleList(SwStyleNameMapper::GetRegisterUINameArray(),
+ bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::TxtColl, SfxStyleFamily::Para ) ;
+ if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwExtra )
+ AppendStyleList(SwStyleNameMapper::GetExtraUINameArray(),
+ bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::TxtColl, SfxStyleFamily::Para ) ;
+ if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwCondColl )
+ {
+ if( !bIsSearchUsed ||
+ rDoc.getIDocumentStylePoolAccess().IsPoolTextCollUsed( RES_POOLCOLL_TEXT ))
+ m_aLst.Append( SfxStyleFamily::Para, SwStyleNameMapper::GetTextUINameArray()[
+ RES_POOLCOLL_TEXT - RES_POOLCOLL_TEXT_BEGIN ] );
+ }
+ if ( bAll ||
+ (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwHtml ||
+ (nSMask & ~SfxStyleSearchBits::Used) ==
+ (SfxStyleSearchBits::SwHtml | SfxStyleSearchBits::UserDefined) )
+ {
+ AppendStyleList(SwStyleNameMapper::GetHTMLUINameArray(),
+ bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::TxtColl, SfxStyleFamily::Para ) ;
+ if( !bAll )
+ {
+ // then also the ones, that we are mapping:
+ static sal_uInt16 aPoolIds[] = {
+ RES_POOLCOLL_SEND_ADDRESS, // --> ADDRESS
+ RES_POOLCOLL_TABLE_HDLN, // --> TH
+ RES_POOLCOLL_TABLE, // --> TD
+ RES_POOLCOLL_STANDARD, // --> P
+ RES_POOLCOLL_TEXT, // --> P
+ RES_POOLCOLL_HEADLINE_BASE, // --> H
+ RES_POOLCOLL_HEADLINE1, // --> H1
+ RES_POOLCOLL_HEADLINE2, // --> H2
+ RES_POOLCOLL_HEADLINE3, // --> H3
+ RES_POOLCOLL_HEADLINE4, // --> H4
+ RES_POOLCOLL_HEADLINE5, // --> H5
+ RES_POOLCOLL_HEADLINE6, // --> H6
+ RES_POOLCOLL_FOOTNOTE,
+ RES_POOLCOLL_ENDNOTE,
+ 0
+ };
+
+ sal_uInt16* pPoolIds = aPoolIds;
+ OUString s;
+ while( *pPoolIds )
+ {
+ if( !bIsSearchUsed || rDoc.getIDocumentStylePoolAccess().IsPoolTextCollUsed( *pPoolIds ) )
+ {
+ s = SwStyleNameMapper::GetUIName( *pPoolIds, s );
+ m_aLst.Append( SfxStyleFamily::Para, s);
+ }
+ ++pPoolIds;
+ }
+ }
+ }
+ }
+
+ if( nSearchFamily == SfxStyleFamily::Frame ||
+ nSearchFamily == SfxStyleFamily::All )
+ {
+ const size_t nArrLen = rDoc.GetFrameFormats()->size();
+ for( size_t i = 0; i < nArrLen; i++ )
+ {
+ const SwFrameFormat* pFormat = (*rDoc.GetFrameFormats())[ i ];
+
+ bool bUsed = bIsSearchUsed && ( bOrganizer || rDoc.IsUsed(*pFormat));
+ if( ( !bSearchHidden && pFormat->IsHidden( ) && !bUsed ) || pFormat->IsDefault() || pFormat->IsAuto() )
+ continue;
+
+ if ( nSrchMask == SfxStyleSearchBits::Hidden && !pFormat->IsHidden( ) )
+ continue;
+
+ const sal_uInt16 nId = pFormat->GetPoolFormatId();
+ if( !bUsed )
+ {
+ if( (nSrchMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::UserDefined
+ ? !(nId & USER_FMT)
+ // searched for used and found none
+ : bIsSearchUsed )
+ {
+ continue;
+ }
+ }
+
+ m_aLst.Append( SfxStyleFamily::Frame, pFormat->GetName() );
+ }
+
+ // PoolFormat
+ if ( bAll )
+ AppendStyleList(SwStyleNameMapper::GetFrameFormatUINameArray(),
+ bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::FrmFmt, SfxStyleFamily::Frame);
+ }
+
+ if( nSearchFamily == SfxStyleFamily::Page ||
+ nSearchFamily == SfxStyleFamily::All )
+ {
+ const size_t nCount = rDoc.GetPageDescCnt();
+ for(size_t i = 0; i < nCount; ++i)
+ {
+ const SwPageDesc& rDesc = rDoc.GetPageDesc(i);
+ const sal_uInt16 nId = rDesc.GetPoolFormatId();
+ bool bUsed = bIsSearchUsed && ( bOrganizer || rDoc.IsUsed(rDesc));
+ if( !bUsed )
+ {
+ if ( ( !bSearchHidden && rDesc.IsHidden() ) ||
+ ( (nSrchMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::UserDefined
+ ? !(nId & USER_FMT)
+ // searched for used and found none
+ : bIsSearchUsed ) )
+ continue;
+ }
+
+ if ( nSrchMask == SfxStyleSearchBits::Hidden && !rDesc.IsHidden( ) )
+ continue;
+
+ m_aLst.Append( SfxStyleFamily::Page, rDesc.GetName() );
+ }
+ if ( bAll )
+ AppendStyleList(SwStyleNameMapper::GetPageDescUINameArray(),
+ bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::PageDesc, SfxStyleFamily::Page);
+ }
+
+ if( nSearchFamily == SfxStyleFamily::Pseudo ||
+ nSearchFamily == SfxStyleFamily::All )
+ {
+ const SwNumRuleTable& rNumTable = rDoc.GetNumRuleTable();
+ for(auto const& rNum: rNumTable)
+ {
+ const SwNumRule& rRule = *rNum;
+ if( !rRule.IsAutoRule() )
+ {
+ if ( nSrchMask == SfxStyleSearchBits::Hidden && !rRule.IsHidden( ) )
+ continue;
+
+ bool bUsed = bIsSearchUsed && (bOrganizer || rDoc.IsUsed(rRule));
+ if( !bUsed )
+ {
+ if( ( !bSearchHidden && rRule.IsHidden() ) ||
+ ( (nSrchMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::UserDefined
+ ? !(rRule.GetPoolFormatId() & USER_FMT)
+ // searched for used and found none
+ : bIsSearchUsed ) )
+ continue;
+ }
+
+ m_aLst.Append( SfxStyleFamily::Pseudo, rRule.GetName() );
+ }
+ }
+ if ( bAll )
+ AppendStyleList(SwStyleNameMapper::GetNumRuleUINameArray(),
+ bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::NumRule, SfxStyleFamily::Pseudo);
+ }
+
+ if( nSearchFamily == SfxStyleFamily::Table ||
+ nSearchFamily == SfxStyleFamily::All )
+ {
+ const SwTableAutoFormatTable& rTableStyles = rDoc.GetTableStyles();
+ for(size_t i = 0; i < rTableStyles.size(); ++i)
+ {
+ const SwTableAutoFormat& rTableStyle = rTableStyles[i];
+
+ bool bUsed = bIsSearchUsed && (bOrganizer || rDoc.IsUsed(rTableStyle));
+ if(!bUsed)
+ {
+ if(nSrchMask == SfxStyleSearchBits::Hidden && !rTableStyle.IsHidden())
+ continue;
+
+ if( (!bSearchHidden && rTableStyle.IsHidden() ) ||
+ ( (nSrchMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::UserDefined
+ ? !rTableStyle.IsUserDefined()
+ // searched for used and found none
+ : bIsSearchUsed ) )
+ continue;
+ }
+
+ m_aLst.Append( SfxStyleFamily::Table, rTableStyle.GetName() );
+ }
+ }
+
+ if( nSearchFamily == SfxStyleFamily::Cell ||
+ nSearchFamily == SfxStyleFamily::All )
+ {
+ const auto& aTableTemplateMap = SwTableAutoFormat::GetTableTemplateMap();
+ if (rDoc.HasTableStyles())
+ {
+ const SwTableAutoFormatTable& rTableStyles = rDoc.GetTableStyles();
+ for(size_t i = 0; i < rTableStyles.size(); ++i)
+ {
+ const SwTableAutoFormat& rTableStyle = rTableStyles[i];
+ for(size_t nBoxFormat = 0; nBoxFormat < aTableTemplateMap.size(); ++nBoxFormat)
+ {
+ const sal_uInt32 nBoxIndex = aTableTemplateMap[nBoxFormat];
+ const SwBoxAutoFormat& rBoxFormat = rTableStyle.GetBoxFormat(nBoxIndex);
+ OUString sBoxFormatName;
+ SwStyleNameMapper::FillProgName(rTableStyle.GetName(), sBoxFormatName, SwGetPoolIdFromName::TabStyle);
+ sBoxFormatName += rTableStyle.GetTableTemplateCellSubName(rBoxFormat);
+ m_aLst.Append( SfxStyleFamily::Cell, sBoxFormatName );
+ }
+ }
+ }
+ const SwCellStyleTable& rCellStyles = rDoc.GetCellStyles();
+ for(size_t i = 0; i < rCellStyles.size(); ++i)
+ m_aLst.Append( SfxStyleFamily::Cell, rCellStyles[i].GetName() );
+ }
+
+ if(!m_aLst.empty())
+ {
+ m_nLastPos = SAL_MAX_UINT32;
+ return Next();
+ }
+ return nullptr;
+}
+
+SfxStyleSheetBase* SwStyleSheetIterator::Next()
+{
+ assert(m_bFirstCalled);
+ ++m_nLastPos;
+ if(m_nLastPos < m_aLst.size())
+ {
+ auto const & rEntry = m_aLst[m_nLastPos];
+ mxIterSheet->PresetNameAndFamily(rEntry.first, rEntry.second);
+ mxIterSheet->SetPhysical( false );
+ mxIterSheet->SetMask( nMask );
+ if(mxIterSheet->pSet)
+ {
+ mxIterSheet->pSet->ClearItem();
+ mxIterSheet->pSet= nullptr;
+ }
+ return mxIterSheet.get();
+ }
+ return nullptr;
+}
+
+SfxStyleSheetBase* SwStyleSheetIterator::Find(const OUString& rName)
+{
+ // searching
+ if( !m_bFirstCalled )
+ First();
+
+ m_nLastPos = m_aLst.FindName( nSearchFamily, rName );
+ if( SAL_MAX_UINT32 != m_nLastPos )
+ {
+ // found
+ auto const & rEntry = m_aLst[m_nLastPos];
+ mxStyleSheet->PresetNameAndFamily(rEntry.first, rEntry.second);
+ // new name is set, so determine its Data
+ mxStyleSheet->FillStyleSheet( SwDocStyleSheet::FillOnlyName );
+ if( !mxStyleSheet->IsPhysical() )
+ mxStyleSheet->SetPhysical( false );
+
+ return mxStyleSheet.get();
+ }
+ return nullptr;
+}
+
+void SwStyleSheetIterator::AppendStyleList(const std::vector<OUString>& rList,
+ bool bTestUsed, bool bTestHidden, bool bOnlyHidden,
+ SwGetPoolIdFromName nSection, SfxStyleFamily eFamily )
+{
+ const SwDoc& rDoc = static_cast<const SwDocStyleSheetPool*>(pBasePool)->GetDoc();
+ bool bUsed = false;
+ for (const auto & i : rList)
+ {
+ bool bHidden = false;
+ sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(i, nSection);
+ switch ( nSection )
+ {
+ case SwGetPoolIdFromName::TxtColl:
+ {
+ bUsed = rDoc.getIDocumentStylePoolAccess().IsPoolTextCollUsed( nId );
+ SwFormat* pFormat = rDoc.FindTextFormatCollByName( i );
+ bHidden = pFormat && pFormat->IsHidden( );
+ }
+ break;
+ case SwGetPoolIdFromName::ChrFmt:
+ {
+ bUsed = rDoc.getIDocumentStylePoolAccess().IsPoolFormatUsed( nId );
+ SwFormat* pFormat = rDoc.FindCharFormatByName( i );
+ bHidden = pFormat && pFormat->IsHidden( );
+ }
+ break;
+ case SwGetPoolIdFromName::FrmFmt:
+ {
+ bUsed = rDoc.getIDocumentStylePoolAccess().IsPoolFormatUsed( nId );
+ SwFormat* pFormat = rDoc.FindFrameFormatByName( i );
+ bHidden = pFormat && pFormat->IsHidden( );
+ }
+ break;
+ case SwGetPoolIdFromName::PageDesc:
+ {
+ bUsed = rDoc.getIDocumentStylePoolAccess().IsPoolPageDescUsed( nId );
+ SwPageDesc* pPgDesc = rDoc.FindPageDesc(i);
+ bHidden = pPgDesc && pPgDesc->IsHidden( );
+ }
+ break;
+ case SwGetPoolIdFromName::NumRule:
+ {
+ SwNumRule* pRule = rDoc.FindNumRulePtr( i );
+ bUsed = pRule && rDoc.IsUsed(*pRule);
+ bHidden = pRule && pRule->IsHidden( );
+ }
+ break;
+ default:
+ OSL_ENSURE( false, "unknown PoolFormat-Id" );
+ }
+
+ bool bMatchHidden = ( bTestHidden && ( bHidden || !bOnlyHidden ) ) || ( !bTestHidden && ( !bHidden || bUsed ) );
+ if ( ( !bTestUsed && bMatchHidden ) || ( bTestUsed && bUsed ) )
+ m_aLst.Append( eFamily, i );
+ }
+}
+
+bool SwStyleSheetIterator::IsUsedInComments(const OUString& rName) const
+{
+ auto pPool = static_cast<const SwDocStyleSheetPool*>(pBasePool)->GetEEStyleSheetPool();
+ SfxStyleSheetIterator aIter(pPool, GetSearchFamily(), SfxStyleSearchBits::Used);
+ return aIter.Find(rName) != nullptr;
+}
+
+void SwDocStyleSheetPool::InvalidateIterator()
+{
+ if (SfxStyleSheetIterator* pIter = GetCachedIterator())
+ dynamic_cast<SwStyleSheetIterator&>(*pIter).InvalidateIterator();
+}
+
+void SwStyleSheetIterator::InvalidateIterator()
+{
+ // potentially we could send an SfxHint to Notify but currently it's
+ // iterating over the vector anyway so would still be slow - why does
+ // this iterator not use a map?
+ m_bFirstCalled = false;
+ m_nLastPos = 0;
+ m_aLst.clear();
+}
+
+void SwStyleSheetIterator::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ // search and remove from View-List!!
+ const SfxStyleSheetHint* pStyleSheetHint = dynamic_cast<const SfxStyleSheetHint*>(&rHint);
+ if( pStyleSheetHint &&
+ SfxHintId::StyleSheetErased == pStyleSheetHint->GetId() )
+ {
+ SfxStyleSheetBase* pStyle = pStyleSheetHint->GetStyleSheet();
+
+ if (pStyle)
+ m_aLst.RemoveName(pStyle->GetFamily(), pStyle->GetName());
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/app/mainwn.cxx b/sw/source/uibase/app/mainwn.cxx
new file mode 100644
index 0000000000..7c21797f8e
--- /dev/null
+++ b/sw/source/uibase/app/mainwn.cxx
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <mdiexp.hxx>
+#include <sfx2/progress.hxx>
+#include <docsh.hxx>
+#include <swmodule.hxx>
+#include <swtypes.hxx>
+
+class SwDocShell;
+
+namespace {
+
+struct SwProgress
+{
+ tools::Long nStartValue,
+ nStartCount;
+ SwDocShell *pDocShell;
+ std::unique_ptr<SfxProgress> pProgress;
+};
+
+}
+
+static std::vector<std::unique_ptr<SwProgress>> *pProgressContainer = nullptr;
+
+static SwProgress *lcl_SwFindProgress( SwDocShell const *pDocShell )
+{
+ for (const auto& pTmp : *pProgressContainer)
+ {
+ if ( pTmp->pDocShell == pDocShell )
+ return pTmp.get();
+ }
+ return nullptr;
+}
+
+void StartProgress( TranslateId pMessResId, tools::Long nStartValue, tools::Long nEndValue,
+ SwDocShell *pDocShell )
+{
+ if( SW_MOD()->IsEmbeddedLoadSave() )
+ return;
+
+ SwProgress *pProgress = nullptr;
+
+ if ( !pProgressContainer )
+ pProgressContainer = new std::vector<std::unique_ptr<SwProgress>>;
+ else
+ {
+ pProgress = lcl_SwFindProgress( pDocShell );
+ if ( pProgress )
+ ++pProgress->nStartCount;
+ }
+
+ if ( !pProgress )
+ {
+ pProgress = new SwProgress;
+ pProgress->pProgress.reset( new SfxProgress( pDocShell,
+ SwResId(pMessResId),
+ nEndValue - nStartValue ) );
+ pProgress->nStartCount = 1;
+ pProgress->pDocShell = pDocShell;
+ pProgressContainer->insert( pProgressContainer->begin(), std::unique_ptr<SwProgress>(pProgress) );
+ }
+ pProgress->nStartValue = nStartValue;
+}
+
+void SetProgressState( tools::Long nPosition, SwDocShell const *pDocShell )
+{
+ if( pProgressContainer && !SW_MOD()->IsEmbeddedLoadSave() )
+ {
+ SwProgress *pProgress = lcl_SwFindProgress( pDocShell );
+ if ( pProgress )
+ pProgress->pProgress->SetState(nPosition - pProgress->nStartValue);
+ }
+}
+
+void EndProgress( SwDocShell const *pDocShell )
+{
+ if( !pProgressContainer || SW_MOD()->IsEmbeddedLoadSave() )
+ return;
+
+ SwProgress *pProgress = nullptr;
+ std::vector<SwProgress *>::size_type i;
+ for ( i = 0; i < pProgressContainer->size(); ++i )
+ {
+ SwProgress *pTmp = (*pProgressContainer)[i].get();
+ if ( pTmp->pDocShell == pDocShell )
+ {
+ pProgress = pTmp;
+ break;
+ }
+ }
+
+ if ( pProgress && 0 == --pProgress->nStartCount )
+ {
+ pProgress->pProgress->Stop();
+ pProgressContainer->erase( pProgressContainer->begin() + i );
+ //#112337# it may happen that the container has been removed
+ //while rescheduling
+ if ( pProgressContainer && pProgressContainer->empty() )
+ {
+ delete pProgressContainer;
+ pProgressContainer = nullptr;
+ }
+ }
+}
+
+void RescheduleProgress( SwDocShell const *pDocShell )
+{
+ if( pProgressContainer && !SW_MOD()->IsEmbeddedLoadSave() )
+ {
+ SwProgress *pProgress = lcl_SwFindProgress( pDocShell );
+ if ( pProgress )
+ SfxProgress::Reschedule();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/app/swdll.cxx b/sw/source/uibase/app/swdll.cxx
new file mode 100644
index 0000000000..c4564a4741
--- /dev/null
+++ b/sw/source/uibase/app/swdll.cxx
@@ -0,0 +1,184 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+
+#include <svx/svdobj.hxx>
+
+#include <swdll.hxx>
+#include <wdocsh.hxx>
+#include <globdoc.hxx>
+#include <initui.hxx>
+#include <swmodule.hxx>
+#include <init.hxx>
+#include <dobjfac.hxx>
+
+#include <com/sun/star/frame/Desktop.hpp>
+#include <unotools/configmgr.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <comphelper/unique_disposing_ptr.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include <sal/log.hxx>
+#include <svx/fmobjfac.hxx>
+#include <svx/objfac3d.hxx>
+#include <editeng/acorrcfg.hxx>
+
+#include <swacorr.hxx>
+#include <swabstdlg.hxx>
+
+#include "swdllimpl.hxx"
+
+using namespace com::sun::star;
+
+namespace
+{
+ //Holds a SwDLL and release it on exit, or dispose of the
+ //default XComponent, whichever comes first
+ class SwDLLInstance : public comphelper::unique_disposing_solar_mutex_reset_ptr<SwDLL>
+ {
+ public:
+ SwDLLInstance() : comphelper::unique_disposing_solar_mutex_reset_ptr<SwDLL>(uno::Reference<lang::XComponent>( frame::Desktop::create(comphelper::getProcessComponentContext()), uno::UNO_QUERY_THROW), new SwDLL, true)
+ {
+ }
+ };
+
+ SwDLLInstance& theSwDLLInstance()
+ {
+ static SwDLLInstance aInstance;
+ return aInstance;
+ }
+}
+
+namespace SwGlobals
+{
+ void ensure()
+ {
+ // coverity[side_effect_free : FALSE] - not actually side-effect-free
+ theSwDLLInstance();
+ }
+
+ sw::Filters & getFilters()
+ {
+ return theSwDLLInstance()->getFilters();
+ }
+}
+
+SwDLL::SwDLL()
+ : m_pAutoCorrCfg(nullptr)
+{
+ if ( SfxApplication::GetModule(SfxToolsModule::Writer) ) // Module already active
+ return;
+
+ std::unique_ptr<SvtModuleOptions> xOpt;
+ if (!utl::ConfigManager::IsFuzzing())
+ xOpt.reset(new SvtModuleOptions);
+ SfxObjectFactory* pDocFact = nullptr;
+ SfxObjectFactory* pGlobDocFact = nullptr;
+ if (!xOpt || xOpt->IsWriter())
+ {
+ pDocFact = &SwDocShell::Factory();
+ pGlobDocFact = &SwGlobalDocShell::Factory();
+ }
+
+ SfxObjectFactory* pWDocFact = &SwWebDocShell::Factory();
+
+ auto pUniqueModule = std::make_unique<SwModule>(pWDocFact, pDocFact, pGlobDocFact);
+ SwModule* pModule = pUniqueModule.get();
+ SfxApplication::SetModule(SfxToolsModule::Writer, std::move(pUniqueModule));
+
+ pWDocFact->SetDocumentServiceName("com.sun.star.text.WebDocument");
+
+ if (!xOpt || xOpt->IsWriter())
+ {
+ pGlobDocFact->SetDocumentServiceName("com.sun.star.text.GlobalDocument");
+ pDocFact->SetDocumentServiceName("com.sun.star.text.TextDocument");
+ }
+
+ // register 3D-object-Factory
+ E3dObjFactory();
+
+ // register form::component::Form-object-Factory
+ FmFormObjFactory();
+
+ SdrObjFactory::InsertMakeObjectHdl( LINK( &aSwObjectFactory, SwObjectFactory, MakeObject ) );
+
+ SAL_INFO( "sw.ui", "Init Core/UI/Filter" );
+ // Initialisation of Statics
+ ::InitCore();
+ m_pFilters.reset(new sw::Filters);
+ ::InitUI();
+
+ pModule->InitAttrPool();
+ // now SWModule can create its Pool
+
+ // register your view-factories here
+ RegisterFactories();
+
+ // register your shell-interfaces here
+ RegisterInterfaces();
+
+ // register your controllers here
+ RegisterControls();
+
+ if (!utl::ConfigManager::IsFuzzing())
+ {
+ // replace SvxAutocorrect with SwAutocorrect
+ SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get();
+ const SvxAutoCorrect* pOld = rACfg.GetAutoCorrect();
+ rACfg.SetAutoCorrect(new SwAutoCorrect( *pOld ));
+ m_pAutoCorrCfg = &rACfg;
+ }
+}
+
+SwDLL::~SwDLL() COVERITY_NOEXCEPT_FALSE
+{
+ if (m_pAutoCorrCfg)
+ {
+ // fdo#86494 SwAutoCorrect must be deleted before FinitCore
+ m_pAutoCorrCfg->SetAutoCorrect(nullptr); // delete SwAutoCorrect before exit handlers
+ }
+
+ // Pool has to be deleted before statics are
+ SW_MOD()->RemoveAttrPool();
+
+ ::FinitUI();
+ m_pFilters.reset();
+ ::FinitCore();
+ // sign out object-Factory
+ SdrObjFactory::RemoveMakeObjectHdl(LINK(&aSwObjectFactory, SwObjectFactory, MakeObject ));
+}
+
+sw::Filters & SwDLL::getFilters()
+{
+ assert(m_pFilters);
+ return *m_pFilters;
+}
+
+#ifndef DISABLE_DYNLOADING
+
+extern "C" SAL_DLLPUBLIC_EXPORT
+void lok_preload_hook()
+{
+ SwAbstractDialogFactory::Create();
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/app/swdllimpl.hxx b/sw/source/uibase/app/swdllimpl.hxx
new file mode 100644
index 0000000000..7dab66d6ce
--- /dev/null
+++ b/sw/source/uibase/app/swdllimpl.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <sal/config.h>
+
+#include <sal/types.h>
+
+#include <memory>
+
+namespace sw
+{
+class Filters;
+}
+
+class SvxAutoCorrCfg;
+
+class SwDLL
+{
+public:
+ static void RegisterFactories();
+ static void RegisterInterfaces();
+ static void RegisterControls();
+
+ SwDLL();
+ ~SwDLL() COVERITY_NOEXCEPT_FALSE;
+
+ sw::Filters& getFilters();
+
+private:
+ SwDLL(SwDLL const&) = delete;
+ SwDLL& operator=(SwDLL const&) = delete;
+
+ std::unique_ptr<sw::Filters> m_pFilters;
+ SvxAutoCorrCfg* m_pAutoCorrCfg;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/app/swmodul1.cxx b/sw/source/uibase/app/swmodul1.cxx
new file mode 100644
index 0000000000..64bd38f444
--- /dev/null
+++ b/sw/source/uibase/app/swmodul1.cxx
@@ -0,0 +1,693 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include <hintids.hxx>
+#include <sfx2/request.hxx>
+#include <unotools/useroptions.hxx>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <svx/colorwindow.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#include <editeng/editids.hrc>
+#include <editeng/wghtitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/crossedoutitem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/brushitem.hxx>
+#include <svl/cjkoptions.hxx>
+#include <osl/diagnose.h>
+#include <swmodule.hxx>
+#include <swtypes.hxx>
+#include <usrpref.hxx>
+#include <modcfg.hxx>
+#include <view.hxx>
+#include <pview.hxx>
+#include <wview.hxx>
+#include <wrtsh.hxx>
+#include <docsh.hxx>
+#include <uinums.hxx>
+#include <prtopt.hxx>
+#include <navicfg.hxx>
+#include <doc.hxx>
+#include <strings.hrc>
+#include <IDocumentLayoutAccess.hxx>
+
+#include <tools/color.hxx>
+#include <tools/json_writer.hxx>
+#include <PostItMgr.hxx>
+
+using namespace ::svx;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::view;
+using namespace ::com::sun::star::lang;
+
+static void lcl_SetUIPrefs(const SwViewOption &rPref, SwView* pView, SwViewShell* pSh )
+{
+ // in FrameSets the actual visibility can differ from the ViewOption's setting
+ bool bVScrollChanged = rPref.IsViewVScrollBar() != pSh->GetViewOptions()->IsViewVScrollBar();
+ bool bHScrollChanged = rPref.IsViewHScrollBar() != pSh->GetViewOptions()->IsViewHScrollBar();
+ bool bVAlignChanged = rPref.IsVRulerRight() != pSh->GetViewOptions()->IsVRulerRight();
+
+ pSh->SetUIOptions(rPref);
+ const SwViewOption* pNewPref = pSh->GetViewOptions();
+
+ // Scrollbars on / off
+ if(bVScrollChanged)
+ {
+ pView->EnableVScrollbar(pNewPref->IsViewVScrollBar());
+ }
+ if(bHScrollChanged)
+ {
+ pView->EnableHScrollbar( pNewPref->IsViewHScrollBar() || pNewPref->getBrowseMode() );
+ }
+ //if only the position of the vertical ruler has been changed initiate an update
+ if(bVAlignChanged && !bHScrollChanged && !bVScrollChanged)
+ pView->InvalidateBorder();
+
+ // Rulers on / off
+ if(pNewPref->IsViewVRuler())
+ pView->CreateVRuler();
+ else
+ pView->KillVRuler();
+
+ // TabWindow on / off
+ if(pNewPref->IsViewHRuler())
+ pView->CreateTab();
+ else
+ pView->KillTab();
+
+ pView->GetPostItMgr()->PrepareView(true);
+}
+
+SwWrtShell* GetActiveWrtShell()
+{
+ if (SwView *pActive = GetActiveView())
+ return &pActive->GetWrtShell();
+ return nullptr;
+}
+
+SwView* GetActiveView()
+{
+ SfxViewShell* pView = SfxViewShell::Current();
+ return dynamic_cast<SwView*>( pView );
+}
+
+SwView* SwModule::GetFirstView()
+{
+ // returns only visible SwView
+ SwView* pView = static_cast<SwView*>(SfxViewShell::GetFirst(true, checkSfxViewShell<SwView>));
+ return pView;
+}
+
+SwView* SwModule::GetNextView(SwView const * pView)
+{
+ OSL_ENSURE( pView,"return no SwView" );
+ SwView* pNView = static_cast<SwView*>(SfxViewShell::GetNext(*pView, true, checkSfxViewShell<SwView>));
+ return pNView;
+}
+
+// New Master for the settings is set; this affects the current view and all following.
+void SwModule::ApplyUsrPref(const SwViewOption &rUsrPref, SwView* pActView,
+ SvViewOpt nDest )
+{
+ SwView* pCurrView = pActView;
+ SwViewShell* pSh = pCurrView ? &pCurrView->GetWrtShell() : nullptr;
+
+ SwMasterUsrPref* pPref = const_cast<SwMasterUsrPref*>(GetUsrPref(
+ nDest == SvViewOpt::DestWeb
+ || (nDest != SvViewOpt::DestText
+ && dynamic_cast< const SwWebView *>( pCurrView )) ));
+
+ // with Uno, only sdbcx::View, but not the Module should be changed
+ bool bViewOnly = SvViewOpt::DestViewOnly == nDest;
+ // fob Preview off
+ SwPagePreview* pPPView;
+ if( !pCurrView && nullptr != (pPPView = dynamic_cast<SwPagePreview*>( SfxViewShell::Current())) )
+ {
+ if(!bViewOnly)
+ pPref->SetUIOptions( rUsrPref );
+ pPPView->EnableVScrollbar(pPref->IsViewVScrollBar());
+ pPPView->EnableHScrollbar(pPref->IsViewHScrollBar());
+ if(!bViewOnly)
+ {
+ pPref->SetPagePrevRow(rUsrPref.GetPagePrevRow());
+ pPref->SetPagePrevCol(rUsrPref.GetPagePrevCol());
+ }
+ return;
+ }
+
+ if(!bViewOnly)
+ {
+ pPref->SetUsrPref( rUsrPref );
+ pPref->SetModified();
+ }
+
+ if( !pCurrView )
+ return;
+
+ // Passing on to CORE
+ bool bReadonly;
+ const SwDocShell* pDocSh = pCurrView->GetDocShell();
+ if (pDocSh)
+ bReadonly = pDocSh->IsReadOnly();
+ else //Use existing option if DocShell missing
+ bReadonly = pSh->GetViewOptions()->IsReadonly();
+ std::unique_ptr<SwViewOption> xViewOpt;
+ if (!bViewOnly)
+ xViewOpt.reset(new SwViewOption(*pPref));
+ else
+ xViewOpt.reset(new SwViewOption(rUsrPref));
+ xViewOpt->SetReadonly( bReadonly );
+ if( !(*pSh->GetViewOptions() == *xViewOpt) )
+ {
+ //is maybe only a SwViewShell
+ pSh->StartAction();
+ pSh->ApplyViewOptions( *xViewOpt );
+ static_cast<SwWrtShell*>(pSh)->SetReadOnlyAvailable(xViewOpt->IsCursorInProtectedArea());
+ pSh->EndAction();
+ }
+ if ( pSh->GetViewOptions()->IsReadonly() != bReadonly )
+ pSh->SetReadonlyOption(bReadonly);
+
+ lcl_SetUIPrefs(*xViewOpt, pCurrView, pSh);
+
+ // in the end the Idle-Flag is set again
+ pPref->SetIdle(true);
+}
+
+void SwModule::ApplyUserMetric( FieldUnit eMetric, bool bWeb )
+{
+ SwMasterUsrPref* pPref;
+ if(bWeb)
+ {
+ if(!m_pWebUsrPref)
+ GetUsrPref(true);
+ pPref = m_pWebUsrPref.get();
+ }
+ else
+ {
+ if(!m_pUsrPref)
+ GetUsrPref(false);
+ pPref = m_pUsrPref.get();
+ }
+ assert(pPref && "pPref is set by here");
+ FieldUnit eOldMetric = pPref->GetMetric();
+ if(eOldMetric != eMetric)
+ pPref->SetMetric(eMetric);
+
+ FieldUnit eHScrollMetric = pPref->IsHScrollMetric() ? pPref->GetHScrollMetric() : eMetric;
+ FieldUnit eVScrollMetric = pPref->IsVScrollMetric() ? pPref->GetVScrollMetric() : eMetric;
+
+ SwView* pTmpView = SwModule::GetFirstView();
+ // switch the ruler for all MDI-Windows
+ while(pTmpView)
+ {
+ if(bWeb == (dynamic_cast<SwWebView*>( pTmpView) != nullptr) )
+ {
+ pTmpView->ChangeVRulerMetric(eVScrollMetric);
+ pTmpView->ChangeTabMetric(eHScrollMetric);
+ }
+
+ pTmpView = SwModule::GetNextView(pTmpView);
+ }
+}
+
+void SwModule::ApplyRulerMetric( FieldUnit eMetric, bool bHorizontal, bool bWeb )
+{
+ SwMasterUsrPref* pPref;
+ if(bWeb)
+ {
+ if(!m_pWebUsrPref)
+ GetUsrPref(true);
+ pPref = m_pWebUsrPref.get();
+ }
+ else
+ {
+ if(!m_pUsrPref)
+ GetUsrPref(false);
+ pPref = m_pUsrPref.get();
+ }
+ assert(pPref && "pPref will be set by now");
+ if( bHorizontal )
+ pPref->SetHScrollMetric(eMetric);
+ else
+ pPref->SetVScrollMetric(eMetric);
+
+ SwView* pTmpView = SwModule::GetFirstView();
+ // switch metric at the appropriate rulers
+ while(pTmpView)
+ {
+ if(bWeb == (dynamic_cast<SwWebView *>( pTmpView ) != nullptr))
+ {
+ if( bHorizontal )
+ pTmpView->ChangeTabMetric(eMetric);
+ else
+ pTmpView->ChangeVRulerMetric(eMetric);
+ }
+ pTmpView = SwModule::GetNextView(pTmpView);
+ }
+}
+
+//set the usrpref 's char unit attribute and set rulers unit as char if the "apply char unit" is checked
+void SwModule::ApplyUserCharUnit(bool bApplyChar, bool bWeb)
+{
+ SwMasterUsrPref* pPref;
+ if(bWeb)
+ {
+ if(!m_pWebUsrPref)
+ GetUsrPref(true);
+ pPref = m_pWebUsrPref.get();
+ }
+ else
+ {
+ if(!m_pUsrPref)
+ GetUsrPref(false);
+ pPref = m_pUsrPref.get();
+ }
+ assert(pPref && "pPref is set by here");
+ bool bOldApplyCharUnit = pPref->IsApplyCharUnit();
+ bool bHasChanged = false;
+ if(bOldApplyCharUnit != bApplyChar)
+ {
+ pPref->SetApplyCharUnit(bApplyChar);
+ bHasChanged = true;
+ }
+
+ if( !bHasChanged )
+ return;
+
+ FieldUnit eHScrollMetric = pPref->IsHScrollMetric() ? pPref->GetHScrollMetric() : pPref->GetMetric();
+ FieldUnit eVScrollMetric = pPref->IsVScrollMetric() ? pPref->GetVScrollMetric() : pPref->GetMetric();
+ if(bApplyChar)
+ {
+ eHScrollMetric = FieldUnit::CHAR;
+ eVScrollMetric = FieldUnit::LINE;
+ }
+ else
+ {
+ if ( !SvtCJKOptions::IsAsianTypographyEnabled() && ( eHScrollMetric == FieldUnit::CHAR ))
+ eHScrollMetric = FieldUnit::INCH;
+ else if ( eHScrollMetric == FieldUnit::CHAR )
+ eHScrollMetric = FieldUnit::CM;
+ if ( !SvtCJKOptions::IsAsianTypographyEnabled() && ( eVScrollMetric == FieldUnit::LINE ))
+ eVScrollMetric = FieldUnit::INCH;
+ else if ( eVScrollMetric == FieldUnit::LINE )
+ eVScrollMetric = FieldUnit::CM;
+ }
+ SwView* pTmpView = SwModule::GetFirstView();
+ // switch rulers for all MDI-Windows
+ while(pTmpView)
+ {
+ if(bWeb == (dynamic_cast<SwWebView*>( pTmpView) != nullptr) )
+ {
+ pTmpView->ChangeVRulerMetric(eVScrollMetric);
+ pTmpView->ChangeTabMetric(eHScrollMetric);
+ }
+
+ pTmpView = SwModule::GetNextView(pTmpView);
+ }
+}
+
+SwNavigationConfig* SwModule::GetNavigationConfig()
+{
+ if(!m_pNavigationConfig)
+ {
+ m_pNavigationConfig.reset( new SwNavigationConfig );
+ }
+ return m_pNavigationConfig.get();
+}
+
+SwPrintOptions* SwModule::GetPrtOptions(bool bWeb)
+{
+ if(bWeb && !m_pWebPrintOptions)
+ {
+ m_pWebPrintOptions.reset(new SwPrintOptions(true));
+ }
+ else if(!bWeb && !m_pPrintOptions)
+ {
+ m_pPrintOptions.reset(new SwPrintOptions(false));
+ }
+
+ return bWeb ? m_pWebPrintOptions.get() : m_pPrintOptions.get();
+}
+
+SwChapterNumRules* SwModule::GetChapterNumRules()
+{
+ if(!m_pChapterNumRules)
+ m_pChapterNumRules.reset(new SwChapterNumRules);
+ return m_pChapterNumRules.get();
+}
+
+void SwModule::ShowDBObj(SwView const & rView, const SwDBData& rData)
+{
+ Reference<XFrame> xFrame = rView.GetViewFrame().GetFrame().GetFrameInterface();
+
+ uno::Reference<XFrame> xBeamerFrame = xFrame->findFrame("_beamer", FrameSearchFlag::CHILDREN);
+ if (!xBeamerFrame.is())
+ return;
+
+// the beamer has been opened by the SfxViewFrame
+ Reference<XController> xController = xBeamerFrame->getController();
+ Reference<XSelectionSupplier> xControllerSelection(xController, UNO_QUERY);
+ if (xControllerSelection.is())
+ {
+
+ ODataAccessDescriptor aSelection;
+ aSelection.setDataSource(rData.sDataSource);
+ aSelection[DataAccessDescriptorProperty::Command] <<= rData.sCommand;
+ aSelection[DataAccessDescriptorProperty::CommandType] <<= rData.nCommandType;
+ xControllerSelection->select(Any(aSelection.createPropertyValueSequence()));
+ }
+ else {
+ OSL_FAIL("no selection supplier in the beamer!");
+ }
+}
+
+std::size_t SwModule::GetRedlineAuthor()
+{
+ if (!m_bAuthorInitialised)
+ {
+ const SvtUserOptions& rOpt = GetUserOptions();
+ m_sActAuthor = rOpt.GetFullName();
+ if (m_sActAuthor.isEmpty())
+ {
+ m_sActAuthor = rOpt.GetID();
+ if (m_sActAuthor.isEmpty())
+ m_sActAuthor = SwResId( STR_REDLINE_UNKNOWN_AUTHOR );
+ }
+ m_bAuthorInitialised = true;
+ }
+ return InsertRedlineAuthor( m_sActAuthor );
+}
+
+void SwModule::SetRedlineAuthor(const OUString &rAuthor)
+{
+ m_bAuthorInitialised = true;
+ m_sActAuthor = rAuthor;
+ InsertRedlineAuthor( m_sActAuthor );
+}
+
+OUString const & SwModule::GetRedlineAuthor(std::size_t nPos)
+{
+ OSL_ENSURE(nPos < m_pAuthorNames.size(), "author not found!"); //#i45342# RTF doc with no author table caused reader to crash
+ while(nPos >= m_pAuthorNames.size())
+ {
+ InsertRedlineAuthor("nn");
+ }
+ return m_pAuthorNames[nPos];
+}
+
+void SwModule::ClearRedlineAuthors()
+{
+ m_pAuthorNames.clear();
+}
+
+static Color lcl_GetAuthorColor(std::size_t nPos)
+{
+ static const Color aColArr[] =
+ {
+ COL_AUTHOR1_DARK, COL_AUTHOR2_DARK, COL_AUTHOR3_DARK,
+ COL_AUTHOR4_DARK, COL_AUTHOR5_DARK, COL_AUTHOR6_DARK,
+ COL_AUTHOR7_DARK, COL_AUTHOR8_DARK, COL_AUTHOR9_DARK
+ };
+
+ return aColArr[nPos % SAL_N_ELEMENTS(aColArr)];
+}
+
+/// Returns a JSON representation of a redline author.
+void SwModule::GetRedlineAuthorInfo(tools::JsonWriter& rJsonWriter)
+{
+ auto authorsNode = rJsonWriter.startArray("authors");
+ for (std::size_t nAuthor = 0; nAuthor < m_pAuthorNames.size(); ++nAuthor)
+ {
+ auto authorNode = rJsonWriter.startStruct();
+ rJsonWriter.put("index", static_cast<sal_Int64>(nAuthor));
+ rJsonWriter.put("name", m_pAuthorNames[nAuthor]);
+ rJsonWriter.put("color", sal_uInt32(lcl_GetAuthorColor(nAuthor)));
+ }
+}
+
+std::size_t SwModule::InsertRedlineAuthor(const OUString& rAuthor)
+{
+ std::size_t nPos = 0;
+
+ while(nPos < m_pAuthorNames.size() && m_pAuthorNames[nPos] != rAuthor)
+ ++nPos;
+
+ if (nPos == m_pAuthorNames.size())
+ m_pAuthorNames.push_back(rAuthor);
+
+ return nPos;
+}
+
+static void lcl_FillAuthorAttr( std::size_t nAuthor, SfxItemSet &rSet,
+ const AuthorCharAttr &rAttr )
+{
+ Color aCol( rAttr.m_nColor );
+
+ if( rAttr.m_nColor == COL_TRANSPARENT )
+ aCol = lcl_GetAuthorColor(nAuthor);
+
+ bool bBackGr = rAttr.m_nColor == COL_NONE_COLOR;
+
+ switch (rAttr.m_nItemId)
+ {
+ case SID_ATTR_CHAR_WEIGHT:
+ {
+ SvxWeightItem aW( static_cast<FontWeight>(rAttr.m_nAttr), RES_CHRATR_WEIGHT );
+ rSet.Put( aW );
+ aW.SetWhich( RES_CHRATR_CJK_WEIGHT );
+ rSet.Put( aW );
+ aW.SetWhich( RES_CHRATR_CTL_WEIGHT );
+ rSet.Put( aW );
+ }
+ break;
+
+ case SID_ATTR_CHAR_POSTURE:
+ {
+ SvxPostureItem aP( static_cast<FontItalic>(rAttr.m_nAttr), RES_CHRATR_POSTURE );
+ rSet.Put( aP );
+ aP.SetWhich( RES_CHRATR_CJK_POSTURE );
+ rSet.Put( aP );
+ aP.SetWhich( RES_CHRATR_CTL_POSTURE );
+ rSet.Put( aP );
+ }
+ break;
+
+ case SID_ATTR_CHAR_UNDERLINE:
+ rSet.Put( SvxUnderlineItem( static_cast<FontLineStyle>(rAttr.m_nAttr),
+ RES_CHRATR_UNDERLINE));
+ break;
+
+ case SID_ATTR_CHAR_STRIKEOUT:
+ rSet.Put(SvxCrossedOutItem( static_cast<FontStrikeout>(rAttr.m_nAttr),
+ RES_CHRATR_CROSSEDOUT));
+ break;
+
+ case SID_ATTR_CHAR_CASEMAP:
+ rSet.Put( SvxCaseMapItem( static_cast<SvxCaseMap>(rAttr.m_nAttr),
+ RES_CHRATR_CASEMAP));
+ break;
+
+ case SID_ATTR_BRUSH:
+ rSet.Put( SvxBrushItem( aCol, RES_CHRATR_BACKGROUND ));
+ bBackGr = true;
+ break;
+ }
+
+ if( !bBackGr )
+ rSet.Put( SvxColorItem( aCol, RES_CHRATR_COLOR ) );
+}
+
+void SwModule::GetInsertAuthorAttr(std::size_t nAuthor, SfxItemSet &rSet)
+{
+ lcl_FillAuthorAttr(nAuthor, rSet, m_pModuleConfig->GetInsertAuthorAttr());
+}
+
+void SwModule::GetDeletedAuthorAttr(std::size_t nAuthor, SfxItemSet &rSet)
+{
+ lcl_FillAuthorAttr(nAuthor, rSet, m_pModuleConfig->GetDeletedAuthorAttr());
+}
+
+// For future extension:
+void SwModule::GetFormatAuthorAttr( std::size_t nAuthor, SfxItemSet &rSet )
+{
+ lcl_FillAuthorAttr( nAuthor, rSet, m_pModuleConfig->GetFormatAuthorAttr() );
+}
+
+sal_uInt16 SwModule::GetRedlineMarkPos() const
+{
+ return m_pModuleConfig->GetMarkAlignMode();
+}
+
+bool SwModule::IsInsTableFormatNum(bool bHTML) const
+{
+ return m_pModuleConfig->IsInsTableFormatNum(bHTML);
+}
+
+bool SwModule::IsInsTableChangeNumFormat(bool bHTML) const
+{
+ return m_pModuleConfig->IsInsTableChangeNumFormat(bHTML);
+}
+
+bool SwModule::IsInsTableAlignNum(bool bHTML) const
+{
+ return m_pModuleConfig->IsInsTableAlignNum(bHTML);
+}
+
+bool SwModule::IsSplitVerticalByDefault(bool bHTML) const
+{
+ return m_pModuleConfig->IsSplitVerticalByDefault(bHTML);
+}
+
+void SwModule::SetSplitVerticalByDefault(bool bHTML, bool value)
+{
+ m_pModuleConfig->SetSplitVerticalByDefault(bHTML, value);
+}
+
+const Color &SwModule::GetRedlineMarkColor() const
+{
+ return m_pModuleConfig->GetMarkAlignColor();
+}
+
+const SwViewOption* SwModule::GetViewOption(bool bWeb)
+{
+ return GetUsrPref( bWeb );
+}
+
+OUString const & SwModule::GetDocStatWordDelim() const
+{
+ return m_pModuleConfig->GetWordDelimiter();
+}
+
+// Passing-through of the ModuleConfig's Metric (for HTML-Export)
+FieldUnit SwModule::GetMetric( bool bWeb ) const
+{
+ SwMasterUsrPref* pPref;
+ if(bWeb)
+ {
+ if(!m_pWebUsrPref)
+ GetUsrPref(true);
+ pPref = m_pWebUsrPref.get();
+ }
+ else
+ {
+ if(!m_pUsrPref)
+ GetUsrPref(false);
+ pPref = m_pUsrPref.get();
+ }
+ assert(pPref && "pPref is set by here");
+ return pPref->GetMetric();
+}
+
+// Pass-through Update-Status
+sal_uInt16 SwModule::GetLinkUpdMode() const
+{
+ if (!m_pUsrPref)
+ GetUsrPref(false);
+ assert(m_pUsrPref && "m_pUsrPref is set by here");
+ return o3tl::narrowing<sal_uInt16>(m_pUsrPref->GetUpdateLinkMode());
+}
+
+SwFieldUpdateFlags SwModule::GetFieldUpdateFlags() const
+{
+ if (!m_pUsrPref)
+ GetUsrPref(false);
+ assert(m_pUsrPref && "m_pUsrPref is set by here");
+ return m_pUsrPref->GetFieldUpdateFlags();
+}
+
+void SwModule::ApplyFieldUpdateFlags(SwFieldUpdateFlags eFieldFlags)
+{
+ if (!m_pUsrPref)
+ GetUsrPref(false);
+ assert(m_pUsrPref && "m_pUsrPref is set by here");
+ m_pUsrPref->SetFieldUpdateFlags(eFieldFlags);
+}
+
+void SwModule::ApplyLinkMode(sal_Int32 nNewLinkMode)
+{
+ if (!m_pUsrPref)
+ GetUsrPref(false);
+ assert(m_pUsrPref && "m_pUsrPref is set by here");
+ m_pUsrPref->SetUpdateLinkMode(nNewLinkMode);
+}
+
+void SwModule::CheckSpellChanges( bool bOnlineSpelling,
+ bool bIsSpellWrongAgain, bool bIsSpellAllAgain, bool bSmartTags )
+{
+ bool bOnlyWrong = bIsSpellWrongAgain && !bIsSpellAllAgain;
+ bool bInvalid = bOnlyWrong || bIsSpellAllAgain;
+ if( !(bOnlineSpelling || bInvalid) )
+ return;
+
+ for( SwDocShell *pDocSh = static_cast<SwDocShell*>(SfxObjectShell::GetFirst(checkSfxObjectShell<SwDocShell>));
+ pDocSh;
+ pDocSh = static_cast<SwDocShell*>(SfxObjectShell::GetNext( *pDocSh, checkSfxObjectShell<SwDocShell> ) ) )
+ {
+ SwDoc* pTmp = pDocSh->GetDoc();
+ if ( pTmp->getIDocumentLayoutAccess().GetCurrentViewShell() )
+ {
+ pTmp->SpellItAgainSam( bInvalid, bOnlyWrong, bSmartTags );
+ SwViewShell* pViewShell = pTmp->getIDocumentLayoutAccess().GetCurrentViewShell();
+ if ( bSmartTags && pViewShell && pViewShell->GetWin() )
+ pViewShell->GetWin()->Invalidate();
+ }
+ }
+}
+
+void SwModule::ApplyDefaultPageMode(bool bIsSquaredPageMode)
+{
+ if (!m_pUsrPref)
+ GetUsrPref(false);
+ assert(m_pUsrPref && "pPref is set by here");
+ m_pUsrPref->SetDefaultPageMode(bIsSquaredPageMode);
+}
+
+SwCompareMode SwModule::GetCompareMode() const
+{
+ return m_pModuleConfig->GetCompareMode();
+}
+
+bool SwModule::IsUseRsid() const
+{
+ return m_pModuleConfig->IsUseRsid();
+}
+
+bool SwModule::IsIgnorePieces() const
+{
+ return m_pModuleConfig->IsIgnorePieces();
+}
+
+sal_uInt16 SwModule::GetPieceLen() const
+{
+ return m_pModuleConfig->GetPieceLen();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/app/swmodule.cxx b/sw/source/uibase/app/swmodule.cxx
new file mode 100644
index 0000000000..e7a97f4b8c
--- /dev/null
+++ b/sw/source/uibase/app/swmodule.cxx
@@ -0,0 +1,401 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+
+#include <svtools/ehdl.hxx>
+#include <svtools/accessibilityoptions.hxx>
+#include <unotools/resmgr.hxx>
+#include <unotools/useroptions.hxx>
+#include <svl/ctloptions.hxx>
+#include <svx/ParaSpacingControl.hxx>
+#include <svx/pszctrl.hxx>
+#include <svx/insctrl.hxx>
+#include <svx/selctrl.hxx>
+#include <svx/linectrl.hxx>
+#include <svx/tbxctl.hxx>
+#include <svx/fillctrl.hxx>
+#include <svx/formatpaintbrushctrl.hxx>
+#include <svx/contdlg.hxx>
+#include <svx/fontwork.hxx>
+#include <SwSpellDialogChildWindow.hxx>
+#include <svx/grafctrl.hxx>
+#include <svx/clipboardctl.hxx>
+#include <svx/imapdlg.hxx>
+#include <svx/srchdlg.hxx>
+#include <svx/hyperdlg.hxx>
+#include <svx/modctrl.hxx>
+#include <com/sun/star/scanner/ScannerManager.hpp>
+#include <com/sun/star/linguistic2/LanguageGuessing.hpp>
+#include <ooo/vba/XSinkCaller.hpp>
+#include <comphelper/lok.hxx>
+#include <comphelper/processfactory.hxx>
+#include <docsh.hxx>
+#include <swmodule.hxx>
+#include <cmdid.h>
+#include <pview.hxx>
+#include <wview.hxx>
+#include <wdocsh.hxx>
+#include <srcview.hxx>
+#include <glshell.hxx>
+#include <tabsh.hxx>
+#include <listsh.hxx>
+#include <grfsh.hxx>
+#include <mediash.hxx>
+#include <olesh.hxx>
+#include <drawsh.hxx>
+#include <wformsh.hxx>
+#include <drwtxtsh.hxx>
+#include <beziersh.hxx>
+#include <wtextsh.hxx>
+#include <wfrmsh.hxx>
+#include <drformsh.hxx>
+#include <wgrfsh.hxx>
+#include <wolesh.hxx>
+#include <wlistsh.hxx>
+#include <wtabsh.hxx>
+#include <navipi.hxx>
+#include <inputwin.hxx>
+#include <usrpref.hxx>
+#include <uinums.hxx>
+#include <prtopt.hxx>
+#include <bookctrl.hxx>
+#include <tmplctrl.hxx>
+#include <viewlayoutctrl.hxx>
+#include <svx/zoomsliderctrl.hxx>
+#include <zoomctrl.hxx>
+#include <wordcountctrl.hxx>
+#include <AccessibilityStatusBarControl.hxx>
+#include <workctrl.hxx>
+#include <fldwrap.hxx>
+#include <redlndlg.hxx>
+#include <syncbtn.hxx>
+#include <modcfg.hxx>
+#include <fontcfg.hxx>
+#include <sfx2/sidebar/SidebarChildWindow.hxx>
+#include <sfx2/devtools/DevelopmentToolChildWindow.hxx>
+#include <swatrset.hxx>
+#include <idxmrk.hxx>
+#include <wordcountdialog.hxx>
+#include <dlelstnr.hxx>
+#include <barcfg.hxx>
+#include <svx/rubydialog.hxx>
+#include <svtools/colorcfg.hxx>
+
+#include <unotools/configmgr.hxx>
+#include <unotools/moduleoptions.hxx>
+
+#include <avmedia/mediaplayer.hxx>
+#include <avmedia/mediatoolbox.hxx>
+
+#include <annotsh.hxx>
+#include <navsh.hxx>
+
+#include <app.hrc>
+#include <error.hrc>
+#include <strings.hrc>
+#include <bitmaps.hlst>
+#include <svx/xmlsecctrl.hxx>
+bool g_bNoInterrupt = false;
+
+#include <sfx2/app.hxx>
+
+#include <svx/svxerr.hxx>
+
+#include "swdllimpl.hxx"
+#include <dbconfig.hxx>
+#include <navicfg.hxx>
+
+using namespace com::sun::star;
+using namespace ::com::sun::star::uno;
+
+SwModule::SwModule( SfxObjectFactory* pWebFact,
+ SfxObjectFactory* pFact,
+ SfxObjectFactory* pGlobalFact )
+ : SfxModule("sw"_ostr, {pWebFact, pFact, pGlobalFact}),
+ m_pView(nullptr),
+ m_bAuthorInitialised(false),
+ m_bEmbeddedLoadSave( false ),
+ m_pDragDrop( nullptr ),
+ m_pXSelection( nullptr )
+{
+ SetName( "StarWriter" );
+ SvxErrorHandler::ensure();
+ m_pErrorHandler.reset( new SfxErrorHandler( RID_SW_ERRHDL,
+ ErrCodeArea::Sw,
+ ErrCodeArea::Sw,
+ GetResLocale() ) );
+
+ m_pModuleConfig.reset(new SwModuleOptions);
+
+ // We need them anyways
+ m_pToolbarConfig.reset(new SwToolbarConfigItem( false ));
+ m_pWebToolbarConfig.reset(new SwToolbarConfigItem( true ));
+
+ m_pStdFontConfig.reset(new SwStdFontConfig);
+
+ {
+ SolarMutexGuard g;
+ StartListening( *SfxGetpApp() );
+ }
+
+ if (!utl::ConfigManager::IsFuzzing())
+ {
+ // init color configuration
+ // member <pColorConfig> is created and the color configuration is applied
+ // at the view options.
+ GetColorConfig();
+ m_xLinguServiceEventListener = new SwLinguServiceEventListener;
+ }
+}
+
+OUString SwResId(TranslateId aId)
+{
+ return Translate::get(aId, SW_MOD()->GetResLocale());
+}
+
+OUString SwResId(TranslateNId aContextSingularPlural, int nCardinality)
+{
+ return Translate::nget(aContextSingularPlural, nCardinality, SW_MOD()->GetResLocale());
+}
+
+uno::Reference< scanner::XScannerManager2 > const &
+SwModule::GetScannerManager()
+{
+ static bool bTestScannerManager = true;
+ if (bTestScannerManager && !m_xScannerManager.is())
+ {
+ try {
+ m_xScannerManager = scanner::ScannerManager::create( comphelper::getProcessComponentContext() );
+ }
+ catch (...) {}
+ bTestScannerManager = false;
+ }
+ return m_xScannerManager;
+}
+
+uno::Reference< linguistic2::XLanguageGuessing > const & SwModule::GetLanguageGuesser()
+{
+ if (!m_xLanguageGuesser.is())
+ {
+ m_xLanguageGuesser = linguistic2::LanguageGuessing::create( comphelper::getProcessComponentContext() );
+ }
+ return m_xLanguageGuesser;
+}
+
+SwModule::~SwModule()
+{
+ css::uno::Sequence< css::uno::Any > aArgs;
+ CallAutomationApplicationEventSinks( "Quit", aArgs );
+ m_pErrorHandler.reset();
+ EndListening( *SfxGetpApp() );
+}
+
+void SwDLL::RegisterFactories()
+{
+ // These Id's must not be changed. Through these Id's the View (resume Documentview)
+ // is created by Sfx.
+ if (utl::ConfigManager::IsFuzzing() || SvtModuleOptions().IsWriter())
+ SwView::RegisterFactory ( SFX_INTERFACE_SFXDOCSH );
+
+#if HAVE_FEATURE_DESKTOP
+ SwWebView::RegisterFactory ( SFX_INTERFACE_SFXMODULE );
+
+ if (utl::ConfigManager::IsFuzzing() || SvtModuleOptions().IsWriter())
+ {
+ SwSrcView::RegisterFactory ( SfxInterfaceId(6) );
+ SwPagePreview::RegisterFactory ( SfxInterfaceId(7) );
+ }
+#endif
+}
+
+void SwDLL::RegisterInterfaces()
+{
+ SwModule* pMod = SW_MOD();
+ SwModule::RegisterInterface( pMod );
+ SwDocShell::RegisterInterface( pMod );
+ SwWebDocShell::RegisterInterface( pMod );
+ SwGlosDocShell::RegisterInterface( pMod );
+ SwWebGlosDocShell::RegisterInterface( pMod );
+ SwView::RegisterInterface( pMod );
+ SwWebView::RegisterInterface( pMod );
+ SwPagePreview::RegisterInterface( pMod );
+ SwSrcView::RegisterInterface( pMod );
+
+ SwBaseShell::RegisterInterface(pMod);
+ SwTextShell::RegisterInterface(pMod);
+ SwTableShell::RegisterInterface(pMod);
+ SwListShell::RegisterInterface(pMod);
+ SwFrameShell::RegisterInterface(pMod);
+ SwDrawBaseShell::RegisterInterface(pMod);
+ SwDrawShell::RegisterInterface(pMod);
+ SwDrawFormShell::RegisterInterface(pMod);
+ SwDrawTextShell::RegisterInterface(pMod);
+ SwBezierShell::RegisterInterface(pMod);
+ SwGrfShell::RegisterInterface(pMod);
+ SwOleShell::RegisterInterface(pMod);
+ SwNavigationShell::RegisterInterface(pMod);
+ SwWebTextShell::RegisterInterface(pMod);
+ SwWebFrameShell::RegisterInterface(pMod);
+ SwWebGrfShell::RegisterInterface(pMod);
+ SwWebListShell::RegisterInterface(pMod);
+ SwWebTableShell::RegisterInterface(pMod);
+ SwWebDrawFormShell::RegisterInterface(pMod);
+ SwWebOleShell::RegisterInterface(pMod);
+ SwMediaShell::RegisterInterface(pMod);
+ SwAnnotationShell::RegisterInterface(pMod);
+}
+
+void SwDLL::RegisterControls()
+{
+ SwModule* pMod = SW_MOD();
+
+ SvxTbxCtlDraw::RegisterControl(SID_INSERT_DRAW, pMod );
+ SvxTbxCtlDraw::RegisterControl(SID_TRACK_CHANGES_BAR, pMod );
+ SwTbxAutoTextCtrl::RegisterControl(FN_GLOSSARY_DLG, pMod );
+ svx::ParaAboveSpacingControl::RegisterControl(SID_ATTR_PARA_ABOVESPACE, pMod);
+ svx::ParaBelowSpacingControl::RegisterControl(SID_ATTR_PARA_BELOWSPACE, pMod);
+ svx::ParaLeftSpacingControl::RegisterControl(SID_ATTR_PARA_LEFTSPACE, pMod);
+ svx::ParaRightSpacingControl::RegisterControl(SID_ATTR_PARA_RIGHTSPACE, pMod);
+ svx::ParaFirstLineSpacingControl::RegisterControl(SID_ATTR_PARA_FIRSTLINESPACE, pMod);
+
+ SvxClipBoardControl::RegisterControl(SID_PASTE, pMod );
+ svx::FormatPaintBrushToolBoxControl::RegisterControl(SID_FORMATPAINTBRUSH, pMod );
+
+ SvxFillToolBoxControl::RegisterControl(SID_ATTR_FILL_STYLE, pMod );
+ SvxLineWidthToolBoxControl::RegisterControl(SID_ATTR_LINE_WIDTH, pMod );
+
+ SwZoomControl::RegisterControl(SID_ATTR_ZOOM, pMod );
+ SwPreviewZoomControl::RegisterControl(FN_PREVIEW_ZOOM, pMod);
+ SvxPosSizeStatusBarControl::RegisterControl(0, pMod );
+ SvxInsertStatusBarControl::RegisterControl(SID_ATTR_INSERT, pMod );
+ SvxSelectionModeControl::RegisterControl(FN_STAT_SELMODE, pMod );
+ XmlSecStatusBarControl::RegisterControl( SID_SIGNATURE, pMod );
+ SwWordCountStatusBarControl::RegisterControl(FN_STAT_WORDCOUNT, pMod);
+ sw::AccessibilityStatusBarControl::RegisterControl(FN_STAT_ACCESSIBILITY_CHECK, pMod);
+
+ SwBookmarkControl::RegisterControl(FN_STAT_PAGE, pMod );
+ SwTemplateControl::RegisterControl(FN_STAT_TEMPLATE, pMod );
+ SwViewLayoutControl::RegisterControl( SID_ATTR_VIEWLAYOUT, pMod );
+ SvxModifyControl::RegisterControl( SID_DOC_MODIFIED, pMod );
+ SvxZoomSliderControl::RegisterControl( SID_ATTR_ZOOMSLIDER, pMod );
+
+ SvxIMapDlgChildWindow::RegisterChildWindow( false, pMod );
+ SvxSearchDialogWrapper::RegisterChildWindow( false, pMod );
+ SvxHlinkDlgWrapper::RegisterChildWindow( false, pMod );
+ SvxFontWorkChildWindow::RegisterChildWindow( false, pMod );
+ SwFieldDlgWrapper::RegisterChildWindow( false, pMod );
+ SwFieldDataOnlyDlgWrapper::RegisterChildWindow( false, pMod );
+ SvxContourDlgChildWindow::RegisterChildWindow( false, pMod );
+ SwInputChild::RegisterChildWindow( false, pMod, SfxChildWindowFlags::FORCEDOCK );
+ SwRedlineAcceptChild::RegisterChildWindow( false, pMod );
+ SwSyncChildWin::RegisterChildWindow( true, pMod );
+ SwInsertIdxMarkWrapper::RegisterChildWindow( false, pMod );
+ SwInsertAuthMarkWrapper::RegisterChildWindow( false, pMod );
+ SwWordCountWrapper::RegisterChildWindow( false, pMod );
+ SvxRubyChildWindow::RegisterChildWindow( false, pMod);
+ SwSpellDialogChildWindow::RegisterChildWindow(
+ false, pMod, comphelper::LibreOfficeKit::isActive() ? SfxChildWindowFlags::NEVERCLONE
+ : SfxChildWindowFlags::NONE);
+ DevelopmentToolChildWindow::RegisterChildWindow(false, pMod);
+
+ SvxGrafRedToolBoxControl::RegisterControl( SID_ATTR_GRAF_RED, pMod );
+ SvxGrafGreenToolBoxControl::RegisterControl( SID_ATTR_GRAF_GREEN, pMod );
+ SvxGrafBlueToolBoxControl::RegisterControl( SID_ATTR_GRAF_BLUE, pMod );
+ SvxGrafLuminanceToolBoxControl::RegisterControl( SID_ATTR_GRAF_LUMINANCE, pMod );
+ SvxGrafContrastToolBoxControl::RegisterControl( SID_ATTR_GRAF_CONTRAST, pMod );
+ SvxGrafGammaToolBoxControl::RegisterControl( SID_ATTR_GRAF_GAMMA, pMod );
+ SvxGrafTransparenceToolBoxControl::RegisterControl( SID_ATTR_GRAF_TRANSPARENCE, pMod );
+ SvxGrafModeToolBoxControl::RegisterControl( SID_ATTR_GRAF_MODE, pMod );
+
+#if HAVE_FEATURE_AVMEDIA
+ ::avmedia::MediaToolBoxControl::RegisterControl(SID_AVMEDIA_TOOLBOX, pMod);
+ ::avmedia::MediaPlayer::RegisterChildWindow(false, pMod);
+#endif
+
+ ::sfx2::sidebar::SidebarChildWindow::RegisterChildWindow(false, pMod);
+
+ SwNavigatorWrapper::RegisterChildWindow(false, pMod, SfxChildWindowFlags::NEVERHIDE);
+
+ SwJumpToSpecificPageControl::RegisterControl(SID_JUMP_TO_SPECIFIC_PAGE, pMod);
+}
+
+// Load Module (only dummy for linking of the DLL)
+void SwModule::InitAttrPool()
+{
+ OSL_ENSURE(!m_pAttrPool, "Pool already exists!");
+ m_pAttrPool = new SwAttrPool(nullptr);
+ SetPool(m_pAttrPool.get());
+}
+
+void SwModule::RemoveAttrPool()
+{
+ SetPool(nullptr);
+ m_pAttrPool.clear();
+}
+
+std::optional<SfxStyleFamilies> SwModule::CreateStyleFamilies()
+{
+ SfxStyleFamilies aStyleFamilies;
+
+ aStyleFamilies.emplace_back(SfxStyleFamily::Para,
+ SwResId(STR_PARAGRAPHSTYLEFAMILY),
+ BMP_STYLES_FAMILY_PARA,
+ RID_PARAGRAPHSTYLEFAMILY, GetResLocale());
+
+ aStyleFamilies.emplace_back(SfxStyleFamily::Char,
+ SwResId(STR_CHARACTERSTYLEFAMILY),
+ BMP_STYLES_FAMILY_CHAR,
+ RID_CHARACTERSTYLEFAMILY, GetResLocale());
+
+ aStyleFamilies.emplace_back(SfxStyleFamily::Frame,
+ SwResId(STR_FRAMESTYLEFAMILY),
+ BMP_STYLES_FAMILY_FRAME,
+ RID_FRAMESTYLEFAMILY, GetResLocale());
+
+ aStyleFamilies.emplace_back(SfxStyleFamily::Page,
+ SwResId(STR_PAGESTYLEFAMILY),
+ BMP_STYLES_FAMILY_PAGE,
+ RID_PAGESTYLEFAMILY, GetResLocale());
+
+ aStyleFamilies.emplace_back(SfxStyleFamily::Pseudo,
+ SwResId(STR_LISTSTYLEFAMILY),
+ BMP_STYLES_FAMILY_LIST,
+ RID_LISTSTYLEFAMILY, GetResLocale());
+
+ aStyleFamilies.emplace_back(SfxStyleFamily::Table,
+ SwResId(STR_TABLESTYLEFAMILY),
+ BMP_STYLES_FAMILY_TABLE,
+ RID_TABLESTYLEFAMILY, GetResLocale());
+
+ return aStyleFamilies;
+}
+
+void SwModule::RegisterAutomationApplicationEventsCaller(css::uno::Reference< ooo::vba::XSinkCaller > const& xCaller)
+{
+ mxAutomationApplicationEventsCaller = xCaller;
+}
+
+void SwModule::CallAutomationApplicationEventSinks(const OUString& Method, css::uno::Sequence< css::uno::Any >& Arguments)
+{
+ if (mxAutomationApplicationEventsCaller.is())
+ mxAutomationApplicationEventsCaller->CallSinks(Method, Arguments);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/app/swwait.cxx b/sw/source/uibase/app/swwait.cxx
new file mode 100644
index 0000000000..62d8b277d6
--- /dev/null
+++ b/sw/source/uibase/app/swwait.cxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <swwait.hxx>
+#include <docsh.hxx>
+
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/dispatch.hxx>
+
+#include <vcl/window.hxx>
+
+SwWait::SwWait(
+ SwDocShell &rDocShell,
+ const bool bLockUnlockDispatcher )
+ : mrDoc ( rDocShell )
+ , mbLockUnlockDispatcher( bLockUnlockDispatcher )
+{
+ EnterWaitAndLockDispatcher();
+}
+
+SwWait::~SwWait()
+{
+ LeaveWaitAndUnlockDispatcher();
+}
+
+void SwWait::EnterWaitAndLockDispatcher()
+{
+ SfxViewFrame *pFrame = SfxViewFrame::GetFirst( &mrDoc, false );
+ while ( pFrame )
+ {
+ pFrame->GetWindow().EnterWait();
+ if ( mbLockUnlockDispatcher )
+ {
+ // do not look already locked dispatchers
+ SfxDispatcher* pDispatcher = pFrame->GetDispatcher();
+ if ( !pDispatcher->IsLocked() )
+ {
+ pDispatcher->Lock( true );
+ mpLockedDispatchers.insert( pDispatcher );
+ }
+ }
+
+ pFrame = SfxViewFrame::GetNext( *pFrame, &mrDoc, false );
+ }
+}
+
+void SwWait::LeaveWaitAndUnlockDispatcher()
+{
+ SfxViewFrame *pFrame = SfxViewFrame::GetFirst( &mrDoc, false );
+ while ( pFrame )
+ {
+ pFrame->GetWindow().LeaveWait();
+ if ( mbLockUnlockDispatcher )
+ {
+ // only unlock dispatchers which had been locked
+ SfxDispatcher* pDispatcher = pFrame->GetDispatcher();
+ if ( mpLockedDispatchers.erase( pDispatcher ) )
+ {
+ pDispatcher->Lock( false );
+ }
+ }
+
+ pFrame = SfxViewFrame::GetNext( *pFrame, &mrDoc, false );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/chrdlg/ccoll.cxx b/sw/source/uibase/chrdlg/ccoll.cxx
new file mode 100644
index 0000000000..547566c427
--- /dev/null
+++ b/sw/source/uibase/chrdlg/ccoll.cxx
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cmdid.h>
+
+#include <ccoll.hxx>
+#include <fmtcol.hxx>
+#include <o3tl/string_view.hxx>
+
+//!! order of entries has to be the same as in
+//!! CommandStruct SwCondCollItem::aCmds[]
+
+// note: also keep this in sync with the list of conditions in xmloff/source/style/prstylecond.cxx
+
+const char * const aCommandContext[COND_COMMAND_COUNT] =
+{
+ "TableHeader",
+ "Table",
+ "Frame",
+ "Section",
+ "Footnote",
+ "Endnote",
+ "Header",
+ "Footer",
+ "OutlineLevel1",
+ "OutlineLevel2",
+ "OutlineLevel3",
+ "OutlineLevel4",
+ "OutlineLevel5",
+ "OutlineLevel6",
+ "OutlineLevel7",
+ "OutlineLevel8",
+ "OutlineLevel9",
+ "OutlineLevel10",
+ "NumberingLevel1",
+ "NumberingLevel2",
+ "NumberingLevel3",
+ "NumberingLevel4",
+ "NumberingLevel5",
+ "NumberingLevel6",
+ "NumberingLevel7",
+ "NumberingLevel8",
+ "NumberingLevel9",
+ "NumberingLevel10"
+};
+
+sal_Int16 GetCommandContextIndex( std::u16string_view rContextName )
+{
+ sal_Int16 nRes = -1;
+ for (sal_Int16 i = 0; nRes == -1 && i < COND_COMMAND_COUNT; ++i)
+ {
+ if (o3tl::equalsAscii( rContextName, aCommandContext[i] ))
+ nRes = i;
+ }
+ return nRes;
+}
+
+OUString GetCommandContextByIndex( sal_Int16 nIndex )
+{
+ OUString aRes;
+ if (0 <= nIndex && nIndex < COND_COMMAND_COUNT)
+ {
+ aRes = OUString::createFromAscii( aCommandContext[ nIndex ] );
+ }
+ return aRes;
+}
+
+// Globals
+
+const CommandStruct SwCondCollItem::s_aCmds[] =
+{
+ { Master_CollCondition::PARA_IN_TABLEHEAD, 0 },
+ { Master_CollCondition::PARA_IN_TABLEBODY, 0 },
+ { Master_CollCondition::PARA_IN_FRAME, 0 },
+ { Master_CollCondition::PARA_IN_SECTION, 0 },
+ { Master_CollCondition::PARA_IN_FOOTNOTE, 0 },
+ { Master_CollCondition::PARA_IN_ENDNOTE, 0 },
+ { Master_CollCondition::PARA_IN_HEADER, 0 },
+ { Master_CollCondition::PARA_IN_FOOTER, 0 },
+ { Master_CollCondition::PARA_IN_OUTLINE, 0 },
+ { Master_CollCondition::PARA_IN_OUTLINE, 1 },
+ { Master_CollCondition::PARA_IN_OUTLINE, 2 },
+ { Master_CollCondition::PARA_IN_OUTLINE, 3 },
+ { Master_CollCondition::PARA_IN_OUTLINE, 4 },
+ { Master_CollCondition::PARA_IN_OUTLINE, 5 },
+ { Master_CollCondition::PARA_IN_OUTLINE, 6 },
+ { Master_CollCondition::PARA_IN_OUTLINE, 7 },
+ { Master_CollCondition::PARA_IN_OUTLINE, 8 },
+ { Master_CollCondition::PARA_IN_OUTLINE, 9 },
+ { Master_CollCondition::PARA_IN_LIST, 0 },
+ { Master_CollCondition::PARA_IN_LIST, 1 },
+ { Master_CollCondition::PARA_IN_LIST, 2 },
+ { Master_CollCondition::PARA_IN_LIST, 3 },
+ { Master_CollCondition::PARA_IN_LIST, 4 },
+ { Master_CollCondition::PARA_IN_LIST, 5 },
+ { Master_CollCondition::PARA_IN_LIST, 6 },
+ { Master_CollCondition::PARA_IN_LIST, 7 },
+ { Master_CollCondition::PARA_IN_LIST, 8 },
+ { Master_CollCondition::PARA_IN_LIST, 9 }
+};
+
+
+// Item for the transport of the condition table
+SwCondCollItem::SwCondCollItem() :
+ SfxPoolItem(FN_COND_COLL)
+{
+}
+
+SwCondCollItem::~SwCondCollItem()
+{
+}
+
+SwCondCollItem* SwCondCollItem::Clone( SfxItemPool * /*pPool*/ ) const
+{
+ return new SwCondCollItem(*this);
+}
+
+bool SwCondCollItem::operator==( const SfxPoolItem& rItem) const
+{
+ assert(SfxPoolItem::operator==(rItem));
+ bool bReturn = true;
+ for(sal_uInt16 i = 0; i < COND_COMMAND_COUNT; i++)
+ if (m_sStyles[i] !=
+ static_cast<SwCondCollItem const&>(rItem).m_sStyles[i])
+ {
+ bReturn = false;
+ break;
+ }
+
+ return bReturn;
+}
+
+OUString SwCondCollItem::GetStyle(sal_uInt16 const nPos) const
+{
+ return (nPos < COND_COMMAND_COUNT) ? m_sStyles[nPos] : OUString();
+}
+
+void
+SwCondCollItem::SetStyle(OUString const*const pStyle, sal_uInt16 const nPos)
+{
+ if( nPos < COND_COMMAND_COUNT )
+ m_sStyles[nPos] = pStyle ? *pStyle : OUString();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/config/StoredChapterNumbering.cxx b/sw/source/uibase/config/StoredChapterNumbering.cxx
new file mode 100644
index 0000000000..a74f7329b2
--- /dev/null
+++ b/sw/source/uibase/config/StoredChapterNumbering.cxx
@@ -0,0 +1,459 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <uinums.hxx>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/util/MeasureUnit.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+
+#include <comphelper/processfactory.hxx>
+
+#include <unotools/streamwrap.hxx>
+
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmlnume.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlnumi.hxx>
+
+#include <vcl/svapp.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <unosett.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+namespace sw {
+
+class StoredChapterNumberingRules
+ : public ::cppu::WeakImplHelper<container::XNamed,container::XIndexReplace>
+{
+private:
+ // TODO in case this ever becomes accessible via API need an invalidate
+ SwChapterNumRules & m_rNumRules;
+ sal_uInt16 const m_nIndex;
+
+ SwNumRulesWithName * GetOrCreateRules()
+ {
+ SwNumRulesWithName const* pRules(m_rNumRules.GetRules(m_nIndex));
+ if (!pRules)
+ {
+ m_rNumRules.CreateEmptyNumRule(m_nIndex);
+ pRules = m_rNumRules.GetRules(m_nIndex);
+ assert(pRules);
+ }
+ return const_cast<SwNumRulesWithName*>(pRules);
+ }
+
+public:
+ StoredChapterNumberingRules(
+ SwChapterNumRules & rNumRules, sal_uInt16 const nIndex)
+ : m_rNumRules(rNumRules)
+ , m_nIndex(nIndex)
+ {
+ assert(m_nIndex < SwChapterNumRules::nMaxRules);
+ }
+
+ // XNamed
+ virtual OUString SAL_CALL getName() override
+ {
+ SolarMutexGuard g;
+ SwNumRulesWithName const* pRules(m_rNumRules.GetRules(m_nIndex));
+ if (!pRules)
+ {
+ return OUString();
+ }
+ return pRules->GetName();
+ }
+
+ virtual void SAL_CALL setName(OUString const& rName) override
+ {
+ SolarMutexGuard g;
+ SwNumRulesWithName *const pRules(GetOrCreateRules());
+ pRules->SetName(rName);
+ }
+
+ // XElementAccess
+ virtual uno::Type SAL_CALL getElementType() override
+ {
+ return ::cppu::UnoType<uno::Sequence<beans::PropertyValue>>::get();
+ }
+
+ virtual ::sal_Bool SAL_CALL hasElements() override
+ {
+ return true;
+ }
+
+ // XIndexAccess
+ virtual sal_Int32 SAL_CALL getCount() override
+ {
+ return MAXLEVEL;
+ }
+
+ virtual uno::Any SAL_CALL getByIndex(sal_Int32 nIndex) override
+ {
+ if (nIndex < 0 || MAXLEVEL <= nIndex)
+ throw lang::IndexOutOfBoundsException();
+
+ SolarMutexGuard g;
+ SwNumRulesWithName const* pRules(m_rNumRules.GetRules(m_nIndex));
+ if (!pRules)
+ {
+ return uno::Any();
+ }
+ SwNumFormat const* pNumFormat(nullptr);
+ OUString const* pCharStyleName(nullptr);
+ pRules->GetNumFormat(nIndex, pNumFormat, pCharStyleName);
+ if (!pNumFormat)
+ { // the dialog only fills in those levels that are non-default
+ return uno::Any(); // the export will ignore this level, yay
+ }
+ assert(pCharStyleName);
+ OUString dummy; // pass in empty HeadingStyleName - can't import anyway
+ uno::Sequence<beans::PropertyValue> const ret(
+ SwXNumberingRules::GetPropertiesForNumFormat(
+ *pNumFormat, *pCharStyleName, &dummy, ""));
+ return uno::Any(ret);
+ }
+
+ // XIndexReplace
+ virtual void SAL_CALL replaceByIndex(
+ sal_Int32 nIndex, uno::Any const& rElement) override
+ {
+ if (nIndex < 0 || MAXLEVEL <= nIndex)
+ throw lang::IndexOutOfBoundsException();
+ uno::Sequence<beans::PropertyValue> props;
+ if (!(rElement >>= props))
+ throw lang::IllegalArgumentException("invalid type",
+ getXWeak(), 1);
+
+ SolarMutexGuard g;
+ SwNumFormat aNumberFormat;
+ OUString charStyleName;
+ SwXNumberingRules::SetPropertiesToNumFormat(
+ aNumberFormat,
+ charStyleName,
+ nullptr, nullptr, nullptr, nullptr, nullptr,
+ props);
+ SwNumRulesWithName *const pRules(GetOrCreateRules());
+ pRules->SetNumFormat(nIndex, aNumberFormat, charStyleName);
+ }
+};
+
+namespace {
+
+class StoredChapterNumberingExport
+ : public SvXMLExport
+{
+public:
+ StoredChapterNumberingExport(
+ uno::Reference<uno::XComponentContext> const& xContext,
+ OUString const& rFileName,
+ uno::Reference<xml::sax::XDocumentHandler> const& xHandler)
+ : SvXMLExport(xContext, "sw::StoredChapterNumberingExport", rFileName,
+ util::MeasureUnit::CM, xHandler)
+ {
+ GetNamespaceMap_().Add(GetXMLToken(XML_NP_OFFICE),
+ GetXMLToken(XML_N_OFFICE), XML_NAMESPACE_OFFICE);
+ GetNamespaceMap_().Add(GetXMLToken(XML_NP_TEXT),
+ GetXMLToken(XML_N_TEXT), XML_NAMESPACE_TEXT);
+ GetNamespaceMap_().Add(GetXMLToken(XML_NP_STYLE),
+ GetXMLToken(XML_N_STYLE), XML_NAMESPACE_STYLE);
+ GetNamespaceMap_().Add(GetXMLToken(XML_NP_FO),
+ GetXMLToken(XML_N_FO), XML_NAMESPACE_FO);
+ GetNamespaceMap_().Add(GetXMLToken(XML_NP_SVG),
+ GetXMLToken(XML_N_SVG), XML_NAMESPACE_SVG);
+ }
+
+ virtual void ExportAutoStyles_() override {}
+ virtual void ExportMasterStyles_() override {}
+ virtual void ExportContent_() override {}
+
+ void ExportRule(SvxXMLNumRuleExport & rExport,
+ uno::Reference<container::XIndexReplace> const& xRule)
+ {
+ uno::Reference<container::XNamed> const xNamed(xRule, uno::UNO_QUERY);
+ OUString const name(xNamed->getName());
+ bool bEncoded(false);
+ AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
+ EncodeStyleName(name, &bEncoded) );
+ if (bEncoded)
+ {
+ AddAttribute(XML_NAMESPACE_STYLE, XML_DISPLAY_NAME, name);
+ }
+
+ SvXMLElementExport aElem( *this, XML_NAMESPACE_TEXT,
+ XML_OUTLINE_STYLE, true, true );
+ rExport.exportLevelStyles(xRule, true);
+ }
+
+ void ExportRules(
+ std::set<OUString> const& rCharStyles,
+ std::vector<uno::Reference<container::XIndexReplace>> const& rRules)
+ {
+ GetDocHandler()->startDocument();
+
+ AddAttribute(XML_NAMESPACE_NONE,
+ GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_OFFICE),
+ GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_OFFICE));
+ AddAttribute(XML_NAMESPACE_NONE,
+ GetNamespaceMap_().GetAttrNameByKey (XML_NAMESPACE_TEXT),
+ GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_TEXT));
+ AddAttribute(XML_NAMESPACE_NONE,
+ GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_STYLE),
+ GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_STYLE));
+ AddAttribute(XML_NAMESPACE_NONE,
+ GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_FO),
+ GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_FO));
+ AddAttribute(XML_NAMESPACE_NONE,
+ GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_SVG),
+ GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_SVG));
+
+ {
+ // let's just have an office:styles as a dummy root
+ SvXMLElementExport styles(*this,
+ XML_NAMESPACE_OFFICE, XML_STYLES, true, true);
+
+ // horrible hack for char styles to get display-name mapping
+ for (const auto& rCharStyle : rCharStyles)
+ {
+ AddAttribute( XML_NAMESPACE_STYLE, XML_FAMILY, XML_TEXT );
+ bool bEncoded(false);
+ AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
+ EncodeStyleName(rCharStyle, &bEncoded) );
+ if (bEncoded)
+ {
+ AddAttribute(XML_NAMESPACE_STYLE, XML_DISPLAY_NAME, rCharStyle);
+ }
+
+ SvXMLElementExport style(*this,
+ XML_NAMESPACE_STYLE, XML_STYLE, true, true);
+ }
+
+ SvxXMLNumRuleExport numRuleExport(*this);
+
+ for (const auto& rRule : rRules)
+ {
+ ExportRule(numRuleExport, rRule);
+ }
+ }
+
+ GetDocHandler()->endDocument();
+ }
+};
+
+/** Dummy import context for style:style element that can just read the
+ attributes needed to map name to display-name.
+ Unfortunately the "real" context for this depends on some other things.
+ The mapping is necessary to import the text:style-name attribute
+ of the text:outline-level-style element.
+ */
+class StoredChapterNumberingDummyStyleContext
+ : public SvXMLImportContext
+{
+public:
+ StoredChapterNumberingDummyStyleContext(
+ SvXMLImport & rImport,
+ uno::Reference<xml::sax::XFastAttributeList> const& xAttrList)
+ : SvXMLImportContext(rImport)
+ {
+ OUString name;
+ OUString displayName;
+ XmlStyleFamily nFamily(XmlStyleFamily::DATA_STYLE);
+
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ if (aIter.getToken() == (XML_NAMESPACE_STYLE | XML_FAMILY))
+ {
+ if (IsXMLToken(aIter, XML_TEXT))
+ nFamily = XmlStyleFamily::TEXT_TEXT;
+ else if (IsXMLToken(aIter, XML_NAME))
+ name = aIter.toString();
+ else if (IsXMLToken(aIter, XML_DISPLAY_NAME))
+ displayName = aIter.toString();
+ else
+ SAL_WARN("xmloff", "unknown value for style:family=" << aIter.toString());
+ }
+ else
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+
+ if (nFamily != XmlStyleFamily::DATA_STYLE && !name.isEmpty() && !displayName.isEmpty())
+ {
+ rImport.AddStyleDisplayName(nFamily, name, displayName);
+ }
+ }
+};
+
+class StoredChapterNumberingImport;
+
+class StoredChapterNumberingRootContext
+ : public SvXMLImportContext
+{
+private:
+ SwChapterNumRules & m_rNumRules;
+ size_t m_nCounter;
+ std::vector<rtl::Reference<SvxXMLListStyleContext>> m_Contexts;
+
+public:
+ StoredChapterNumberingRootContext(
+ SwChapterNumRules & rNumRules, SvXMLImport & rImport)
+ : SvXMLImportContext(rImport)
+ , m_rNumRules(rNumRules)
+ , m_nCounter(0)
+ {
+ }
+
+ virtual void SAL_CALL endFastElement(sal_Int32 /*Element*/) override
+ {
+ assert(m_Contexts.size() <= SwChapterNumRules::nMaxRules);
+ for (auto iter = m_Contexts.begin(); iter != m_Contexts.end(); ++iter)
+ {
+ uno::Reference<container::XIndexReplace> const xRule(
+ new sw::StoredChapterNumberingRules(m_rNumRules,
+ iter - m_Contexts.begin()));
+ (*iter)->FillUnoNumRule(xRule);
+ // TODO: xmloff's outline-style import seems to ignore this???
+ uno::Reference<container::XNamed> const xNamed(xRule, uno::UNO_QUERY);
+ xNamed->setName((*iter)->GetDisplayName());
+ }
+ }
+
+ virtual css::uno::Reference<XFastContextHandler> SAL_CALL createFastChildContext(
+ sal_Int32 Element,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) override
+ {
+ if (Element == XML_ELEMENT(STYLE, XML_STYLE))
+ {
+ return new StoredChapterNumberingDummyStyleContext(GetImport(), xAttrList);
+ }
+ else if (Element == XML_ELEMENT(TEXT, XML_OUTLINE_STYLE))
+ {
+ ++m_nCounter;
+ if (m_nCounter <= SwChapterNumRules::nMaxRules)
+ {
+ SvxXMLListStyleContext *const pContext(
+ new SvxXMLListStyleContext(GetImport(), true));
+ m_Contexts.emplace_back(pContext);
+ return pContext;
+ }
+ }
+
+ return nullptr;
+ }
+};
+
+class StoredChapterNumberingImport
+ : public SvXMLImport
+{
+private:
+ SwChapterNumRules & m_rNumRules;
+
+public:
+ StoredChapterNumberingImport(
+ uno::Reference<uno::XComponentContext> const& xContext,
+ SwChapterNumRules & rNumRules)
+ : SvXMLImport(xContext, "sw::StoredChapterNumberingImport", SvXMLImportFlags::ALL)
+ , m_rNumRules(rNumRules)
+ {
+ }
+
+ virtual SvXMLImportContext *CreateFastContext( sal_Int32 Element,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & /*xAttrList*/ ) override
+ {
+ if (Element == XML_ELEMENT(OFFICE, XML_STYLES))
+ return new StoredChapterNumberingRootContext(m_rNumRules, *this);
+ return nullptr;
+ }
+};
+
+}
+
+void ExportStoredChapterNumberingRules(SwChapterNumRules & rRules,
+ SvStream & rStream, OUString const& rFileName)
+{
+ uno::Reference<uno::XComponentContext> const xContext(
+ ::comphelper::getProcessComponentContext());
+
+ uno::Reference<io::XOutputStream> const xOutStream(
+ new ::utl::OOutputStreamWrapper(rStream));
+
+ uno::Reference<xml::sax::XWriter> const xWriter(
+ xml::sax::Writer::create(xContext));
+
+ xWriter->setOutputStream(xOutStream);
+
+ rtl::Reference<StoredChapterNumberingExport> exp(new StoredChapterNumberingExport(xContext, rFileName, xWriter));
+
+ // if style name contains a space then name != display-name
+ // ... and the import needs to map from name to display-name then!
+ std::set<OUString> charStyles;
+ std::vector<uno::Reference<container::XIndexReplace>> numRules;
+ for (size_t i = 0; i < SwChapterNumRules::nMaxRules; ++i)
+ {
+ if (SwNumRulesWithName const* pRule = rRules.GetRules(i))
+ {
+ for (size_t j = 0; j < MAXLEVEL; ++j)
+ {
+ SwNumFormat const* pDummy(nullptr);
+ OUString const* pCharStyleName(nullptr);
+ pRule->GetNumFormat(j, pDummy, pCharStyleName);
+ if (pCharStyleName && !pCharStyleName->isEmpty())
+ {
+ charStyles.insert(*pCharStyleName);
+ }
+ }
+ numRules.push_back(new StoredChapterNumberingRules(rRules, i));
+ }
+ }
+
+ try
+ {
+ exp->ExportRules(charStyles, numRules);
+ }
+ catch (uno::Exception const&)
+ {
+ TOOLS_WARN_EXCEPTION("sw.ui", "ExportStoredChapterNumberingRules");
+ }
+}
+
+void ImportStoredChapterNumberingRules(SwChapterNumRules & rRules,
+ SvStream & rStream, OUString const& rFileName)
+{
+ uno::Reference<uno::XComponentContext> const xContext(
+ ::comphelper::getProcessComponentContext());
+
+ uno::Reference<io::XInputStream> const xInStream(
+ new ::utl::OInputStreamWrapper(rStream));
+
+ rtl::Reference<StoredChapterNumberingImport> const xImport(new StoredChapterNumberingImport(xContext, rRules));
+
+ xml::sax::InputSource const source(xInStream, "", "", rFileName);
+
+ try
+ {
+ xImport->parseStream(source);
+ }
+ catch (uno::Exception const&)
+ {
+ TOOLS_WARN_EXCEPTION("sw.ui", "ImportStoredChapterNumberingRules");
+ }
+}
+
+} // namespace sw
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/config/barcfg.cxx b/sw/source/uibase/config/barcfg.cxx
new file mode 100644
index 0000000000..1f54b05cc1
--- /dev/null
+++ b/sw/source/uibase/config/barcfg.cxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <osl/diagnose.h>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <wrtsh.hxx>
+#include <barcfg.hxx>
+
+using namespace utl;
+using namespace com::sun::star::uno;
+
+#define SEL_TYPE_TABLE_TEXT 0
+#define SEL_TYPE_LIST_TEXT 1
+#define SEL_TYPE_TABLE_LIST 2
+#define SEL_TYPE_BEZIER 3
+#define SEL_TYPE_GRAPHIC 4
+
+SwToolbarConfigItem::SwToolbarConfigItem( bool bWeb ) :
+ ConfigItem(bWeb ? OUString("Office.WriterWeb/ObjectBar") : OUString("Office.Writer/ObjectBar"),
+ ConfigItemMode::ReleaseTree)
+{
+ for(int i = 0; i <= SEL_TYPE_GRAPHIC; ++i)
+ m_aTbxIdArray[i] = -1;
+
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ const Any* pValues = aValues.getConstArray();
+ OSL_ENSURE(aValues.getLength() == aNames.getLength(), "GetProperties failed");
+ if(aValues.getLength() == aNames.getLength())
+ {
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ if(pValues[nProp].hasValue())
+ {
+ sal_Int32 nVal = 0;
+ pValues[nProp] >>= nVal;
+ m_aTbxIdArray[nProp] = nVal;
+ }
+ }
+ }
+}
+
+SwToolbarConfigItem::~SwToolbarConfigItem()
+{
+}
+
+static sal_Int32 lcl_getArrayIndex(SelectionType nSelType)
+{
+ sal_Int32 nRet = -1;
+ if(nSelType & SelectionType::NumberList)
+ {
+ if(nSelType & SelectionType::Table)
+ nRet = SEL_TYPE_TABLE_LIST;
+ else
+ nRet = SEL_TYPE_LIST_TEXT;
+ }
+ else if(nSelType & SelectionType::Table)
+ nRet = SEL_TYPE_TABLE_TEXT;
+ else if(nSelType & SelectionType::Ornament)
+ nRet = SEL_TYPE_BEZIER;
+ else if(nSelType & SelectionType::Graphic)
+ nRet = SEL_TYPE_GRAPHIC;
+ return nRet;
+}
+
+void SwToolbarConfigItem::SetTopToolbar(SelectionType nSelType, ToolbarId eBarId)
+{
+ sal_Int32 nProp = lcl_getArrayIndex(nSelType);
+ if(nProp >= 0)
+ {
+ m_aTbxIdArray[nProp] = static_cast<sal_Int32>(eBarId);
+ SetModified();
+ }
+}
+
+Sequence<OUString> SwToolbarConfigItem::GetPropertyNames()
+{
+ static const char* aPropNames[] =
+ {
+ "Selection/Table", // SEL_TYPE_TABLE_TEXT
+ "Selection/NumberedList", // SEL_TYPE_LIST_TEXT
+ "Selection/NumberedList_InTable", // SEL_TYPE_TABLE_LIST
+ "Selection/BezierObject", // SEL_TYPE_BEZIER
+ "Selection/Graphic" //SEL_TYPE_GRAPHIC
+ };
+ const int nCount = 5;
+ Sequence<OUString> aNames(nCount);
+ OUString* pNames = aNames.getArray();
+ for(int i = 0; i < nCount; i++)
+ pNames[i] = OUString::createFromAscii(aPropNames[i]);
+ return aNames;
+}
+
+void SwToolbarConfigItem::ImplCommit()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ pValues[nProp] <<= m_aTbxIdArray[nProp];
+ PutProperties(aNames, aValues);
+}
+
+void SwToolbarConfigItem::Notify( const css::uno::Sequence< OUString >& ) {}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/config/caption.cxx b/sw/source/uibase/config/caption.cxx
new file mode 100644
index 0000000000..d023bd836f
--- /dev/null
+++ b/sw/source/uibase/config/caption.cxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <editeng/svxenum.hxx>
+#include <caption.hxx>
+
+InsCaptionOpt::InsCaptionOpt(const SwCapObjType eType, const SvGlobalName* pOleId) :
+ m_bUseCaption(false),
+ m_eObjType(eType),
+ m_nNumType(SVX_NUM_ARABIC),
+ m_sNumberSeparator(". "),
+ m_nPos(1),
+ m_nLevel(0),
+ m_sSeparator( OUString(": ") ),
+ m_bIgnoreSeqOpts(false),
+ m_bCopyAttributes(false)
+{
+ if (pOleId)
+ m_aOleId = *pOleId;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/config/cfgitems.cxx b/sw/source/uibase/config/cfgitems.cxx
new file mode 100644
index 0000000000..e32c86e14c
--- /dev/null
+++ b/sw/source/uibase/config/cfgitems.cxx
@@ -0,0 +1,261 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <viewopt.hxx>
+#include <cmdid.h>
+#include <cfgitems.hxx>
+#include <crstate.hxx>
+
+
+SwDocDisplayItem::SwDocDisplayItem() :
+ SfxPoolItem(FN_PARAM_DOCDISP)
+{
+ m_bParagraphEnd =
+ m_bTab =
+ m_bSpace =
+ m_bNonbreakingSpace =
+ m_bSoftHyphen =
+ m_bCharHiddenText =
+ m_bBookmarks =
+ m_bManualBreak = true;
+ m_xDefaultAnchor = 1; //FLY_TO_CHAR
+};
+
+// Item for the Settings dialog, page document view
+SwDocDisplayItem::SwDocDisplayItem(const SwViewOption& rVOpt ) :
+ SfxPoolItem( FN_PARAM_DOCDISP )
+{
+ m_bParagraphEnd = rVOpt.IsParagraph(true);
+ m_bTab = rVOpt.IsTab(true);
+ m_bSpace = rVOpt.IsBlank(true);
+ m_bNonbreakingSpace = rVOpt.IsHardBlank();
+ m_bSoftHyphen = rVOpt.IsSoftHyph();
+ m_bCharHiddenText = rVOpt.IsShowHiddenChar(true);
+ m_bBookmarks = rVOpt.IsShowBookmarks(true);
+ m_bManualBreak = rVOpt.IsLineBreak(true);
+ m_xDefaultAnchor = rVOpt.GetDefaultAnchor();
+}
+
+SwDocDisplayItem* SwDocDisplayItem::Clone( SfxItemPool* ) const
+{
+ return new SwDocDisplayItem( *this );
+}
+
+bool SwDocDisplayItem::operator==( const SfxPoolItem& rAttr ) const
+{
+ assert(SfxPoolItem::operator==(rAttr));
+
+ const SwDocDisplayItem& rItem = static_cast<const SwDocDisplayItem&>(rAttr);
+
+ return ( m_bParagraphEnd == rItem.m_bParagraphEnd &&
+ m_bTab == rItem.m_bTab &&
+ m_bSpace == rItem.m_bSpace &&
+ m_bNonbreakingSpace == rItem.m_bNonbreakingSpace &&
+ m_bSoftHyphen == rItem.m_bSoftHyphen &&
+ m_bCharHiddenText == rItem.m_bCharHiddenText &&
+ m_bBookmarks == rItem.m_bBookmarks &&
+ m_bManualBreak == rItem.m_bManualBreak &&
+ m_xDefaultAnchor == rItem.m_xDefaultAnchor);
+}
+
+void SwDocDisplayItem::FillViewOptions( SwViewOption& rVOpt) const
+{
+ rVOpt.SetParagraph (m_bParagraphEnd );
+ rVOpt.SetTab (m_bTab );
+ rVOpt.SetBlank (m_bSpace );
+ rVOpt.SetHardBlank (m_bNonbreakingSpace );
+ rVOpt.SetSoftHyph (m_bSoftHyphen );
+ rVOpt.SetShowHiddenChar(m_bCharHiddenText );
+ rVOpt.SetShowBookmarks(m_bBookmarks );
+ rVOpt.SetLineBreak (m_bManualBreak );
+ rVOpt.SetDefaultAnchor( m_xDefaultAnchor );
+}
+
+SwElemItem::SwElemItem() :
+ SfxPoolItem(FN_PARAM_ELEM)
+{
+ m_bVertRuler =
+ m_bVertRulerRight=
+ m_bCrosshair =
+ m_bSmoothScroll =
+ m_bTable =
+ m_bGraphic =
+ m_bDrawing =
+ m_bNotes = false;
+ m_bShowInlineTooltips = true;
+ m_bShowOutlineContentVisibilityButton =
+ m_bTreatSubOutlineLevelsAsContent =
+ m_bShowChangesInMargin =
+ m_bFieldHiddenText =
+ m_bShowHiddenPara = false;
+}
+
+SwElemItem::SwElemItem(const SwViewOption& rVOpt) :
+ SfxPoolItem( FN_PARAM_ELEM )
+{
+ m_bVertRuler = rVOpt.IsViewVRuler(true);
+ m_bVertRulerRight = rVOpt.IsVRulerRight();
+ m_bCrosshair = rVOpt.IsCrossHair();
+ m_bSmoothScroll = rVOpt.IsSmoothScroll();
+ m_bTable = rVOpt.IsTable();
+ m_bGraphic = rVOpt.IsGraphic();
+ m_bDrawing = rVOpt.IsDraw() && rVOpt.IsControl();
+ m_bNotes = rVOpt.IsPostIts();
+ m_bShowInlineTooltips = rVOpt.IsShowInlineTooltips();
+ m_bShowOutlineContentVisibilityButton = rVOpt.IsShowOutlineContentVisibilityButton();
+ m_bTreatSubOutlineLevelsAsContent = rVOpt.IsTreatSubOutlineLevelsAsContent();
+ m_bShowChangesInMargin = rVOpt.IsShowChangesInMargin();
+ m_bFieldHiddenText = rVOpt.IsShowHiddenField();
+ m_bShowHiddenPara = rVOpt.IsShowHiddenPara();
+}
+
+SwElemItem* SwElemItem::Clone( SfxItemPool* ) const
+{
+ return new SwElemItem( *this );
+}
+
+bool SwElemItem::operator==( const SfxPoolItem& rAttr ) const
+{
+ assert(SfxPoolItem::operator==(rAttr));
+
+ const SwElemItem& rItem = static_cast<const SwElemItem&>(rAttr);
+
+ return ( m_bVertRuler == rItem.m_bVertRuler &&
+ m_bVertRulerRight == rItem.m_bVertRulerRight&&
+ m_bCrosshair == rItem.m_bCrosshair &&
+ m_bSmoothScroll == rItem.m_bSmoothScroll &&
+ m_bTable == rItem.m_bTable &&
+ m_bGraphic == rItem.m_bGraphic &&
+ m_bDrawing == rItem.m_bDrawing &&
+ m_bNotes == rItem.m_bNotes &&
+ m_bShowInlineTooltips == rItem.m_bShowInlineTooltips &&
+ m_bShowOutlineContentVisibilityButton == rItem.m_bShowOutlineContentVisibilityButton &&
+ m_bTreatSubOutlineLevelsAsContent == rItem.m_bTreatSubOutlineLevelsAsContent &&
+ m_bShowChangesInMargin == rItem.m_bShowChangesInMargin &&
+ m_bFieldHiddenText == rItem.m_bFieldHiddenText &&
+ m_bShowHiddenPara == rItem.m_bShowHiddenPara);
+}
+
+void SwElemItem::FillViewOptions( SwViewOption& rVOpt) const
+{
+ rVOpt.SetViewVRuler(m_bVertRuler );
+ rVOpt.SetVRulerRight(m_bVertRulerRight );
+ rVOpt.SetCrossHair(m_bCrosshair );
+ rVOpt.SetSmoothScroll(m_bSmoothScroll);
+ rVOpt.SetTable (m_bTable );
+ rVOpt.SetGraphic (m_bGraphic );
+ rVOpt.SetDraw (m_bDrawing );
+ rVOpt.SetControl (m_bDrawing );
+ rVOpt.SetPostIts (m_bNotes );
+ rVOpt.SetShowInlineTooltips( m_bShowInlineTooltips );
+ rVOpt.SetShowOutlineContentVisibilityButton(m_bShowOutlineContentVisibilityButton);
+ rVOpt.SetTreatSubOutlineLevelsAsContent(m_bTreatSubOutlineLevelsAsContent);
+ rVOpt.SetShowChangesInMargin( m_bShowChangesInMargin );
+ rVOpt.SetShowHiddenField(m_bFieldHiddenText );
+ rVOpt.SetShowHiddenPara(m_bShowHiddenPara );
+}
+
+// CTOR for empty Item
+SwAddPrinterItem::SwAddPrinterItem():
+ SfxPoolItem(FN_PARAM_ADDPRINTER)
+{
+}
+
+// CTOR from SwPrintOptions
+SwAddPrinterItem::SwAddPrinterItem( const SwPrintData& rPrtData ) :
+ SfxPoolItem(FN_PARAM_ADDPRINTER)
+{
+ SwPrintData::operator=(rPrtData);
+}
+
+SwAddPrinterItem* SwAddPrinterItem::Clone( SfxItemPool* ) const
+{
+ return new SwAddPrinterItem( *this );
+}
+
+bool SwAddPrinterItem::operator==( const SfxPoolItem& rAttr ) const
+{
+ assert(SfxPoolItem::operator==(rAttr));
+
+ const SwAddPrinterItem& rItem = static_cast<const SwAddPrinterItem&>(rAttr);
+
+ return SwPrintData::operator==(rItem);
+}
+
+// Item for Settings dialog, ShadowCursorPage
+SwShadowCursorItem::SwShadowCursorItem()
+ : SfxPoolItem( FN_PARAM_SHADOWCURSOR ),
+ m_eMode( SwFillMode::Tab )
+ ,m_bOn( false )
+{
+}
+
+SwShadowCursorItem::SwShadowCursorItem( const SwViewOption& rVOpt )
+ : SfxPoolItem( FN_PARAM_SHADOWCURSOR ),
+ m_eMode( rVOpt.GetShdwCursorFillMode() )
+ ,m_bOn( rVOpt.IsShadowCursor() )
+
+{
+}
+
+SwShadowCursorItem* SwShadowCursorItem::Clone( SfxItemPool* ) const
+{
+ return new SwShadowCursorItem( *this );
+}
+
+bool SwShadowCursorItem::operator==( const SfxPoolItem& rCmp ) const
+{
+ return SfxPoolItem::operator==(rCmp) &&
+ IsOn() == static_cast<const SwShadowCursorItem&>(rCmp).IsOn() &&
+ GetMode() == static_cast<const SwShadowCursorItem&>(rCmp).GetMode();
+}
+
+void SwShadowCursorItem::FillViewOptions( SwViewOption& rVOpt ) const
+{
+ rVOpt.SetShadowCursor( m_bOn );
+ rVOpt.SetShdwCursorFillMode( m_eMode );
+}
+
+#ifdef DBG_UTIL
+SwTestItem* SwTestItem::Clone( SfxItemPool* ) const
+{
+ return new SwTestItem( *this );
+}
+
+bool SwTestItem::operator==( const SfxPoolItem& rAttr ) const
+{
+ assert(SfxPoolItem::operator==(rAttr));
+
+ const SwTestItem& rItem = static_cast<const SwTestItem&>( rAttr);
+
+ return ( m_bTest1==rItem.m_bTest1&&
+ m_bTest2==rItem.m_bTest2&&
+ m_bTest3==rItem.m_bTest3&&
+ m_bTest4==rItem.m_bTest4&&
+ m_bTest5==rItem.m_bTest5&&
+ m_bTest6==rItem.m_bTest6&&
+ m_bTest7==rItem.m_bTest7&&
+ m_bTest8==rItem.m_bTest8&&
+ m_bTest9==rItem.m_bTest9&&
+ m_bTest10==rItem.m_bTest10);
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/config/dbconfig.cxx b/sw/source/uibase/config/dbconfig.cxx
new file mode 100644
index 0000000000..669bda65a4
--- /dev/null
+++ b/sw/source/uibase/config/dbconfig.cxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dbconfig.hxx>
+#include <osl/diagnose.h>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <swdbdata.hxx>
+
+using namespace utl;
+using namespace com::sun::star::uno;
+
+const Sequence<OUString>& SwDBConfig::GetPropertyNames()
+{
+ static Sequence<OUString> aNames {
+ "AddressBook/DataSourceName", // 0
+ "AddressBook/Command", // 1
+ "AddressBook/CommandType", // 2
+ "Bibliography/CurrentDataSource/DataSourceName", // 4
+ "Bibliography/CurrentDataSource/Command", // 5
+ "Bibliography/CurrentDataSource/CommandType" // 6
+ };
+ return aNames;
+}
+
+SwDBConfig::SwDBConfig() :
+ ConfigItem("Office.DataAccess", ConfigItemMode::ReleaseTree)
+{
+};
+
+SwDBConfig::~SwDBConfig()
+{
+ m_pAdrImpl.reset();
+ m_pBibImpl.reset();
+}
+
+void SwDBConfig::Load()
+{
+ const Sequence<OUString>& rNames = GetPropertyNames();
+ if (!m_pAdrImpl)
+ m_pAdrImpl.reset(new SwDBData);
+ if (!m_pBibImpl)
+ m_pBibImpl.reset(new SwDBData);
+ Sequence<Any> aValues = GetProperties(rNames);
+ const Any* pValues = aValues.getConstArray();
+ OSL_ENSURE(aValues.getLength() == rNames.getLength(), "GetProperties failed");
+ if(aValues.getLength() != rNames.getLength())
+ return;
+
+ for(int nProp = 0; nProp < rNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case 0: pValues[nProp] >>= m_pAdrImpl->sDataSource; break;
+ case 1: pValues[nProp] >>= m_pAdrImpl->sCommand; break;
+ case 2: pValues[nProp] >>= m_pAdrImpl->nCommandType; break;
+ case 3: pValues[nProp] >>= m_pBibImpl->sDataSource; break;
+ case 4: pValues[nProp] >>= m_pBibImpl->sCommand; break;
+ case 5: pValues[nProp] >>= m_pBibImpl->nCommandType; break;
+ }
+ }
+}
+
+const SwDBData& SwDBConfig::GetAddressSource()
+{
+ if(!m_pAdrImpl)
+ Load();
+ return *m_pAdrImpl;
+}
+
+const SwDBData& SwDBConfig::GetBibliographySource()
+{
+ if(!m_pBibImpl)
+ Load();
+ return *m_pBibImpl;
+}
+
+void SwDBConfig::ImplCommit() {}
+void SwDBConfig::Notify( const css::uno::Sequence< OUString >& ) {}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/config/fontcfg.cxx b/sw/source/uibase/config/fontcfg.cxx
new file mode 100644
index 0000000000..264d50bc8a
--- /dev/null
+++ b/sw/source/uibase/config/fontcfg.cxx
@@ -0,0 +1,314 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <fontcfg.hxx>
+#include <i18nlangtag/mslangid.hxx>
+#include <osl/diagnose.h>
+#include <tools/UnitConversion.hxx>
+#include <vcl/outdev.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/lingucfg.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/i18n/ScriptType.hpp>
+
+using namespace utl;
+using namespace com::sun::star::uno;
+
+static LanguageType lcl_LanguageOfType(sal_Int16 nType, LanguageType eWestern, LanguageType eCJK, LanguageType eCTL)
+{
+ return nType < FONT_STANDARD_CJK
+ ? eWestern
+ : nType >= FONT_STANDARD_CTL ? eCTL : eCJK;
+}
+
+Sequence<OUString> const & SwStdFontConfig::GetPropertyNames()
+{
+ static Sequence<OUString> aNames {
+ "DefaultFont/Standard", // 0
+ "DefaultFont/Heading", // 1
+ "DefaultFont/List", // 2
+ "DefaultFont/Caption", // 3
+ "DefaultFont/Index", // 4
+ "DefaultFontCJK/Standard", // 5
+ "DefaultFontCJK/Heading", // 6
+ "DefaultFontCJK/List", // 7
+ "DefaultFontCJK/Caption", // 8
+ "DefaultFontCJK/Index", // 9
+ "DefaultFontCTL/Standard", // 10
+ "DefaultFontCTL/Heading", // 11
+ "DefaultFontCTL/List", // 12
+ "DefaultFontCTL/Caption", // 13
+ "DefaultFontCTL/Index", // 14
+ "DefaultFont/StandardHeight", // 15
+ "DefaultFont/HeadingHeight", // 16
+ "DefaultFont/ListHeight", // 17
+ "DefaultFont/CaptionHeight", // 18
+ "DefaultFont/IndexHeight", // 19
+ "DefaultFontCJK/StandardHeight", // 20
+ "DefaultFontCJK/HeadingHeight", // 21
+ "DefaultFontCJK/ListHeight", // 22
+ "DefaultFontCJK/CaptionHeight", // 23
+ "DefaultFontCJK/IndexHeight", // 24
+ "DefaultFontCTL/StandardHeight", // 25
+ "DefaultFontCTL/HeadingHeight", // 26
+ "DefaultFontCTL/ListHeight", // 27
+ "DefaultFontCTL/CaptionHeight", // 28
+ "DefaultFontCTL/IndexHeight" // 29
+ };
+ return aNames;
+}
+
+SwStdFontConfig::SwStdFontConfig() :
+ utl::ConfigItem("Office.Writer")
+{
+ SvtLinguOptions aLinguOpt;
+
+ if (!utl::ConfigManager::IsFuzzing())
+ SvtLinguConfig().GetOptions( aLinguOpt );
+
+ LanguageType eWestern = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage, css::i18n::ScriptType::LATIN),
+ eCJK = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage_CJK, css::i18n::ScriptType::ASIAN),
+ eCTL = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage_CTL, css::i18n::ScriptType::COMPLEX);
+
+ for(sal_Int16 i = 0; i < DEF_FONT_COUNT; i++)
+ {
+ m_sDefaultFonts[i] = GetDefaultFor(i,
+ lcl_LanguageOfType(i, eWestern, eCJK, eCTL));
+ m_nDefaultFontHeight[i] = -1;
+ }
+
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ const Any* pValues = aValues.getConstArray();
+ OSL_ENSURE(aValues.getLength() == aNames.getLength(), "GetProperties failed");
+ if(aValues.getLength() != aNames.getLength())
+ return;
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ if(pValues[nProp].hasValue())
+ {
+ if( nProp < DEF_FONT_COUNT)
+ {
+ OUString sVal;
+ pValues[nProp] >>= sVal;
+ m_sDefaultFonts[nProp] = sVal;
+ }
+ else
+ {
+ pValues[nProp] >>= m_nDefaultFontHeight[nProp - DEF_FONT_COUNT];
+ m_nDefaultFontHeight[nProp - DEF_FONT_COUNT] = o3tl::toTwips(m_nDefaultFontHeight[nProp - DEF_FONT_COUNT], o3tl::Length::mm100);
+ }
+ }
+ }
+}
+
+void SwStdFontConfig::ImplCommit()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+ SvtLinguOptions aLinguOpt;
+
+ SvtLinguConfig().GetOptions( aLinguOpt );
+
+ LanguageType eWestern = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage, css::i18n::ScriptType::LATIN),
+ eCJK = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage_CJK, css::i18n::ScriptType::ASIAN),
+ eCTL = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage_CTL, css::i18n::ScriptType::COMPLEX);
+
+ for(sal_uInt16 nProp = 0;
+ nProp < sal::static_int_cast< sal_uInt16, sal_Int32 >( aNames.getLength() );
+ nProp++)
+ {
+ if( nProp < DEF_FONT_COUNT )
+ {
+ if(GetDefaultFor(nProp, lcl_LanguageOfType(nProp, eWestern, eCJK, eCTL)) != m_sDefaultFonts[nProp])
+ pValues[nProp] <<= m_sDefaultFonts[nProp];
+ }
+ else
+ {
+ if(m_nDefaultFontHeight[nProp - DEF_FONT_COUNT] > 0)
+ pValues[nProp] <<= static_cast<sal_Int32>(convertTwipToMm100(m_nDefaultFontHeight[nProp - DEF_FONT_COUNT]));
+ }
+ }
+ PutProperties(aNames, aValues);
+}
+
+SwStdFontConfig::~SwStdFontConfig()
+{
+}
+
+bool SwStdFontConfig::IsFontDefault(sal_uInt16 nFontType) const
+{
+ bool bSame = false;
+ SvtLinguOptions aLinguOpt;
+
+ if (!utl::ConfigManager::IsFuzzing())
+ SvtLinguConfig().GetOptions(aLinguOpt);
+
+ LanguageType eWestern = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage, css::i18n::ScriptType::LATIN),
+ eCJK = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage_CJK, css::i18n::ScriptType::ASIAN),
+ eCTL = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage_CTL, css::i18n::ScriptType::COMPLEX);
+
+ OUString sDefFont(GetDefaultFor(FONT_STANDARD, eWestern));
+ OUString sDefFontCJK(GetDefaultFor(FONT_STANDARD_CJK, eCJK));
+ OUString sDefFontCTL(GetDefaultFor(FONT_STANDARD_CTL, eCTL));
+ LanguageType eLang = lcl_LanguageOfType(nFontType, eWestern, eCJK, eCTL);
+ switch( nFontType )
+ {
+ case FONT_STANDARD:
+ bSame = m_sDefaultFonts[nFontType] == sDefFont;
+ break;
+ case FONT_STANDARD_CJK:
+ bSame = m_sDefaultFonts[nFontType] == sDefFontCJK;
+ break;
+ case FONT_STANDARD_CTL:
+ bSame = m_sDefaultFonts[nFontType] == sDefFontCTL;
+ break;
+ case FONT_OUTLINE :
+ case FONT_OUTLINE_CJK :
+ case FONT_OUTLINE_CTL :
+ bSame = m_sDefaultFonts[nFontType] ==
+ GetDefaultFor(nFontType, eLang);
+ break;
+ case FONT_LIST :
+ case FONT_CAPTION :
+ case FONT_INDEX :
+ bSame = m_sDefaultFonts[nFontType] == sDefFont &&
+ m_sDefaultFonts[FONT_STANDARD] == sDefFont;
+ break;
+ case FONT_LIST_CJK :
+ case FONT_CAPTION_CJK :
+ case FONT_INDEX_CJK :
+ {
+ bool b1 = m_sDefaultFonts[FONT_STANDARD_CJK] == sDefFontCJK;
+ bSame = b1 && m_sDefaultFonts[nFontType] == sDefFontCJK;
+ }
+ break;
+ case FONT_LIST_CTL :
+ case FONT_CAPTION_CTL :
+ case FONT_INDEX_CTL :
+ {
+ bool b1 = m_sDefaultFonts[FONT_STANDARD_CJK] == sDefFontCTL;
+ bSame = b1 && m_sDefaultFonts[nFontType] == sDefFontCTL;
+ }
+ break;
+ }
+ return bSame;
+}
+
+OUString SwStdFontConfig::GetDefaultFor(sal_uInt16 nFontType, LanguageType eLang)
+{
+ DefaultFontType nFontId;
+ switch( nFontType )
+ {
+ case FONT_OUTLINE :
+ nFontId = DefaultFontType::LATIN_HEADING;
+ break;
+ case FONT_OUTLINE_CJK :
+ nFontId = DefaultFontType::CJK_HEADING;
+ break;
+ case FONT_OUTLINE_CTL :
+ nFontId = DefaultFontType::CTL_HEADING;
+ break;
+ case FONT_STANDARD_CJK:
+ case FONT_LIST_CJK :
+ case FONT_CAPTION_CJK :
+ case FONT_INDEX_CJK :
+ nFontId = DefaultFontType::CJK_TEXT;
+ break;
+ case FONT_STANDARD_CTL:
+ case FONT_LIST_CTL :
+ case FONT_CAPTION_CTL :
+ case FONT_INDEX_CTL :
+ nFontId = DefaultFontType::CTL_TEXT;
+ break;
+ default:
+ nFontId = DefaultFontType::LATIN_TEXT;
+ }
+ vcl::Font aFont = OutputDevice::GetDefaultFont(nFontId, eLang, GetDefaultFontFlags::OnlyOne);
+ return aFont.GetFamilyName();
+}
+
+sal_Int32 SwStdFontConfig::GetDefaultHeightFor(sal_uInt16 nFontType, LanguageType eLang)
+{
+ sal_Int32 nRet = FONTSIZE_DEFAULT;
+ switch( nFontType )
+ {
+ case FONT_OUTLINE:
+ case FONT_OUTLINE_CJK:
+ case FONT_OUTLINE_CTL:
+ nRet = FONTSIZE_OUTLINE;
+ break;
+ case FONT_STANDARD_CJK:
+ nRet = FONTSIZE_CJK_DEFAULT;
+ break;
+ }
+ if( eLang == LANGUAGE_THAI && nFontType >= FONT_STANDARD_CTL )
+ {
+ nRet = nRet * 4 / 3;
+ }
+ if( eLang == LANGUAGE_KOREAN )
+ {
+ nRet = FONTSIZE_KOREAN_DEFAULT;
+ }
+ return nRet;
+}
+
+void SwStdFontConfig::ChangeInt( sal_uInt16 nFontType, sal_Int32 nHeight )
+{
+ OSL_ENSURE( nFontType < DEF_FONT_COUNT, "invalid index in SwStdFontConfig::ChangeInt()");
+ if( nFontType >= DEF_FONT_COUNT || m_nDefaultFontHeight[nFontType] == nHeight)
+ return;
+
+ SvtLinguOptions aLinguOpt;
+ if (!utl::ConfigManager::IsFuzzing())
+ SvtLinguConfig().GetOptions( aLinguOpt );
+
+ LanguageType eWestern = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage, css::i18n::ScriptType::LATIN),
+ eCJK = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage_CJK, css::i18n::ScriptType::ASIAN),
+ eCTL = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage_CTL, css::i18n::ScriptType::COMPLEX);
+
+ // #i92090# default height value sets back to -1
+ const sal_Int32 nDefaultHeight = GetDefaultHeightFor(nFontType, lcl_LanguageOfType(nFontType, eWestern, eCJK, eCTL));
+ const bool bIsDefaultHeight = nHeight == nDefaultHeight;
+ if( bIsDefaultHeight && m_nDefaultFontHeight[nFontType] > 0 )
+ {
+ SetModified();
+ m_nDefaultFontHeight[nFontType] = -1;
+ }
+ else if( !bIsDefaultHeight && nHeight != m_nDefaultFontHeight[nFontType] )
+ {
+ SetModified();
+ m_nDefaultFontHeight[nFontType] = nHeight;
+ }
+}
+
+sal_Int32 SwStdFontConfig::GetFontHeight( sal_uInt8 nFont, sal_uInt8 nScriptType, LanguageType eLang )
+{
+ OSL_ENSURE(nFont + FONT_PER_GROUP * nScriptType < DEF_FONT_COUNT, "wrong index in SwStdFontConfig::GetFontHeight()");
+ sal_Int32 nRet = m_nDefaultFontHeight[nFont + FONT_PER_GROUP * nScriptType];
+ if(nRet <= 0)
+ return GetDefaultHeightFor(nFont + FONT_PER_GROUP * nScriptType, eLang);
+ return nRet;
+}
+
+void SwStdFontConfig::Notify( const css::uno::Sequence< OUString >& ) {}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/config/modcfg.cxx b/sw/source/uibase/config/modcfg.cxx
new file mode 100644
index 0000000000..ff36e0a3e1
--- /dev/null
+++ b/sw/source/uibase/config/modcfg.cxx
@@ -0,0 +1,1336 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <comphelper/classids.hxx>
+#include <o3tl/any.hxx>
+#include <tools/fontenum.hxx>
+#include <editeng/svxenum.hxx>
+#include <editeng/editids.hrc>
+#include <osl/diagnose.h>
+#include <rtl/ustrbuf.hxx>
+#include <svl/typedwhich.hxx>
+
+#include <tools/globname.hxx>
+#include <tools/UnitConversion.hxx>
+#include <itabenum.hxx>
+#include <modcfg.hxx>
+#include <caption.hxx>
+
+using namespace com::sun::star::uno;
+
+#define GLOB_NAME_CALC 0
+#define GLOB_NAME_IMPRESS 1
+#define GLOB_NAME_DRAW 2
+#define GLOB_NAME_MATH 3
+#define GLOB_NAME_CHART 4
+
+InsCaptionOpt* InsCaptionOptArr::Find(const SwCapObjType eType, const SvGlobalName *pOleId)
+{
+ for (auto const& it : m_InsCapOptArr)
+ {
+ InsCaptionOpt &rObj = *it;
+ if (rObj.GetObjType() == eType && (eType != OLE_CAP || (pOleId && rObj.GetOleId() == *pOleId)))
+ return &rObj;
+ }
+
+ return nullptr;
+}
+
+void InsCaptionOptArr::Insert(InsCaptionOpt* pObj)
+{
+ m_InsCapOptArr.push_back(std::unique_ptr<InsCaptionOpt>(pObj)); //takes ownership
+}
+
+const InsCaptionOpt* SwModuleOptions::GetCapOption(
+ bool bHTML, const SwCapObjType eType, const SvGlobalName *pOleId)
+{
+ if(bHTML)
+ {
+ OSL_FAIL("no caption option in sw/web!");
+ return nullptr;
+ }
+ else
+ {
+ if(eType == OLE_CAP && pOleId)
+ {
+ bool bFound = false;
+ for( sal_uInt16 nId = 0; nId <= GLOB_NAME_CHART && !bFound; nId++)
+ bFound = *pOleId == m_aInsertConfig.m_aGlobalNames[nId ];
+ if(!bFound)
+ return m_aInsertConfig.m_pOLEMiscOpt.get();
+ }
+ return m_aInsertConfig.m_pCapOptions->Find(eType, pOleId);
+ }
+}
+
+bool SwModuleOptions::SetCapOption(bool bHTML, const InsCaptionOpt* pOpt)
+{
+ bool bRet = false;
+
+ if(bHTML)
+ {
+ OSL_FAIL("no caption option in sw/web!");
+ }
+ else if (pOpt)
+ {
+ if(pOpt->GetObjType() == OLE_CAP)
+ {
+ bool bFound = false;
+ for( sal_uInt16 nId = 0; nId <= GLOB_NAME_CHART; nId++)
+ bFound = pOpt->GetOleId() == m_aInsertConfig.m_aGlobalNames[nId ];
+ if(!bFound)
+ {
+ if(m_aInsertConfig.m_pOLEMiscOpt)
+ *m_aInsertConfig.m_pOLEMiscOpt = *pOpt;
+ else
+ m_aInsertConfig.m_pOLEMiscOpt.reset(new InsCaptionOpt(*pOpt));
+ }
+ }
+
+ InsCaptionOptArr& rArr = *m_aInsertConfig.m_pCapOptions;
+ InsCaptionOpt *pObj = rArr.Find(pOpt->GetObjType(), &pOpt->GetOleId());
+
+ if (pObj)
+ {
+ *pObj = *pOpt;
+ }
+ else
+ rArr.Insert(new InsCaptionOpt(*pOpt));
+
+ m_aInsertConfig.SetModified();
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+SwModuleOptions::SwModuleOptions() :
+ m_aInsertConfig(false),
+ m_aWebInsertConfig(true),
+ m_aTableConfig(false),
+ m_aWebTableConfig(true),
+ m_bHideFieldTips(false)
+{
+}
+
+OUString SwModuleOptions::ConvertWordDelimiter(std::u16string_view aDelim, bool bFromUI)
+{
+ OUStringBuffer sReturn;
+ const sal_Int32 nDelimLen = aDelim.size();
+ if(bFromUI)
+ {
+ for (sal_Int32 i = 0; i < nDelimLen; )
+ {
+ const sal_Unicode c = aDelim[i++];
+
+ if (c == '\\' && i < nDelimLen )
+ {
+ switch (aDelim[i++])
+ {
+ case 'n': sReturn.append("\n"); break;
+ case 't': sReturn.append("\t"); break;
+ case '\\': sReturn.append("\\"); break;
+
+ case 'x':
+ {
+ sal_Unicode nChar = 0;
+ bool bValidData = true;
+ for( sal_Int32 n = 0; n < 2 && i < nDelimLen; ++n, ++i )
+ {
+ sal_Unicode nVal = aDelim[i];
+ if( (nVal >= '0') && ( nVal <= '9') )
+ nVal -= '0';
+ else if( (nVal >= 'A') && (nVal <= 'F') )
+ nVal -= 'A' - 10;
+ else if( (nVal >= 'a') && (nVal <= 'f') )
+ nVal -= 'a' - 10;
+ else
+ {
+ OSL_FAIL("wrong hex value" );
+ bValidData = false;
+ break;
+ }
+
+ nChar <<= 4;
+ nChar += nVal;
+ }
+ if( bValidData )
+ sReturn.append(nChar);
+ break;
+ }
+
+ default: // Unknown, so insert backslash
+ sReturn.append("\\");
+ i--;
+ break;
+ }
+ }
+ else
+ sReturn.append(c);
+ }
+ }
+ else
+ {
+ for (sal_Int32 i = 0; i < nDelimLen; ++i)
+ {
+ const sal_Unicode c = aDelim[i];
+
+ switch (c)
+ {
+ case '\n': sReturn.append("\\n"); break;
+ case '\t': sReturn.append("\\t"); break;
+ case '\\': sReturn.append("\\\\"); break;
+
+ default:
+ if( c <= 0x1f || c >= 0x7f )
+ {
+ sReturn.append("\\x" + OUString::number( static_cast<sal_Int32>(c), 16 ));
+ }
+ else
+ {
+ sReturn.append(c);
+ }
+ }
+ }
+ }
+ return sReturn.makeStringAndClear();
+}
+
+const Sequence<OUString>& SwRevisionConfig::GetPropertyNames()
+{
+ static Sequence<OUString> const aNames
+ {
+ "TextDisplay/Insert/Attribute", // 0
+ "TextDisplay/Insert/Color", // 1
+ "TextDisplay/Delete/Attribute", // 2
+ "TextDisplay/Delete/Color", // 3
+ "TextDisplay/ChangedAttribute/Attribute", // 4
+ "TextDisplay/ChangedAttribute/Color", // 5
+ "LinesChanged/Mark", // 6
+ "LinesChanged/Color" // 7
+ };
+ return aNames;
+}
+
+SwRevisionConfig::SwRevisionConfig()
+ : ConfigItem("Office.Writer/Revision", ConfigItemMode::ReleaseTree)
+ , m_nMarkAlign(0)
+{
+ m_aInsertAttr.m_nItemId = SID_ATTR_CHAR_UNDERLINE;
+ m_aInsertAttr.m_nAttr = LINESTYLE_SINGLE;
+ m_aInsertAttr.m_nColor = COL_TRANSPARENT;
+ m_aDeletedAttr.m_nItemId = SID_ATTR_CHAR_STRIKEOUT;
+ // coverity[mixed_enums : FALSE] - unhelpfully warns different enum than LINESTYLE_SINGLE above
+ m_aDeletedAttr.m_nAttr = STRIKEOUT_SINGLE;
+ m_aDeletedAttr.m_nColor = COL_TRANSPARENT;
+ m_aFormatAttr.m_nItemId = SID_ATTR_CHAR_WEIGHT;
+ // coverity[mixed_enums : FALSE] - unhelpfully warns different enum than STRIKEOUT_SINGLE above
+ m_aFormatAttr.m_nAttr = WEIGHT_BOLD;
+ m_aFormatAttr.m_nColor = COL_BLACK;
+ Load();
+}
+
+SwRevisionConfig::~SwRevisionConfig()
+{
+}
+
+static sal_Int32 lcl_ConvertAttrToCfg(const AuthorCharAttr& rAttr)
+{
+ sal_Int32 nRet = 0;
+ switch(rAttr.m_nItemId)
+ {
+ case SID_ATTR_CHAR_WEIGHT: nRet = 1; break;
+ case SID_ATTR_CHAR_POSTURE: nRet = 2; break;
+ case SID_ATTR_CHAR_UNDERLINE: nRet = LINESTYLE_SINGLE == rAttr.m_nAttr ? 3 : 4; break;
+ case SID_ATTR_CHAR_STRIKEOUT: nRet = 3; break;
+ case SID_ATTR_CHAR_CASEMAP:
+ {
+ switch(static_cast<SvxCaseMap>(rAttr.m_nAttr))
+ {
+ case SvxCaseMap::Uppercase : nRet = 5;break;
+ case SvxCaseMap::Lowercase : nRet = 6;break;
+ case SvxCaseMap::SmallCaps : nRet = 7;break;
+ case SvxCaseMap::Capitalize: nRet = 8;break;
+ default: break;
+ }
+ }
+ break;
+ case SID_ATTR_BRUSH : nRet = 9; break;
+ }
+ return nRet;
+}
+
+void SwRevisionConfig::Notify( const css::uno::Sequence< OUString >& ) {}
+
+void SwRevisionConfig::ImplCommit()
+{
+ const Sequence<OUString>& aNames = GetPropertyNames();
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case 0 : pValues[nProp] <<= lcl_ConvertAttrToCfg(m_aInsertAttr); break;
+ case 1 : pValues[nProp] <<= m_aInsertAttr.m_nColor; break;
+ case 2 : pValues[nProp] <<= lcl_ConvertAttrToCfg(m_aDeletedAttr); break;
+ case 3 : pValues[nProp] <<= m_aDeletedAttr.m_nColor; break;
+ case 4 : pValues[nProp] <<= lcl_ConvertAttrToCfg(m_aFormatAttr); break;
+ case 5 : pValues[nProp] <<= m_aFormatAttr.m_nColor; break;
+ case 6 : pValues[nProp] <<= m_nMarkAlign; break;
+ case 7 : pValues[nProp] <<= m_aMarkColor; break;
+ }
+ }
+ PutProperties(aNames, aValues);
+}
+
+static void lcl_ConvertCfgToAttr(sal_Int32 nVal, AuthorCharAttr& rAttr, bool bDelete = false)
+{
+ rAttr.m_nItemId = rAttr.m_nAttr = 0;
+ switch(nVal)
+ {
+ case 1: rAttr.m_nItemId = SID_ATTR_CHAR_WEIGHT; rAttr.m_nAttr = WEIGHT_BOLD ; break;
+ case 2: rAttr.m_nItemId = SID_ATTR_CHAR_POSTURE; rAttr.m_nAttr = ITALIC_NORMAL ; break;
+ case 3: if(bDelete)
+ {
+ rAttr.m_nItemId = SID_ATTR_CHAR_STRIKEOUT;
+ rAttr.m_nAttr = STRIKEOUT_SINGLE;
+ }
+ else
+ {
+ rAttr.m_nItemId = SID_ATTR_CHAR_UNDERLINE;
+ rAttr.m_nAttr = LINESTYLE_SINGLE;
+ }
+ break;
+ case 4: rAttr.m_nItemId = SID_ATTR_CHAR_UNDERLINE;rAttr.m_nAttr = LINESTYLE_DOUBLE ; break;
+ case 5: rAttr.m_nItemId = SID_ATTR_CHAR_CASEMAP; rAttr.m_nAttr = sal_uInt16(SvxCaseMap::Uppercase); break;
+ case 6: rAttr.m_nItemId = SID_ATTR_CHAR_CASEMAP; rAttr.m_nAttr = sal_uInt16(SvxCaseMap::Lowercase); break;
+ case 7: rAttr.m_nItemId = SID_ATTR_CHAR_CASEMAP; rAttr.m_nAttr = sal_uInt16(SvxCaseMap::SmallCaps); break;
+ case 8: rAttr.m_nItemId = SID_ATTR_CHAR_CASEMAP; rAttr.m_nAttr = sal_uInt16(SvxCaseMap::Capitalize); break;
+ case 9: rAttr.m_nItemId = SID_ATTR_BRUSH; break;
+ }
+}
+void SwRevisionConfig::Load()
+{
+ const Sequence<OUString>& aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ const Any* pValues = aValues.getConstArray();
+ assert(aValues.getLength() == aNames.getLength());
+ for (sal_Int32 nProp = 0; nProp < aNames.getLength(); ++nProp)
+ {
+ if (pValues[nProp].hasValue())
+ {
+ sal_Int32 nVal = 0;
+ pValues[nProp] >>= nVal;
+ switch (nProp)
+ {
+ case 0 : lcl_ConvertCfgToAttr(nVal, m_aInsertAttr); break;
+ case 1 : m_aInsertAttr.m_nColor = Color(ColorTransparency, nVal); break;
+ case 2 : lcl_ConvertCfgToAttr(nVal, m_aDeletedAttr, true); break;
+ case 3 : m_aDeletedAttr.m_nColor = Color(ColorTransparency, nVal); break;
+ case 4 : lcl_ConvertCfgToAttr(nVal, m_aFormatAttr); break;
+ case 5 : m_aFormatAttr.m_nColor = Color(ColorTransparency, nVal); break;
+ case 6 : m_nMarkAlign = sal::static_int_cast< sal_uInt16, sal_Int32>(nVal); break;
+ case 7 : m_aMarkColor = Color(ColorTransparency, nVal); break;
+ }
+ }
+ }
+}
+
+namespace {
+
+enum InsertConfigProp
+{
+ INS_PROP_TABLE_HEADER = 0,
+ INS_PROP_TABLE_REPEATHEADER, // 1
+ INS_PROP_TABLE_BORDER, // 2
+ INS_PROP_TABLE_SPLIT, // 3 from here not in writer/web
+ INS_PROP_CAP_AUTOMATIC, // 4
+ INS_PROP_CAP_CAPTIONORDERNUMBERINGFIRST, // 5
+ INS_PROP_CAP_OBJECT_TABLE_ENABLE, // 6
+ INS_PROP_CAP_OBJECT_TABLE_CATEGORY, // 7
+ INS_PROP_CAP_OBJECT_TABLE_NUMBERING, // 8
+ INS_PROP_CAP_OBJECT_TABLE_NUMBERINGSEPARATOR, // 9
+ INS_PROP_CAP_OBJECT_TABLE_CAPTIONTEXT, //10
+ INS_PROP_CAP_OBJECT_TABLE_DELIMITER, //11
+ INS_PROP_CAP_OBJECT_TABLE_LEVEL, //12
+ INS_PROP_CAP_OBJECT_TABLE_POSITION, //13
+ INS_PROP_CAP_OBJECT_TABLE_CHARACTERSTYLE, //14
+ INS_PROP_CAP_OBJECT_FRAME_ENABLE, //15
+ INS_PROP_CAP_OBJECT_FRAME_CATEGORY, //16
+ INS_PROP_CAP_OBJECT_FRAME_NUMBERING, //17
+ INS_PROP_CAP_OBJECT_FRAME_NUMBERINGSEPARATOR, //18
+ INS_PROP_CAP_OBJECT_FRAME_CAPTIONTEXT, //19
+ INS_PROP_CAP_OBJECT_FRAME_DELIMITER, //20
+ INS_PROP_CAP_OBJECT_FRAME_LEVEL, //21
+ INS_PROP_CAP_OBJECT_FRAME_POSITION, //22
+ INS_PROP_CAP_OBJECT_FRAME_CHARACTERSTYLE, //23
+ INS_PROP_CAP_OBJECT_GRAPHIC_ENABLE, //24
+ INS_PROP_CAP_OBJECT_GRAPHIC_CATEGORY, //25
+ INS_PROP_CAP_OBJECT_GRAPHIC_NUMBERING, //26
+ INS_PROP_CAP_OBJECT_GRAPHIC_NUMBERINGSEPARATOR, //27
+ INS_PROP_CAP_OBJECT_GRAPHIC_CAPTIONTEXT, //28
+ INS_PROP_CAP_OBJECT_GRAPHIC_DELIMITER, //29
+ INS_PROP_CAP_OBJECT_GRAPHIC_LEVEL, //30
+ INS_PROP_CAP_OBJECT_GRAPHIC_POSITION, //31
+ INS_PROP_CAP_OBJECT_GRAPHIC_CHARACTERSTYLE, //32
+ INS_PROP_CAP_OBJECT_GRAPHIC_APPLYATTRIBUTES, //33
+ INS_PROP_CAP_OBJECT_CALC_ENABLE, //34
+ INS_PROP_CAP_OBJECT_CALC_CATEGORY, //35
+ INS_PROP_CAP_OBJECT_CALC_NUMBERING, //36
+ INS_PROP_CAP_OBJECT_CALC_NUMBERINGSEPARATOR, //37
+ INS_PROP_CAP_OBJECT_CALC_CAPTIONTEXT, //38
+ INS_PROP_CAP_OBJECT_CALC_DELIMITER, //39
+ INS_PROP_CAP_OBJECT_CALC_LEVEL, //40
+ INS_PROP_CAP_OBJECT_CALC_POSITION, //41
+ INS_PROP_CAP_OBJECT_CALC_CHARACTERSTYLE, //42
+ INS_PROP_CAP_OBJECT_CALC_APPLYATTRIBUTES, //43
+ INS_PROP_CAP_OBJECT_IMPRESS_ENABLE, //44
+ INS_PROP_CAP_OBJECT_IMPRESS_CATEGORY, //45
+ INS_PROP_CAP_OBJECT_IMPRESS_NUMBERING, //46
+ INS_PROP_CAP_OBJECT_IMPRESS_NUMBERINGSEPARATOR, //47
+ INS_PROP_CAP_OBJECT_IMPRESS_CAPTIONTEXT, //48
+ INS_PROP_CAP_OBJECT_IMPRESS_DELIMITER, //49
+ INS_PROP_CAP_OBJECT_IMPRESS_LEVEL, //50
+ INS_PROP_CAP_OBJECT_IMPRESS_POSITION, //51
+ INS_PROP_CAP_OBJECT_IMPRESS_CHARACTERSTYLE, //52
+ INS_PROP_CAP_OBJECT_IMPRESS_APPLYATTRIBUTES, //53
+ INS_PROP_CAP_OBJECT_CHART_ENABLE, //54
+ INS_PROP_CAP_OBJECT_CHART_CATEGORY, //55
+ INS_PROP_CAP_OBJECT_CHART_NUMBERING, //56
+ INS_PROP_CAP_OBJECT_CHART_NUMBERINGSEPARATOR, //57
+ INS_PROP_CAP_OBJECT_CHART_CAPTIONTEXT, //58
+ INS_PROP_CAP_OBJECT_CHART_DELIMITER, //59
+ INS_PROP_CAP_OBJECT_CHART_LEVEL, //60
+ INS_PROP_CAP_OBJECT_CHART_POSITION, //61
+ INS_PROP_CAP_OBJECT_CHART_CHARACTERSTYLE, //62
+ INS_PROP_CAP_OBJECT_CHART_APPLYATTRIBUTES, //63
+ INS_PROP_CAP_OBJECT_FORMULA_ENABLE, //64
+ INS_PROP_CAP_OBJECT_FORMULA_CATEGORY, //65
+ INS_PROP_CAP_OBJECT_FORMULA_NUMBERING, //66
+ INS_PROP_CAP_OBJECT_FORMULA_NUMBERINGSEPARATOR, //67
+ INS_PROP_CAP_OBJECT_FORMULA_CAPTIONTEXT, //68
+ INS_PROP_CAP_OBJECT_FORMULA_DELIMITER, //69
+ INS_PROP_CAP_OBJECT_FORMULA_LEVEL, //70
+ INS_PROP_CAP_OBJECT_FORMULA_POSITION, //71
+ INS_PROP_CAP_OBJECT_FORMULA_CHARACTERSTYLE, //72
+ INS_PROP_CAP_OBJECT_FORMULA_APPLYATTRIBUTES, //73
+ INS_PROP_CAP_OBJECT_DRAW_ENABLE, //74
+ INS_PROP_CAP_OBJECT_DRAW_CATEGORY, //75
+ INS_PROP_CAP_OBJECT_DRAW_NUMBERING, //76
+ INS_PROP_CAP_OBJECT_DRAW_NUMBERINGSEPARATOR, //77
+ INS_PROP_CAP_OBJECT_DRAW_CAPTIONTEXT, //78
+ INS_PROP_CAP_OBJECT_DRAW_DELIMITER, //79
+ INS_PROP_CAP_OBJECT_DRAW_LEVEL, //80
+ INS_PROP_CAP_OBJECT_DRAW_POSITION, //81
+ INS_PROP_CAP_OBJECT_DRAW_CHARACTERSTYLE, //82
+ INS_PROP_CAP_OBJECT_DRAW_APPLYATTRIBUTES, //83
+ INS_PROP_CAP_OBJECT_OLEMISC_ENABLE, //84
+ INS_PROP_CAP_OBJECT_OLEMISC_CATEGORY, //85
+ INS_PROP_CAP_OBJECT_OLEMISC_NUMBERING, //86
+ INS_PROP_CAP_OBJECT_OLEMISC_NUMBERINGSEPARATOR, //87
+ INS_PROP_CAP_OBJECT_OLEMISC_CAPTIONTEXT, //88
+ INS_PROP_CAP_OBJECT_OLEMISC_DELIMITER, //89
+ INS_PROP_CAP_OBJECT_OLEMISC_LEVEL, //90
+ INS_PROP_CAP_OBJECT_OLEMISC_POSITION, //91
+ INS_PROP_CAP_OBJECT_OLEMISC_CHARACTERSTYLE, //92
+ INS_PROP_CAP_OBJECT_OLEMISC_APPLYATTRIBUTES //93
+};
+
+}
+
+const Sequence<OUString>& SwInsertConfig::GetPropertyNames() const
+{
+ static Sequence<OUString> aNames
+ {
+ "Table/Header", // 0
+ "Table/RepeatHeader", // 1
+ "Table/Border", // 2
+ "Table/Split", // 3 from here not in writer/web
+ "Caption/Automatic", // 4
+ "Caption/CaptionOrderNumberingFirst", // 5
+ "Caption/WriterObject/Table/Enable", // 6
+ "Caption/WriterObject/Table/Settings/Category", // 7
+ "Caption/WriterObject/Table/Settings/Numbering", // 8
+ "Caption/WriterObject/Table/Settings/NumberingSeparator", // 9
+ "Caption/WriterObject/Table/Settings/CaptionText", //10
+ "Caption/WriterObject/Table/Settings/Delimiter", //11
+ "Caption/WriterObject/Table/Settings/Level", //12
+ "Caption/WriterObject/Table/Settings/Position", //13
+ "Caption/WriterObject/Table/Settings/CharacterStyle", //14
+ "Caption/WriterObject/Frame/Enable", //15
+ "Caption/WriterObject/Frame/Settings/Category", //16
+ "Caption/WriterObject/Frame/Settings/Numbering", //17
+ "Caption/WriterObject/Frame/Settings/NumberingSeparator", //18
+ "Caption/WriterObject/Frame/Settings/CaptionText", //19
+ "Caption/WriterObject/Frame/Settings/Delimiter", //20
+ "Caption/WriterObject/Frame/Settings/Level", //21
+ "Caption/WriterObject/Frame/Settings/Position", //22
+ "Caption/WriterObject/Frame/Settings/CharacterStyle", //23
+ "Caption/WriterObject/Graphic/Enable", //24
+ "Caption/WriterObject/Graphic/Settings/Category", //25
+ "Caption/WriterObject/Graphic/Settings/Numbering", //26
+ "Caption/WriterObject/Graphic/Settings/NumberingSeparator", //27
+ "Caption/WriterObject/Graphic/Settings/CaptionText", //28
+ "Caption/WriterObject/Graphic/Settings/Delimiter", //29
+ "Caption/WriterObject/Graphic/Settings/Level", //30
+ "Caption/WriterObject/Graphic/Settings/Position", //31
+ "Caption/WriterObject/Graphic/Settings/CharacterStyle", //32
+ "Caption/WriterObject/Graphic/Settings/ApplyAttributes", //33
+ "Caption/OfficeObject/Calc/Enable", //34
+ "Caption/OfficeObject/Calc/Settings/Category", //35
+ "Caption/OfficeObject/Calc/Settings/Numbering", //36
+ "Caption/OfficeObject/Calc/Settings/NumberingSeparator", //37
+ "Caption/OfficeObject/Calc/Settings/CaptionText", //38
+ "Caption/OfficeObject/Calc/Settings/Delimiter", //39
+ "Caption/OfficeObject/Calc/Settings/Level", //40
+ "Caption/OfficeObject/Calc/Settings/Position", //41
+ "Caption/OfficeObject/Calc/Settings/CharacterStyle", //42
+ "Caption/OfficeObject/Calc/Settings/ApplyAttributes", //43
+ "Caption/OfficeObject/Impress/Enable", //44
+ "Caption/OfficeObject/Impress/Settings/Category", //45
+ "Caption/OfficeObject/Impress/Settings/Numbering", //46
+ "Caption/OfficeObject/Impress/Settings/NumberingSeparator", //47
+ "Caption/OfficeObject/Impress/Settings/CaptionText", //48
+ "Caption/OfficeObject/Impress/Settings/Delimiter", //49
+ "Caption/OfficeObject/Impress/Settings/Level", //50
+ "Caption/OfficeObject/Impress/Settings/Position", //51
+ "Caption/OfficeObject/Impress/Settings/CharacterStyle", //52
+ "Caption/OfficeObject/Impress/Settings/ApplyAttributes", //53
+ "Caption/OfficeObject/Chart/Enable", //54
+ "Caption/OfficeObject/Chart/Settings/Category", //55
+ "Caption/OfficeObject/Chart/Settings/Numbering", //56
+ "Caption/OfficeObject/Chart/Settings/NumberingSeparator", //57
+ "Caption/OfficeObject/Chart/Settings/CaptionText", //58
+ "Caption/OfficeObject/Chart/Settings/Delimiter", //59
+ "Caption/OfficeObject/Chart/Settings/Level", //60
+ "Caption/OfficeObject/Chart/Settings/Position", //61
+ "Caption/OfficeObject/Chart/Settings/CharacterStyle", //62
+ "Caption/OfficeObject/Chart/Settings/ApplyAttributes", //63
+ "Caption/OfficeObject/Formula/Enable", //64
+ "Caption/OfficeObject/Formula/Settings/Category", //65
+ "Caption/OfficeObject/Formula/Settings/Numbering", //66
+ "Caption/OfficeObject/Formula/Settings/NumberingSeparator", //67
+ "Caption/OfficeObject/Formula/Settings/CaptionText", //68
+ "Caption/OfficeObject/Formula/Settings/Delimiter", //69
+ "Caption/OfficeObject/Formula/Settings/Level", //70
+ "Caption/OfficeObject/Formula/Settings/Position", //71
+ "Caption/OfficeObject/Formula/Settings/CharacterStyle", //72
+ "Caption/OfficeObject/Formula/Settings/ApplyAttributes", //73
+ "Caption/OfficeObject/Draw/Enable", //74
+ "Caption/OfficeObject/Draw/Settings/Category", //75
+ "Caption/OfficeObject/Draw/Settings/Numbering", //76
+ "Caption/OfficeObject/Draw/Settings/NumberingSeparator", //77
+ "Caption/OfficeObject/Draw/Settings/CaptionText", //78
+ "Caption/OfficeObject/Draw/Settings/Delimiter", //79
+ "Caption/OfficeObject/Draw/Settings/Level", //80
+ "Caption/OfficeObject/Draw/Settings/Position", //81
+ "Caption/OfficeObject/Draw/Settings/CharacterStyle", //82
+ "Caption/OfficeObject/Draw/Settings/ApplyAttributes", //83
+ "Caption/OfficeObject/OLEMisc/Enable", //84
+ "Caption/OfficeObject/OLEMisc/Settings/Category", //85
+ "Caption/OfficeObject/OLEMisc/Settings/Numbering", //86
+ "Caption/OfficeObject/OLEMisc/Settings/NumberingSeparator", //87
+ "Caption/OfficeObject/OLEMisc/Settings/CaptionText", //88
+ "Caption/OfficeObject/OLEMisc/Settings/Delimiter", //89
+ "Caption/OfficeObject/OLEMisc/Settings/Level", //90
+ "Caption/OfficeObject/OLEMisc/Settings/Position", //91
+ "Caption/OfficeObject/OLEMisc/Settings/CharacterStyle", //92
+ "Caption/OfficeObject/OLEMisc/Settings/ApplyAttributes" //93
+ };
+ static Sequence<OUString> const aWebNames(aNames.getArray(), INS_PROP_TABLE_BORDER + 1);
+ return m_bIsWeb ? aWebNames : aNames;
+}
+
+SwInsertConfig::SwInsertConfig(bool bWeb) :
+ ConfigItem(bWeb ? OUString("Office.WriterWeb/Insert") : OUString("Office.Writer/Insert"),
+ ConfigItemMode::ReleaseTree),
+ m_bInsWithCaption( false ),
+ m_bCaptionOrderNumberingFirst( false ),
+ m_aInsTableOpts(SwInsertTableFlags::NONE,0),
+ m_bIsWeb(bWeb)
+{
+ m_aGlobalNames[GLOB_NAME_CALC ] = SvGlobalName(SO3_SC_CLASSID);
+ m_aGlobalNames[GLOB_NAME_IMPRESS] = SvGlobalName(SO3_SIMPRESS_CLASSID);
+ m_aGlobalNames[GLOB_NAME_DRAW ] = SvGlobalName(SO3_SDRAW_CLASSID);
+ m_aGlobalNames[GLOB_NAME_MATH ] = SvGlobalName(SO3_SM_CLASSID);
+ m_aGlobalNames[GLOB_NAME_CHART ] = SvGlobalName(SO3_SCH_CLASSID);
+ if(!m_bIsWeb)
+ m_pCapOptions.reset(new InsCaptionOptArr);
+
+ Load();
+}
+
+SwInsertConfig::~SwInsertConfig()
+{
+ m_pCapOptions.reset();
+ m_pOLEMiscOpt.reset();
+}
+
+static void lcl_WriteOpt(const InsCaptionOpt& rOpt, Any* pValues, sal_Int32 nProp, sal_Int32 nOffset)
+{
+ switch(nOffset)
+ {
+ case 0: pValues[nProp] <<= rOpt.UseCaption(); break;//Enable
+ case 1: pValues[nProp] <<= rOpt.GetCategory(); break;//Category
+ case 2: pValues[nProp] <<= static_cast<sal_Int32>(rOpt.GetNumType()); break;//Numbering",
+ case 3: pValues[nProp] <<= rOpt.GetNumSeparator(); break;//NumberingSeparator",
+ case 4: pValues[nProp] <<= rOpt.GetCaption(); break;//CaptionText",
+ case 5: pValues[nProp] <<= rOpt.GetSeparator();break;//Delimiter",
+ case 6: pValues[nProp] <<= static_cast<sal_Int32>(rOpt.GetLevel()); break;//Level",
+ case 7: pValues[nProp] <<= static_cast<sal_Int32>(rOpt.GetPos()); break;//Position",
+ case 8: pValues[nProp] <<= rOpt.GetCharacterStyle(); break; //CharacterStyle
+ case 9: pValues[nProp] <<= rOpt.CopyAttributes(); break; //ApplyAttributes
+ }
+}
+
+void SwInsertConfig::Notify( const css::uno::Sequence< OUString >& ) {}
+
+void SwInsertConfig::ImplCommit()
+{
+ const Sequence<OUString>& aNames = GetPropertyNames();
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ const InsCaptionOpt* pWriterTableOpt = nullptr;
+ const InsCaptionOpt* pWriterFrameOpt = nullptr;
+ const InsCaptionOpt* pWriterGraphicOpt = nullptr;
+ const InsCaptionOpt* pOLECalcOpt = nullptr;
+ const InsCaptionOpt* pOLEImpressOpt = nullptr;
+ const InsCaptionOpt* pOLEChartOpt = nullptr;
+ const InsCaptionOpt* pOLEFormulaOpt = nullptr;
+ const InsCaptionOpt* pOLEDrawOpt = nullptr;
+ if(m_pCapOptions)
+ {
+ pWriterTableOpt = m_pCapOptions->Find(TABLE_CAP);
+ pWriterFrameOpt = m_pCapOptions->Find(FRAME_CAP);
+ pWriterGraphicOpt = m_pCapOptions->Find(GRAPHIC_CAP);
+ pOLECalcOpt = m_pCapOptions->Find(OLE_CAP, &m_aGlobalNames[GLOB_NAME_CALC]);
+ pOLEImpressOpt = m_pCapOptions->Find(OLE_CAP, &m_aGlobalNames[GLOB_NAME_IMPRESS]);
+ pOLEDrawOpt = m_pCapOptions->Find(OLE_CAP, &m_aGlobalNames[GLOB_NAME_DRAW ]);
+ pOLEFormulaOpt = m_pCapOptions->Find(OLE_CAP, &m_aGlobalNames[GLOB_NAME_MATH ]);
+ pOLEChartOpt = m_pCapOptions->Find(OLE_CAP, &m_aGlobalNames[GLOB_NAME_CHART ]);
+ }
+ switch(nProp)
+ {
+ case INS_PROP_TABLE_HEADER:
+ pValues[nProp] <<= bool(m_aInsTableOpts.mnInsMode & SwInsertTableFlags::Headline);
+ break;//"Table/Header",
+ case INS_PROP_TABLE_REPEATHEADER:
+ pValues[nProp] <<= m_aInsTableOpts.mnRowsToRepeat > 0;
+ break;//"Table/RepeatHeader",
+ case INS_PROP_TABLE_BORDER:
+ pValues[nProp] <<= bool(m_aInsTableOpts.mnInsMode & SwInsertTableFlags::DefaultBorder);
+ break;//"Table/Border",
+ case INS_PROP_TABLE_SPLIT:
+ pValues[nProp] <<= bool(m_aInsTableOpts.mnInsMode & SwInsertTableFlags::SplitLayout);
+ break;//"Table/Split",
+ case INS_PROP_CAP_AUTOMATIC:
+ pValues[nProp] <<= m_bInsWithCaption;
+ break;//"Caption/Automatic",
+ case INS_PROP_CAP_CAPTIONORDERNUMBERINGFIRST:
+ pValues[nProp] <<= m_bCaptionOrderNumberingFirst;
+ break;//"Caption/CaptionOrderNumberingFirst"
+
+ case INS_PROP_CAP_OBJECT_TABLE_ENABLE:
+ case INS_PROP_CAP_OBJECT_TABLE_CATEGORY:
+ case INS_PROP_CAP_OBJECT_TABLE_NUMBERING:
+ case INS_PROP_CAP_OBJECT_TABLE_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_TABLE_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_TABLE_DELIMITER:
+ case INS_PROP_CAP_OBJECT_TABLE_LEVEL:
+ case INS_PROP_CAP_OBJECT_TABLE_POSITION:
+ case INS_PROP_CAP_OBJECT_TABLE_CHARACTERSTYLE:
+ if(pWriterTableOpt)
+ lcl_WriteOpt(*pWriterTableOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_TABLE_ENABLE);
+ break;
+ case INS_PROP_CAP_OBJECT_FRAME_ENABLE:
+ case INS_PROP_CAP_OBJECT_FRAME_CATEGORY:
+ case INS_PROP_CAP_OBJECT_FRAME_NUMBERING:
+ case INS_PROP_CAP_OBJECT_FRAME_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_FRAME_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_FRAME_DELIMITER:
+ case INS_PROP_CAP_OBJECT_FRAME_LEVEL:
+ case INS_PROP_CAP_OBJECT_FRAME_POSITION:
+ case INS_PROP_CAP_OBJECT_FRAME_CHARACTERSTYLE:
+ if(pWriterFrameOpt)
+ lcl_WriteOpt(*pWriterFrameOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_FRAME_ENABLE);
+ break;
+ case INS_PROP_CAP_OBJECT_GRAPHIC_ENABLE:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_CATEGORY:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_NUMBERING:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_DELIMITER:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_LEVEL:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_POSITION:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_CHARACTERSTYLE:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_APPLYATTRIBUTES:
+ if(pWriterGraphicOpt)
+ lcl_WriteOpt(*pWriterGraphicOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_GRAPHIC_ENABLE);
+ break;
+ case INS_PROP_CAP_OBJECT_CALC_ENABLE:
+ case INS_PROP_CAP_OBJECT_CALC_CATEGORY:
+ case INS_PROP_CAP_OBJECT_CALC_NUMBERING:
+ case INS_PROP_CAP_OBJECT_CALC_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_CALC_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_CALC_DELIMITER:
+ case INS_PROP_CAP_OBJECT_CALC_LEVEL:
+ case INS_PROP_CAP_OBJECT_CALC_POSITION:
+ case INS_PROP_CAP_OBJECT_CALC_CHARACTERSTYLE:
+ case INS_PROP_CAP_OBJECT_CALC_APPLYATTRIBUTES:
+ if(pOLECalcOpt)
+ lcl_WriteOpt(*pOLECalcOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_CALC_ENABLE);
+ break;
+ case INS_PROP_CAP_OBJECT_IMPRESS_ENABLE:
+ case INS_PROP_CAP_OBJECT_IMPRESS_CATEGORY:
+ case INS_PROP_CAP_OBJECT_IMPRESS_NUMBERING:
+ case INS_PROP_CAP_OBJECT_IMPRESS_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_IMPRESS_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_IMPRESS_DELIMITER:
+ case INS_PROP_CAP_OBJECT_IMPRESS_LEVEL:
+ case INS_PROP_CAP_OBJECT_IMPRESS_POSITION:
+ case INS_PROP_CAP_OBJECT_IMPRESS_CHARACTERSTYLE:
+ case INS_PROP_CAP_OBJECT_IMPRESS_APPLYATTRIBUTES:
+ if(pOLEImpressOpt)
+ lcl_WriteOpt(*pOLEImpressOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_IMPRESS_ENABLE);
+ break;
+ case INS_PROP_CAP_OBJECT_CHART_ENABLE:
+ case INS_PROP_CAP_OBJECT_CHART_CATEGORY:
+ case INS_PROP_CAP_OBJECT_CHART_NUMBERING:
+ case INS_PROP_CAP_OBJECT_CHART_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_CHART_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_CHART_DELIMITER:
+ case INS_PROP_CAP_OBJECT_CHART_LEVEL:
+ case INS_PROP_CAP_OBJECT_CHART_POSITION:
+ case INS_PROP_CAP_OBJECT_CHART_CHARACTERSTYLE:
+ case INS_PROP_CAP_OBJECT_CHART_APPLYATTRIBUTES:
+ if(pOLEChartOpt)
+ lcl_WriteOpt(*pOLEChartOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_CHART_ENABLE);
+ break;
+ case INS_PROP_CAP_OBJECT_FORMULA_ENABLE:
+ case INS_PROP_CAP_OBJECT_FORMULA_CATEGORY:
+ case INS_PROP_CAP_OBJECT_FORMULA_NUMBERING:
+ case INS_PROP_CAP_OBJECT_FORMULA_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_FORMULA_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_FORMULA_DELIMITER:
+ case INS_PROP_CAP_OBJECT_FORMULA_LEVEL:
+ case INS_PROP_CAP_OBJECT_FORMULA_POSITION:
+ case INS_PROP_CAP_OBJECT_FORMULA_CHARACTERSTYLE:
+ case INS_PROP_CAP_OBJECT_FORMULA_APPLYATTRIBUTES:
+ if(pOLEFormulaOpt)
+ lcl_WriteOpt(*pOLEFormulaOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_FORMULA_ENABLE);
+ break;
+ case INS_PROP_CAP_OBJECT_DRAW_ENABLE:
+ case INS_PROP_CAP_OBJECT_DRAW_CATEGORY:
+ case INS_PROP_CAP_OBJECT_DRAW_NUMBERING:
+ case INS_PROP_CAP_OBJECT_DRAW_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_DRAW_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_DRAW_DELIMITER:
+ case INS_PROP_CAP_OBJECT_DRAW_LEVEL:
+ case INS_PROP_CAP_OBJECT_DRAW_POSITION:
+ case INS_PROP_CAP_OBJECT_DRAW_CHARACTERSTYLE:
+ case INS_PROP_CAP_OBJECT_DRAW_APPLYATTRIBUTES:
+ if(pOLEDrawOpt)
+ lcl_WriteOpt(*pOLEDrawOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_DRAW_ENABLE);
+ break;
+ case INS_PROP_CAP_OBJECT_OLEMISC_ENABLE:
+ case INS_PROP_CAP_OBJECT_OLEMISC_CATEGORY:
+ case INS_PROP_CAP_OBJECT_OLEMISC_NUMBERING:
+ case INS_PROP_CAP_OBJECT_OLEMISC_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_OLEMISC_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_OLEMISC_DELIMITER:
+ case INS_PROP_CAP_OBJECT_OLEMISC_LEVEL:
+ case INS_PROP_CAP_OBJECT_OLEMISC_POSITION:
+ case INS_PROP_CAP_OBJECT_OLEMISC_CHARACTERSTYLE:
+ case INS_PROP_CAP_OBJECT_OLEMISC_APPLYATTRIBUTES:
+ if(m_pOLEMiscOpt)
+ lcl_WriteOpt(*m_pOLEMiscOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_OLEMISC_ENABLE);
+ break;
+
+ }
+ }
+ PutProperties(aNames, aValues);
+}
+
+static void lcl_ReadOpt(InsCaptionOpt& rOpt, const Any* pValues, sal_Int32 nProp, sal_Int32 nOffset)
+{
+ switch(nOffset)
+ {
+ case 0:
+ rOpt.UseCaption() = *o3tl::doAccess<bool>(pValues[nProp]);
+ break;//Enable
+ case 1:
+ {
+ OUString sTemp; pValues[nProp] >>= sTemp;
+ rOpt.SetCategory(sTemp);
+ }
+ break;//Category
+ case 2:
+ {
+ sal_Int32 nTemp = 0;
+ pValues[nProp] >>= nTemp;
+ rOpt.SetNumType(sal::static_int_cast< sal_uInt16, sal_Int32>(nTemp));
+ }
+ break;//Numbering",
+ case 3:
+ {
+ OUString sTemp; pValues[nProp] >>= sTemp;
+ rOpt.SetNumSeparator(sTemp);
+ }
+ break;//NumberingSeparator",
+ case 4:
+ {
+ OUString sTemp; pValues[nProp] >>= sTemp;
+ rOpt.SetCaption(sTemp);
+ }
+ break;//CaptionText",
+ case 5:
+ {
+ OUString sTemp;
+ if(pValues[nProp] >>= sTemp)
+ rOpt.SetSeparator(sTemp);
+ }
+ break;//Delimiter",
+ case 6:
+ {
+ sal_Int32 nTemp = 0;
+ pValues[nProp] >>= nTemp;
+ rOpt.SetLevel(sal::static_int_cast< sal_uInt16, sal_Int32>(nTemp));
+ }
+ break;//Level",
+ case 7:
+ {
+ sal_Int32 nTemp = 0;
+ pValues[nProp] >>= nTemp;
+ rOpt.SetPos(sal::static_int_cast< sal_uInt16, sal_Int32>(nTemp));
+ }
+ break;//Position",
+ case 8 : //CharacterStyle
+ {
+ OUString sTemp; pValues[nProp] >>= sTemp;
+ rOpt.SetCharacterStyle( sTemp );
+ }
+ break;
+ case 9 : //ApplyAttributes
+ {
+ pValues[nProp] >>= rOpt.CopyAttributes();
+ }
+ break;
+ }
+}
+
+void SwInsertConfig::Load()
+{
+ const Sequence<OUString>& aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ const Any* pValues = aValues.getConstArray();
+ assert(aValues.getLength() == aNames.getLength());
+ InsCaptionOpt* pWriterTableOpt = nullptr;
+ InsCaptionOpt* pWriterFrameOpt = nullptr;
+ InsCaptionOpt* pWriterGraphicOpt = nullptr;
+ InsCaptionOpt* pOLECalcOpt = nullptr;
+ InsCaptionOpt* pOLEImpressOpt = nullptr;
+ InsCaptionOpt* pOLEChartOpt = nullptr;
+ InsCaptionOpt* pOLEFormulaOpt = nullptr;
+ InsCaptionOpt* pOLEDrawOpt = nullptr;
+ if (m_pCapOptions)
+ {
+ pWriterTableOpt = m_pCapOptions->Find(TABLE_CAP);
+ pWriterFrameOpt = m_pCapOptions->Find(FRAME_CAP);
+ pWriterGraphicOpt = m_pCapOptions->Find(GRAPHIC_CAP);
+ pOLECalcOpt = m_pCapOptions->Find(OLE_CAP, &m_aGlobalNames[GLOB_NAME_CALC]);
+ pOLEImpressOpt = m_pCapOptions->Find(OLE_CAP, &m_aGlobalNames[GLOB_NAME_IMPRESS]);
+ pOLEDrawOpt = m_pCapOptions->Find(OLE_CAP, &m_aGlobalNames[GLOB_NAME_DRAW ]);
+ pOLEFormulaOpt = m_pCapOptions->Find(OLE_CAP, &m_aGlobalNames[GLOB_NAME_MATH ]);
+ pOLEChartOpt = m_pCapOptions->Find(OLE_CAP, &m_aGlobalNames[GLOB_NAME_CHART ]);
+ }
+ else if (!m_bIsWeb)
+ return;
+
+ SwInsertTableFlags nInsTableFlags = SwInsertTableFlags::NONE;
+ for (sal_Int32 nProp = 0; nProp < aNames.getLength(); ++nProp)
+ {
+ if (pValues[nProp].hasValue())
+ {
+ bool bBool = nProp < INS_PROP_CAP_OBJECT_TABLE_ENABLE && *o3tl::doAccess<bool>(pValues[nProp]);
+ switch (nProp)
+ {
+ case INS_PROP_TABLE_HEADER:
+ {
+ if(bBool)
+ nInsTableFlags |= SwInsertTableFlags::Headline;
+ }
+ break;//"Table/Header",
+ case INS_PROP_TABLE_REPEATHEADER:
+ {
+ m_aInsTableOpts.mnRowsToRepeat = bBool? 1 : 0;
+
+ }
+ break;//"Table/RepeatHeader",
+ case INS_PROP_TABLE_BORDER:
+ {
+ if(bBool)
+ nInsTableFlags |= SwInsertTableFlags::DefaultBorder;
+ }
+ break;//"Table/Border",
+ case INS_PROP_TABLE_SPLIT:
+ {
+ if(bBool)
+ nInsTableFlags |= SwInsertTableFlags::SplitLayout;
+ }
+ break;//"Table/Split",
+ case INS_PROP_CAP_AUTOMATIC:
+ m_bInsWithCaption = bBool;
+ break;
+ case INS_PROP_CAP_CAPTIONORDERNUMBERINGFIRST: m_bCaptionOrderNumberingFirst = bBool; break;
+ case INS_PROP_CAP_OBJECT_TABLE_ENABLE:
+ case INS_PROP_CAP_OBJECT_TABLE_CATEGORY:
+ case INS_PROP_CAP_OBJECT_TABLE_NUMBERING:
+ case INS_PROP_CAP_OBJECT_TABLE_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_TABLE_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_TABLE_DELIMITER:
+ case INS_PROP_CAP_OBJECT_TABLE_LEVEL:
+ case INS_PROP_CAP_OBJECT_TABLE_POSITION:
+ case INS_PROP_CAP_OBJECT_TABLE_CHARACTERSTYLE:
+ if(!pWriterTableOpt)
+ {
+ pWriterTableOpt = new InsCaptionOpt(TABLE_CAP);
+ m_pCapOptions->Insert(pWriterTableOpt);
+ }
+ lcl_ReadOpt(*pWriterTableOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_TABLE_ENABLE);
+ break;
+ case INS_PROP_CAP_OBJECT_FRAME_ENABLE:
+ case INS_PROP_CAP_OBJECT_FRAME_CATEGORY:
+ case INS_PROP_CAP_OBJECT_FRAME_NUMBERING:
+ case INS_PROP_CAP_OBJECT_FRAME_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_FRAME_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_FRAME_DELIMITER:
+ case INS_PROP_CAP_OBJECT_FRAME_LEVEL:
+ case INS_PROP_CAP_OBJECT_FRAME_POSITION:
+ case INS_PROP_CAP_OBJECT_FRAME_CHARACTERSTYLE:
+ if(!pWriterFrameOpt)
+ {
+ pWriterFrameOpt = new InsCaptionOpt(FRAME_CAP);
+ m_pCapOptions->Insert(pWriterFrameOpt);
+ }
+ lcl_ReadOpt(*pWriterFrameOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_FRAME_ENABLE);
+ break;
+ case INS_PROP_CAP_OBJECT_GRAPHIC_ENABLE:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_CATEGORY:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_NUMBERING:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_DELIMITER:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_LEVEL:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_POSITION:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_CHARACTERSTYLE:
+ case INS_PROP_CAP_OBJECT_GRAPHIC_APPLYATTRIBUTES:
+ if(!pWriterGraphicOpt)
+ {
+ pWriterGraphicOpt = new InsCaptionOpt(GRAPHIC_CAP);
+ m_pCapOptions->Insert(pWriterGraphicOpt);
+ }
+ lcl_ReadOpt(*pWriterGraphicOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_GRAPHIC_ENABLE);
+ break;
+ case INS_PROP_CAP_OBJECT_CALC_ENABLE:
+ case INS_PROP_CAP_OBJECT_CALC_CATEGORY:
+ case INS_PROP_CAP_OBJECT_CALC_NUMBERING:
+ case INS_PROP_CAP_OBJECT_CALC_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_CALC_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_CALC_DELIMITER:
+ case INS_PROP_CAP_OBJECT_CALC_LEVEL:
+ case INS_PROP_CAP_OBJECT_CALC_POSITION:
+ case INS_PROP_CAP_OBJECT_CALC_CHARACTERSTYLE:
+ case INS_PROP_CAP_OBJECT_CALC_APPLYATTRIBUTES:
+ if(!pOLECalcOpt)
+ {
+ pOLECalcOpt = new InsCaptionOpt(OLE_CAP, &m_aGlobalNames[GLOB_NAME_CALC]);
+ m_pCapOptions->Insert(pOLECalcOpt);
+ }
+ lcl_ReadOpt(*pOLECalcOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_CALC_ENABLE);
+ break;
+ case INS_PROP_CAP_OBJECT_IMPRESS_ENABLE:
+ case INS_PROP_CAP_OBJECT_IMPRESS_CATEGORY:
+ case INS_PROP_CAP_OBJECT_IMPRESS_NUMBERING:
+ case INS_PROP_CAP_OBJECT_IMPRESS_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_IMPRESS_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_IMPRESS_DELIMITER:
+ case INS_PROP_CAP_OBJECT_IMPRESS_LEVEL:
+ case INS_PROP_CAP_OBJECT_IMPRESS_POSITION:
+ case INS_PROP_CAP_OBJECT_IMPRESS_CHARACTERSTYLE:
+ case INS_PROP_CAP_OBJECT_IMPRESS_APPLYATTRIBUTES:
+ if(!pOLEImpressOpt)
+ {
+ pOLEImpressOpt = new InsCaptionOpt(OLE_CAP, &m_aGlobalNames[GLOB_NAME_IMPRESS]);
+ m_pCapOptions->Insert(pOLEImpressOpt);
+ }
+ lcl_ReadOpt(*pOLEImpressOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_IMPRESS_ENABLE);
+ break;
+ case INS_PROP_CAP_OBJECT_CHART_ENABLE:
+ case INS_PROP_CAP_OBJECT_CHART_CATEGORY:
+ case INS_PROP_CAP_OBJECT_CHART_NUMBERING:
+ case INS_PROP_CAP_OBJECT_CHART_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_CHART_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_CHART_DELIMITER:
+ case INS_PROP_CAP_OBJECT_CHART_LEVEL:
+ case INS_PROP_CAP_OBJECT_CHART_POSITION:
+ case INS_PROP_CAP_OBJECT_CHART_CHARACTERSTYLE:
+ case INS_PROP_CAP_OBJECT_CHART_APPLYATTRIBUTES:
+ if(!pOLEChartOpt)
+ {
+ pOLEChartOpt = new InsCaptionOpt(OLE_CAP, &m_aGlobalNames[GLOB_NAME_CHART]);
+ m_pCapOptions->Insert(pOLEChartOpt);
+ }
+ lcl_ReadOpt(*pOLEChartOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_CHART_ENABLE);
+ break;
+ case INS_PROP_CAP_OBJECT_FORMULA_ENABLE:
+ case INS_PROP_CAP_OBJECT_FORMULA_CATEGORY:
+ case INS_PROP_CAP_OBJECT_FORMULA_NUMBERING:
+ case INS_PROP_CAP_OBJECT_FORMULA_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_FORMULA_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_FORMULA_DELIMITER:
+ case INS_PROP_CAP_OBJECT_FORMULA_LEVEL:
+ case INS_PROP_CAP_OBJECT_FORMULA_POSITION:
+ case INS_PROP_CAP_OBJECT_FORMULA_CHARACTERSTYLE:
+ case INS_PROP_CAP_OBJECT_FORMULA_APPLYATTRIBUTES:
+ if(!pOLEFormulaOpt)
+ {
+ pOLEFormulaOpt = new InsCaptionOpt(OLE_CAP, &m_aGlobalNames[GLOB_NAME_MATH]);
+ m_pCapOptions->Insert(pOLEFormulaOpt);
+ }
+ lcl_ReadOpt(*pOLEFormulaOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_FORMULA_ENABLE);
+ break;
+ case INS_PROP_CAP_OBJECT_DRAW_ENABLE:
+ case INS_PROP_CAP_OBJECT_DRAW_CATEGORY:
+ case INS_PROP_CAP_OBJECT_DRAW_NUMBERING:
+ case INS_PROP_CAP_OBJECT_DRAW_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_DRAW_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_DRAW_DELIMITER:
+ case INS_PROP_CAP_OBJECT_DRAW_LEVEL:
+ case INS_PROP_CAP_OBJECT_DRAW_POSITION:
+ case INS_PROP_CAP_OBJECT_DRAW_CHARACTERSTYLE:
+ case INS_PROP_CAP_OBJECT_DRAW_APPLYATTRIBUTES:
+ if(!pOLEDrawOpt)
+ {
+ pOLEDrawOpt = new InsCaptionOpt(OLE_CAP, &m_aGlobalNames[GLOB_NAME_DRAW]);
+ m_pCapOptions->Insert(pOLEDrawOpt);
+ }
+ lcl_ReadOpt(*pOLEDrawOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_DRAW_ENABLE);
+ break;
+ case INS_PROP_CAP_OBJECT_OLEMISC_ENABLE:
+ case INS_PROP_CAP_OBJECT_OLEMISC_CATEGORY:
+ case INS_PROP_CAP_OBJECT_OLEMISC_NUMBERING:
+ case INS_PROP_CAP_OBJECT_OLEMISC_NUMBERINGSEPARATOR:
+ case INS_PROP_CAP_OBJECT_OLEMISC_CAPTIONTEXT:
+ case INS_PROP_CAP_OBJECT_OLEMISC_DELIMITER:
+ case INS_PROP_CAP_OBJECT_OLEMISC_LEVEL:
+ case INS_PROP_CAP_OBJECT_OLEMISC_POSITION:
+ case INS_PROP_CAP_OBJECT_OLEMISC_CHARACTERSTYLE:
+ case INS_PROP_CAP_OBJECT_OLEMISC_APPLYATTRIBUTES:
+ if(!m_pOLEMiscOpt)
+ {
+ m_pOLEMiscOpt.reset(new InsCaptionOpt(OLE_CAP));
+ }
+ lcl_ReadOpt(*m_pOLEMiscOpt, pValues, nProp, nProp - INS_PROP_CAP_OBJECT_OLEMISC_ENABLE);
+ break;
+ }
+ }
+ else if (nProp == INS_PROP_CAP_CAPTIONORDERNUMBERINGFIRST)
+ {
+ m_bCaptionOrderNumberingFirst = false;
+ }
+
+ }
+ m_aInsTableOpts.mnInsMode = nInsTableFlags;
+}
+
+const Sequence<OUString>& SwTableConfig::GetPropertyNames()
+{
+ static Sequence<OUString> const aNames
+ {
+ "Shift/Row", // 0
+ "Shift/Column", // 1
+ "Insert/Row", // 2
+ "Insert/Column", // 3
+ "Change/Effect", // 4
+ "Input/NumberRecognition", // 5
+ "Input/NumberFormatRecognition",// 6
+ "Input/Alignment", // 7
+ "Input/SplitVerticalByDefault" // 8
+ };
+ return aNames;
+}
+
+SwTableConfig::SwTableConfig(bool bWeb)
+ : ConfigItem(bWeb ? OUString("Office.WriterWeb/Table") : OUString("Office.Writer/Table"),
+ ConfigItemMode::ReleaseTree)
+ , m_nTableHMove(0)
+ , m_nTableVMove(0)
+ , m_nTableHInsert(0)
+ , m_nTableVInsert(0)
+ , m_eTableChgMode(TableChgMode::FixedWidthChangeAbs)
+ , m_bInsTableFormatNum(false)
+ , m_bInsTableChangeNumFormat(false)
+ , m_bInsTableAlignNum(false)
+ , m_bSplitVerticalByDefault(false)
+{
+ Load();
+}
+
+SwTableConfig::~SwTableConfig()
+{
+}
+
+void SwTableConfig::Notify( const css::uno::Sequence< OUString >& ) {}
+
+void SwTableConfig::ImplCommit()
+{
+ const Sequence<OUString>& aNames = GetPropertyNames();
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case 0 : pValues[nProp] <<= static_cast<sal_Int32>(convertTwipToMm100(m_nTableHMove)); break; //"Shift/Row",
+ case 1 : pValues[nProp] <<= static_cast<sal_Int32>(convertTwipToMm100(m_nTableVMove)); break; //"Shift/Column",
+ case 2 : pValues[nProp] <<= static_cast<sal_Int32>(convertTwipToMm100(m_nTableHInsert)); break; //"Insert/Row",
+ case 3 : pValues[nProp] <<= static_cast<sal_Int32>(convertTwipToMm100(m_nTableVInsert)); break; //"Insert/Column",
+ case 4 : pValues[nProp] <<= static_cast<sal_Int32>(m_eTableChgMode); break; //"Change/Effect",
+ case 5 : pValues[nProp] <<= m_bInsTableFormatNum; break; //"Input/NumberRecognition",
+ case 6 : pValues[nProp] <<= m_bInsTableChangeNumFormat; break; //"Input/NumberFormatRecognition",
+ case 7 : pValues[nProp] <<= m_bInsTableAlignNum; break; //"Input/Alignment"
+ case 8 : pValues[nProp] <<= m_bSplitVerticalByDefault; break; //"Input/SplitVerticalByDefault"
+ }
+ }
+ PutProperties(aNames, aValues);
+}
+
+void SwTableConfig::Load()
+{
+ const Sequence<OUString>& aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ const Any* pValues = aValues.getConstArray();
+ assert(aValues.getLength() == aNames.getLength());
+ for (sal_Int32 nProp = 0; nProp < aNames.getLength(); ++nProp)
+ {
+ if (pValues[nProp].hasValue())
+ {
+ sal_Int32 nTemp = 0;
+ switch (nProp)
+ {
+ case 0 : pValues[nProp] >>= nTemp; m_nTableHMove = o3tl::toTwips(nTemp, o3tl::Length::mm100); break; //"Shift/Row",
+ case 1 : pValues[nProp] >>= nTemp; m_nTableVMove = o3tl::toTwips(nTemp, o3tl::Length::mm100); break; //"Shift/Column",
+ case 2 : pValues[nProp] >>= nTemp; m_nTableHInsert = o3tl::toTwips(nTemp, o3tl::Length::mm100); break; //"Insert/Row",
+ case 3 : pValues[nProp] >>= nTemp; m_nTableVInsert = o3tl::toTwips(nTemp, o3tl::Length::mm100); break; //"Insert/Column",
+ case 4 : pValues[nProp] >>= nTemp; m_eTableChgMode = static_cast<TableChgMode>(nTemp); break; //"Change/Effect",
+ case 5 : m_bInsTableFormatNum = *o3tl::doAccess<bool>(pValues[nProp]); break; //"Input/NumberRecognition",
+ case 6 : m_bInsTableChangeNumFormat = *o3tl::doAccess<bool>(pValues[nProp]); break; //"Input/NumberFormatRecognition",
+ case 7 : m_bInsTableAlignNum = *o3tl::doAccess<bool>(pValues[nProp]); break; //"Input/Alignment"
+ case 8 : m_bSplitVerticalByDefault = *o3tl::doAccess<bool>(pValues[nProp]); break; //"Input/SplitVerticalByDefault"
+ }
+ }
+ }
+}
+
+SwMiscConfig::SwMiscConfig() :
+ ConfigItem("Office.Writer", ConfigItemMode::ReleaseTree),
+ m_bDefaultFontsInCurrDocOnly(false),
+ m_bShowIndexPreview(false),
+ m_bGrfToGalleryAsLnk(true),
+ m_bNumAlignSize(true),
+ m_bSinglePrintJob(false),
+ m_bIsNameFromColumn(true),
+ m_bIsPasswordFromColumn(false),
+ m_bAskForMailMergeInPrint(true),
+ m_nMailingFormats(MailTextFormats::NONE)
+{
+ Load();
+}
+
+SwMiscConfig::~SwMiscConfig()
+{
+}
+
+const Sequence<OUString>& SwMiscConfig::GetPropertyNames()
+{
+ static Sequence<OUString> const aNames
+ {
+ "Statistics/WordNumber/Delimiter", // 0
+ "DefaultFont/Document", // 1
+ "Index/ShowPreview", // 2
+ "Misc/GraphicToGalleryAsLink", // 3
+ "Numbering/Graphic/KeepRatio", // 4
+ "FormLetter/PrintOutput/SinglePrintJobs", // 5
+ "FormLetter/MailingOutput/Format", // 6
+ "FormLetter/FileOutput/FileName/FromDatabaseField", // 7
+ "FormLetter/FileOutput/Path", // 8
+ "FormLetter/FileOutput/FileName/FromManualSetting", // 9
+ "FormLetter/FileOutput/FileName/Generation",//10
+ "FormLetter/PrintOutput/AskForMerge", //11
+ "FormLetter/FileOutput/FilePassword/FromDatabaseField", // 12
+ "FormLetter/FileOutput/FilePassword/Generation" //13
+ };
+ return aNames;
+}
+
+void SwMiscConfig::Notify( const css::uno::Sequence< OUString >& ) {}
+
+void SwMiscConfig::ImplCommit()
+{
+ const Sequence<OUString>& aNames = GetPropertyNames();
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case 0 :
+ pValues[nProp] <<=
+ SwModuleOptions::ConvertWordDelimiter(m_sWordDelimiter, false);
+ break;
+ case 1 : pValues[nProp] <<= m_bDefaultFontsInCurrDocOnly; break;
+ case 2 : pValues[nProp] <<= m_bShowIndexPreview; break;
+ case 3 : pValues[nProp] <<= m_bGrfToGalleryAsLnk; break;
+ case 4 : pValues[nProp] <<= m_bNumAlignSize; break;
+ case 5 : pValues[nProp] <<= m_bSinglePrintJob; break;
+ case 6 : pValues[nProp] <<= static_cast<sal_Int32>(m_nMailingFormats); break;
+ case 7 : pValues[nProp] <<= m_sNameFromColumn; break;
+ case 8 : pValues[nProp] <<= m_sMailingPath; break;
+ case 9 : pValues[nProp] <<= m_sMailName; break;
+ case 10: pValues[nProp] <<= m_bIsNameFromColumn; break;
+ case 11: pValues[nProp] <<= m_bAskForMailMergeInPrint; break;
+ case 12: pValues[nProp] <<= m_sPasswordFromColumn; break;
+ case 13: pValues[nProp] <<= m_bIsPasswordFromColumn; break;
+ }
+ }
+ PutProperties(aNames, aValues);
+}
+
+void SwMiscConfig::Load()
+{
+ const Sequence<OUString>& aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ const Any* pValues = aValues.getConstArray();
+ assert(aValues.getLength() == aNames.getLength());
+ OUString sTmp;
+ for (sal_Int32 nProp = 0; nProp < aNames.getLength(); ++nProp)
+ {
+ if (pValues[nProp].hasValue())
+ {
+ switch (nProp)
+ {
+ case 0 : pValues[nProp] >>= sTmp;
+ m_sWordDelimiter = SwModuleOptions::ConvertWordDelimiter(sTmp, true);
+ break;
+ case 1 : m_bDefaultFontsInCurrDocOnly = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 2 : m_bShowIndexPreview = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 3 : m_bGrfToGalleryAsLnk = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 4 : m_bNumAlignSize = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 5 : m_bSinglePrintJob = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 6 : m_nMailingFormats = static_cast<MailTextFormats>(*o3tl::doAccess<sal_Int32>(pValues[nProp])); break;
+ case 7 : pValues[nProp] >>= sTmp; m_sNameFromColumn = sTmp; break;
+ case 8 : pValues[nProp] >>= sTmp; m_sMailingPath = sTmp; break;
+ case 9 : pValues[nProp] >>= sTmp; m_sMailName = sTmp; break;
+ case 10: m_bIsNameFromColumn = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 11: pValues[nProp] >>= m_bAskForMailMergeInPrint; break;
+ case 12: pValues[nProp] >>= sTmp; m_sPasswordFromColumn = sTmp; break;
+ case 13: m_bIsPasswordFromColumn = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ }
+ }
+ }
+}
+
+const Sequence<OUString>& SwCompareConfig::GetPropertyNames()
+{
+ static Sequence<OUString> const aNames
+ {
+ "Mode", // 0
+ "UseRSID", // 1
+ "IgnorePieces", // 2
+ "IgnoreLength", // 3
+ "StoreRSID" // 4
+ };
+ return aNames;
+}
+
+SwCompareConfig::SwCompareConfig() :
+ ConfigItem("Office.Writer/Comparison", ConfigItemMode::ReleaseTree)
+ ,m_bStoreRsid(true)
+{
+ m_eCmpMode = SwCompareMode::Auto;
+ m_bUseRsid = false;
+ m_bIgnorePieces = false;
+ m_nPieceLen = 1;
+
+ Load();
+}
+
+SwCompareConfig::~SwCompareConfig()
+{
+}
+
+void SwCompareConfig::ImplCommit()
+{
+ const Sequence<OUString>& aNames = GetPropertyNames();
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ pValues[0] <<= static_cast<sal_Int16>(m_eCmpMode);
+ pValues[1] <<= m_bUseRsid;
+ pValues[2] <<= m_bIgnorePieces;
+ pValues[3] <<= static_cast<sal_Int16>(m_nPieceLen);
+ pValues[4] <<= m_bStoreRsid;
+
+ PutProperties(aNames, aValues);
+}
+
+void SwCompareConfig::Load()
+{
+ const Sequence<OUString>& aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ const Any* pValues = aValues.getConstArray();
+ assert(aValues.getLength() == aNames.getLength());
+ for (sal_Int32 nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ if (pValues[nProp].hasValue())
+ {
+ sal_Int32 nVal = 0;
+ pValues[nProp] >>= nVal;
+
+ switch(nProp)
+ {
+ case 0 : m_eCmpMode = static_cast<SwCompareMode>(nVal); break;
+ case 1 : m_bUseRsid = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 2 : m_bIgnorePieces = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 3 : m_nPieceLen = nVal; break;
+ case 4 : m_bStoreRsid = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/config/prtopt.cxx b/sw/source/uibase/config/prtopt.cxx
new file mode 100644
index 0000000000..68764fab1a
--- /dev/null
+++ b/sw/source/uibase/config/prtopt.cxx
@@ -0,0 +1,168 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <unotools/configmgr.hxx>
+#include <prtopt.hxx>
+#include <o3tl/any.hxx>
+#include <osl/diagnose.h>
+#include <com/sun/star/uno/Sequence.hxx>
+
+using namespace utl;
+using namespace com::sun::star::uno;
+
+// Ctor
+Sequence<OUString> SwPrintOptions::GetPropertyNames() const
+{
+ static const char* aPropNames[] =
+ {
+ "Content/Graphic", // 0
+ "Content/Table", // 1
+ "Content/Control", // 2
+ "Content/Background", // 3
+ "Content/PrintBlack", // 4
+ "Content/Note", // 5
+ "Page/Reversed", // 6
+ "Page/Brochure", // 7
+ "Page/BrochureRightToLeft", // 8
+ "Output/SinglePrintJob", // 9
+ "Output/Fax", // 10
+ "Papertray/FromPrinterSetup", // 11
+ "Content/Drawing", // 12 not in SW/Web
+ "Page/LeftPage", // 13 not in SW/Web
+ "Page/RightPage", // 14 not in SW/Web
+ "EmptyPages", // 15 not in SW/Web
+ "Content/PrintPlaceholders", // 16 not in Sw/Web
+ "Content/PrintHiddenText" // 17 not in Sw/Web
+ };
+ const int nCount = m_bIsWeb ? 12 : 18;
+ Sequence<OUString> aNames(nCount);
+ OUString* pNames = aNames.getArray();
+ for(int i = 0; i < nCount; i++)
+ {
+ pNames[i] = OUString::createFromAscii(aPropNames[i]);
+ }
+ return aNames;
+}
+
+SwPrintOptions::SwPrintOptions(bool bWeb) :
+ ConfigItem(bWeb ? OUString("Office.WriterWeb/Print") : OUString("Office.Writer/Print"),
+ ConfigItemMode::ReleaseTree),
+ m_bIsWeb(bWeb)
+{
+ m_bPrintPageBackground = !bWeb;
+ m_bPrintBlackFont = bWeb;
+ m_bPrintTextPlaceholder = m_bPrintHiddenText = false;
+ if (bWeb)
+ m_bPrintEmptyPages = false;
+
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ const Any* pValues = aValues.getConstArray();
+ OSL_ENSURE(aValues.getLength() == aNames.getLength(), "GetProperties failed");
+ if(aValues.getLength() == aNames.getLength())
+ {
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ if(pValues[nProp].hasValue())
+ {
+ switch(nProp)
+ {
+ case 0: m_bPrintGraphic = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 1: m_bPrintTable = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 2: m_bPrintControl = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 3: m_bPrintPageBackground= *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 4: m_bPrintBlackFont = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 5:
+ {
+ sal_Int32 nTmp = 0;
+ pValues[nProp] >>= nTmp;
+ m_nPrintPostIts = static_cast<SwPostItMode>(nTmp);
+ }
+ break;
+ case 6: m_bPrintReverse = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 7: m_bPrintProspect = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 8: m_bPrintProspectRTL = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 9: m_bPrintSingleJobs = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 10: pValues[nProp] >>= m_sFaxName; break;
+ case 11: m_bPaperFromSetup = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 12: m_bPrintDraw = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 13: m_bPrintLeftPages = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 14: m_bPrintRightPages = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 15: m_bPrintEmptyPages = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 16: m_bPrintTextPlaceholder = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 17: m_bPrintHiddenText = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ }
+ }
+ }
+ }
+
+ // currently there is just one checkbox for print drawings and print graphics
+ // In the UI. (File/Print dialog and Tools/Options/.../Print)
+ // And since print graphics is the only available in Writer and WriterWeb...
+
+ m_bPrintDraw = m_bPrintGraphic;
+}
+
+SwPrintOptions::~SwPrintOptions()
+{
+}
+
+void SwPrintOptions::Notify( const css::uno::Sequence< OUString >& ) {}
+
+void SwPrintOptions::ImplCommit()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case 0: pValues[nProp] <<= m_bPrintGraphic; break;
+ case 1: pValues[nProp] <<= m_bPrintTable; break;
+ case 2: pValues[nProp] <<= m_bPrintControl; break;
+ case 3: pValues[nProp] <<= m_bPrintPageBackground; break;
+ case 4: pValues[nProp] <<= m_bPrintBlackFont; break;
+ case 5: pValues[nProp] <<= static_cast<sal_Int32>(m_nPrintPostIts) ; break;
+ case 6: pValues[nProp] <<= m_bPrintReverse; break;
+ case 7: pValues[nProp] <<= m_bPrintProspect; break;
+ case 8: pValues[nProp] <<= m_bPrintProspectRTL; break;
+ case 9: pValues[nProp] <<= m_bPrintSingleJobs; break;
+ case 10: pValues[nProp] <<= m_sFaxName; break;
+ case 11: pValues[nProp] <<= m_bPaperFromSetup; break;
+ case 12: pValues[nProp] <<= m_bPrintDraw; break;
+ case 13: pValues[nProp] <<= m_bPrintLeftPages; break;
+ case 14: pValues[nProp] <<= m_bPrintRightPages; break;
+ case 15: pValues[nProp] <<= m_bPrintEmptyPages; break;
+ case 16: pValues[nProp] <<= m_bPrintTextPlaceholder; break;
+ case 17: pValues[nProp] <<= m_bPrintHiddenText; break;
+ }
+ }
+
+ // currently there is just one checkbox for print drawings and print graphics
+ // In the UI. (File/Print dialog and Tools/Options/.../Print)
+ // And since print graphics is the only available in Writer and WriterWeb...
+ m_bPrintDraw = m_bPrintGraphic;
+
+ PutProperties(aNames, aValues);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/config/uinums.cxx b/sw/source/uibase/config/uinums.cxx
new file mode 100644
index 0000000000..99d0ceb8c1
--- /dev/null
+++ b/sw/source/uibase/config/uinums.cxx
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <uinums.hxx>
+
+#include <unotools/pathoptions.hxx>
+#include <tools/stream.hxx>
+#include <sfx2/docfile.hxx>
+#include <svl/itemiter.hxx>
+
+#include <swtypes.hxx>
+#include <utility>
+#include <wrtsh.hxx>
+#include <poolfmt.hxx>
+#include <charfmt.hxx>
+
+using namespace ::com::sun::star;
+
+constexpr OUString CHAPTER_FILENAME = u"chapter.cfg"_ustr;
+
+/*
+ Description: Saving a rule
+ Parameter: rCopy -- the rule to save
+ nIdx -- position, where the rule is to be saved.
+ An old rule at that position will be overwritten.
+*/
+
+SwChapterNumRules::SwChapterNumRules()
+{
+ Init();
+}
+
+void SwChapterNumRules::Save()
+{
+ INetURLObject aURL;
+ SvtPathOptions aPathOpt;
+ aURL.SetSmartURL( aPathOpt.GetUserConfigPath() );
+ aURL.setFinalSlash();
+ aURL.Append(CHAPTER_FILENAME);
+
+ SfxMedium aMedium( aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::WRITE );
+ SvStream* pStream = aMedium.GetOutStream();
+ bool bRet = (pStream && pStream->GetError() == ERRCODE_NONE);
+ if (bRet)
+ {
+ sw::ExportStoredChapterNumberingRules(*this, *pStream,CHAPTER_FILENAME);
+
+ pStream->FlushBuffer();
+
+ aMedium.Commit();
+ }
+}
+
+SwChapterNumRules::~SwChapterNumRules()
+{
+}
+
+void SwChapterNumRules::Init()
+{
+ for(auto & rpNumRule : m_pNumRules)
+ rpNumRule.reset();
+
+ OUString sNm(CHAPTER_FILENAME);
+ SvtPathOptions aOpt;
+ if( aOpt.SearchFile( sNm ))
+ {
+ SfxMedium aStrm( sNm, StreamMode::STD_READ );
+ sw::ImportStoredChapterNumberingRules(*this, *aStrm.GetInStream(),
+ CHAPTER_FILENAME);
+ }
+}
+
+void SwChapterNumRules::CreateEmptyNumRule(sal_uInt16 const nIndex)
+{
+ assert(nIndex < nMaxRules);
+ assert(!m_pNumRules[nIndex]);
+ m_pNumRules[nIndex].reset(new SwNumRulesWithName);
+}
+
+void SwChapterNumRules::ApplyNumRules(const SwNumRulesWithName &rCopy, sal_uInt16 nIdx)
+{
+ assert(nIdx < nMaxRules);
+ if( !m_pNumRules[nIdx] )
+ m_pNumRules[nIdx].reset(new SwNumRulesWithName( rCopy ));
+ else
+ *m_pNumRules[nIdx] = rCopy;
+ Save(); // store it immediately
+}
+
+SwNumRulesWithName::SwNumRulesWithName( const SwNumRule &rCopy,
+ OUString aName )
+ : maName(std::move(aName))
+{
+ for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
+ {
+ const SwNumFormat* pFormat = rCopy.GetNumFormat( n );
+ if( pFormat )
+ m_aFormats[ n ].reset(new SwNumFormatGlobal( *pFormat ));
+ else
+ m_aFormats[ n ].reset();
+ }
+}
+
+SwNumRulesWithName::SwNumRulesWithName( const SwNumRulesWithName& rCopy )
+{
+ *this = rCopy;
+}
+
+SwNumRulesWithName::~SwNumRulesWithName()
+{
+}
+
+SwNumRulesWithName& SwNumRulesWithName::operator=(const SwNumRulesWithName &rCopy)
+{
+ if( this != &rCopy )
+ {
+ maName = rCopy.maName;
+ for( int n = 0; n < MAXLEVEL; ++n )
+ {
+ SwNumFormatGlobal* pFormat = rCopy.m_aFormats[ n ].get();
+ if( pFormat )
+ m_aFormats[ n ].reset(new SwNumFormatGlobal( *pFormat ));
+ else
+ m_aFormats[ n ].reset();
+ }
+ }
+ return *this;
+}
+
+void SwNumRulesWithName::ResetNumRule(SwWrtShell& rSh, SwNumRule& rNumRule) const
+{
+ // #i89178#
+ rNumRule.Reset(maName);
+ rNumRule.SetAutoRule( false );
+ for (sal_uInt16 n = 0; n < MAXLEVEL; ++n)
+ {
+ SwNumFormatGlobal* pFormat = m_aFormats[ n ].get();
+ if (!pFormat)
+ continue;
+ rNumRule.Set(n, pFormat->MakeNumFormat(rSh));
+ }
+}
+
+void SwNumRulesWithName::GetNumFormat(
+ size_t const nIndex, SwNumFormat const*& rpNumFormat, OUString const*& rpName) const
+{
+ rpNumFormat = (m_aFormats[nIndex]) ? &m_aFormats[nIndex]->m_aFormat : nullptr;
+ rpName = (m_aFormats[nIndex]) ? &m_aFormats[nIndex]->m_sCharFormatName : nullptr;
+}
+
+void SwNumRulesWithName::SetNumFormat(
+ size_t const nIndex, SwNumFormat const& rNumFormat, OUString const& rName)
+{
+ m_aFormats[nIndex].reset( new SwNumFormatGlobal(rNumFormat) );
+ m_aFormats[nIndex]->m_sCharFormatName = rName;
+ m_aFormats[nIndex]->m_nCharPoolId = USHRT_MAX;
+ m_aFormats[nIndex]->m_Items.clear();
+}
+
+SwNumRulesWithName::SwNumFormatGlobal::SwNumFormatGlobal( const SwNumFormat& rFormat )
+ : m_aFormat( rFormat ), m_nCharPoolId( USHRT_MAX )
+{
+ // relative gaps?????
+
+ SwCharFormat* pFormat = rFormat.GetCharFormat();
+ if( !pFormat )
+ return;
+
+ m_sCharFormatName = pFormat->GetName();
+ m_nCharPoolId = pFormat->GetPoolFormatId();
+ if( pFormat->GetAttrSet().Count() )
+ {
+ SfxItemIter aIter( pFormat->GetAttrSet() );
+ const SfxPoolItem *pCurr = aIter.GetCurItem();
+ do
+ {
+ m_Items.push_back(std::unique_ptr<SfxPoolItem>(pCurr->Clone()));
+ pCurr = aIter.NextItem();
+ } while (pCurr);
+ }
+
+ m_aFormat.SetCharFormat( nullptr );
+}
+
+SwNumRulesWithName::SwNumFormatGlobal::SwNumFormatGlobal( const SwNumFormatGlobal& rFormat )
+ :
+ m_aFormat( rFormat.m_aFormat ),
+ m_sCharFormatName( rFormat.m_sCharFormatName ),
+ m_nCharPoolId( rFormat.m_nCharPoolId )
+{
+ for (size_t n = rFormat.m_Items.size(); n; )
+ {
+ m_Items.push_back(std::unique_ptr<SfxPoolItem>(rFormat.m_Items[ --n ]->Clone()));
+ }
+}
+
+SwNumRulesWithName::SwNumFormatGlobal::~SwNumFormatGlobal()
+{
+}
+
+SwNumFormat SwNumRulesWithName::SwNumFormatGlobal::MakeNumFormat(SwWrtShell& rSh) const
+{
+ SwCharFormat* pFormat = nullptr;
+ if( !m_sCharFormatName.isEmpty() )
+ {
+ // at first, look for the name
+ sal_uInt16 nArrLen = rSh.GetCharFormatCount();
+ for( sal_uInt16 i = 1; i < nArrLen; ++i )
+ {
+ pFormat = &rSh.GetCharFormat( i );
+ if (pFormat->GetName()==m_sCharFormatName)
+ // exists, so leave attributes as they are!
+ break;
+ pFormat = nullptr;
+ }
+
+ if( !pFormat )
+ {
+ if( IsPoolUserFormat( m_nCharPoolId ) )
+ {
+ pFormat = rSh.MakeCharFormat( m_sCharFormatName );
+ pFormat->SetAuto(false);
+ }
+ else
+ pFormat = rSh.GetCharFormatFromPool( m_nCharPoolId );
+
+ if( !pFormat->HasWriterListeners() ) // set attributes
+ {
+ for (size_t n = m_Items.size(); n; )
+ {
+ pFormat->SetFormatAttr( *m_Items[ --n ] );
+ }
+ }
+ }
+ }
+ const_cast<SwNumFormat&>(m_aFormat).SetCharFormat(pFormat);
+ SwNumFormat aNew = m_aFormat;
+ if (pFormat)
+ const_cast<SwNumFormat&>(m_aFormat).SetCharFormat(nullptr);
+ return aNew;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/config/usrpref.cxx b/sw/source/uibase/config/usrpref.cxx
new file mode 100644
index 0000000000..c04d775c3a
--- /dev/null
+++ b/sw/source/uibase/config/usrpref.cxx
@@ -0,0 +1,622 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <osl/diagnose.h>
+#include <o3tl/any.hxx>
+#include <tools/UnitConversion.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/syslocale.hxx>
+
+#include <usrpref.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <unotools/localedatawrapper.hxx>
+
+using namespace utl;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+void SwMasterUsrPref::SetUsrPref(const SwViewOption &rCopy)
+{
+ *static_cast<SwViewOption*>(this) = rCopy;
+}
+
+SwMasterUsrPref::SwMasterUsrPref(bool bWeb) :
+ m_eFieldUpdateFlags(AUTOUPD_OFF),
+ m_nLinkUpdateMode(0),
+ m_bIsHScrollMetricSet(false),
+ m_bIsVScrollMetricSet(false),
+ m_nDefTabInMm100( 2000 ), // 2 cm
+ m_bIsSquaredPageMode(false),
+ m_bIsAlignMathObjectsToBaseline(false),
+ m_aContentConfig(bWeb, *this),
+ m_aLayoutConfig(bWeb, *this),
+ m_aGridConfig(bWeb, *this),
+ m_aCursorConfig(*this),
+ m_pWebColorConfig(bWeb ? new SwWebColorConfig(*this) : nullptr),
+ m_bApplyCharUnit(false)
+{
+ if (utl::ConfigManager::IsFuzzing())
+ {
+ m_eHScrollMetric = m_eVScrollMetric = m_eUserMetric = FieldUnit::CM;
+ // match defaults
+ SetCore2Option(true, ViewOptCoreFlags2::CursorInProt);
+ SetCore2Option(false, ViewOptCoreFlags2::HiddenPara);
+ m_nDefTabInMm100 = 1250;
+ return;
+ }
+ MeasurementSystem eSystem = SvtSysLocale().GetLocaleData().getMeasurementSystemEnum();
+ m_eUserMetric = MeasurementSystem::Metric == eSystem ? FieldUnit::CM : FieldUnit::INCH;
+ m_eHScrollMetric = m_eVScrollMetric = m_eUserMetric;
+
+ m_aContentConfig.Load();
+ m_aLayoutConfig.Load();
+ m_aGridConfig.Load();
+ m_aCursorConfig.Load();
+ if(m_pWebColorConfig)
+ m_pWebColorConfig->Load();
+}
+
+SwMasterUsrPref::~SwMasterUsrPref()
+{
+}
+
+const auto g_UpdateLinkIndex = 17;
+const auto g_DefaultAnchor = 25;
+
+Sequence<OUString> SwContentViewConfig::GetPropertyNames() const
+{
+ static constexpr const char*const aPropNames[] =
+ {
+ "Display/GraphicObject", // 0
+ "Display/Table", // 1
+ "Display/DrawingControl", // 2
+ "Display/FieldCode", // 3
+ "Display/Note", // 4
+ "Display/ShowContentTips", // 5
+ "NonprintingCharacter/MetaCharacters", // 6
+ "NonprintingCharacter/ParagraphEnd", // 7
+ "NonprintingCharacter/OptionalHyphen", // 8
+ "NonprintingCharacter/Space", // 9
+ "NonprintingCharacter/Break", // 10
+ "NonprintingCharacter/ProtectedSpace", // 11
+ "NonprintingCharacter/Tab", // 12 //not in Writer/Web
+ "NonprintingCharacter/HiddenText", // 13
+ "NonprintingCharacter/HiddenParagraph", // 14
+ "NonprintingCharacter/HiddenCharacter", // 15
+ "NonprintingCharacter/Bookmarks", // 16
+ "Update/Link", // 17
+ "Update/Field", // 18
+ "Update/Chart", // 19
+ "Display/ShowInlineTooltips", // 20
+ "Display/UseHeaderFooterMenu", // 21
+ "Display/ShowOutlineContentVisibilityButton", // 22
+ "Display/TreatSubOutlineLevelsAsContent", // 23
+ "Display/ShowChangesInMargin", // 24
+ "Display/DefaultAnchor" // 25
+ };
+#if defined(__GNUC__) && !defined(__clang__)
+ // clang 8.0.0 says strcmp isn't constexpr
+ static_assert(std::strcmp("Update/Link", aPropNames[g_UpdateLinkIndex]) == 0);
+ static_assert(std::strcmp("Display/DefaultAnchor", aPropNames[g_DefaultAnchor]) == 0);
+#endif
+ const int nCount = m_bWeb ? 12 : SAL_N_ELEMENTS(aPropNames);
+ Sequence<OUString> aNames(nCount);
+ OUString* pNames = aNames.getArray();
+ for(int i = 0; i < nCount; i++)
+ {
+ pNames[i] = OUString::createFromAscii(aPropNames[i]);
+ }
+ return aNames;
+}
+
+SwContentViewConfig::SwContentViewConfig(bool bIsWeb, SwMasterUsrPref& rPar) :
+ ConfigItem(bIsWeb ? OUString("Office.WriterWeb/Content") : OUString("Office.Writer/Content")),
+ m_rParent(rPar),
+ m_bWeb(bIsWeb)
+{
+ Load();
+ EnableNotification( GetPropertyNames() );
+}
+
+SwContentViewConfig::~SwContentViewConfig()
+{
+}
+
+void SwContentViewConfig::Notify( const Sequence< OUString > & /*rPropertyNames*/ )
+{
+ Load();
+}
+
+void SwContentViewConfig::ImplCommit()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ bool bVal = false;
+ switch(nProp)
+ {
+ case 0: bVal = m_rParent.IsGraphic(); break;// "Display/GraphicObject",
+ case 1: bVal = m_rParent.IsTable(); break;// "Display/Table",
+ case 2: bVal = m_rParent.IsDraw(); break;// "Display/DrawingControl",
+ case 3: bVal = m_rParent.IsFieldName(); break;// "Display/FieldCode",
+ case 4: bVal = m_rParent.IsPostIts(); break;// "Display/Note",
+ case 5: bVal = m_rParent.IsShowContentTips(); break; // "Display/ShowContentTips"
+ case 6: bVal = m_rParent.IsViewMetaChars(); break; //"NonprintingCharacter/MetaCharacters"
+ case 7: bVal = m_rParent.IsParagraph(true); break;// "NonprintingCharacter/ParagraphEnd",
+ case 8: bVal = m_rParent.IsSoftHyph(); break;// "NonprintingCharacter/OptionalHyphen",
+ case 9: bVal = m_rParent.IsBlank(true); break;// "NonprintingCharacter/Space",
+ case 10: bVal = m_rParent.IsLineBreak(true);break;// "NonprintingCharacter/Break",
+ case 11: bVal = m_rParent.IsHardBlank(); break;// "NonprintingCharacter/ProtectedSpace",
+ case 12: bVal = m_rParent.IsTab(true); break;// "NonprintingCharacter/Tab",
+ case 13: bVal = m_rParent.IsShowHiddenField(); break;// "NonprintingCharacter/Fields: HiddenText",
+ case 14: bVal = m_rParent.IsShowHiddenPara(); break;// "NonprintingCharacter/Fields: HiddenParagraph",
+ case 15: bVal = m_rParent.IsShowHiddenChar(true); break;// "NonprintingCharacter/HiddenCharacter",
+ case 16: bVal = m_rParent.IsShowBookmarks(true); break;// "NonprintingCharacter/Bookmarks",
+ case 17: pValues[nProp] <<= m_rParent.GetUpdateLinkMode(); break;// "Update/Link",
+ case 18: bVal = m_rParent.IsUpdateFields(); break;// "Update/Field",
+ case 19: bVal = m_rParent.IsUpdateCharts(); break;// "Update/Chart"
+ case 20: bVal = m_rParent.IsShowInlineTooltips(); break;// "Display/ShowInlineTooltips"
+ case 21: bVal = m_rParent.IsUseHeaderFooterMenu(); break;// "Display/UseHeaderFooterMenu"
+ case 22: bVal = m_rParent.IsShowOutlineContentVisibilityButton(); break;// "Display/ShowOutlineContentVisibilityButton"
+ case 23: bVal = m_rParent.IsTreatSubOutlineLevelsAsContent(); break;// "Display/TreatSubOutlineLevelsAsContent"
+ case 24: bVal = m_rParent.IsShowChangesInMargin(); break;// "Display/ShowChangesInMargin"
+ case 25: pValues[nProp] <<= m_rParent.GetDefaultAnchor(); break;// "Display/DefaultAnchor"
+ }
+ if ((nProp != g_UpdateLinkIndex) && (nProp != g_DefaultAnchor))
+ pValues[nProp] <<= bVal;
+ }
+ PutProperties(aNames, aValues);
+}
+
+void SwContentViewConfig::Load()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ const Any* pValues = aValues.getConstArray();
+ OSL_ENSURE(aValues.getLength() == aNames.getLength(), "GetProperties failed");
+ if(aValues.getLength() != aNames.getLength())
+ return;
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ if(pValues[nProp].hasValue())
+ {
+ bool bSet = ((nProp != g_UpdateLinkIndex) && (nProp != g_DefaultAnchor))
+ && *o3tl::doAccess<bool>(pValues[nProp]);
+ switch(nProp)
+ {
+ case 0: m_rParent.SetGraphic(bSet); break;// "Display/GraphicObject",
+ case 1: m_rParent.SetTable(bSet); break;// "Display/Table",
+ case 2: m_rParent.SetDraw(bSet); break;// "Display/DrawingControl",
+ case 3: m_rParent.SetFieldName(bSet); break;// "Display/FieldCode",
+ case 4: m_rParent.SetPostIts(bSet); break;// "Display/Note",
+ case 5: m_rParent.SetShowContentTips(bSet); break;// "Display/ShowContentTips",
+ case 6: m_rParent.SetViewMetaChars(bSet); break; //"NonprintingCharacter/MetaCharacters"
+ case 7: m_rParent.SetParagraph(bSet); break;// "NonprintingCharacter/ParagraphEnd",
+ case 8: m_rParent.SetSoftHyph(bSet); break;// "NonprintingCharacter/OptionalHyphen",
+ case 9: m_rParent.SetBlank(bSet); break;// "NonprintingCharacter/Space",
+ case 10: m_rParent.SetLineBreak(bSet);break;// "NonprintingCharacter/Break",
+ case 11: m_rParent.SetHardBlank(bSet); break;// "NonprintingCharacter/ProtectedSpace",
+ case 12: m_rParent.SetTab(bSet); break;// "NonprintingCharacter/Tab",
+ case 13: m_rParent.SetShowHiddenField(bSet); break;// "NonprintingCharacter/Fields: HiddenText",
+ case 14: m_rParent.SetShowHiddenPara(bSet); break;// "NonprintingCharacter/Fields: HiddenParagraph",
+ case 15: m_rParent.SetShowHiddenChar(bSet); break;// "NonprintingCharacter/HiddenCharacter",
+ case 16: m_rParent.SetShowBookmarks(bSet); break;// "NonprintingCharacter/Bookmarks",
+ case 17:
+ {
+ sal_Int32 nSet = 0;
+ pValues[nProp] >>= nSet;
+ m_rParent.SetUpdateLinkMode(nSet, true);
+ }
+ break;// "Update/Link",
+ case 18: m_rParent.SetUpdateFields(bSet); break;// "Update/Field",
+ case 19: m_rParent.SetUpdateCharts(bSet); break;// "Update/Chart"
+ case 20: m_rParent.SetShowInlineTooltips(bSet); break;// "Display/ShowInlineTooltips"
+ case 21: m_rParent.SetUseHeaderFooterMenu(bSet); break;// "Display/UseHeaderFooterMenu"
+ case 22: m_rParent.SetShowOutlineContentVisibilityButton(bSet); break;// "Display/ShowOutlineContententVisibilityButton"
+ case 23: m_rParent.SetTreatSubOutlineLevelsAsContent(bSet); break;// "Display/TreatSubOutlineLevelsAsContent"
+ case 24: m_rParent.SetShowChangesInMargin(bSet); break;// "Display/ShowChangesInMargin"
+ case 25:
+ {
+ sal_Int32 nSet = 0;
+ pValues[nProp] >>= nSet;
+ m_rParent.SetDefaultAnchor(nSet);
+ }
+ break; // "Display/DefaultAnchor"
+ }
+ }
+ }
+}
+
+Sequence<OUString> SwLayoutViewConfig::GetPropertyNames() const
+{
+ static const char* aPropNames[] =
+ {
+ "Line/Guide", // 0
+ "Window/HorizontalScroll", // 1
+ "Window/VerticalScroll", // 2
+ "Window/ShowRulers", // 3
+ "Window/HorizontalRuler", // 4
+ "Window/VerticalRuler", // 5
+ "Window/HorizontalRulerUnit", // 6
+ "Window/VerticalRulerUnit", // 7
+ "Window/SmoothScroll", // 8
+ "Zoom/Value", // 9
+ "Zoom/Type", //10
+ "Other/IsAlignMathObjectsToBaseline", //11
+ "Other/MeasureUnit", //12
+ // below properties are not available in WriterWeb
+ "Other/TabStop", //13
+ "Window/IsVerticalRulerRight", //14
+ "ViewLayout/Columns", //15
+ "ViewLayout/BookMode", //16
+ "Other/IsSquaredPageMode", //17
+ "Other/ApplyCharUnit", //18
+ "Window/ShowScrollBarTips", //19
+ };
+ const int nCount = m_bWeb ? 13 : 20;
+ Sequence<OUString> aNames(nCount);
+ OUString* pNames = aNames.getArray();
+ for(int i = 0; i < nCount; i++)
+ {
+ pNames[i] = OUString::createFromAscii(aPropNames[i]);
+ }
+ return aNames;
+}
+
+SwLayoutViewConfig::SwLayoutViewConfig(bool bIsWeb, SwMasterUsrPref& rPar) :
+ ConfigItem(bIsWeb ? OUString("Office.WriterWeb/Layout") : OUString("Office.Writer/Layout"),
+ ConfigItemMode::ReleaseTree),
+ m_rParent(rPar),
+ m_bWeb(bIsWeb)
+{
+}
+
+SwLayoutViewConfig::~SwLayoutViewConfig()
+{
+}
+
+void SwLayoutViewConfig::ImplCommit()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ Any &rVal = pValues[nProp];
+ switch(nProp)
+ {
+ case 0: rVal <<= m_rParent.IsCrossHair(); break; // "Line/Guide",
+ case 1: rVal <<= m_rParent.IsViewHScrollBar(); break; // "Window/HorizontalScroll",
+ case 2: rVal <<= m_rParent.IsViewVScrollBar(); break; // "Window/VerticalScroll",
+ case 3: rVal <<= m_rParent.IsViewAnyRuler(); break; // "Window/ShowRulers"
+ // #i14593# use IsView*Ruler(true) instead of IsView*Ruler()
+ // this preserves the single ruler states even if "Window/ShowRulers" is off
+ case 4: rVal <<= m_rParent.IsViewHRuler(true); break; // "Window/HorizontalRuler",
+ case 5: rVal <<= m_rParent.IsViewVRuler(true); break; // "Window/VerticalRuler",
+ case 6:
+ if(m_rParent.m_bIsHScrollMetricSet)
+ rVal <<= static_cast<sal_Int32>(m_rParent.m_eHScrollMetric); // "Window/HorizontalRulerUnit"
+ break;
+ case 7:
+ if(m_rParent.m_bIsVScrollMetricSet)
+ rVal <<= static_cast<sal_Int32>(m_rParent.m_eVScrollMetric); // "Window/VerticalRulerUnit"
+ break;
+ case 8: rVal <<= m_rParent.IsSmoothScroll(); break; // "Window/SmoothScroll",
+ case 9: rVal <<= static_cast<sal_Int32>(m_rParent.GetZoom()); break; // "Zoom/Value",
+ case 10: rVal <<= static_cast<sal_Int32>(m_rParent.GetZoomType()); break; // "Zoom/Type",
+ case 11: rVal <<= m_rParent.IsAlignMathObjectsToBaseline(); break; // "Other/IsAlignMathObjectsToBaseline"
+ case 12: rVal <<= static_cast<sal_Int32>(m_rParent.GetMetric()); break; // "Other/MeasureUnit",
+ case 13: rVal <<= m_rParent.GetDefTabInMm100(); break;// "Other/TabStop",
+ case 14: rVal <<= m_rParent.IsVRulerRight(); break; // "Window/IsVerticalRulerRight",
+ case 15: rVal <<= static_cast<sal_Int32>(m_rParent.GetViewLayoutColumns()); break; // "ViewLayout/Columns",
+ case 16: rVal <<= m_rParent.IsViewLayoutBookMode(); break; // "ViewLayout/BookMode",
+ case 17: rVal <<= m_rParent.IsSquaredPageMode(); break; // "Other/IsSquaredPageMode",
+ case 18: rVal <<= m_rParent.IsApplyCharUnit(); break; // "Other/ApplyCharUnit",
+ case 19: rVal <<= m_rParent.IsShowScrollBarTips(); break; // "Window/ShowScrollBarTips",
+ }
+ }
+ PutProperties(aNames, aValues);
+}
+
+void SwLayoutViewConfig::Load()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ const Any* pValues = aValues.getConstArray();
+ OSL_ENSURE(aValues.getLength() == aNames.getLength(), "GetProperties failed");
+ if(aValues.getLength() != aNames.getLength())
+ return;
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ if(pValues[nProp].hasValue())
+ {
+ sal_Int32 nInt32Val = 0;
+ bool bSet = false;
+ pValues[nProp] >>= nInt32Val;
+ pValues[nProp] >>= bSet;
+
+ switch(nProp)
+ {
+ case 0: m_rParent.SetCrossHair(bSet); break;// "Line/Guide",
+ case 1: m_rParent.SetViewHScrollBar(bSet); break;// "Window/HorizontalScroll",
+ case 2: m_rParent.SetViewVScrollBar(bSet); break;// "Window/VerticalScroll",
+ case 3: m_rParent.SetViewAnyRuler(bSet);break; // "Window/ShowRulers"
+ case 4: m_rParent.SetViewHRuler(bSet); break;// "Window/HorizontalRuler",
+ case 5: m_rParent.SetViewVRuler(bSet); break;// "Window/VerticalRuler",
+ case 6:
+ {
+ m_rParent.m_bIsHScrollMetricSet = true;
+ m_rParent.m_eHScrollMetric = static_cast<FieldUnit>(nInt32Val); // "Window/HorizontalRulerUnit"
+ }
+ break;
+ case 7:
+ {
+ m_rParent.m_bIsVScrollMetricSet = true;
+ m_rParent.m_eVScrollMetric = static_cast<FieldUnit>(nInt32Val); // "Window/VerticalRulerUnit"
+ }
+ break;
+ case 8: m_rParent.SetSmoothScroll(bSet); break;// "Window/SmoothScroll",
+ case 9: m_rParent.SetZoom( static_cast< sal_uInt16 >(nInt32Val) ); break;// "Zoom/Value",
+ case 10: m_rParent.SetZoomType( static_cast< SvxZoomType >(nInt32Val) ); break;// "Zoom/Type",
+ case 11: m_rParent.SetAlignMathObjectsToBaseline(bSet, true); break;// "Other/IsAlignMathObjectsToBaseline"
+ case 12: m_rParent.SetMetric(static_cast<FieldUnit>(nInt32Val), true); break;// "Other/MeasureUnit",
+ case 13: m_rParent.SetDefTabInMm100(nInt32Val, true); break;// "Other/TabStop",
+ case 14: m_rParent.SetVRulerRight(bSet); break;// "Window/IsVerticalRulerRight",
+ case 15: m_rParent.SetViewLayoutColumns( o3tl::narrowing<sal_uInt16>(nInt32Val) ); break;// "ViewLayout/Columns",
+ case 16: m_rParent.SetViewLayoutBookMode(bSet); break;// "ViewLayout/BookMode",
+ case 17: m_rParent.SetDefaultPageMode(bSet,true); break;// "Other/IsSquaredPageMode",
+ case 18: m_rParent.SetApplyCharUnit(bSet, true); break;// "Other/ApplyUserChar"
+ case 19: m_rParent.SetShowScrollBarTips(bSet); break;// "Window/ShowScrollBarTips",
+ }
+ }
+ }
+}
+
+void SwLayoutViewConfig::Notify( const css::uno::Sequence< OUString >& ) {}
+
+Sequence<OUString> SwGridConfig::GetPropertyNames()
+{
+ static const char* aPropNames[] =
+ {
+ "Option/SnapToGrid", // 0
+ "Option/VisibleGrid", // 1
+ "Option/Synchronize", // 2
+ "Resolution/XAxis", // 3
+ "Resolution/YAxis", // 4
+ "Subdivision/XAxis", // 5
+ "Subdivision/YAxis" // 6
+ };
+ const int nCount = 7;
+ Sequence<OUString> aNames(nCount);
+ OUString* pNames = aNames.getArray();
+ for(int i = 0; i < nCount; i++)
+ {
+ pNames[i] = OUString::createFromAscii(aPropNames[i]);
+ }
+ return aNames;
+}
+
+SwGridConfig::SwGridConfig(bool bIsWeb, SwMasterUsrPref& rPar) :
+ ConfigItem(bIsWeb ? OUString("Office.WriterWeb/Grid") : OUString("Office.Writer/Grid"),
+ ConfigItemMode::ReleaseTree),
+ m_rParent(rPar)
+{
+}
+
+SwGridConfig::~SwGridConfig()
+{
+}
+
+void SwGridConfig::ImplCommit()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case 0: pValues[nProp] <<= m_rParent.IsSnap(); break;// "Option/SnapToGrid",
+ case 1: pValues[nProp] <<= m_rParent.IsGridVisible(); break;//"Option/VisibleGrid",
+ case 2: pValues[nProp] <<= m_rParent.IsSynchronize(); break;// "Option/Synchronize",
+ case 3: pValues[nProp] <<= static_cast<sal_Int32>(convertTwipToMm100(m_rParent.GetSnapSize().Width())); break;// "Resolution/XAxis",
+ case 4: pValues[nProp] <<= static_cast<sal_Int32>(convertTwipToMm100(m_rParent.GetSnapSize().Height())); break;// "Resolution/YAxis",
+ case 5: pValues[nProp] <<= static_cast<sal_Int16>(m_rParent.GetDivisionX()); break;// "Subdivision/XAxis",
+ case 6: pValues[nProp] <<= static_cast<sal_Int16>(m_rParent.GetDivisionY()); break;// "Subdivision/YAxis"
+ }
+ }
+ PutProperties(aNames, aValues);
+}
+
+void SwGridConfig::Load()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ const Any* pValues = aValues.getConstArray();
+ OSL_ENSURE(aValues.getLength() == aNames.getLength(), "GetProperties failed");
+ if(aValues.getLength() != aNames.getLength())
+ return;
+
+ Size aSnap(m_rParent.GetSnapSize());
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ if(pValues[nProp].hasValue())
+ {
+ bool bSet = nProp < 3 && *o3tl::doAccess<bool>(pValues[nProp]);
+ sal_Int32 nSet = 0;
+ if(nProp >= 3)
+ pValues[nProp] >>= nSet;
+ switch(nProp)
+ {
+ case 0: m_rParent.SetSnap(bSet); break;// "Option/SnapToGrid",
+ case 1: m_rParent.SetGridVisible(bSet); break;//"Option/VisibleGrid",
+ case 2: m_rParent.SetSynchronize(bSet); break;// "Option/Synchronize",
+ case 3: aSnap.setWidth( o3tl::toTwips(nSet, o3tl::Length::mm100) ); break;// "Resolution/XAxis",
+ case 4: aSnap.setHeight( o3tl::toTwips(nSet, o3tl::Length::mm100) ); break;// "Resolution/YAxis",
+ case 5: m_rParent.SetDivisionX(static_cast<short>(nSet)); break;// "Subdivision/XAxis",
+ case 6: m_rParent.SetDivisionY(static_cast<short>(nSet)); break;// "Subdivision/YAxis"
+ }
+ }
+ }
+ m_rParent.SetSnapSize(aSnap);
+}
+
+void SwGridConfig::Notify( const css::uno::Sequence< OUString >& ) {}
+
+Sequence<OUString> SwCursorConfig::GetPropertyNames()
+{
+ static const char* aPropNames[] =
+ {
+ "DirectCursor/UseDirectCursor", // 0
+ "DirectCursor/Insert", // 1
+ "Option/ProtectedArea", // 2
+ };
+ const int nCount = SAL_N_ELEMENTS(aPropNames);
+ Sequence<OUString> aNames(nCount);
+ OUString* pNames = aNames.getArray();
+ for(int i = 0; i < nCount; i++)
+ pNames[i] = OUString::createFromAscii(aPropNames[i]);
+ return aNames;
+}
+
+SwCursorConfig::SwCursorConfig(SwMasterUsrPref& rPar) :
+ ConfigItem("Office.Writer/Cursor", ConfigItemMode::ReleaseTree),
+ m_rParent(rPar)
+{
+}
+
+SwCursorConfig::~SwCursorConfig()
+{
+}
+
+void SwCursorConfig::ImplCommit()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case 0: pValues[nProp] <<= m_rParent.IsShadowCursor(); break; // "DirectCursor/UseDirectCursor",
+ case 1: pValues[nProp] <<= static_cast<sal_Int32>(m_rParent.GetShdwCursorFillMode()); break; // "DirectCursor/Insert",
+ case 2: pValues[nProp] <<= m_rParent.IsCursorInProtectedArea(); break; // "Option/ProtectedArea"
+ }
+ }
+ PutProperties(aNames, aValues);
+}
+
+void SwCursorConfig::Load()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ const Any* pValues = aValues.getConstArray();
+ OSL_ENSURE(aValues.getLength() == aNames.getLength(), "GetProperties failed");
+ if(aValues.getLength() != aNames.getLength())
+ return;
+
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ if(pValues[nProp].hasValue())
+ {
+ bool bSet = false;
+ sal_Int32 nSet = 0;
+ if(nProp != 1 )
+ bSet = *o3tl::doAccess<bool>(pValues[nProp]);
+ else
+ pValues[nProp] >>= nSet;
+ switch(nProp)
+ {
+ case 0: m_rParent.SetShadowCursor(bSet); break; // "DirectCursor/UseDirectCursor",
+ case 1: m_rParent.SetShdwCursorFillMode(static_cast<SwFillMode>(nSet)); break; // "DirectCursor/Insert",
+ case 2: m_rParent.SetCursorInProtectedArea(bSet); break; // "Option/ProtectedArea"
+ }
+ }
+ }
+}
+
+void SwCursorConfig::Notify( const css::uno::Sequence< OUString >& ) {}
+
+SwWebColorConfig::SwWebColorConfig(SwMasterUsrPref& rPar) :
+ ConfigItem("Office.WriterWeb/Background", ConfigItemMode::ReleaseTree),
+ m_rParent(rPar),
+ m_aPropNames(1)
+{
+ m_aPropNames.getArray()[0] = "Color";
+}
+
+SwWebColorConfig::~SwWebColorConfig()
+{
+}
+
+void SwWebColorConfig::ImplCommit()
+{
+ Sequence<Any> aValues(m_aPropNames.getLength());
+ Any* pValues = aValues.getArray();
+ for(int nProp = 0; nProp < m_aPropNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case 0: pValues[nProp] <<= m_rParent.GetRetoucheColor(); break;// "Color",
+ }
+ }
+ PutProperties(m_aPropNames, aValues);
+}
+
+void SwWebColorConfig::Notify( const css::uno::Sequence< OUString >& ) {}
+
+void SwWebColorConfig::Load()
+{
+ Sequence<Any> aValues = GetProperties(m_aPropNames);
+ const Any* pValues = aValues.getConstArray();
+ OSL_ENSURE(aValues.getLength() == m_aPropNames.getLength(), "GetProperties failed");
+ if(aValues.getLength() != m_aPropNames.getLength())
+ return;
+
+ for(int nProp = 0; nProp < m_aPropNames.getLength(); nProp++)
+ {
+ if(pValues[nProp].hasValue())
+ {
+ switch(nProp)
+ {
+ case 0:
+ Color nSet;
+ pValues[nProp] >>= nSet; m_rParent.SetRetoucheColor(nSet);
+ break;// "Color",
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/config/viewopt.cxx b/sw/source/uibase/config/viewopt.cxx
new file mode 100644
index 0000000000..538efd4a86
--- /dev/null
+++ b/sw/source/uibase/config/viewopt.cxx
@@ -0,0 +1,631 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/htmlmode.hxx>
+#include <svtools/htmlcfg.hxx>
+
+#include <editeng/editids.hrc>
+#include <editeng/svxacorr.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <vcl/outdev.hxx>
+#include <swmodule.hxx>
+#include <viewopt.hxx>
+#include <wdocsh.hxx>
+#include <swrect.hxx>
+#include <viewsh.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <crstate.hxx>
+#include <authratr.hxx>
+#include <svtools/colorcfg.hxx>
+#include <svtools/accessibilityoptions.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/syslocale.hxx>
+
+#include <editeng/acorrcfg.hxx>
+#include <comphelper/lok.hxx>
+#include <comphelper/configurationlistener.hxx>
+
+sal_uInt16 SwViewOption::s_nPixelTwips = 0; // one pixel on the screen
+SwViewColors SwViewOption::s_aInitialColorConfig {};
+
+SwViewColors::SwViewColors() :
+ m_aDocColor(COL_LIGHTGRAY),
+ m_aDocBoundColor(COL_LIGHTGRAY),
+ m_aObjectBoundColor(COL_LIGHTGRAY),
+ m_aAppBackgroundColor(COL_LIGHTGRAY),
+ m_aTableBoundColor(COL_LIGHTGRAY),
+ m_aFontColor(COL_BLACK),
+ m_aIndexShadingsColor(COL_LIGHTGRAY),
+ m_aLinksColor(COL_BLUE),
+ m_aVisitedLinksColor(COL_RED),
+ m_aTextGridColor(COL_LIGHTGRAY),
+ m_aSpellColor(COL_LIGHTRED),
+ m_aGrammarColor(COL_LIGHTBLUE),
+ m_aSmarttagColor(COL_LIGHTMAGENTA),
+ m_aFieldShadingsColor(COL_LIGHTGRAY),
+ m_aSectionBoundColor(COL_LIGHTGRAY),
+ m_aPageBreakColor(COL_BLUE),
+ m_aScriptIndicatorColor(COL_GREEN),
+ m_aShadowColor(COL_GRAY),
+ m_aHeaderFooterMarkColor(COL_BLUE),
+ m_nAppearanceFlags(ViewOptFlags::NONE)
+{}
+
+SwViewColors::SwViewColors(const svtools::ColorConfig& rConfig)
+{
+ m_aDocColor = rConfig.GetColorValue(svtools::DOCCOLOR).nColor;
+
+ svtools::ColorConfigValue aValue = rConfig.GetColorValue(svtools::DOCBOUNDARIES);
+ m_aDocBoundColor = aValue.nColor;
+ m_nAppearanceFlags = ViewOptFlags::NONE;
+ if(aValue.bIsVisible)
+ m_nAppearanceFlags |= ViewOptFlags::DocBoundaries;
+
+ m_aAppBackgroundColor = rConfig.GetColorValue(svtools::APPBACKGROUND).nColor;
+
+ aValue = rConfig.GetColorValue(svtools::OBJECTBOUNDARIES);
+ m_aObjectBoundColor = aValue.nColor;
+ if(aValue.bIsVisible)
+ m_nAppearanceFlags |= ViewOptFlags::ObjectBoundaries;
+
+ aValue = rConfig.GetColorValue(svtools::TABLEBOUNDARIES);
+ m_aTableBoundColor = aValue.nColor;
+ if(aValue.bIsVisible)
+ m_nAppearanceFlags |= ViewOptFlags::TableBoundaries;
+
+ aValue = rConfig.GetColorValue(svtools::WRITERIDXSHADINGS);
+ m_aIndexShadingsColor = aValue.nColor;
+ if(aValue.bIsVisible)
+ m_nAppearanceFlags |= ViewOptFlags::IndexShadings;
+
+ aValue = rConfig.GetColorValue(svtools::LINKS);
+ m_aLinksColor = aValue.nColor;
+ if(aValue.bIsVisible)
+ m_nAppearanceFlags |= ViewOptFlags::Links;
+
+ aValue = rConfig.GetColorValue(svtools::LINKSVISITED);
+ m_aVisitedLinksColor = aValue.nColor;
+ if(aValue.bIsVisible)
+ m_nAppearanceFlags |= ViewOptFlags::VisitedLinks;
+
+ aValue = rConfig.GetColorValue(svtools::SHADOWCOLOR);
+ m_aShadowColor = aValue.nColor;
+ if(aValue.bIsVisible)
+ m_nAppearanceFlags |= ViewOptFlags::Shadow;
+
+ m_aTextGridColor = rConfig.GetColorValue(svtools::WRITERTEXTGRID).nColor;
+
+ m_aSpellColor = rConfig.GetColorValue(svtools::SPELL).nColor;
+ m_aGrammarColor = rConfig.GetColorValue(svtools::GRAMMAR).nColor;
+
+ m_aSmarttagColor = rConfig.GetColorValue(svtools::SMARTTAGS).nColor;
+
+ m_aFontColor = rConfig.GetColorValue(svtools::FONTCOLOR).nColor;
+
+ aValue = rConfig.GetColorValue(svtools::WRITERFIELDSHADINGS);
+ m_aFieldShadingsColor = aValue.nColor;
+ // as in initializeForTiledRendering we don't want to enable
+ // field shadings for the online case
+ if (aValue.bIsVisible && !comphelper::LibreOfficeKit::isActive())
+ m_nAppearanceFlags |= ViewOptFlags::FieldShadings;
+
+ aValue = rConfig.GetColorValue(svtools::WRITERSECTIONBOUNDARIES);
+ m_aSectionBoundColor = aValue.nColor;
+ if(aValue.bIsVisible)
+ m_nAppearanceFlags |= ViewOptFlags::SectionBoundaries;
+
+ aValue = rConfig.GetColorValue(svtools::WRITERPAGEBREAKS);
+ m_aPageBreakColor = aValue.nColor;
+
+ aValue = rConfig.GetColorValue(svtools::WRITERHEADERFOOTERMARK);
+ m_aHeaderFooterMarkColor = aValue.nColor;
+
+ m_aScriptIndicatorColor = rConfig.GetColorValue(svtools::WRITERSCRIPTINDICATOR).nColor;
+}
+
+bool SwViewOption::IsEqualFlags( const SwViewOption &rOpt ) const
+{
+ return m_nCoreOptions == rOpt.m_nCoreOptions
+ && m_nCore2Options == rOpt.m_nCore2Options
+ && m_aSnapSize == rOpt.m_aSnapSize
+ && mnViewLayoutColumns == rOpt.mnViewLayoutColumns
+ && m_nDivisionX == rOpt.GetDivisionX()
+ && m_nDivisionY == rOpt.GetDivisionY()
+ && m_nPagePreviewRow == rOpt.GetPagePrevRow()
+ && m_nPagePreviewCol == rOpt.GetPagePrevCol()
+ && m_aRetouchColor == rOpt.GetRetoucheColor()
+ && mbFormView == rOpt.IsFormView()
+ && mbBrowseMode == rOpt.getBrowseMode()
+ && mbViewLayoutBookMode == rOpt.mbViewLayoutBookMode
+ && mbHideWhitespaceMode == rOpt.mbHideWhitespaceMode
+ && m_bShowPlaceHolderFields == rOpt.m_bShowPlaceHolderFields
+ && m_bIdle == rOpt.m_bIdle
+ && m_nDefaultAnchor == rOpt.m_nDefaultAnchor
+#ifdef DBG_UTIL
+ // correspond to the statements in ui/config/cfgvw.src
+ && m_bTest1 == rOpt.IsTest1()
+ && m_bTest2 == rOpt.IsTest2()
+ && m_bTest3 == rOpt.IsTest3()
+ && m_bTest4 == rOpt.IsTest4()
+ && m_bTest5 == rOpt.IsTest5()
+ && m_bTest6 == rOpt.IsTest6()
+ && m_bTest7 == rOpt.IsTest7()
+ && m_bTest8 == rOpt.IsTest8()
+ && m_bTest10 == rOpt.IsTest10()
+#endif
+ ;
+}
+
+bool SwViewOption::IsShowOutlineContentVisibilityButton() const
+{
+ return m_nCoreOptions.bShowOutlineContentVisibilityButton;
+}
+
+bool SwViewOption::IsTreatSubOutlineLevelsAsContent() const
+{
+ return m_nCoreOptions.bTreatSubOutlineLevelsAsContent;
+}
+
+bool SwViewOption::IsShowHiddenChar(bool bHard) const
+{
+ bool bCharHidden = comphelper::LibreOfficeKit::isActive() ? true : m_nCoreOptions.bCharHidden;
+ return !m_bReadonly && bCharHidden && (m_nCoreOptions.bViewMetachars || bHard);
+}
+
+void SwViewOption::DrawRect( OutputDevice *pOut,
+ const SwRect &rRect, ::Color nCol )
+{
+ if ( pOut->GetOutDevType() != OUTDEV_PRINTER )
+ {
+ const Color aCol( nCol );
+ const Color aOldColor( pOut->GetFillColor() );
+ pOut->SetFillColor( aCol );
+ pOut->DrawRect( rRect.SVRect() );
+ pOut->SetFillColor( aOldColor );
+ }
+ else
+ DrawRectPrinter( pOut, rRect );
+}
+
+void SwViewOption::DrawRectPrinter( OutputDevice *pOut,
+ const SwRect &rRect )
+{
+ Color aOldColor(pOut->GetLineColor());
+ Color aOldFillColor( pOut->GetFillColor() );
+ pOut->SetLineColor( COL_BLACK );
+ pOut->SetFillColor( COL_TRANSPARENT);
+ pOut->DrawRect( rRect.SVRect() );
+ pOut->SetFillColor( aOldFillColor );
+ pOut->SetLineColor( aOldColor );
+}
+
+sal_uInt16 SwViewOption::GetPostItsWidth( const OutputDevice *pOut )
+{
+ assert(pOut && "no Outdev");
+ return sal_uInt16(pOut->GetTextWidth(" "));
+}
+
+void SwViewOption::PaintPostIts( OutputDevice *pOut, const SwRect &rRect, bool bIsScript ) const
+{
+ if( !(pOut && bIsScript) )
+ return;
+
+ Color aOldLineColor( pOut->GetLineColor() );
+ pOut->SetLineColor( COL_GRAY );
+ // to make it look nice, we subtract two pixels everywhere
+ sal_uInt16 nPix = s_nPixelTwips * 2;
+ if( rRect.Width() <= 2 * nPix || rRect.Height() <= 2 * nPix )
+ nPix = 0;
+ const Point aTopLeft( rRect.Left() + nPix, rRect.Top() + nPix );
+ const Point aBotRight( rRect.Right() - nPix, rRect.Bottom() - nPix );
+ const SwRect aRect( aTopLeft, aBotRight );
+ DrawRect( pOut, aRect, m_aColorConfig.m_aScriptIndicatorColor );
+ pOut->SetLineColor( aOldLineColor );
+}
+
+SwViewOption::SwViewOption() :
+ m_sThemeName( "Default" ),
+ m_sSymbolFont( "symbol" ),
+ m_aRetouchColor( COL_TRANSPARENT ),
+ mnViewLayoutColumns( 0 ),
+ m_nPagePreviewRow( 1 ),
+ m_nPagePreviewCol( 2 ),
+ m_nShadowCursorFillMode( SwFillMode::Tab ),
+ m_bReadonly(false),
+ m_bStarOneSetting(false),
+ m_bIsPagePreview(false),
+ m_bSelectionInReadonly(false),
+ mbFormView(false),
+ mbBrowseMode(false),
+ mbBookView(false),
+ mbViewLayoutBookMode(false),
+ mbHideWhitespaceMode(false),
+ m_bShowPlaceHolderFields( true ),
+ m_nZoom( 100 ),
+ m_eZoom( SvxZoomType::PERCENT ),
+ m_nTableDestination(TBL_DEST_CELL)
+{
+ m_nCore2Options =
+ ViewOptCoreFlags2::BlackFont |
+ ViewOptCoreFlags2::HiddenPara;
+
+ m_nUIOptions =
+ ViewOptFlags2::Modified |
+ ViewOptFlags2::GrfKeepZoom |
+ ViewOptFlags2::ResolvedPostits |
+ ViewOptFlags2::AnyRuler;
+
+ if (!utl::ConfigManager::IsFuzzing() && MeasurementSystem::Metric != SvtSysLocale().GetLocaleData().getMeasurementSystemEnum())
+ {
+ m_aSnapSize.setWidth(720); // 1/2"
+ m_aSnapSize.setHeight(720); // 1/2"
+
+ }
+ else
+ {
+ m_aSnapSize.setWidth(567); // 1 cm
+ m_aSnapSize.setHeight(567); // 1 cm
+ }
+ m_nDivisionX = m_nDivisionY = 1;
+
+ m_bSelectionInReadonly = utl::ConfigManager::IsFuzzing() || SvtAccessibilityOptions::IsSelectionInReadonly();
+
+ m_bIdle = true;
+
+ m_nDefaultAnchor = 1; //FLY_TO_CHAR
+
+ // tdf#135266 - tox dialog: remember last used entry level depending on the index type
+ m_nTocEntryLvl = 0;
+ m_nIdxEntryLvl = 1;
+
+#ifdef DBG_UTIL
+ // correspond to the statements in ui/config/cfgvw.src
+ m_bTest1 = m_bTest2 = m_bTest3 = m_bTest4 =
+ m_bTest5 = m_bTest6 = m_bTest7 = m_bTest8 = m_bTest10 = false;
+#endif
+ m_aColorConfig = s_aInitialColorConfig;
+ if (comphelper::LibreOfficeKit::isActive())
+ m_aColorConfig.m_aAppBackgroundColor = COL_TRANSPARENT;
+}
+
+SwViewOption::SwViewOption(const SwViewOption& rVOpt)
+{
+ m_bReadonly = false;
+ m_bSelectionInReadonly = false;
+ // #114856# Form view
+ m_sThemeName = rVOpt.m_sThemeName;
+ mbFormView = rVOpt.mbFormView;
+ m_nZoom = rVOpt.m_nZoom ;
+ m_aSnapSize = rVOpt.m_aSnapSize ;
+ mnViewLayoutColumns = rVOpt.mnViewLayoutColumns ;
+ m_nDivisionX = rVOpt.m_nDivisionX ;
+ m_nDivisionY = rVOpt.m_nDivisionY ;
+ m_nPagePreviewRow = rVOpt.m_nPagePreviewRow;
+ m_nPagePreviewCol = rVOpt.m_nPagePreviewCol;
+ m_bIsPagePreview = rVOpt.m_bIsPagePreview;
+ m_eZoom = rVOpt.m_eZoom ;
+ m_nTableDestination = rVOpt.m_nTableDestination ;
+ m_nUIOptions = rVOpt.m_nUIOptions ;
+ m_nCoreOptions = rVOpt.m_nCoreOptions ;
+ m_nCore2Options = rVOpt.m_nCore2Options ;
+ m_aRetouchColor = rVOpt.GetRetoucheColor();
+ m_sSymbolFont = rVOpt.m_sSymbolFont;
+ m_nShadowCursorFillMode = rVOpt.m_nShadowCursorFillMode;
+ m_bStarOneSetting = rVOpt.m_bStarOneSetting;
+ mbBookView = rVOpt.mbBookView;
+ mbBrowseMode = rVOpt.mbBrowseMode;
+ mbViewLayoutBookMode = rVOpt.mbViewLayoutBookMode;
+ mbHideWhitespaceMode = rVOpt.mbHideWhitespaceMode;
+ m_bShowPlaceHolderFields = rVOpt.m_bShowPlaceHolderFields;
+ m_bIdle = rVOpt.m_bIdle;
+ m_nDefaultAnchor = rVOpt.m_nDefaultAnchor;
+ m_nTocEntryLvl = rVOpt.m_nTocEntryLvl;
+ m_nIdxEntryLvl = rVOpt.m_nIdxEntryLvl;
+ m_aColorConfig = rVOpt.m_aColorConfig;
+
+#ifdef DBG_UTIL
+ m_bTest1 = rVOpt.m_bTest1;
+ m_bTest2 = rVOpt.m_bTest2;
+ m_bTest3 = rVOpt.m_bTest3;
+ m_bTest4 = rVOpt.m_bTest4;
+ m_bTest5 = rVOpt.m_bTest5;
+ m_bTest6 = rVOpt.m_bTest6;
+ m_bTest7 = rVOpt.m_bTest7;
+ m_bTest8 = rVOpt.m_bTest8;
+ m_bTest10 = rVOpt.m_bTest10;
+#endif
+}
+
+SwViewOption& SwViewOption::operator=( const SwViewOption &rVOpt )
+{
+ // #114856# Form view
+ m_sThemeName = rVOpt.m_sThemeName;
+ mbFormView = rVOpt.mbFormView ;
+ m_nZoom = rVOpt.m_nZoom ;
+ m_aSnapSize = rVOpt.m_aSnapSize ;
+ mnViewLayoutColumns = rVOpt.mnViewLayoutColumns ;
+ m_nDivisionX = rVOpt.m_nDivisionX ;
+ m_nDivisionY = rVOpt.m_nDivisionY ;
+ m_nPagePreviewRow = rVOpt.m_nPagePreviewRow;
+ m_nPagePreviewCol = rVOpt.m_nPagePreviewCol;
+ m_bIsPagePreview = rVOpt.m_bIsPagePreview;
+ m_eZoom = rVOpt.m_eZoom ;
+ m_nTableDestination = rVOpt.m_nTableDestination ;
+ m_nUIOptions = rVOpt.m_nUIOptions ;
+ m_nCoreOptions = rVOpt.m_nCoreOptions;
+ m_nCore2Options = rVOpt.m_nCore2Options;
+ m_aRetouchColor = rVOpt.GetRetoucheColor();
+ m_sSymbolFont = rVOpt.m_sSymbolFont;
+ m_nShadowCursorFillMode = rVOpt.m_nShadowCursorFillMode;
+ m_bStarOneSetting = rVOpt.m_bStarOneSetting;
+ mbBookView = rVOpt.mbBookView;
+ mbBrowseMode = rVOpt.mbBrowseMode;
+ mbViewLayoutBookMode = rVOpt.mbViewLayoutBookMode;
+ mbHideWhitespaceMode = rVOpt.mbHideWhitespaceMode;
+ m_bShowPlaceHolderFields = rVOpt.m_bShowPlaceHolderFields;
+ m_bIdle = rVOpt.m_bIdle;
+ m_nDefaultAnchor = rVOpt.m_nDefaultAnchor;
+ m_aColorConfig = rVOpt.m_aColorConfig;
+
+#ifdef DBG_UTIL
+ m_bTest1 = rVOpt.m_bTest1;
+ m_bTest2 = rVOpt.m_bTest2;
+ m_bTest3 = rVOpt.m_bTest3;
+ m_bTest4 = rVOpt.m_bTest4;
+ m_bTest5 = rVOpt.m_bTest5;
+ m_bTest6 = rVOpt.m_bTest6;
+ m_bTest7 = rVOpt.m_bTest7;
+ m_bTest8 = rVOpt.m_bTest8;
+ m_bTest10 = rVOpt.m_bTest10;
+#endif
+ return *this;
+}
+
+SwViewOption::~SwViewOption()
+{
+}
+
+void SwViewOption::Init(const OutputDevice* pWin)
+{
+ if( !s_nPixelTwips && pWin )
+ {
+ s_nPixelTwips = o3tl::narrowing<sal_uInt16>(pWin->PixelToLogic( Size(1,1) ).Height());
+ }
+}
+
+bool SwViewOption::IsAutoCompleteWords()
+{
+ const SvxSwAutoFormatFlags& rFlags = SvxAutoCorrCfg::Get().GetAutoCorrect()->GetSwFlags();
+ return rFlags.bAutoCmpltCollectWords;
+}
+
+AuthorCharAttr::AuthorCharAttr() :
+ m_nItemId (SID_ATTR_CHAR_UNDERLINE),
+ m_nAttr (LINESTYLE_SINGLE),
+ m_nColor (COL_TRANSPARENT)
+{
+}
+
+sal_uInt16 GetHtmlMode(const SwDocShell* pShell)
+{
+ sal_uInt16 nRet = 0;
+ if(!pShell || dynamic_cast<const SwWebDocShell*>( pShell) )
+ {
+ nRet = HTMLMODE_ON | HTMLMODE_SOME_STYLES;
+ switch ( SvxHtmlOptions::GetExportMode() )
+ {
+ case HTML_CFG_MSIE:
+ nRet |= HTMLMODE_FULL_STYLES;
+ break;
+ case HTML_CFG_NS40:
+ // no special features for this browser
+ break;
+ case HTML_CFG_WRITER:
+ nRet |= HTMLMODE_FULL_STYLES;
+ break;
+ }
+ }
+ return nRet;
+}
+
+RndStdIds SwViewOption::GetDefaultAnchorType() const
+{
+ switch ( m_nDefaultAnchor )
+ {
+ case 0:
+ return RndStdIds::FLY_AT_PARA; //0
+ case 1:
+ return RndStdIds::FLY_AT_CHAR; //4
+ case 2:
+ return RndStdIds::FLY_AS_CHAR; //1
+ default:
+ return RndStdIds::FLY_AT_CHAR; //4
+ }//switch
+}
+
+const Color& SwViewOption::GetDocColor() const
+{
+ return m_aColorConfig.m_aDocColor;
+}
+
+const Color& SwViewOption::GetDocBoundariesColor() const
+{
+ return m_aColorConfig.m_aDocBoundColor;
+}
+
+const Color& SwViewOption::GetObjectBoundariesColor() const
+{
+ return m_aColorConfig.m_aObjectBoundColor;
+}
+
+const Color& SwViewOption::GetAppBackgroundColor() const
+{
+ return m_aColorConfig.m_aAppBackgroundColor;
+}
+
+const Color& SwViewOption::GetTableBoundariesColor() const
+{
+ return m_aColorConfig.m_aTableBoundColor;
+}
+
+const Color& SwViewOption::GetIndexShadingsColor() const
+{
+ return m_aColorConfig.m_aIndexShadingsColor;
+}
+
+const Color& SwViewOption::GetLinksColor() const
+{
+ return m_aColorConfig.m_aLinksColor;
+}
+
+const Color& SwViewOption::GetVisitedLinksColor() const
+{
+ return m_aColorConfig.m_aVisitedLinksColor;
+}
+
+const Color& SwViewOption::GetTextGridColor() const
+{
+ return m_aColorConfig.m_aTextGridColor;
+}
+
+const Color& SwViewOption::GetSpellColor() const
+{
+ return m_aColorConfig.m_aSpellColor;
+}
+
+const Color& SwViewOption::GetGrammarColor() const
+{
+ return m_aColorConfig.m_aGrammarColor;
+}
+
+const Color& SwViewOption::GetSmarttagColor() const
+{
+ return m_aColorConfig.m_aSmarttagColor;
+}
+
+const Color& SwViewOption::GetShadowColor() const
+{
+ return m_aColorConfig.m_aShadowColor;
+}
+
+const Color& SwViewOption::GetFontColor() const
+{
+ return m_aColorConfig.m_aFontColor;
+}
+
+const Color& SwViewOption::GetFieldShadingsColor() const
+{
+ return m_aColorConfig.m_aFieldShadingsColor;
+}
+
+const Color& SwViewOption::GetSectionBoundColor() const
+{
+ return m_aColorConfig.m_aSectionBoundColor;
+}
+
+const Color& SwViewOption::GetPageBreakColor() const
+{
+ return m_aColorConfig.m_aPageBreakColor;
+}
+
+const Color& SwViewOption::GetHeaderFooterMarkColor() const
+{
+ return m_aColorConfig.m_aHeaderFooterMarkColor;
+}
+
+void SwViewOption::SetAppearanceFlag(ViewOptFlags nFlag, bool bSet, bool bSaveInConfig )
+{
+ if(bSet)
+ m_aColorConfig.m_nAppearanceFlags |= nFlag;
+ else
+ m_aColorConfig.m_nAppearanceFlags &= ~nFlag;
+ if(!bSaveInConfig)
+ return;
+
+ //create an editable svtools::ColorConfig and store the change
+ svtools::EditableColorConfig aEditableConfig;
+ struct FlagToConfig_Impl
+ {
+ ViewOptFlags nFlag;
+ svtools::ColorConfigEntry eEntry;
+ };
+ static const FlagToConfig_Impl aFlags[] =
+ {
+ { ViewOptFlags::DocBoundaries , svtools::DOCBOUNDARIES },
+ { ViewOptFlags::ObjectBoundaries , svtools::OBJECTBOUNDARIES },
+ { ViewOptFlags::TableBoundaries , svtools::TABLEBOUNDARIES },
+ { ViewOptFlags::IndexShadings , svtools::WRITERIDXSHADINGS },
+ { ViewOptFlags::Links , svtools::LINKS },
+ { ViewOptFlags::VisitedLinks , svtools::LINKSVISITED },
+ { ViewOptFlags::FieldShadings , svtools::WRITERFIELDSHADINGS },
+ { ViewOptFlags::SectionBoundaries , svtools::WRITERSECTIONBOUNDARIES },
+ { ViewOptFlags::Shadow , svtools::SHADOWCOLOR },
+ { ViewOptFlags::NONE , svtools::ColorConfigEntryCount }
+ };
+ sal_uInt16 nPos = 0;
+ while(aFlags[nPos].nFlag != ViewOptFlags::NONE)
+ {
+ if(nFlag & aFlags[nPos].nFlag)
+ {
+ svtools::ColorConfigValue aValue = aEditableConfig.GetColorValue(aFlags[nPos].eEntry);
+ aValue.bIsVisible = bSet;
+ aEditableConfig.SetColorValue(aFlags[nPos].eEntry, aValue);
+ }
+ nPos++;
+ }
+}
+
+bool SwViewOption::IsAppearanceFlag(ViewOptFlags nFlag) const
+{
+ return bool(m_aColorConfig.m_nAppearanceFlags & nFlag);
+}
+
+namespace{
+rtl::Reference<comphelper::ConfigurationListener> const & getWCOptionListener()
+{
+ static rtl::Reference<comphelper::ConfigurationListener> xListener(new comphelper::ConfigurationListener("/org.openoffice.Office.Writer/Cursor/Option"));
+ return xListener;
+}
+}
+
+bool SwViewOption::IsIgnoreProtectedArea()
+{
+ if (utl::ConfigManager::IsFuzzing())
+ return false;
+ static comphelper::ConfigurationListenerProperty<bool> gIgnoreProtectedArea(getWCOptionListener(), "IgnoreProtectedArea");
+ return gIgnoreProtectedArea.get();
+}
+
+const SwViewOption& SwViewOption::GetCurrentViewOptions()
+{
+ SfxViewShell* pCurrentShell = SfxViewShell::Current();
+ SwView* pView = dynamic_cast<SwView*>(pCurrentShell);
+ if(pView)
+ {
+ return *pView->GetWrtShell().GetViewOptions();
+ }
+
+ // Some unit tests don't have a SfxViewShell, so we need to return something
+ static SwViewOption aDefaultViewOptions;
+ return aDefaultViewOptions;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/dbui/README b/sw/source/uibase/dbui/README
new file mode 100644
index 0000000000..ba9745c777
--- /dev/null
+++ b/sw/source/uibase/dbui/README
@@ -0,0 +1,48 @@
+Mail merge (MM) has *four modes*. The modes 1-3 are directly exposed to the
+user via different GUIs. The modes are:
+
+1. FILE = saves the result as documents
+2. PRINTER = directly prints resulting documents
+3. EMAIL = sends results as individual emails
+4. SHELL = returns an internal document shell for further programming
+
+There is one property, which changes the overall behaviour of these modes:
+*bCreateSingleFile*. This is the primary controller of the mail merge source
+code workflow, as it affects all modes!
+
+This also has timing constraints: for individual files the result can be
+defined in advance, while further processing of the single result can just
+be done after the merging. It mainly affects printing and the generation
+of huge (1000+ datasets) combined non-PRINT merge results. A valid
+combined document has to follow constraints, which are already met by
+individual documents, as these are just modified copies.
+
+LO currently has five working combinations of mode and *bCreateSingleFile*
+The others, ''PRINTER+false'', ''EMAIL+true'' and ''SHELL+false'', are currently not
+implemented. But the list contains implementation proposals for them.
+
+* Mode: FILE
+** false: Saves each merged document as an individual file. The file name can
+ be selected from a database column!
+** true: Saves a combined file of concatenated documents. Each document starts
+ with a new / reset page style. Depending on the page style this inserts
+ hidden blank pages
+* Mode: PRINTER
+** false: *not implemented*. This could generate individual print jobs, which could be grouped on some
+ platforms for easier abortion (needs verification!). All print options
+ affect only the individual document! Printing could start after the first
+ document is generated.
+** true: Generates a single print job. All print options affect the combined
+ document! This especially effects the results of reverse and N-UP printing.
+ Printing can just start after all documents are generated.
+* Mode: EMAIL
+** false: Each document can either be used as the email body (html or txt) or
+ be attached to a general email text. The emails are extracted from a DB
+ column, which must be provided!
+** true: *not implemented*. Could send the combined document to a single
+ email address.
+* Mode: SHELL
+** false: *not implemented*. Instead of a single shell this could return a
+ sequence of shells for the individual documents.
+** true: Returns the shell of the generated document. This is mainly
+ interesting for programmers. The document is just generated internally.
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
new file mode 100644
index 0000000000..bb4cdc12cd
--- /dev/null
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -0,0 +1,3298 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <cassert>
+
+#include <unotxdoc.hxx>
+#include <sfx2/app.hxx>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/XDocumentDataSource.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/XEventListener.hpp>
+#include <com/sun/star/uri/UriReferenceFactory.hpp>
+#include <com/sun/star/uri/VndSunStarPkgUrlReferenceFactory.hpp>
+#include <com/sun/star/util/NumberFormatter.hpp>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/sdb/TextConnectionSettings.hpp>
+#include <com/sun/star/sdb/XCompletedConnection.hpp>
+#include <com/sun/star/sdb/XCompletedExecution.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/text/MailMergeEvent.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <vcl/errinf.hxx>
+#include <vcl/print.hxx>
+#include <vcl/scheduler.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <dbconfig.hxx>
+#include <unotools/tempfile.hxx>
+#include <unotools/pathoptions.hxx>
+#include <svl/numformat.hxx>
+#include <svl/zforlist.hxx>
+#include <svl/stritem.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/progress.hxx>
+#include <sfx2/dispatch.hxx>
+#include <cmdid.h>
+#include <swmodule.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <edtwin.hxx>
+#include <wrtsh.hxx>
+#include <fldbas.hxx>
+#include <dbui.hxx>
+#include <dbmgr.hxx>
+#include <doc.hxx>
+#include <IDocumentLinksAdministration.hxx>
+#include <IDocumentFieldsAccess.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <swwait.hxx>
+#include <swunohelper.hxx>
+#include <strings.hrc>
+#include <mmconfigitem.hxx>
+#include <com/sun/star/sdbc/XRowSet.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/sdb/XColumn.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/ResultSetType.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/mail/MailAttachment.hpp>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/property.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <comphelper/string.hxx>
+#include <comphelper/types.hxx>
+#include <mailmergehelper.hxx>
+#include <maildispatcher.hxx>
+#include <svtools/htmlcfg.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <com/sun/star/util/XNumberFormatTypes.hpp>
+#include <svl/numuno.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/dbconversion.hxx>
+#include <unotools/charclass.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <unomailmerge.hxx>
+#include <sfx2/event.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#include <rtl/textenc.h>
+#include <rtl/tencinfo.h>
+#include <cppuhelper/implbase.hxx>
+#include <ndindex.hxx>
+#include <swevent.hxx>
+#include <sal/log.hxx>
+#include <swabstdlg.hxx>
+#include <vector>
+#include <section.hxx>
+#include <rootfrm.hxx>
+#include <calc.hxx>
+#include <dbfld.hxx>
+#include <IDocumentState.hxx>
+#include <imaildsplistener.hxx>
+#include <iodetect.hxx>
+#include <IDocumentDeviceAccess.hxx>
+
+#include <memory>
+#include <mutex>
+#include <comphelper/propertysequence.hxx>
+
+using namespace ::com::sun::star;
+using namespace sw;
+
+namespace {
+
+void lcl_emitEvent(SfxEventHintId nEventId, sal_Int32 nStrId, SfxObjectShell* pDocShell)
+{
+ SfxGetpApp()->NotifyEvent(SfxEventHint(nEventId,
+ SwDocShell::GetEventName(nStrId),
+ pDocShell));
+}
+
+// Construct vnd.sun.star.pkg:// URL
+OUString ConstructVndSunStarPkgUrl(const OUString& rMainURL, std::u16string_view rStreamRelPath)
+{
+ auto xContext(comphelper::getProcessComponentContext());
+ auto xUri = css::uri::UriReferenceFactory::create(xContext)->parse(rMainURL);
+ assert(xUri.is());
+ xUri = css::uri::VndSunStarPkgUrlReferenceFactory::create(xContext)
+ ->createVndSunStarPkgUrlReference(xUri);
+ assert(xUri.is());
+ return xUri->getUriReference() + "/"
+ + INetURLObject::encode(
+ rStreamRelPath, INetURLObject::PART_FPATH,
+ INetURLObject::EncodeMechanism::All);
+}
+
+}
+
+std::vector<std::pair<SwDocShell*, OUString>> SwDBManager::s_aUncommittedRegistrations;
+
+namespace {
+
+enum class SwDBNextRecord { NEXT, FIRST };
+
+}
+
+static bool lcl_ToNextRecord( SwDSParam* pParam, const SwDBNextRecord action = SwDBNextRecord::NEXT );
+
+namespace {
+
+enum class WorkingDocType { SOURCE, TARGET, COPY };
+
+}
+
+static SfxObjectShell* lcl_CreateWorkingDocument(
+ const WorkingDocType aType, const SwWrtShell &rSourceWrtShell,
+ const vcl::Window *pSourceWindow,
+ SwDBManager** const ppDBManager,
+ SwView** const pView, SwWrtShell** const pWrtShell, rtl::Reference<SwDoc>* const pDoc );
+
+static bool lcl_getCountFromResultSet( sal_Int32& rCount, const SwDSParam* pParam )
+{
+ rCount = pParam->aSelection.getLength();
+ if ( rCount > 0 )
+ return true;
+
+ uno::Reference<beans::XPropertySet> xPrSet(pParam->xResultSet, uno::UNO_QUERY);
+ if ( xPrSet.is() )
+ {
+ try
+ {
+ bool bFinal = false;
+ uno::Any aFinal = xPrSet->getPropertyValue("IsRowCountFinal");
+ aFinal >>= bFinal;
+ if(!bFinal)
+ {
+ pParam->xResultSet->last();
+ pParam->xResultSet->first();
+ }
+ uno::Any aCount = xPrSet->getPropertyValue("RowCount");
+ if( aCount >>= rCount )
+ return true;
+ }
+ catch(const uno::Exception&)
+ {
+ }
+ }
+ return false;
+}
+
+class SwDBManager::ConnectionDisposedListener_Impl
+ : public cppu::WeakImplHelper< lang::XEventListener >
+{
+private:
+ SwDBManager * m_pDBManager;
+
+ virtual void SAL_CALL disposing( const lang::EventObject& Source ) override;
+
+public:
+ explicit ConnectionDisposedListener_Impl(SwDBManager& rMgr);
+
+ void Dispose() { m_pDBManager = nullptr; }
+
+};
+
+namespace {
+
+/// Listens to removed data sources, and if it's one that's embedded into this document, triggers embedding removal.
+class SwDataSourceRemovedListener : public cppu::WeakImplHelper<sdb::XDatabaseRegistrationsListener>
+{
+ uno::Reference<sdb::XDatabaseContext> m_xDatabaseContext;
+ SwDBManager* m_pDBManager;
+
+public:
+ explicit SwDataSourceRemovedListener(SwDBManager& rDBManager);
+ virtual ~SwDataSourceRemovedListener() override;
+ virtual void SAL_CALL registeredDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) override;
+ virtual void SAL_CALL revokedDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) override;
+ virtual void SAL_CALL changedDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) override;
+ virtual void SAL_CALL disposing(const lang::EventObject& rObject) override;
+ void Dispose();
+};
+
+}
+
+SwDataSourceRemovedListener::SwDataSourceRemovedListener(SwDBManager& rDBManager)
+ : m_pDBManager(&rDBManager)
+{
+ uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
+ m_xDatabaseContext = sdb::DatabaseContext::create(xComponentContext);
+ m_xDatabaseContext->addDatabaseRegistrationsListener(this);
+}
+
+SwDataSourceRemovedListener::~SwDataSourceRemovedListener()
+{
+ if (m_xDatabaseContext.is())
+ m_xDatabaseContext->removeDatabaseRegistrationsListener(this);
+}
+
+void SAL_CALL SwDataSourceRemovedListener::registeredDatabaseLocation(const sdb::DatabaseRegistrationEvent& /*rEvent*/)
+{
+}
+
+void SAL_CALL SwDataSourceRemovedListener::revokedDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent)
+{
+ if (!m_pDBManager || m_pDBManager->getEmbeddedName().isEmpty())
+ return;
+
+ SwDoc* pDoc = m_pDBManager->getDoc();
+ if (!pDoc)
+ return;
+
+ SwDocShell* pDocShell = pDoc->GetDocShell();
+ if (!pDocShell)
+ return;
+
+ const OUString sTmpName = ConstructVndSunStarPkgUrl(
+ pDocShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::NONE),
+ m_pDBManager->getEmbeddedName());
+
+ if (sTmpName != rEvent.OldLocation)
+ return;
+
+ // The revoked database location is inside this document, then remove the
+ // embedding, as otherwise it would be back on the next reload of the
+ // document.
+ pDocShell->GetStorage()->removeElement(m_pDBManager->getEmbeddedName());
+ m_pDBManager->setEmbeddedName(OUString(), *pDocShell);
+}
+
+void SAL_CALL SwDataSourceRemovedListener::changedDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent)
+{
+ if (rEvent.OldLocation != rEvent.NewLocation)
+ revokedDatabaseLocation(rEvent);
+}
+
+void SwDataSourceRemovedListener::disposing(const lang::EventObject& /*rObject*/)
+{
+ m_xDatabaseContext.clear();
+}
+
+void SwDataSourceRemovedListener::Dispose()
+{
+ m_pDBManager = nullptr;
+}
+
+struct SwDBManager::SwDBManager_Impl
+{
+ std::unique_ptr<SwDSParam> pMergeData;
+ VclPtr<AbstractMailMergeDlg> pMergeDialog;
+ rtl::Reference<SwDBManager::ConnectionDisposedListener_Impl> m_xDisposeListener;
+ rtl::Reference<SwDataSourceRemovedListener> m_xDataSourceRemovedListener;
+ std::mutex m_aAllEmailSendMutex;
+ uno::Reference< mail::XMailMessage> m_xLastMessage;
+
+ explicit SwDBManager_Impl(SwDBManager& rDBManager)
+ : m_xDisposeListener(new ConnectionDisposedListener_Impl(rDBManager))
+ {}
+
+ ~SwDBManager_Impl()
+ {
+ m_xDisposeListener->Dispose();
+ if (m_xDataSourceRemovedListener.is())
+ m_xDataSourceRemovedListener->Dispose();
+ }
+};
+
+static void lcl_InitNumberFormatter(SwDSParam& rParam, uno::Reference<sdbc::XDataSource> const & xSource)
+{
+ uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
+ rParam.xFormatter = util::NumberFormatter::create(xContext);
+ uno::Reference<beans::XPropertySet> xSourceProps(
+ (xSource.is()
+ ? xSource
+ : SwDBManager::getDataSourceAsParent(
+ rParam.xConnection, rParam.sDataSource)),
+ uno::UNO_QUERY);
+ if(!xSourceProps.is())
+ return;
+
+ uno::Any aFormats = xSourceProps->getPropertyValue("NumberFormatsSupplier");
+ if(!aFormats.hasValue())
+ return;
+
+ uno::Reference<util::XNumberFormatsSupplier> xSuppl;
+ aFormats >>= xSuppl;
+ if(xSuppl.is())
+ {
+ uno::Reference< beans::XPropertySet > xSettings = xSuppl->getNumberFormatSettings();
+ uno::Any aNull = xSettings->getPropertyValue("NullDate");
+ aNull >>= rParam.aNullDate;
+ if(rParam.xFormatter.is())
+ rParam.xFormatter->attachNumberFormatsSupplier(xSuppl);
+ }
+}
+
+static bool lcl_MoveAbsolute(SwDSParam* pParam, tools::Long nAbsPos)
+{
+ bool bRet = false;
+ try
+ {
+ if(pParam->aSelection.hasElements())
+ {
+ if(pParam->aSelection.getLength() <= nAbsPos)
+ {
+ pParam->bEndOfDB = true;
+ bRet = false;
+ }
+ else
+ {
+ pParam->nSelectionIndex = nAbsPos;
+ sal_Int32 nPos = 0;
+ pParam->aSelection.getConstArray()[ pParam->nSelectionIndex ] >>= nPos;
+ pParam->bEndOfDB = !pParam->xResultSet->absolute( nPos );
+ bRet = !pParam->bEndOfDB;
+ }
+ }
+ else if(pParam->bScrollable)
+ {
+ bRet = pParam->xResultSet->absolute( nAbsPos );
+ }
+ else
+ {
+ OSL_FAIL("no absolute positioning available");
+ }
+ }
+ catch(const uno::Exception&)
+ {
+ }
+ return bRet;
+}
+
+static void lcl_GetColumnCnt(SwDSParam *pParam,
+ const uno::Reference< beans::XPropertySet > &rColumnProps,
+ LanguageType nLanguage, OUString &rResult, double* pNumber)
+{
+ SwDBFormatData aFormatData;
+ if(!pParam->xFormatter.is())
+ {
+ uno::Reference<sdbc::XDataSource> xSource = SwDBManager::getDataSourceAsParent(
+ pParam->xConnection,pParam->sDataSource);
+ lcl_InitNumberFormatter(*pParam, xSource );
+ }
+ aFormatData.aNullDate = pParam->aNullDate;
+ aFormatData.xFormatter = pParam->xFormatter;
+
+ aFormatData.aLocale = LanguageTag( nLanguage ).getLocale();
+
+ rResult = SwDBManager::GetDBField( rColumnProps, aFormatData, pNumber);
+}
+
+static bool lcl_GetColumnCnt(SwDSParam* pParam, const OUString& rColumnName,
+ LanguageType nLanguage, OUString& rResult, double* pNumber)
+{
+ uno::Reference< sdbcx::XColumnsSupplier > xColsSupp( pParam->xResultSet, uno::UNO_QUERY );
+ uno::Reference<container::XNameAccess> xCols;
+ try
+ {
+ xCols = xColsSupp->getColumns();
+ }
+ catch(const lang::DisposedException&)
+ {
+ }
+ if(!xCols.is() || !xCols->hasByName(rColumnName))
+ return false;
+ uno::Any aCol = xCols->getByName(rColumnName);
+ uno::Reference< beans::XPropertySet > xColumnProps;
+ aCol >>= xColumnProps;
+ lcl_GetColumnCnt( pParam, xColumnProps, nLanguage, rResult, pNumber );
+ return true;
+};
+
+// import data
+bool SwDBManager::Merge( const SwMergeDescriptor& rMergeDesc )
+{
+ assert( !m_bInMerge && !m_pImpl->pMergeData && "merge already activated!" );
+
+ SfxObjectShellLock xWorkObjSh;
+ SwWrtShell *pWorkShell = nullptr;
+ rtl::Reference<SwDoc> pWorkDoc;
+ SwDBManager *pWorkDocOrigDBManager = nullptr;
+
+ switch( rMergeDesc.nMergeType )
+ {
+ case DBMGR_MERGE_PRINTER:
+ case DBMGR_MERGE_EMAIL:
+ case DBMGR_MERGE_FILE:
+ case DBMGR_MERGE_SHELL:
+ {
+ SwDocShell *pSourceDocSh = rMergeDesc.rSh.GetView().GetDocShell();
+ if( pSourceDocSh->IsModified() )
+ {
+ pWorkDocOrigDBManager = this;
+ xWorkObjSh = lcl_CreateWorkingDocument(
+ WorkingDocType::SOURCE, rMergeDesc.rSh, nullptr,
+ &pWorkDocOrigDBManager, nullptr, &pWorkShell, &pWorkDoc );
+ }
+ [[fallthrough]];
+ }
+
+ default:
+ if( !xWorkObjSh.Is() )
+ pWorkShell = &rMergeDesc.rSh;
+ break;
+ }
+
+ SwDBData aData;
+ aData.nCommandType = sdb::CommandType::TABLE;
+ uno::Reference<sdbc::XResultSet> xResSet;
+ uno::Sequence<uno::Any> aSelection;
+ uno::Reference< sdbc::XConnection> xConnection;
+
+ aData.sDataSource = rMergeDesc.rDescriptor.getDataSource();
+ rMergeDesc.rDescriptor[svx::DataAccessDescriptorProperty::Command] >>= aData.sCommand;
+ rMergeDesc.rDescriptor[svx::DataAccessDescriptorProperty::CommandType] >>= aData.nCommandType;
+
+ if ( rMergeDesc.rDescriptor.has(svx::DataAccessDescriptorProperty::Cursor) )
+ rMergeDesc.rDescriptor[svx::DataAccessDescriptorProperty::Cursor] >>= xResSet;
+ if ( rMergeDesc.rDescriptor.has(svx::DataAccessDescriptorProperty::Selection) )
+ rMergeDesc.rDescriptor[svx::DataAccessDescriptorProperty::Selection] >>= aSelection;
+ if ( rMergeDesc.rDescriptor.has(svx::DataAccessDescriptorProperty::Connection) )
+ rMergeDesc.rDescriptor[svx::DataAccessDescriptorProperty::Connection] >>= xConnection;
+
+ if((aData.sDataSource.isEmpty() || aData.sCommand.isEmpty()) && !xResSet.is())
+ {
+ return false;
+ }
+
+ m_pImpl->pMergeData.reset(new SwDSParam(aData, xResSet, aSelection));
+ SwDSParam* pTemp = FindDSData(aData, false);
+ if(pTemp)
+ *pTemp = *m_pImpl->pMergeData;
+ else
+ {
+ // calls from the calculator may have added a connection with an invalid commandtype
+ //"real" data base connections added here have to re-use the already available
+ //DSData and set the correct CommandType
+ aData.nCommandType = -1;
+ pTemp = FindDSData(aData, false);
+ if(pTemp)
+ *pTemp = *m_pImpl->pMergeData;
+ else
+ {
+ m_DataSourceParams.push_back(std::make_unique<SwDSParam>(*m_pImpl->pMergeData));
+ try
+ {
+ uno::Reference<lang::XComponent> xComponent(m_DataSourceParams.back()->xConnection, uno::UNO_QUERY);
+ if(xComponent.is())
+ xComponent->addEventListener(m_pImpl->m_xDisposeListener);
+ }
+ catch(const uno::Exception&)
+ {
+ }
+ }
+ }
+ if(!m_pImpl->pMergeData->xConnection.is())
+ m_pImpl->pMergeData->xConnection = xConnection;
+ // add an XEventListener
+
+ lcl_ToNextRecord(m_pImpl->pMergeData.get(), SwDBNextRecord::FIRST);
+
+ uno::Reference<sdbc::XDataSource> xSource = SwDBManager::getDataSourceAsParent(xConnection,aData.sDataSource);
+
+ lcl_InitNumberFormatter(*m_pImpl->pMergeData, xSource);
+
+ pWorkShell->ChgDBData(aData);
+ m_bInMerge = true;
+
+ if (IsInitDBFields())
+ {
+ // with database fields without DB-Name, use DB-Name from Doc
+ std::vector<OUString> aDBNames;
+ aDBNames.emplace_back();
+ SwDBData aInsertData = pWorkShell->GetDBData();
+ OUString sDBName = aInsertData.sDataSource
+ + OUStringChar(DB_DELIM) + aInsertData.sCommand
+ + OUStringChar(DB_DELIM)
+ + OUString::number(aInsertData.nCommandType);
+ pWorkShell->ChangeDBFields( aDBNames, sDBName);
+ SetInitDBFields(false);
+ }
+
+ bool bRet = true;
+ switch(rMergeDesc.nMergeType)
+ {
+ case DBMGR_MERGE:
+ pWorkShell->StartAllAction();
+ pWorkShell->SwViewShell::UpdateFields( true );
+ pWorkShell->SetModified();
+ pWorkShell->EndAllAction();
+ break;
+
+ case DBMGR_MERGE_PRINTER:
+ case DBMGR_MERGE_EMAIL:
+ case DBMGR_MERGE_FILE:
+ case DBMGR_MERGE_SHELL:
+ // save files and send them as e-Mail if required
+ bRet = MergeMailFiles(pWorkShell, rMergeDesc);
+ break;
+
+ default:
+ // insert selected entries
+ // (was: InsertRecord)
+ ImportFromConnection(pWorkShell);
+ break;
+ }
+
+ m_pImpl->pMergeData.reset();
+
+ if( xWorkObjSh.Is() )
+ {
+ pWorkDoc->SetDBManager( pWorkDocOrigDBManager );
+ xWorkObjSh->DoClose();
+ }
+
+ m_bInMerge = false;
+
+ return bRet;
+}
+
+void SwDBManager::ImportFromConnection( SwWrtShell* pSh )
+{
+ if(!m_pImpl->pMergeData || m_pImpl->pMergeData->bEndOfDB)
+ return;
+
+ pSh->StartAllAction();
+ pSh->StartUndo();
+ bool bGroupUndo(pSh->DoesGroupUndo());
+ pSh->DoGroupUndo(false);
+
+ if( pSh->HasSelection() )
+ pSh->DelRight();
+
+ std::optional<SwWait> oWait;
+
+ {
+ sal_uInt32 i = 0;
+ do {
+
+ ImportDBEntry(pSh);
+ if( 10 == ++i )
+ oWait.emplace( *pSh->GetView().GetDocShell(), true);
+
+ } while(ToNextMergeRecord());
+ }
+
+ pSh->DoGroupUndo(bGroupUndo);
+ pSh->EndUndo();
+ pSh->EndAllAction();
+}
+
+void SwDBManager::ImportDBEntry(SwWrtShell* pSh)
+{
+ if(!m_pImpl->pMergeData || m_pImpl->pMergeData->bEndOfDB)
+ return;
+
+ uno::Reference< sdbcx::XColumnsSupplier > xColsSupp( m_pImpl->pMergeData->xResultSet, uno::UNO_QUERY );
+ uno::Reference<container::XNameAccess> xCols = xColsSupp->getColumns();
+ OUStringBuffer sStr;
+ uno::Sequence<OUString> aColNames = xCols->getElementNames();
+ const OUString* pColNames = aColNames.getConstArray();
+ tools::Long nLength = aColNames.getLength();
+ for(tools::Long i = 0; i < nLength; i++)
+ {
+ uno::Any aCol = xCols->getByName(pColNames[i]);
+ uno::Reference< beans::XPropertySet > xColumnProp;
+ aCol >>= xColumnProp;
+ SwDBFormatData aDBFormat;
+ sStr.append(GetDBField( xColumnProp, aDBFormat));
+ if (i < nLength - 1)
+ sStr.append("\t");
+ }
+ pSh->SwEditShell::Insert2(sStr.makeStringAndClear());
+ pSh->SwFEShell::SplitNode(); // line feed
+}
+
+bool SwDBManager::GetTableNames(weld::ComboBox& rBox, const OUString& rDBName)
+{
+ bool bRet = false;
+ OUString sOldTableName(rBox.get_active_text());
+ rBox.clear();
+ SwDSParam* pParam = FindDSConnection(rDBName, false);
+ uno::Reference< sdbc::XConnection> xConnection;
+ if (pParam && pParam->xConnection.is())
+ xConnection = pParam->xConnection;
+ else
+ {
+ if ( !rDBName.isEmpty() )
+ xConnection = RegisterConnection( rDBName );
+ }
+ if (xConnection.is())
+ {
+ uno::Reference<sdbcx::XTablesSupplier> xTSupplier(xConnection, uno::UNO_QUERY);
+ if(xTSupplier.is())
+ {
+ uno::Reference<container::XNameAccess> xTables = xTSupplier->getTables();
+ const uno::Sequence<OUString> aTables = xTables->getElementNames();
+ for (const OUString& rTable : aTables)
+ rBox.append("0", rTable);
+ }
+ uno::Reference<sdb::XQueriesSupplier> xQSupplier(xConnection, uno::UNO_QUERY);
+ if(xQSupplier.is())
+ {
+ uno::Reference<container::XNameAccess> xQueries = xQSupplier->getQueries();
+ const uno::Sequence<OUString> aQueries = xQueries->getElementNames();
+ for (const OUString& rQuery : aQueries)
+ rBox.append("1", rQuery);
+ }
+ if (!sOldTableName.isEmpty())
+ rBox.set_active_text(sOldTableName);
+ bRet = true;
+ }
+ return bRet;
+}
+
+// fill Listbox with column names of a database
+void SwDBManager::GetColumnNames(weld::ComboBox& rBox,
+ const OUString& rDBName, const OUString& rTableName)
+{
+ SwDBData aData;
+ aData.sDataSource = rDBName;
+ aData.sCommand = rTableName;
+ aData.nCommandType = -1;
+ SwDSParam* pParam = FindDSData(aData, false);
+ uno::Reference< sdbc::XConnection> xConnection;
+ if(pParam && pParam->xConnection.is())
+ xConnection = pParam->xConnection;
+ else
+ {
+ xConnection = RegisterConnection( rDBName );
+ }
+ GetColumnNames(rBox, xConnection, rTableName);
+}
+
+void SwDBManager::GetColumnNames(weld::ComboBox& rBox,
+ uno::Reference< sdbc::XConnection> const & xConnection,
+ const OUString& rTableName)
+{
+ rBox.clear();
+ uno::Reference< sdbcx::XColumnsSupplier> xColsSupp = SwDBManager::GetColumnSupplier(xConnection, rTableName);
+ if(xColsSupp.is())
+ {
+ uno::Reference<container::XNameAccess> xCols = xColsSupp->getColumns();
+ const uno::Sequence<OUString> aColNames = xCols->getElementNames();
+ for (const OUString& rColName : aColNames)
+ {
+ rBox.append_text(rColName);
+ }
+ ::comphelper::disposeComponent( xColsSupp );
+ }
+}
+
+SwDBManager::SwDBManager(SwDoc* pDoc)
+ : m_aMergeStatus( MergeStatus::Ok )
+ , m_bInitDBFields(false)
+ , m_bInMerge(false)
+ , m_bMergeSilent(false)
+ , m_pImpl(new SwDBManager_Impl(*this))
+ , m_pMergeEvtSrc(nullptr)
+ , m_pDoc(pDoc)
+{
+}
+
+void SwDBManager::ImplDestroy()
+{
+ RevokeLastRegistrations();
+
+ // copy required, m_DataSourceParams can be modified while disposing components
+ std::vector<uno::Reference<sdbc::XConnection>> aCopiedConnections;
+ for (const auto & pParam : m_DataSourceParams)
+ {
+ if(pParam->xConnection.is())
+ {
+ aCopiedConnections.push_back(pParam->xConnection);
+ }
+ }
+ for (const auto & xConnection : aCopiedConnections)
+ {
+ try
+ {
+ uno::Reference<lang::XComponent> xComp(xConnection, uno::UNO_QUERY);
+ if(xComp.is())
+ xComp->dispose();
+ }
+ catch(const uno::RuntimeException&)
+ {
+ //may be disposed already since multiple entries may have used the same connection
+ }
+ }
+}
+
+SwDBManager::~SwDBManager()
+{
+ suppress_fun_call_w_exception(ImplDestroy());
+}
+
+static void lcl_RemoveSectionLinks( SwWrtShell& rWorkShell )
+{
+ //reset all links of the sections of synchronized labels
+ size_t nSections = rWorkShell.GetSectionFormatCount();
+ for (size_t nSection = 0; nSection < nSections; ++nSection)
+ {
+ SwSectionData aSectionData( *rWorkShell.GetSectionFormat( nSection ).GetSection() );
+ if( aSectionData.GetType() == SectionType::FileLink )
+ {
+ aSectionData.SetType( SectionType::Content );
+ aSectionData.SetLinkFileName( OUString() );
+ rWorkShell.UpdateSection( nSection, aSectionData );
+ }
+ }
+ rWorkShell.SetLabelDoc( false );
+}
+
+static void lcl_SaveDebugDoc( SfxObjectShell *xTargetDocShell,
+ const char *name, int no = 0 )
+{
+ static OUString sTempDirURL;
+ if( sTempDirURL.isEmpty() )
+ {
+ SvtPathOptions aPathOpt;
+ utl::TempFileNamed aTempDir( &aPathOpt.GetTempPath(), true );
+ if( aTempDir.IsValid() )
+ {
+ INetURLObject aTempDirURL( aTempDir.GetURL() );
+ sTempDirURL = aTempDirURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ SAL_INFO( "sw.mailmerge", "Dump directory: " << sTempDirURL );
+ }
+ }
+ if( sTempDirURL.isEmpty() )
+ return;
+
+ OUString basename = OUString::createFromAscii( name );
+ if (no > 0)
+ basename += OUString::number(no) + "-";
+ // aTempFile is not deleted, but that seems to be intentional
+ utl::TempFileNamed aTempFile( basename, true, u".odt", &sTempDirURL );
+ INetURLObject aTempFileURL( aTempFile.GetURL() );
+ auto pDstMed = std::make_unique<SfxMedium>(
+ aTempFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
+ StreamMode::STD_READWRITE );
+ bool bAnyError = !xTargetDocShell->DoSaveAs( *pDstMed );
+ // xObjectShell->DoSaveCompleted crashes the mail merge unit tests, so skip it
+ bAnyError |= (ERRCODE_NONE != xTargetDocShell->GetErrorIgnoreWarning());
+ if( bAnyError )
+ SAL_WARN( "sw.mailmerge", "Error saving: " << aTempFile.GetURL() );
+ else
+ SAL_INFO( "sw.mailmerge", "Saved doc as: " << aTempFile.GetURL() );
+}
+
+static bool lcl_SaveDoc(
+ const INetURLObject* pFileURL,
+ const std::shared_ptr<const SfxFilter>& pStoreToFilter,
+ const OUString* pStoreToFilterOptions,
+ const uno::Sequence< beans::PropertyValue >* pSaveToFilterData,
+ const bool bIsPDFexport,
+ SfxObjectShell* xObjectShell,
+ SwWrtShell& rWorkShell,
+ OUString * const decodedURL = nullptr )
+{
+ OUString url = pFileURL->GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ if( decodedURL )
+ (*decodedURL) = url;
+
+ SfxMedium* pDstMed = new SfxMedium( url, StreamMode::STD_READWRITE );
+ pDstMed->SetFilter( pStoreToFilter );
+ if( pStoreToFilterOptions )
+ pDstMed->GetItemSet().Put( SfxStringItem(SID_FILE_FILTEROPTIONS,
+ *pStoreToFilterOptions));
+ if( pSaveToFilterData->hasElements() )
+ pDstMed->GetItemSet().Put( SfxUnoAnyItem(SID_FILTER_DATA,
+ uno::Any(*pSaveToFilterData)));
+
+ // convert fields to text if we are exporting to PDF.
+ // this prevents a second merge while updating the fields
+ // in SwXTextDocument::getRendererCount()
+ if( bIsPDFexport )
+ rWorkShell.ConvertFieldsToText();
+
+ bool bAnyError = !xObjectShell->DoSaveAs(*pDstMed);
+ // Actually this should be a bool... so in case of email and individual
+ // files, where this is set, we skip the recently used handling
+ bAnyError |= !xObjectShell->DoSaveCompleted( pDstMed, !decodedURL );
+ bAnyError |= (ERRCODE_NONE != xObjectShell->GetErrorIgnoreWarning());
+ if( bAnyError )
+ {
+ // error message ??
+ ErrorHandler::HandleError( xObjectShell->GetErrorIgnoreWarning() );
+ }
+ return !bAnyError;
+}
+
+static void lcl_PreparePrinterOptions(
+ const uno::Sequence< beans::PropertyValue >& rInPrintOptions,
+ uno::Sequence< beans::PropertyValue >& rOutPrintOptions)
+{
+ // printing should be done synchronously otherwise the document
+ // might already become invalid during the process
+
+ rOutPrintOptions = { comphelper::makePropertyValue("Wait", true) };
+
+ // copy print options
+ sal_Int32 nIndex = 1;
+ for( const beans::PropertyValue& rOption : rInPrintOptions)
+ {
+ if( rOption.Name == "CopyCount" || rOption.Name == "FileName"
+ || rOption.Name == "Collate" || rOption.Name == "Pages"
+ || rOption.Name == "Wait" || rOption.Name == "PrinterName" )
+ {
+ // add an option
+ rOutPrintOptions.realloc( nIndex + 1 );
+ auto pOutPrintOptions = rOutPrintOptions.getArray();
+ pOutPrintOptions[ nIndex ].Name = rOption.Name;
+ pOutPrintOptions[ nIndex++ ].Value = rOption.Value ;
+ }
+ }
+}
+
+static void lcl_PrepareSaveFilterDataOptions(
+ const uno::Sequence< beans::PropertyValue >& rInSaveFilterDataptions,
+ uno::Sequence< beans::PropertyValue >& rOutSaveFilterDataOptions,
+ const OUString& sPassword)
+{
+ rOutSaveFilterDataOptions
+ = { comphelper::makePropertyValue("EncryptFile", true),
+ comphelper::makePropertyValue("DocumentOpenPassword", sPassword) };
+
+ // copy other options
+ sal_Int32 nIndex = 2;
+ for( const beans::PropertyValue& rOption : rInSaveFilterDataptions)
+ {
+ rOutSaveFilterDataOptions.realloc( nIndex + 1 );
+ auto pOutSaveFilterDataOptions = rOutSaveFilterDataOptions.getArray();
+ pOutSaveFilterDataOptions[ nIndex ].Name = rOption.Name;
+ pOutSaveFilterDataOptions[ nIndex++ ].Value = rOption.Value ;
+ }
+
+}
+
+
+static SfxObjectShell* lcl_CreateWorkingDocument(
+ // input
+ const WorkingDocType aType, const SwWrtShell &rSourceWrtShell,
+ // optional input
+ const vcl::Window *pSourceWindow,
+ // optional in and output to swap the DB manager
+ SwDBManager** const ppDBManager,
+ // optional output
+ SwView** const pView, SwWrtShell** const pWrtShell, rtl::Reference<SwDoc>* const pDoc )
+{
+ const SwDoc *pSourceDoc = rSourceWrtShell.GetDoc();
+ SfxObjectShellRef xWorkObjectShell = pSourceDoc->CreateCopy( true, (aType == WorkingDocType::TARGET) );
+ SfxViewFrame* pWorkFrame = SfxViewFrame::LoadHiddenDocument( *xWorkObjectShell, SFX_INTERFACE_NONE );
+
+ if( pSourceWindow )
+ {
+ // the created window has to be located at the same position as the source window
+ vcl::Window& rTargetWindow = pWorkFrame->GetFrame().GetWindow();
+ rTargetWindow.SetPosPixel( pSourceWindow->GetPosPixel() );
+ }
+
+ SwView* pWorkView = static_cast< SwView* >( pWorkFrame->GetViewShell() );
+
+ if (SwWrtShell* pWorkWrtShell = pWorkView->GetWrtShellPtr())
+ {
+ pWorkWrtShell->GetViewOptions()->SetIdle( false );
+ pWorkView->AttrChangedNotify(nullptr);// in order for SelectShell to be called
+ SwDoc* pWorkDoc = pWorkWrtShell->GetDoc();
+ pWorkDoc->GetIDocumentUndoRedo().DoUndo( false );
+ pWorkDoc->ReplaceDocumentProperties( *pSourceDoc );
+
+ // import print settings
+ const SwPrintData &rPrintData = pSourceDoc->getIDocumentDeviceAccess().getPrintData();
+ pWorkDoc->getIDocumentDeviceAccess().setPrintData(rPrintData);
+ const JobSetup *pJobSetup = pSourceDoc->getIDocumentDeviceAccess().getJobsetup();
+ if (pJobSetup)
+ pWorkDoc->getIDocumentDeviceAccess().setJobsetup(*pJobSetup);
+
+ if( aType == WorkingDocType::TARGET )
+ {
+ assert( !ppDBManager );
+ pWorkDoc->SetInMailMerge( true );
+ pWorkWrtShell->SetLabelDoc( false );
+ }
+ else
+ {
+ // We have to swap the DBmanager of the new doc, so we also need input
+ assert(ppDBManager && *ppDBManager);
+ SwDBManager *pWorkDBManager = pWorkDoc->GetDBManager();
+ pWorkDoc->SetDBManager( *ppDBManager );
+ *ppDBManager = pWorkDBManager;
+
+ if( aType == WorkingDocType::SOURCE )
+ {
+ // the GetDBData call constructs the data, if it's missing - kind of const...
+ pWorkWrtShell->ChgDBData( const_cast<SwDoc*>(pSourceDoc)->GetDBData() );
+ // some DocumentSettings are currently not copied by SwDoc::CreateCopy
+ pWorkWrtShell->SetLabelDoc( rSourceWrtShell.IsLabelDoc() );
+ pWorkDoc->getIDocumentState().ResetModified();
+ }
+ else
+ pWorkDoc->getIDocumentLinksAdministration().EmbedAllLinks();
+ }
+
+ if( pView ) *pView = pWorkView;
+ if( pWrtShell ) *pWrtShell = pWorkWrtShell;
+ if( pDoc ) *pDoc = pWorkDoc;
+ }
+
+ return xWorkObjectShell.get();
+}
+
+static rtl::Reference<SwMailMessage> lcl_CreateMailFromDoc(
+ const SwMergeDescriptor &rMergeDescriptor,
+ const OUString &sFileURL, const OUString &sMailRecipient,
+ const OUString &sMailBodyMimeType, rtl_TextEncoding sMailEncoding,
+ const OUString &sAttachmentMimeType )
+{
+ rtl::Reference<SwMailMessage> pMessage = new SwMailMessage;
+ if( rMergeDescriptor.pMailMergeConfigItem->IsMailReplyTo() )
+ pMessage->setReplyToAddress(rMergeDescriptor.pMailMergeConfigItem->GetMailReplyTo());
+ pMessage->addRecipient( sMailRecipient );
+ pMessage->SetSenderAddress( rMergeDescriptor.pMailMergeConfigItem->GetMailAddress() );
+
+ OUStringBuffer sBody;
+ if( rMergeDescriptor.bSendAsAttachment )
+ {
+ sBody = rMergeDescriptor.sMailBody;
+ mail::MailAttachment aAttach;
+ aAttach.Data = new SwMailTransferable( sFileURL,
+ rMergeDescriptor.sAttachmentName, sAttachmentMimeType );
+ aAttach.ReadableName = rMergeDescriptor.sAttachmentName;
+ pMessage->addAttachment( aAttach );
+ }
+ else
+ {
+ //read in the temporary file and use it as mail body
+ SfxMedium aMedium( sFileURL, StreamMode::READ );
+ SvStream* pInStream = aMedium.GetInStream();
+ assert( pInStream && "no output file created?" );
+ if( !pInStream )
+ return pMessage;
+
+ pInStream->SetStreamCharSet( sMailEncoding );
+ OStringBuffer sLine;
+ while ( pInStream->ReadLine( sLine ) )
+ {
+ sBody.append(OStringToOUString( sLine, sMailEncoding ) + "\n");
+ }
+ }
+ pMessage->setSubject( rMergeDescriptor.sSubject );
+ uno::Reference< datatransfer::XTransferable> xBody =
+ new SwMailTransferable( sBody.makeStringAndClear(), sMailBodyMimeType );
+ pMessage->setBody( xBody );
+
+ for( const OUString& sCcRecipient : rMergeDescriptor.aCopiesTo )
+ pMessage->addCcRecipient( sCcRecipient );
+ for( const OUString& sBccRecipient : rMergeDescriptor.aBlindCopiesTo )
+ pMessage->addBccRecipient( sBccRecipient );
+
+ return pMessage;
+}
+
+class SwDBManager::MailDispatcherListener_Impl : public IMailDispatcherListener
+{
+ SwDBManager &m_rDBManager;
+
+public:
+ explicit MailDispatcherListener_Impl( SwDBManager &rDBManager )
+ : m_rDBManager( rDBManager ) {}
+
+ virtual void idle() override {}
+
+ virtual void mailDelivered( uno::Reference< mail::XMailMessage> xMessage ) override
+ {
+ std::unique_lock aGuard( m_rDBManager.m_pImpl->m_aAllEmailSendMutex );
+ if ( m_rDBManager.m_pImpl->m_xLastMessage == xMessage )
+ m_rDBManager.m_pImpl->m_xLastMessage.clear();
+ }
+
+ virtual void mailDeliveryError( ::rtl::Reference<MailDispatcher> xMailDispatcher,
+ uno::Reference< mail::XMailMessage>, const OUString& ) override
+ {
+ std::unique_lock aGuard( m_rDBManager.m_pImpl->m_aAllEmailSendMutex );
+ m_rDBManager.m_aMergeStatus = MergeStatus::Error;
+ m_rDBManager.m_pImpl->m_xLastMessage.clear();
+ xMailDispatcher->stop();
+ }
+};
+
+/**
+ * Please have a look at the README in the same directory, before you make
+ * larger changes in this function!
+ */
+bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
+ const SwMergeDescriptor& rMergeDescriptor)
+{
+ // deconstruct mail merge type for better readability.
+ // uppercase naming is intentional!
+ const bool bMT_EMAIL = rMergeDescriptor.nMergeType == DBMGR_MERGE_EMAIL;
+ const bool bMT_SHELL = rMergeDescriptor.nMergeType == DBMGR_MERGE_SHELL;
+ const bool bMT_PRINTER = rMergeDescriptor.nMergeType == DBMGR_MERGE_PRINTER;
+ const bool bMT_FILE = rMergeDescriptor.nMergeType == DBMGR_MERGE_FILE;
+
+ //check if the doc is synchronized and contains at least one linked section
+ const bool bSynchronizedDoc = pSourceShell->IsLabelDoc() && pSourceShell->GetSectionFormatCount() > 1;
+ const bool bNeedsTempFiles = ( bMT_EMAIL || bMT_FILE );
+ const bool bIsMergeSilent = IsMergeSilent();
+
+ bool bCheckSingleFile_ = rMergeDescriptor.bCreateSingleFile;
+ OUString sPrefix_ = rMergeDescriptor.sPrefix;
+ if( bMT_EMAIL )
+ {
+ assert( !rMergeDescriptor.bPrefixIsFilename );
+ assert(!bCheckSingleFile_);
+ bCheckSingleFile_ = false;
+ }
+ else if( bMT_SHELL || bMT_PRINTER )
+ {
+ assert(bCheckSingleFile_);
+ bCheckSingleFile_ = true;
+ assert(sPrefix_.isEmpty());
+ sPrefix_.clear();
+ }
+ const bool bCreateSingleFile = bCheckSingleFile_;
+ const OUString sDescriptorPrefix = sPrefix_;
+
+ // Setup for dumping debugging documents
+ static const sal_Int32 nMaxDumpDocs = []() {
+ if (const char* sEnv = getenv("SW_DEBUG_MAILMERGE_DOCS"))
+ return OUString(sEnv, strlen(sEnv), osl_getThreadTextEncoding()).toInt32();
+ else
+ return sal_Int32(0);
+ }();
+
+ ::rtl::Reference< MailDispatcher > xMailDispatcher;
+ ::rtl::Reference< IMailDispatcherListener > xMailListener;
+ OUString sMailBodyMimeType;
+ rtl_TextEncoding sMailEncoding = ::osl_getThreadTextEncoding();
+
+ uno::Reference< beans::XPropertySet > xColumnProp;
+ uno::Reference< beans::XPropertySet > xPasswordColumnProp;
+
+ // Check for (mandatory) email or (optional) filename column
+ SwDBFormatData aColumnDBFormat;
+ bool bColumnName = !rMergeDescriptor.sDBcolumn.isEmpty();
+ bool bPasswordColumnName = !rMergeDescriptor.sDBPasswordColumn.isEmpty();
+
+ if( ! bColumnName )
+ {
+ if( bMT_EMAIL )
+ return false;
+ }
+ else
+ {
+ uno::Reference< sdbcx::XColumnsSupplier > xColsSupp( m_pImpl->pMergeData->xResultSet, uno::UNO_QUERY );
+ uno::Reference<container::XNameAccess> xCols = xColsSupp->getColumns();
+ if( !xCols->hasByName( rMergeDescriptor.sDBcolumn ) )
+ return false;
+ uno::Any aCol = xCols->getByName( rMergeDescriptor.sDBcolumn );
+ aCol >>= xColumnProp;
+
+ if(bPasswordColumnName)
+ {
+ aCol = xCols->getByName( rMergeDescriptor.sDBPasswordColumn );
+ aCol >>= xPasswordColumnProp;
+ }
+
+ aColumnDBFormat.xFormatter = m_pImpl->pMergeData->xFormatter;
+ aColumnDBFormat.aNullDate = m_pImpl->pMergeData->aNullDate;
+
+ if( bMT_EMAIL )
+ {
+ // Reset internal mail accounting data
+ m_pImpl->m_xLastMessage.clear();
+
+ xMailDispatcher.set( new MailDispatcher(rMergeDescriptor.xSmtpServer) );
+ xMailListener = new MailDispatcherListener_Impl( *this );
+ xMailDispatcher->addListener( xMailListener );
+ if(!rMergeDescriptor.bSendAsAttachment && rMergeDescriptor.bSendAsHTML)
+ {
+ sMailBodyMimeType = "text/html; charset=utf-8";
+ sMailEncoding = RTL_TEXTENCODING_UTF8;
+ }
+ else
+ sMailBodyMimeType = "text/plain; charset=UTF-8; format=flowed";
+ }
+ }
+
+ SwDocShell *pSourceDocSh = pSourceShell->GetView().GetDocShell();
+
+ // setup the output format
+ std::shared_ptr<const SfxFilter> pStoreToFilter = SwIoSystem::GetFileFilter(
+ pSourceDocSh->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::NONE));
+ SfxFilterContainer* pFilterContainer = SwDocShell::Factory().GetFilterContainer();
+ const OUString* pStoreToFilterOptions = nullptr;
+
+ // if a save_to filter is set then use it - otherwise use the default
+ if( bMT_EMAIL && !rMergeDescriptor.bSendAsAttachment )
+ {
+ OUString sExtension = rMergeDescriptor.bSendAsHTML ? OUString("html") : OUString("txt");
+ pStoreToFilter = pFilterContainer->GetFilter4Extension(sExtension, SfxFilterFlags::EXPORT);
+ }
+ else if( !rMergeDescriptor.sSaveToFilter.isEmpty())
+ {
+ std::shared_ptr<const SfxFilter> pFilter =
+ pFilterContainer->GetFilter4FilterName( rMergeDescriptor.sSaveToFilter );
+ if(pFilter)
+ {
+ pStoreToFilter = pFilter;
+ if(!rMergeDescriptor.sSaveToFilterOptions.isEmpty())
+ pStoreToFilterOptions = &rMergeDescriptor.sSaveToFilterOptions;
+ }
+ }
+ const bool bIsPDFexport = pStoreToFilter && pStoreToFilter->GetFilterName() == "writer_pdf_Export";
+ const bool bIsMultiFile = bMT_FILE && !bCreateSingleFile;
+
+ m_aMergeStatus = MergeStatus::Ok;
+
+ // in case of creating a single resulting file this has to be created here
+ SwView* pTargetView = rMergeDescriptor.pMailMergeConfigItem ?
+ rMergeDescriptor.pMailMergeConfigItem->GetTargetView() : nullptr;
+ SwWrtShell* pTargetShell = nullptr;
+ SfxObjectShellRef xTargetDocShell;
+ rtl::Reference<SwDoc> pTargetDoc;
+
+ std::unique_ptr< utl::TempFileNamed > aTempFile;
+ sal_uInt16 nStartingPageNo = 0;
+
+ std::shared_ptr<weld::GenericDialogController> xProgressDlg;
+
+ try
+ {
+ vcl::Window *pSourceWindow = nullptr;
+ if( !bIsMergeSilent )
+ {
+ // construct the process dialog
+ pSourceWindow = &pSourceShell->GetView().GetEditWin();
+ if (!bMT_PRINTER)
+ xProgressDlg = std::make_shared<CreateMonitor>(pSourceWindow->GetFrameWeld());
+ else
+ {
+ xProgressDlg = std::make_shared<PrintMonitor>(pSourceWindow->GetFrameWeld());
+ static_cast<PrintMonitor*>(xProgressDlg.get())->set_title(
+ pSourceDocSh->GetTitle(22));
+ }
+ weld::DialogController::runAsync(xProgressDlg, [this, &xProgressDlg](sal_Int32 nResult){
+ if (nResult == RET_CANCEL)
+ MergeCancel();
+ xProgressDlg.reset();
+ });
+
+ Application::Reschedule( true );
+ }
+
+ if( bCreateSingleFile && !pTargetView )
+ {
+ // create a target docshell to put the merged document into
+ xTargetDocShell = lcl_CreateWorkingDocument( WorkingDocType::TARGET,
+ *pSourceShell, bMT_SHELL ? pSourceWindow : nullptr,
+ nullptr, &pTargetView, &pTargetShell, &pTargetDoc );
+
+ if (nMaxDumpDocs)
+ lcl_SaveDebugDoc( xTargetDocShell.get(), "MergeDoc" );
+ }
+ else if( pTargetView )
+ {
+ pTargetShell = pTargetView->GetWrtShellPtr();
+ if (pTargetShell)
+ {
+ pTargetDoc = pTargetShell->GetDoc();
+ xTargetDocShell = pTargetView->GetDocShell();
+ }
+ }
+
+ if( bCreateSingleFile )
+ {
+ // determine the page style and number used at the start of the source document
+ pSourceShell->SttEndDoc(true);
+ nStartingPageNo = pSourceShell->GetVirtPageNum();
+ }
+
+ // Progress, to prohibit KeyInputs
+ SfxProgress aProgress(pSourceDocSh, OUString(), 1);
+
+ // lock all dispatchers
+ SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst(pSourceDocSh);
+ while (pViewFrame)
+ {
+ pViewFrame->GetDispatcher()->Lock(true);
+ pViewFrame = SfxViewFrame::GetNext(*pViewFrame, pSourceDocSh);
+ }
+
+ sal_Int32 nDocNo = 1;
+
+ // For single file mode, the number of pages in the target document so far, which is used
+ // by AppendDoc() to adjust position of page-bound objects. Getting this information directly
+ // from the target doc would require repeated layouts of the doc, which is expensive, but
+ // it can be manually computed from the source documents (for which we do layouts, so the page
+ // count is known, and there is a blank page between each of them in the target document).
+ int targetDocPageCount = 0;
+
+ if( !bIsMergeSilent && !bMT_PRINTER )
+ {
+ sal_Int32 nRecordCount = 1;
+ lcl_getCountFromResultSet( nRecordCount, m_pImpl->pMergeData.get() );
+
+ // Synchronized docs don't auto-advance the record set, but there is a
+ // "security" check, which will always advance the record set, if there
+ // is no "next record" field in a synchronized doc => nRecordPerDoc > 0
+ sal_Int32 nRecordPerDoc = pSourceShell->GetDoc()
+ ->getIDocumentFieldsAccess().GetRecordsPerDocument();
+ if ( bSynchronizedDoc && (nRecordPerDoc > 1) )
+ --nRecordPerDoc;
+ assert( nRecordPerDoc > 0 );
+
+ sal_Int32 nMaxDocs = nRecordCount / nRecordPerDoc;
+ if ( 0 != nRecordCount % nRecordPerDoc )
+ nMaxDocs += 1;
+ static_cast<CreateMonitor*>(xProgressDlg.get())->SetTotalCount(nMaxDocs);
+ }
+
+ sal_Int32 nStartRow, nEndRow;
+ bool bFreezedLayouts = false;
+ // to collect temporary email files
+ std::vector< OUString> aFilesToRemove;
+
+ // The SfxObjectShell will be closed explicitly later but
+ // it is more safe to use SfxObjectShellLock here
+ SfxObjectShellLock xWorkDocSh;
+ SwView* pWorkView = nullptr;
+ rtl::Reference<SwDoc> pWorkDoc;
+ SwDBManager* pWorkDocOrigDBManager = nullptr;
+ SwWrtShell* pWorkShell = nullptr;
+ bool bWorkDocInitialized = false;
+
+ do
+ {
+ nStartRow = m_pImpl->pMergeData ? m_pImpl->pMergeData->xResultSet->getRow() : 0;
+
+ OUString sColumnData;
+
+ // Read the indicated data column, which should contain a valid mail
+ // address or an optional file name
+ if( bMT_EMAIL || bColumnName )
+ {
+ sColumnData = GetDBField( xColumnProp, aColumnDBFormat );
+ }
+
+ // create a new temporary file name - only done once in case of bCreateSingleFile
+ if( bNeedsTempFiles && ( !bWorkDocInitialized || !bCreateSingleFile ))
+ {
+ OUString sPrefix = sDescriptorPrefix;
+ OUString sLeading;
+
+ //#i97667# if the name is from a database field then it will be used _as is_
+ if( bColumnName && !bMT_EMAIL )
+ {
+ if (!sColumnData.isEmpty())
+ sLeading = sColumnData;
+ else
+ sLeading = "_";
+ }
+ else
+ {
+ INetURLObject aEntry( sPrefix );
+ sLeading = aEntry.GetBase();
+ aEntry.removeSegment();
+ sPrefix = aEntry.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ }
+
+ OUString sExt(comphelper::string::stripStart(pStoreToFilter->GetDefaultExtension(), '*'));
+ aTempFile.reset( new utl::TempFileNamed(sLeading, sColumnData.isEmpty(), sExt, &sPrefix, true) );
+ if( !aTempFile->IsValid() )
+ {
+ ErrorHandler::HandleError( ERRCODE_IO_NOTSUPPORTED );
+ m_aMergeStatus = MergeStatus::Error;
+ }
+ }
+
+ uno::Sequence< beans::PropertyValue > aSaveToFilterDataOptions( rMergeDescriptor.aSaveToFilterData );
+
+ if( bMT_EMAIL || bPasswordColumnName )
+ {
+ OUString sPasswordColumnData = GetDBField( xPasswordColumnProp, aColumnDBFormat );
+ lcl_PrepareSaveFilterDataOptions( rMergeDescriptor.aSaveToFilterData, aSaveToFilterDataOptions, sPasswordColumnData );
+ }
+
+ if( IsMergeOk() )
+ {
+ std::unique_ptr< INetURLObject > aTempFileURL;
+ if( bNeedsTempFiles )
+ aTempFileURL.reset( new INetURLObject(aTempFile->GetURL()));
+ if( !bIsMergeSilent ) {
+ if( !bMT_PRINTER )
+ static_cast<CreateMonitor*>(xProgressDlg.get())->SetCurrentPosition(nDocNo);
+ else {
+ PrintMonitor *pPrintMonDlg = static_cast<PrintMonitor*>(xProgressDlg.get());
+ pPrintMonDlg->m_xPrinter->set_label(bNeedsTempFiles
+ ? aTempFileURL->GetBase() : pSourceDocSh->GetTitle( 2));
+ OUString sStat = SwResId(STR_STATSTR_LETTER) + " " + OUString::number( nDocNo );
+ pPrintMonDlg->m_xPrintInfo->set_label(sStat);
+ }
+ //TODO xProgressDlg->queue_draw();
+ }
+
+ Scheduler::ProcessEventsToIdle();
+
+ // Create a copy of the source document and work with that one instead of the source.
+ // If we're not in the single file mode (which requires modifying the document for the merging),
+ // it is enough to do this just once. Currently PDF also has to be treated special.
+ if( !bWorkDocInitialized || bCreateSingleFile || bIsPDFexport || bIsMultiFile )
+ {
+ assert( !xWorkDocSh.Is());
+ pWorkDocOrigDBManager = this;
+ xWorkDocSh = lcl_CreateWorkingDocument( WorkingDocType::COPY,
+ *pSourceShell, nullptr, &pWorkDocOrigDBManager,
+ &pWorkView, &pWorkShell, &pWorkDoc );
+ if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
+ lcl_SaveDebugDoc( xWorkDocSh, "WorkDoc", nDocNo );
+
+ // #i69458# lock fields to prevent access to the result set while calculating layout
+ // tdf#92324: and do not unlock: keep document locked during printing to avoid
+ // ExpFields update during printing, generation of preview, etc.
+ pWorkShell->LockExpFields();
+ pWorkShell->CalcLayout();
+ // tdf#121168: Now force correct page descriptions applied to page frames. Without
+ // this, e.g., page frames starting with sections could have page descriptions set
+ // wrong. This would lead to wrong page styles applied in SwDoc::AppendDoc below.
+ pWorkShell->GetViewOptions()->SetIdle(true);
+ for (auto aLayout : pWorkShell->GetDoc()->GetAllLayouts())
+ {
+ aLayout->FreezeLayout(false);
+ aLayout->AllCheckPageDescs();
+ }
+ }
+
+ lcl_emitEvent(SfxEventHintId::SwEventFieldMerge, STR_SW_EVENT_FIELD_MERGE, xWorkDocSh);
+
+ // tdf#92324: Allow ExpFields update only by explicit instruction to avoid
+ // database cursor movement on any other fields update, for example during
+ // print preview and other operations
+ if ( pWorkShell->IsExpFieldsLocked() )
+ pWorkShell->UnlockExpFields();
+ pWorkShell->SwViewShell::UpdateFields();
+ pWorkShell->LockExpFields();
+
+ lcl_emitEvent(SfxEventHintId::SwEventFieldMergeFinished, STR_SW_EVENT_FIELD_MERGE_FINISHED, xWorkDocSh);
+
+ // also emit MailMergeEvent on XInterface if possible
+ const SwXMailMerge *pEvtSrc = GetMailMergeEvtSrc();
+ if(pEvtSrc)
+ {
+ rtl::Reference< SwXMailMerge > xRef(
+ const_cast<SwXMailMerge*>(pEvtSrc) );
+ text::MailMergeEvent aEvt( static_cast<text::XMailMergeBroadcaster*>(xRef.get()), xWorkDocSh->GetModel() );
+ SolarMutexReleaser rel;
+ xRef->LaunchMailMergeEvent( aEvt );
+ }
+
+ // working copy is merged - prepare final steps depending on merge options
+
+ if( bCreateSingleFile )
+ {
+ assert( pTargetShell && "no target shell available!" );
+
+ // prepare working copy and target to append
+
+ pWorkDoc->RemoveInvisibleContent();
+ // remove of invisible content has influence on page count and so on fields for page count,
+ // therefore layout has to be updated before fields are converted to text
+ pWorkShell->CalcLayout();
+ pWorkShell->ConvertFieldsToText();
+ pWorkShell->SetNumberingRestart();
+ if( bSynchronizedDoc )
+ {
+ lcl_RemoveSectionLinks( *pWorkShell );
+ }
+
+ if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
+ lcl_SaveDebugDoc( xWorkDocSh, "WorkDoc", nDocNo );
+
+ // append the working document to the target document
+ if( targetDocPageCount % 2 == 1 )
+ ++targetDocPageCount; // Docs always start on odd pages (so offset must be even).
+ SwNodeIndex appendedDocStart = pTargetDoc->AppendDoc( *pWorkDoc,
+ nStartingPageNo, !bWorkDocInitialized, targetDocPageCount, nDocNo);
+ targetDocPageCount += pWorkShell->GetPageCnt();
+
+ if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
+ lcl_SaveDebugDoc( xTargetDocShell.get(), "MergeDoc" );
+
+ if (bMT_SHELL)
+ {
+ SwDocMergeInfo aMergeInfo;
+ // Name of the mark is actually irrelevant, UNO bookmarks have internals names.
+ aMergeInfo.startPageInTarget = pTargetDoc->getIDocumentMarkAccess()->makeMark(
+ SwPaM(appendedDocStart), "", IDocumentMarkAccess::MarkType::UNO_BOOKMARK,
+ ::sw::mark::InsertMode::New);
+ aMergeInfo.nDBRow = nStartRow;
+ rMergeDescriptor.pMailMergeConfigItem->AddMergedDocument( aMergeInfo );
+ }
+ }
+ else
+ {
+ assert( bNeedsTempFiles );
+ assert( pWorkShell->IsExpFieldsLocked() );
+
+ if (bIsMultiFile && pWorkDoc->HasInvisibleContent())
+ {
+ pWorkDoc->RemoveInvisibleContent();
+ pWorkShell->CalcLayout();
+ pWorkShell->ConvertFieldsToText();
+ }
+
+ // fields are locked, so it's fine to
+ // restore the old / empty DB manager for save
+ pWorkDoc->SetDBManager( pWorkDocOrigDBManager );
+
+ // save merged document
+ OUString sFileURL;
+ if( !lcl_SaveDoc( aTempFileURL.get(), pStoreToFilter, pStoreToFilterOptions,
+ &aSaveToFilterDataOptions, bIsPDFexport,
+ xWorkDocSh, *pWorkShell, &sFileURL ) )
+ {
+ m_aMergeStatus = MergeStatus::Error;
+ }
+
+ // back to the MM DB manager
+ pWorkDoc->SetDBManager( this );
+
+ if( bMT_EMAIL && !IsMergeError() )
+ {
+ // schedule file for later removal
+ aFilesToRemove.push_back( sFileURL );
+
+ if( !SwMailMergeHelper::CheckMailAddress( sColumnData ) )
+ {
+ OSL_FAIL("invalid e-Mail address in database column");
+ }
+ else
+ {
+ uno::Reference< mail::XMailMessage > xMessage = lcl_CreateMailFromDoc(
+ rMergeDescriptor, sFileURL, sColumnData, sMailBodyMimeType,
+ sMailEncoding, pStoreToFilter->GetMimeType() );
+ if( xMessage.is() )
+ {
+ std::unique_lock aGuard( m_pImpl->m_aAllEmailSendMutex );
+ m_pImpl->m_xLastMessage.set( xMessage );
+ xMailDispatcher->enqueueMailMessage( xMessage );
+ if( !xMailDispatcher->isStarted() )
+ xMailDispatcher->start();
+ }
+ }
+ }
+ }
+ if( bCreateSingleFile || bIsPDFexport || bIsMultiFile)
+ {
+ pWorkDoc->SetDBManager( pWorkDocOrigDBManager );
+ pWorkDoc.clear();
+ xWorkDocSh->DoClose();
+ xWorkDocSh = nullptr;
+ }
+ }
+
+ bWorkDocInitialized = true;
+ nDocNo++;
+ nEndRow = m_pImpl->pMergeData ? m_pImpl->pMergeData->xResultSet->getRow() : 0;
+
+ // Freeze the layouts of the target document after the first inserted
+ // sub-document, to get the correct PageDesc.
+ if(!bFreezedLayouts && bCreateSingleFile)
+ {
+ for ( auto aLayout : pTargetShell->GetDoc()->GetAllLayouts() )
+ aLayout->FreezeLayout(true);
+ bFreezedLayouts = true;
+ }
+ } while( IsMergeOk() &&
+ ((bSynchronizedDoc && (nStartRow != nEndRow)) ? IsValidMergeRecord() : ToNextMergeRecord()));
+
+ if ( xWorkDocSh.Is() && pWorkView->GetWrtShell().IsExpFieldsLocked() )
+ {
+ // Unlock document fields after merge complete
+ pWorkView->GetWrtShell().UnlockExpFields();
+ }
+
+ if( !bCreateSingleFile )
+ {
+ if( bMT_PRINTER )
+ Printer::FinishPrintJob( pWorkView->GetPrinterController());
+ if( !bIsPDFexport )
+ {
+ if (pWorkDoc)
+ pWorkDoc->SetDBManager(pWorkDocOrigDBManager);
+ if (xWorkDocSh.Is())
+ xWorkDocSh->DoClose();
+ }
+ }
+ else if( IsMergeOk() ) // && bCreateSingleFile
+ {
+ Application::Reschedule( true );
+
+ // sw::DocumentLayoutManager::CopyLayoutFormat() did not generate
+ // unique fly names, do it here once.
+ pTargetDoc->SetInMailMerge(false);
+ pTargetDoc->SetAllUniqueFlyNames();
+
+ // Unfreeze target document layouts and correct all PageDescs.
+ SAL_INFO( "sw.pageframe", "(MergeMailFiles pTargetShell->CalcLayout in" );
+ pTargetShell->CalcLayout();
+ SAL_INFO( "sw.pageframe", "MergeMailFiles pTargetShell->CalcLayout out)" );
+ pTargetShell->GetViewOptions()->SetIdle( true );
+ pTargetDoc->GetIDocumentUndoRedo().DoUndo( true );
+ for ( auto aLayout : pTargetShell->GetDoc()->GetAllLayouts() )
+ {
+ aLayout->FreezeLayout(false);
+ aLayout->AllCheckPageDescs();
+ }
+
+ Application::Reschedule( true );
+
+ if( IsMergeOk() && bMT_FILE )
+ {
+ // save merged document
+ assert( aTempFile );
+ INetURLObject aTempFileURL;
+ if (sDescriptorPrefix.isEmpty() || !rMergeDescriptor.bPrefixIsFilename)
+ aTempFileURL.SetURL( aTempFile->GetURL() );
+ else
+ {
+ aTempFileURL.SetURL(sDescriptorPrefix);
+ // remove the unneeded temporary file
+ aTempFile->EnableKillingFile();
+ }
+ if( !lcl_SaveDoc( &aTempFileURL, pStoreToFilter,
+ pStoreToFilterOptions, &rMergeDescriptor.aSaveToFilterData,
+ bIsPDFexport, xTargetDocShell.get(), *pTargetShell ) )
+ {
+ m_aMergeStatus = MergeStatus::Error;
+ }
+ }
+ else if( IsMergeOk() && bMT_PRINTER )
+ {
+ // print the target document
+ uno::Sequence< beans::PropertyValue > aOptions( rMergeDescriptor.aPrintOptions );
+ lcl_PreparePrinterOptions( rMergeDescriptor.aPrintOptions, aOptions );
+ pTargetView->ExecPrint( aOptions, bIsMergeSilent, false/*bPrintAsync*/ );
+ }
+ }
+
+ // we also show canceled documents, as long as there was no error
+ if( !IsMergeError() && bMT_SHELL )
+ // leave docshell available for caller (e.g. MM wizard)
+ rMergeDescriptor.pMailMergeConfigItem->SetTargetView( pTargetView );
+ else if( xTargetDocShell.is() )
+ xTargetDocShell->DoClose();
+
+ Application::Reschedule( true );
+
+ if (xProgressDlg)
+ {
+ xProgressDlg->response(RET_OK);
+ }
+
+ // unlock all dispatchers
+ pViewFrame = SfxViewFrame::GetFirst(pSourceDocSh);
+ while (pViewFrame)
+ {
+ pViewFrame->GetDispatcher()->Lock(false);
+ pViewFrame = SfxViewFrame::GetNext(*pViewFrame, pSourceDocSh);
+ }
+
+ SW_MOD()->SetView(&pSourceShell->GetView());
+
+ if( xMailDispatcher.is() )
+ {
+ if( IsMergeOk() )
+ {
+ // TODO: Instead of polling via an AutoTimer, post an Idle event,
+ // if the main loop has been made thread-safe.
+ AutoTimer aEmailDispatcherPollTimer("sw::SwDBManager aEmailDispatcherPollTimer");
+ aEmailDispatcherPollTimer.SetTimeout( 500 );
+ aEmailDispatcherPollTimer.Start();
+ while( IsMergeOk() && m_pImpl->m_xLastMessage.is() && !Application::IsQuit())
+ Application::Yield();
+ aEmailDispatcherPollTimer.Stop();
+ }
+ xMailDispatcher->stop();
+ xMailDispatcher->shutdown();
+ }
+
+ // remove the temporary files
+ // has to be done after xMailDispatcher is finished, as mails may be
+ // delivered as message attachments!
+ for( const OUString &sFileURL : aFilesToRemove )
+ SWUnoHelper::UCB_DeleteFile( sFileURL );
+ }
+ catch (const uno::Exception&)
+ {
+ if (xProgressDlg)
+ {
+ xProgressDlg->response(RET_CANCEL);
+ }
+ }
+
+ return !IsMergeError();
+}
+
+void SwDBManager::MergeCancel()
+{
+ if (m_aMergeStatus < MergeStatus::Cancel)
+ m_aMergeStatus = MergeStatus::Cancel;
+}
+
+// determine the column's Numberformat and transfer to the forwarded Formatter,
+// if applicable.
+sal_uInt32 SwDBManager::GetColumnFormat( const OUString& rDBName,
+ const OUString& rTableName,
+ const OUString& rColNm,
+ SvNumberFormatter* pNFormatr,
+ LanguageType nLanguage )
+{
+ sal_uInt32 nRet = 0;
+ if(pNFormatr)
+ {
+ uno::Reference< sdbc::XDataSource> xSource;
+ uno::Reference< sdbc::XConnection> xConnection;
+ bool bUseMergeData = false;
+ uno::Reference< sdbcx::XColumnsSupplier> xColsSupp;
+ bool bDisposeConnection = false;
+ if(m_pImpl->pMergeData &&
+ ((m_pImpl->pMergeData->sDataSource == rDBName && m_pImpl->pMergeData->sCommand == rTableName) ||
+ (rDBName.isEmpty() && rTableName.isEmpty())))
+ {
+ xConnection = m_pImpl->pMergeData->xConnection;
+ xSource = SwDBManager::getDataSourceAsParent(xConnection,rDBName);
+ bUseMergeData = true;
+ xColsSupp.set(m_pImpl->pMergeData->xResultSet, css::uno::UNO_QUERY);
+ }
+ if(!xConnection.is())
+ {
+ SwDBData aData;
+ aData.sDataSource = rDBName;
+ aData.sCommand = rTableName;
+ aData.nCommandType = -1;
+ SwDSParam* pParam = FindDSData(aData, false);
+ if(pParam && pParam->xConnection.is())
+ {
+ xConnection = pParam->xConnection;
+ xColsSupp.set(pParam->xResultSet, css::uno::UNO_QUERY);
+ }
+ else
+ {
+ xConnection = RegisterConnection( rDBName );
+ bDisposeConnection = true;
+ }
+ if(bUseMergeData)
+ m_pImpl->pMergeData->xConnection = xConnection;
+ }
+ bool bDispose = !xColsSupp.is();
+ if(bDispose)
+ {
+ xColsSupp = SwDBManager::GetColumnSupplier(xConnection, rTableName);
+ }
+ if(xColsSupp.is())
+ {
+ uno::Reference<container::XNameAccess> xCols;
+ try
+ {
+ xCols = xColsSupp->getColumns();
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("sw.mailmerge", "Exception in getColumns()");
+ }
+ if(!xCols.is() || !xCols->hasByName(rColNm))
+ return nRet;
+ uno::Any aCol = xCols->getByName(rColNm);
+ uno::Reference< beans::XPropertySet > xColumn;
+ aCol >>= xColumn;
+ nRet = GetColumnFormat(xSource, xConnection, xColumn, pNFormatr, nLanguage);
+ if(bDispose)
+ {
+ ::comphelper::disposeComponent( xColsSupp );
+ }
+ if(bDisposeConnection)
+ {
+ ::comphelper::disposeComponent( xConnection );
+ }
+ }
+ else
+ nRet = pNFormatr->GetFormatIndex( NF_NUMBER_STANDARD, LANGUAGE_SYSTEM );
+ }
+ return nRet;
+}
+
+sal_uInt32 SwDBManager::GetColumnFormat( uno::Reference< sdbc::XDataSource> const & xSource_in,
+ uno::Reference< sdbc::XConnection> const & xConnection,
+ uno::Reference< beans::XPropertySet> const & xColumn,
+ SvNumberFormatter* pNFormatr,
+ LanguageType nLanguage )
+{
+ auto xSource = xSource_in;
+
+ // set the NumberFormat in the doc if applicable
+ sal_uInt32 nRet = 0;
+
+ if(!xSource.is())
+ {
+ uno::Reference<container::XChild> xChild(xConnection, uno::UNO_QUERY);
+ if ( xChild.is() )
+ xSource.set(xChild->getParent(), uno::UNO_QUERY);
+ }
+ if(xSource.is() && xConnection.is() && xColumn.is() && pNFormatr)
+ {
+ rtl::Reference<SvNumberFormatsSupplierObj> pNumFormat = new SvNumberFormatsSupplierObj( pNFormatr );
+ uno::Reference< util::XNumberFormats > xDocNumberFormats = pNumFormat->getNumberFormats();
+ uno::Reference< util::XNumberFormatTypes > xDocNumberFormatTypes(xDocNumberFormats, uno::UNO_QUERY);
+
+ css::lang::Locale aLocale( LanguageTag( nLanguage ).getLocale());
+
+ //get the number formatter of the data source
+ uno::Reference<beans::XPropertySet> xSourceProps(xSource, uno::UNO_QUERY);
+ uno::Reference< util::XNumberFormats > xNumberFormats;
+ if(xSourceProps.is())
+ {
+ uno::Any aFormats = xSourceProps->getPropertyValue("NumberFormatsSupplier");
+ if(aFormats.hasValue())
+ {
+ uno::Reference<util::XNumberFormatsSupplier> xSuppl;
+ aFormats >>= xSuppl;
+ if(xSuppl.is())
+ {
+ xNumberFormats = xSuppl->getNumberFormats();
+ }
+ }
+ }
+ bool bUseDefault = true;
+ try
+ {
+ uno::Any aFormatKey = xColumn->getPropertyValue("FormatKey");
+ if(aFormatKey.hasValue())
+ {
+ sal_Int32 nFormat = 0;
+ aFormatKey >>= nFormat;
+ if(xNumberFormats.is())
+ {
+ try
+ {
+ uno::Reference<beans::XPropertySet> xNumProps = xNumberFormats->getByKey( nFormat );
+ uno::Any aFormatString = xNumProps->getPropertyValue("FormatString");
+ uno::Any aLocaleVal = xNumProps->getPropertyValue("Locale");
+ OUString sFormat;
+ aFormatString >>= sFormat;
+ lang::Locale aLoc;
+ aLocaleVal >>= aLoc;
+ nFormat = xDocNumberFormats->queryKey( sFormat, aLoc, false );
+ if(NUMBERFORMAT_ENTRY_NOT_FOUND == sal::static_int_cast< sal_uInt32, sal_Int32>(nFormat))
+ nFormat = xDocNumberFormats->addNew( sFormat, aLoc );
+
+ nRet = nFormat;
+ bUseDefault = false;
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("sw.mailmerge", "illegal number format key");
+ }
+ }
+ }
+ }
+ catch(const uno::Exception&)
+ {
+ SAL_WARN("sw.mailmerge", "no FormatKey property found");
+ }
+ if(bUseDefault)
+ nRet = dbtools::getDefaultNumberFormat(xColumn, xDocNumberFormatTypes, aLocale);
+ }
+ return nRet;
+}
+
+sal_Int32 SwDBManager::GetColumnType( const OUString& rDBName,
+ const OUString& rTableName,
+ const OUString& rColNm )
+{
+ sal_Int32 nRet = sdbc::DataType::SQLNULL;
+ SwDBData aData;
+ aData.sDataSource = rDBName;
+ aData.sCommand = rTableName;
+ aData.nCommandType = -1;
+ SwDSParam* pParam = FindDSData(aData, false);
+ uno::Reference< sdbc::XConnection> xConnection;
+ uno::Reference< sdbcx::XColumnsSupplier > xColsSupp;
+ bool bDispose = false;
+ if(pParam && pParam->xConnection.is())
+ {
+ xConnection = pParam->xConnection;
+ xColsSupp.set( pParam->xResultSet, uno::UNO_QUERY );
+ }
+ else
+ {
+ xConnection = RegisterConnection( rDBName );
+ }
+ if( !xColsSupp.is() )
+ {
+ xColsSupp = SwDBManager::GetColumnSupplier(xConnection, rTableName);
+ bDispose = true;
+ }
+ if(xColsSupp.is())
+ {
+ uno::Reference<container::XNameAccess> xCols = xColsSupp->getColumns();
+ if(xCols->hasByName(rColNm))
+ {
+ uno::Any aCol = xCols->getByName(rColNm);
+ uno::Reference<beans::XPropertySet> xCol;
+ aCol >>= xCol;
+ uno::Any aType = xCol->getPropertyValue("Type");
+ aType >>= nRet;
+ }
+ if(bDispose)
+ ::comphelper::disposeComponent( xColsSupp );
+ }
+ return nRet;
+}
+
+uno::Reference< sdbc::XConnection> SwDBManager::GetConnection(const OUString& rDataSource,
+ uno::Reference<sdbc::XDataSource>& rxSource, const SwView *pView)
+{
+ uno::Reference< sdbc::XConnection> xConnection;
+ uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
+ try
+ {
+ uno::Reference<sdb::XCompletedConnection> xComplConnection(dbtools::getDataSource(rDataSource, xContext), uno::UNO_QUERY);
+ if ( xComplConnection.is() )
+ {
+ rxSource.set(xComplConnection, uno::UNO_QUERY);
+ weld::Window* pWindow = pView ? pView->GetFrameWeld() : nullptr;
+ uno::Reference< task::XInteractionHandler > xHandler( task::InteractionHandler::createWithParent(xContext, pWindow ? pWindow->GetXWindow() : nullptr), uno::UNO_QUERY_THROW );
+ xConnection = xComplConnection->connectWithCompletion( xHandler );
+ }
+ }
+ catch(const uno::Exception&)
+ {
+ }
+
+ return xConnection;
+}
+
+uno::Reference< sdbcx::XColumnsSupplier> SwDBManager::GetColumnSupplier(uno::Reference<sdbc::XConnection> const & xConnection,
+ const OUString& rTableOrQuery,
+ SwDBSelect eTableOrQuery)
+{
+ uno::Reference< sdbcx::XColumnsSupplier> xRet;
+ try
+ {
+ if(eTableOrQuery == SwDBSelect::UNKNOWN)
+ {
+ //search for a table with the given command name
+ uno::Reference<sdbcx::XTablesSupplier> xTSupplier(xConnection, uno::UNO_QUERY);
+ if(xTSupplier.is())
+ {
+ uno::Reference<container::XNameAccess> xTables = xTSupplier->getTables();
+ eTableOrQuery = xTables->hasByName(rTableOrQuery) ?
+ SwDBSelect::TABLE : SwDBSelect::QUERY;
+ }
+ }
+ sal_Int32 nCommandType = SwDBSelect::TABLE == eTableOrQuery ?
+ sdb::CommandType::TABLE : sdb::CommandType::QUERY;
+ uno::Reference< lang::XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
+ uno::Reference<sdbc::XRowSet> xRowSet(xMgr->createInstance("com.sun.star.sdb.RowSet"), uno::UNO_QUERY);
+
+ OUString sDataSource;
+ uno::Reference<sdbc::XDataSource> xSource = SwDBManager::getDataSourceAsParent(xConnection, sDataSource);
+ uno::Reference<beans::XPropertySet> xSourceProperties(xSource, uno::UNO_QUERY);
+ if(xSourceProperties.is())
+ {
+ xSourceProperties->getPropertyValue("Name") >>= sDataSource;
+ }
+
+ uno::Reference<beans::XPropertySet> xRowProperties(xRowSet, uno::UNO_QUERY);
+ xRowProperties->setPropertyValue("DataSourceName", uno::Any(sDataSource));
+ xRowProperties->setPropertyValue("Command", uno::Any(rTableOrQuery));
+ xRowProperties->setPropertyValue("CommandType", uno::Any(nCommandType));
+ xRowProperties->setPropertyValue("FetchSize", uno::Any(sal_Int32(10)));
+ xRowProperties->setPropertyValue("ActiveConnection", uno::Any(xConnection));
+ xRowSet->execute();
+ xRet.set( xRowSet, uno::UNO_QUERY );
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("sw.mailmerge", "Exception in SwDBManager::GetColumnSupplier");
+ }
+
+ return xRet;
+}
+
+OUString SwDBManager::GetDBField(uno::Reference<beans::XPropertySet> const & xColumnProps,
+ const SwDBFormatData& rDBFormatData,
+ double* pNumber)
+{
+ uno::Reference< sdb::XColumn > xColumn(xColumnProps, uno::UNO_QUERY);
+ OUString sRet;
+ assert( xColumn.is() && "SwDBManager::::ImportDBField: illegal arguments" );
+ if(!xColumn.is())
+ return sRet;
+
+ uno::Any aType = xColumnProps->getPropertyValue("Type");
+ sal_Int32 eDataType = sdbc::DataType::SQLNULL;
+ aType >>= eDataType;
+ switch(eDataType)
+ {
+ case sdbc::DataType::CHAR:
+ case sdbc::DataType::VARCHAR:
+ case sdbc::DataType::LONGVARCHAR:
+ try
+ {
+ sRet = xColumn->getString();
+ sRet = sRet.replace( '\xb', '\n' ); // MSWord uses \xb as a newline
+ }
+ catch(const sdbc::SQLException&)
+ {
+ }
+ break;
+ case sdbc::DataType::BIT:
+ case sdbc::DataType::BOOLEAN:
+ case sdbc::DataType::TINYINT:
+ case sdbc::DataType::SMALLINT:
+ case sdbc::DataType::INTEGER:
+ case sdbc::DataType::BIGINT:
+ case sdbc::DataType::FLOAT:
+ case sdbc::DataType::REAL:
+ case sdbc::DataType::DOUBLE:
+ case sdbc::DataType::NUMERIC:
+ case sdbc::DataType::DECIMAL:
+ case sdbc::DataType::DATE:
+ case sdbc::DataType::TIME:
+ case sdbc::DataType::TIMESTAMP:
+ {
+
+ try
+ {
+ sRet = dbtools::DBTypeConversion::getFormattedValue(
+ xColumnProps,
+ rDBFormatData.xFormatter,
+ rDBFormatData.aLocale,
+ rDBFormatData.aNullDate);
+ if (pNumber)
+ {
+ double fVal = xColumn->getDouble();
+ if(!xColumn->wasNull())
+ {
+ *pNumber = fVal;
+ }
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("sw.mailmerge", "");
+ }
+
+ }
+ break;
+ }
+
+ return sRet;
+}
+
+// checks if a desired data source table or query is open
+bool SwDBManager::IsDataSourceOpen(const OUString& rDataSource,
+ const OUString& rTableOrQuery, bool bMergeShell)
+{
+ if(m_pImpl->pMergeData)
+ {
+ return ((rDataSource == m_pImpl->pMergeData->sDataSource
+ && rTableOrQuery == m_pImpl->pMergeData->sCommand)
+ || (rDataSource.isEmpty() && rTableOrQuery.isEmpty()))
+ && m_pImpl->pMergeData->xResultSet.is();
+ }
+ else if(!bMergeShell)
+ {
+ SwDBData aData;
+ aData.sDataSource = rDataSource;
+ aData.sCommand = rTableOrQuery;
+ aData.nCommandType = -1;
+ SwDSParam* pFound = FindDSData(aData, false);
+ return (pFound && pFound->xResultSet.is());
+ }
+ return false;
+}
+
+// read column data at a specified position
+bool SwDBManager::GetColumnCnt(const OUString& rSourceName, const OUString& rTableName,
+ const OUString& rColumnName, sal_uInt32 nAbsRecordId,
+ LanguageType nLanguage,
+ OUString& rResult, double* pNumber)
+{
+ bool bRet = false;
+ SwDSParam* pFound = nullptr;
+ //check if it's the merge data source
+ if(m_pImpl->pMergeData &&
+ rSourceName == m_pImpl->pMergeData->sDataSource &&
+ rTableName == m_pImpl->pMergeData->sCommand)
+ {
+ pFound = m_pImpl->pMergeData.get();
+ }
+ else
+ {
+ SwDBData aData;
+ aData.sDataSource = rSourceName;
+ aData.sCommand = rTableName;
+ aData.nCommandType = -1;
+ pFound = FindDSData(aData, false);
+ }
+ if (!pFound)
+ return false;
+ //check validity of supplied record Id
+ if(pFound->aSelection.hasElements())
+ {
+ //the destination has to be an element of the selection
+ bool bFound = std::any_of(std::cbegin(pFound->aSelection), std::cend(pFound->aSelection),
+ [nAbsRecordId](const uno::Any& rSelection) {
+ sal_Int32 nSelection = 0;
+ rSelection >>= nSelection;
+ return nSelection == static_cast<sal_Int32>(nAbsRecordId);
+ });
+ if(!bFound)
+ return false;
+ }
+ if( pFound->HasValidRecord() )
+ {
+ sal_Int32 nOldRow = 0;
+ try
+ {
+ nOldRow = pFound->xResultSet->getRow();
+ }
+ catch(const uno::Exception&)
+ {
+ return false;
+ }
+ //position to the desired index
+ bool bMove = true;
+ if ( nOldRow != static_cast<sal_Int32>(nAbsRecordId) )
+ bMove = lcl_MoveAbsolute(pFound, nAbsRecordId);
+ if(bMove)
+ bRet = lcl_GetColumnCnt(pFound, rColumnName, nLanguage, rResult, pNumber);
+ if ( nOldRow != static_cast<sal_Int32>(nAbsRecordId) )
+ lcl_MoveAbsolute(pFound, nOldRow);
+ }
+ return bRet;
+}
+
+// reads the column data at the current position
+bool SwDBManager::GetMergeColumnCnt(const OUString& rColumnName, LanguageType nLanguage,
+ OUString &rResult, double *pNumber)
+{
+ if( !IsValidMergeRecord() )
+ {
+ rResult.clear();
+ return false;
+ }
+
+ bool bRet = lcl_GetColumnCnt(m_pImpl->pMergeData.get(), rColumnName, nLanguage, rResult, pNumber);
+ return bRet;
+}
+
+bool SwDBManager::ToNextMergeRecord()
+{
+ assert( m_pImpl->pMergeData && m_pImpl->pMergeData->xResultSet.is() && "no data source in merge" );
+ return lcl_ToNextRecord( m_pImpl->pMergeData.get() );
+}
+
+bool SwDBManager::FillCalcWithMergeData( SvNumberFormatter *pDocFormatter,
+ LanguageType nLanguage, SwCalc &rCalc )
+{
+ if( !IsValidMergeRecord() )
+ return false;
+
+ uno::Reference< sdbcx::XColumnsSupplier > xColsSupp( m_pImpl->pMergeData->xResultSet, uno::UNO_QUERY );
+ if( !xColsSupp.is() )
+ return false;
+
+ {
+ uno::Reference<container::XNameAccess> xCols = xColsSupp->getColumns();
+ const uno::Sequence<OUString> aColNames = xCols->getElementNames();
+ OUString aString;
+
+ // add the "record number" variable, as SwCalc::VarLook would.
+ rCalc.VarChange( GetAppCharClass().lowercase(
+ SwFieldType::GetTypeStr(SwFieldTypesEnum::DatabaseSetNumber) ), GetSelectedRecordId() );
+
+ for( const OUString& rColName : aColNames )
+ {
+ // get the column type
+ sal_Int32 nColumnType = sdbc::DataType::SQLNULL;
+ uno::Any aCol = xCols->getByName( rColName );
+ uno::Reference<beans::XPropertySet> xColumnProps;
+ aCol >>= xColumnProps;
+ uno::Any aType = xColumnProps->getPropertyValue( "Type" );
+ aType >>= nColumnType;
+ double aNumber = DBL_MAX;
+
+ lcl_GetColumnCnt( m_pImpl->pMergeData.get(), xColumnProps, nLanguage, aString, &aNumber );
+
+ sal_uInt32 nFormat = GetColumnFormat( m_pImpl->pMergeData->sDataSource,
+ m_pImpl->pMergeData->sCommand,
+ rColName, pDocFormatter, nLanguage );
+ // aNumber is overwritten by SwDBField::FormatValue, so store initial status
+ bool colIsNumber = aNumber != DBL_MAX;
+ bool bValidValue = SwDBField::FormatValue( pDocFormatter, aString, nFormat,
+ aNumber, nColumnType );
+ if( colIsNumber )
+ {
+ if( bValidValue )
+ {
+ SwSbxValue aValue;
+ aValue.PutDouble( aNumber );
+ aValue.SetDBvalue( true );
+ SAL_INFO( "sw.ui", "'" << rColName << "': " << aNumber << " / " << aString );
+ rCalc.VarChange( rColName, aValue );
+ }
+ }
+ else
+ {
+ SwSbxValue aValue;
+ aValue.PutString( aString );
+ aValue.SetDBvalue( true );
+ SAL_INFO( "sw.ui", "'" << rColName << "': " << aString );
+ rCalc.VarChange( rColName, aValue );
+ }
+ }
+ }
+
+ return true;
+}
+
+void SwDBManager::ToNextRecord(
+ const OUString& rDataSource, const OUString& rCommand)
+{
+ SwDSParam* pFound = nullptr;
+ if(m_pImpl->pMergeData &&
+ rDataSource == m_pImpl->pMergeData->sDataSource &&
+ rCommand == m_pImpl->pMergeData->sCommand)
+ {
+ pFound = m_pImpl->pMergeData.get();
+ }
+ else
+ {
+ SwDBData aData;
+ aData.sDataSource = rDataSource;
+ aData.sCommand = rCommand;
+ aData.nCommandType = -1;
+ pFound = FindDSData(aData, false);
+ }
+ lcl_ToNextRecord( pFound );
+}
+
+static bool lcl_ToNextRecord( SwDSParam* pParam, const SwDBNextRecord action )
+{
+ bool bRet = true;
+
+ assert( SwDBNextRecord::NEXT == action ||
+ (SwDBNextRecord::FIRST == action && pParam) );
+ if( nullptr == pParam )
+ return false;
+
+ if( action == SwDBNextRecord::FIRST )
+ {
+ pParam->nSelectionIndex = 0;
+ pParam->bEndOfDB = false;
+ }
+
+ if( !pParam->HasValidRecord() )
+ return false;
+
+ try
+ {
+ if( pParam->aSelection.hasElements() )
+ {
+ if( pParam->nSelectionIndex >= pParam->aSelection.getLength() )
+ pParam->bEndOfDB = true;
+ else
+ {
+ sal_Int32 nPos = 0;
+ pParam->aSelection.getConstArray()[ pParam->nSelectionIndex ] >>= nPos;
+ pParam->bEndOfDB = !pParam->xResultSet->absolute( nPos );
+ }
+ }
+ else if( action == SwDBNextRecord::FIRST )
+ {
+ pParam->bEndOfDB = !pParam->xResultSet->first();
+ }
+ else
+ {
+ sal_Int32 nBefore = pParam->xResultSet->getRow();
+ pParam->bEndOfDB = !pParam->xResultSet->next();
+ if( !pParam->bEndOfDB && nBefore == pParam->xResultSet->getRow() )
+ {
+ // next returned true but it didn't move
+ ::dbtools::throwFunctionSequenceException( pParam->xResultSet );
+ }
+ }
+
+ ++pParam->nSelectionIndex;
+ bRet = !pParam->bEndOfDB;
+ }
+ catch( const uno::Exception & )
+ {
+ // we allow merging with empty databases, so don't warn on init
+ TOOLS_WARN_EXCEPTION_IF(action == SwDBNextRecord::NEXT,
+ "sw.mailmerge", "exception in ToNextRecord()");
+ pParam->bEndOfDB = true;
+ bRet = false;
+ }
+ return bRet;
+}
+
+// synchronized labels contain a next record field at their end
+// to assure that the next page can be created in mail merge
+// the cursor position must be validated
+bool SwDBManager::IsValidMergeRecord() const
+{
+ return( m_pImpl->pMergeData && m_pImpl->pMergeData->HasValidRecord() );
+}
+
+sal_uInt32 SwDBManager::GetSelectedRecordId()
+{
+ sal_uInt32 nRet = 0;
+ assert( m_pImpl->pMergeData &&
+ m_pImpl->pMergeData->xResultSet.is() && "no data source in merge" );
+ if(!m_pImpl->pMergeData || !m_pImpl->pMergeData->xResultSet.is())
+ return 0;
+ try
+ {
+ nRet = m_pImpl->pMergeData->xResultSet->getRow();
+ }
+ catch(const uno::Exception&)
+ {
+ }
+ return nRet;
+}
+
+bool SwDBManager::ToRecordId(sal_Int32 nSet)
+{
+ assert( m_pImpl->pMergeData &&
+ m_pImpl->pMergeData->xResultSet.is() && "no data source in merge" );
+ if(!m_pImpl->pMergeData || !m_pImpl->pMergeData->xResultSet.is()|| nSet < 0)
+ return false;
+ bool bRet = false;
+ sal_Int32 nAbsPos = nSet;
+ assert(nAbsPos >= 0);
+ bRet = lcl_MoveAbsolute(m_pImpl->pMergeData.get(), nAbsPos);
+ m_pImpl->pMergeData->bEndOfDB = !bRet;
+ return bRet;
+}
+
+bool SwDBManager::OpenDataSource(const OUString& rDataSource, const OUString& rTableOrQuery)
+{
+ SwDBData aData;
+ aData.sDataSource = rDataSource;
+ aData.sCommand = rTableOrQuery;
+ aData.nCommandType = -1;
+
+ SwDSParam* pFound = FindDSData(aData, true);
+ if(pFound->xResultSet.is())
+ return true;
+ SwDSParam* pParam = FindDSConnection(rDataSource, false);
+ if(pParam && pParam->xConnection.is())
+ pFound->xConnection = pParam->xConnection;
+ if(pFound->xConnection.is())
+ {
+ try
+ {
+ uno::Reference< sdbc::XDatabaseMetaData > xMetaData = pFound->xConnection->getMetaData();
+ try
+ {
+ pFound->bScrollable = xMetaData
+ ->supportsResultSetType(sal_Int32(sdbc::ResultSetType::SCROLL_INSENSITIVE));
+ }
+ catch(const uno::Exception&)
+ {
+ // DB driver may not be ODBC 3.0 compliant
+ pFound->bScrollable = true;
+ }
+ pFound->xStatement = pFound->xConnection->createStatement();
+ OUString aQuoteChar = xMetaData->getIdentifierQuoteString();
+ OUString sStatement = "SELECT * FROM " + aQuoteChar + rTableOrQuery + aQuoteChar;
+ pFound->xResultSet = pFound->xStatement->executeQuery( sStatement );
+
+ //after executeQuery the cursor must be positioned
+ pFound->bEndOfDB = !pFound->xResultSet->next();
+ ++pFound->nSelectionIndex;
+ }
+ catch (const uno::Exception&)
+ {
+ pFound->xResultSet = nullptr;
+ pFound->xStatement = nullptr;
+ pFound->xConnection = nullptr;
+ }
+ }
+ return pFound->xResultSet.is();
+}
+
+uno::Reference< sdbc::XConnection> const & SwDBManager::RegisterConnection(OUString const& rDataSource)
+{
+ SwDSParam* pFound = SwDBManager::FindDSConnection(rDataSource, true);
+ uno::Reference< sdbc::XDataSource> xSource;
+ if(!pFound->xConnection.is())
+ {
+ SwView* pView = (m_pDoc && m_pDoc->GetDocShell()) ? m_pDoc->GetDocShell()->GetView() : nullptr;
+ pFound->xConnection = SwDBManager::GetConnection(rDataSource, xSource, pView);
+ try
+ {
+ uno::Reference<lang::XComponent> xComponent(pFound->xConnection, uno::UNO_QUERY);
+ if(xComponent.is())
+ xComponent->addEventListener(m_pImpl->m_xDisposeListener);
+ }
+ catch(const uno::Exception&)
+ {
+ }
+ }
+ return pFound->xConnection;
+}
+
+sal_uInt32 SwDBManager::GetSelectedRecordId(
+ const OUString& rDataSource, const OUString& rTableOrQuery, sal_Int32 nCommandType)
+{
+ sal_uInt32 nRet = 0xffffffff;
+ //check for merge data source first
+ if(m_pImpl->pMergeData &&
+ ((rDataSource == m_pImpl->pMergeData->sDataSource &&
+ rTableOrQuery == m_pImpl->pMergeData->sCommand) ||
+ (rDataSource.isEmpty() && rTableOrQuery.isEmpty())) &&
+ (nCommandType == -1 || nCommandType == m_pImpl->pMergeData->nCommandType) &&
+ m_pImpl->pMergeData->xResultSet.is())
+ {
+ nRet = GetSelectedRecordId();
+ }
+ else
+ {
+ SwDBData aData;
+ aData.sDataSource = rDataSource;
+ aData.sCommand = rTableOrQuery;
+ aData.nCommandType = nCommandType;
+ SwDSParam* pFound = FindDSData(aData, false);
+ if(pFound && pFound->xResultSet.is())
+ {
+ try
+ { //if a selection array is set the current row at the result set may not be set yet
+ if(pFound->aSelection.hasElements())
+ {
+ sal_Int32 nSelIndex = pFound->nSelectionIndex;
+ if(nSelIndex >= pFound->aSelection.getLength())
+ nSelIndex = pFound->aSelection.getLength() -1;
+ pFound->aSelection.getConstArray()[nSelIndex] >>= nRet;
+
+ }
+ else
+ nRet = pFound->xResultSet->getRow();
+ }
+ catch(const uno::Exception&)
+ {
+ }
+ }
+ }
+ return nRet;
+}
+
+// close all data sources - after fields were updated
+void SwDBManager::CloseAll(bool bIncludingMerge)
+{
+ //the only thing done here is to reset the selection index
+ //all connections stay open
+ for (auto & pParam : m_DataSourceParams)
+ {
+ if (bIncludingMerge || pParam.get() != m_pImpl->pMergeData.get())
+ {
+ pParam->nSelectionIndex = 0;
+ pParam->bEndOfDB = false;
+ try
+ {
+ if(!m_bInMerge && pParam->xResultSet.is())
+ pParam->xResultSet->first();
+ }
+ catch(const uno::Exception&)
+ {}
+ }
+ }
+}
+
+SwDSParam* SwDBManager::FindDSData(const SwDBData& rData, bool bCreate)
+{
+ //prefer merge data if available
+ if(m_pImpl->pMergeData &&
+ ((rData.sDataSource == m_pImpl->pMergeData->sDataSource &&
+ rData.sCommand == m_pImpl->pMergeData->sCommand) ||
+ (rData.sDataSource.isEmpty() && rData.sCommand.isEmpty())) &&
+ (rData.nCommandType == -1 || rData.nCommandType == m_pImpl->pMergeData->nCommandType ||
+ (bCreate && m_pImpl->pMergeData->nCommandType == -1)))
+ {
+ return m_pImpl->pMergeData.get();
+ }
+
+ SwDSParam* pFound = nullptr;
+ for (size_t nPos = m_DataSourceParams.size(); nPos; nPos--)
+ {
+ SwDSParam* pParam = m_DataSourceParams[nPos - 1].get();
+ if(rData.sDataSource == pParam->sDataSource &&
+ rData.sCommand == pParam->sCommand &&
+ (rData.nCommandType == -1 || rData.nCommandType == pParam->nCommandType ||
+ (bCreate && pParam->nCommandType == -1)))
+ {
+ // calls from the calculator may add a connection with an invalid commandtype
+ //later added "real" data base connections have to re-use the already available
+ //DSData and set the correct CommandType
+ if(bCreate && pParam->nCommandType == -1)
+ pParam->nCommandType = rData.nCommandType;
+ pFound = pParam;
+ break;
+ }
+ }
+ if(bCreate && !pFound)
+ {
+ pFound = new SwDSParam(rData);
+ m_DataSourceParams.push_back(std::unique_ptr<SwDSParam>(pFound));
+ try
+ {
+ uno::Reference<lang::XComponent> xComponent(pFound->xConnection, uno::UNO_QUERY);
+ if(xComponent.is())
+ xComponent->addEventListener(m_pImpl->m_xDisposeListener);
+ }
+ catch(const uno::Exception&)
+ {
+ }
+ }
+ return pFound;
+}
+
+SwDSParam* SwDBManager::FindDSConnection(const OUString& rDataSource, bool bCreate)
+{
+ //prefer merge data if available
+ if(m_pImpl->pMergeData && rDataSource == m_pImpl->pMergeData->sDataSource )
+ {
+ SetAsUsed(rDataSource);
+ return m_pImpl->pMergeData.get();
+ }
+ SwDSParam* pFound = nullptr;
+ for (const auto & pParam : m_DataSourceParams)
+ {
+ if(rDataSource == pParam->sDataSource)
+ {
+ SetAsUsed(rDataSource);
+ pFound = pParam.get();
+ break;
+ }
+ }
+ if(bCreate && !pFound)
+ {
+ SwDBData aData;
+ aData.sDataSource = rDataSource;
+ pFound = new SwDSParam(aData);
+ SetAsUsed(rDataSource);
+ m_DataSourceParams.push_back(std::unique_ptr<SwDSParam>(pFound));
+ try
+ {
+ uno::Reference<lang::XComponent> xComponent(pFound->xConnection, uno::UNO_QUERY);
+ if(xComponent.is())
+ xComponent->addEventListener(m_pImpl->m_xDisposeListener);
+ }
+ catch(const uno::Exception&)
+ {
+ }
+ }
+ return pFound;
+}
+
+const SwDBData& SwDBManager::GetAddressDBName()
+{
+ return SW_MOD()->GetDBConfig()->GetAddressSource();
+}
+
+uno::Sequence<OUString> SwDBManager::GetExistingDatabaseNames()
+{
+ uno::Reference<uno::XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
+ uno::Reference<sdb::XDatabaseContext> xDBContext = sdb::DatabaseContext::create(xContext);
+ return xDBContext->getElementNames();
+}
+
+namespace sw
+{
+DBConnURIType GetDBunoType(const INetURLObject &rURL)
+{
+ OUString sExt(rURL.GetFileExtension());
+ DBConnURIType type = DBConnURIType::UNKNOWN;
+
+ if (sExt == "odb")
+ {
+ type = DBConnURIType::ODB;
+ }
+ else if (sExt.equalsIgnoreAsciiCase("sxc")
+ || sExt.equalsIgnoreAsciiCase("ods")
+ || sExt.equalsIgnoreAsciiCase("xls")
+ || sExt.equalsIgnoreAsciiCase("xlsx"))
+ {
+ type = DBConnURIType::CALC;
+ }
+ else if (sExt.equalsIgnoreAsciiCase("sxw") || sExt.equalsIgnoreAsciiCase("odt") || sExt.equalsIgnoreAsciiCase("doc") || sExt.equalsIgnoreAsciiCase("docx"))
+ {
+ type = DBConnURIType::WRITER;
+ }
+ else if (sExt.equalsIgnoreAsciiCase("dbf"))
+ {
+ type = DBConnURIType::DBASE;
+ }
+ else if (sExt.equalsIgnoreAsciiCase("csv") || sExt.equalsIgnoreAsciiCase("txt"))
+ {
+ type = DBConnURIType::FLAT;
+ }
+#ifdef _WIN32
+ else if (sExt.equalsIgnoreAsciiCase("mdb") || sExt.equalsIgnoreAsciiCase("mde"))
+ {
+ type = DBConnURIType::MSJET;
+ }
+ else if (sExt.equalsIgnoreAsciiCase("accdb") || sExt.equalsIgnoreAsciiCase("accde"))
+ {
+ type = DBConnURIType::MSACE;
+ }
+#endif
+ return type;
+}
+}
+
+namespace
+{
+uno::Any GetDBunoURI(const INetURLObject &rURL, DBConnURIType& rType)
+{
+ uno::Any aURLAny;
+
+ if (rType == DBConnURIType::UNKNOWN)
+ rType = GetDBunoType(rURL);
+
+ switch (rType) {
+ case DBConnURIType::UNKNOWN:
+ case DBConnURIType::ODB:
+ break;
+ case DBConnURIType::CALC:
+ {
+ OUString sDBURL = "sdbc:calc:" +
+ rURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
+ aURLAny <<= sDBURL;
+ }
+ break;
+ case DBConnURIType::WRITER:
+ {
+ OUString sDBURL = "sdbc:writer:" +
+ rURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
+ aURLAny <<= sDBURL;
+ }
+ break;
+ case DBConnURIType::DBASE:
+ {
+ INetURLObject aUrlTmp(rURL);
+ aUrlTmp.removeSegment();
+ aUrlTmp.removeFinalSlash();
+ OUString sDBURL = "sdbc:dbase:" +
+ aUrlTmp.GetMainURL(INetURLObject::DecodeMechanism::NONE);
+ aURLAny <<= sDBURL;
+ }
+ break;
+ case DBConnURIType::FLAT:
+ {
+ INetURLObject aUrlTmp(rURL);
+ aUrlTmp.removeSegment();
+ aUrlTmp.removeFinalSlash();
+ OUString sDBURL = "sdbc:flat:" +
+ //only the 'path' has to be added
+ aUrlTmp.GetMainURL(INetURLObject::DecodeMechanism::NONE);
+ aURLAny <<= sDBURL;
+ }
+ break;
+ case DBConnURIType::MSJET:
+#ifdef _WIN32
+ {
+ OUString sDBURL("sdbc:ado:access:PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=" + rURL.PathToFileName());
+ aURLAny <<= sDBURL;
+ }
+#endif
+ break;
+ case DBConnURIType::MSACE:
+#ifdef _WIN32
+ {
+ OUString sDBURL("sdbc:ado:PROVIDER=Microsoft.ACE.OLEDB.12.0;DATA SOURCE=" + rURL.PathToFileName());
+ aURLAny <<= sDBURL;
+ }
+#endif
+ break;
+ }
+ return aURLAny;
+}
+
+/// Returns the URL of this SwDoc.
+OUString getOwnURL(SfxObjectShell const * pDocShell)
+{
+ OUString aRet;
+
+ if (!pDocShell)
+ return aRet;
+
+ const INetURLObject& rURLObject = pDocShell->GetMedium()->GetURLObject();
+ aRet = rURLObject.GetMainURL(INetURLObject::DecodeMechanism::NONE);
+ return aRet;
+}
+
+/**
+Loads a data source from file and registers it.
+
+In case of success it returns the registered name, otherwise an empty string.
+Optionally add a prefix to the registered DB name.
+*/
+OUString LoadAndRegisterDataSource_Impl(DBConnURIType type, const uno::Reference< beans::XPropertySet > *pSettings,
+ const INetURLObject &rURL, const OUString *pDestDir, SfxObjectShell* pDocShell)
+{
+ OUString sExt(rURL.GetFileExtension());
+ uno::Any aTableFilterAny;
+ uno::Any aSuppressVersionsAny;
+ uno::Any aInfoAny;
+ bool bStore = true;
+ OUString sFind;
+
+ uno::Any aURLAny = GetDBunoURI(rURL, type);
+ switch (type) {
+ case DBConnURIType::UNKNOWN:
+ case DBConnURIType::CALC:
+ case DBConnURIType::WRITER:
+ break;
+ case DBConnURIType::ODB:
+ bStore = false;
+ break;
+ case DBConnURIType::FLAT:
+ case DBConnURIType::DBASE:
+ //set the filter to the file name without extension
+ {
+ uno::Sequence<OUString> aFilters { rURL.getBase(INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset) };
+ aTableFilterAny <<= aFilters;
+ }
+ break;
+ case DBConnURIType::MSJET:
+ case DBConnURIType::MSACE:
+ aSuppressVersionsAny <<= true;
+ break;
+ }
+
+ try
+ {
+ uno::Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext());
+ uno::Reference<sdb::XDatabaseContext> xDBContext = sdb::DatabaseContext::create(xContext);
+
+ OUString sNewName = rURL.getName(
+ INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::Unambiguous);
+ sal_Int32 nExtLen = sExt.getLength();
+ sNewName = sNewName.replaceAt(sNewName.getLength() - nExtLen - 1, nExtLen + 1, u"");
+
+ //find a unique name if sNewName already exists
+ sFind = sNewName;
+ sal_Int32 nIndex = 0;
+ while (xDBContext->hasByName(sFind))
+ sFind = sNewName + OUString::number(++nIndex);
+
+ uno::Reference<uno::XInterface> xNewInstance;
+ if (!bStore)
+ {
+ //odb-file
+ uno::Any aDataSource = xDBContext->getByName(rURL.GetMainURL(INetURLObject::DecodeMechanism::NONE));
+ aDataSource >>= xNewInstance;
+ }
+ else
+ {
+ xNewInstance = xDBContext->createInstance();
+ uno::Reference<beans::XPropertySet> xDataProperties(xNewInstance, uno::UNO_QUERY);
+
+ if (aURLAny.hasValue())
+ xDataProperties->setPropertyValue("URL", aURLAny);
+ if (aTableFilterAny.hasValue())
+ xDataProperties->setPropertyValue("TableFilter", aTableFilterAny);
+ if (aSuppressVersionsAny.hasValue())
+ xDataProperties->setPropertyValue("SuppressVersionColumns", aSuppressVersionsAny);
+ if (aInfoAny.hasValue())
+ xDataProperties->setPropertyValue("Info", aInfoAny);
+
+ if (DBConnURIType::FLAT == type && pSettings)
+ {
+ uno::Any aSettings = xDataProperties->getPropertyValue("Settings");
+ uno::Reference < beans::XPropertySet > xDSSettings;
+ aSettings >>= xDSSettings;
+ ::comphelper::copyProperties(*pSettings, xDSSettings);
+ xDSSettings->setPropertyValue("Extension", uno::Any(sExt));
+ }
+
+ uno::Reference<sdb::XDocumentDataSource> xDS(xNewInstance, uno::UNO_QUERY_THROW);
+ uno::Reference<frame::XStorable> xStore(xDS->getDatabaseDocument(), uno::UNO_QUERY_THROW);
+ OUString aOwnURL = getOwnURL(pDocShell);
+ if (aOwnURL.isEmpty())
+ {
+ // Cannot embed, as embedded data source would need the URL of the parent document.
+ OUString sHomePath(SvtPathOptions().GetWorkPath());
+ const OUString sTmpName = utl::CreateTempURL(sNewName, true, u".odb", pDestDir ? pDestDir : &sHomePath);
+ xStore->storeAsURL(sTmpName, uno::Sequence<beans::PropertyValue>());
+ }
+ else
+ {
+ // Embed.
+ OUString aStreamRelPath = "EmbeddedDatabase";
+ uno::Reference<embed::XStorage> xStorage = pDocShell->GetStorage();
+
+ // Refer to the sub-storage name in the document settings, so
+ // we can load it again next time the file is imported.
+ uno::Reference<lang::XMultiServiceFactory> xFactory(pDocShell->GetModel(), uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xPropertySet(xFactory->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY);
+ xPropertySet->setPropertyValue("EmbeddedDatabaseName", uno::Any(aStreamRelPath));
+
+ // Store it only after setting the above property, so that only one data source gets registered.
+ SwDBManager::StoreEmbeddedDataSource(xStore, xStorage, aStreamRelPath, aOwnURL);
+ }
+ }
+ xDBContext->registerObject(sFind, xNewInstance);
+ }
+ catch (const uno::Exception&)
+ {
+ sFind.clear();
+ }
+ return sFind;
+}
+}
+
+OUString SwDBManager::LoadAndRegisterDataSource(weld::Window* pParent, SwDocShell* pDocShell)
+{
+ sfx2::FileDialogHelper aDlgHelper(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, FileDialogFlags::NONE, pParent);
+ aDlgHelper.SetContext(sfx2::FileDialogHelper::WriterRegisterDataSource);
+ uno::Reference < ui::dialogs::XFilePicker3 > xFP = aDlgHelper.GetFilePicker();
+
+ OUString sFilterAll(SwResId(STR_FILTER_ALL));
+ OUString sFilterAllData(SwResId(STR_FILTER_ALL_DATA));
+
+ const std::vector<std::pair<OUString, OUString>> filters{
+ { SwResId(STR_FILTER_SXB), "*.odb" },
+ { SwResId(STR_FILTER_SXC), "*.ods;*.sxc" },
+ { SwResId(STR_FILTER_SXW), "*.odt;*.sxw" },
+ { SwResId(STR_FILTER_DBF), "*.dbf" },
+ { SwResId(STR_FILTER_XLS), "*.xls;*.xlsx" },
+ { SwResId(STR_FILTER_DOC), "*.doc;*.docx" },
+ { SwResId(STR_FILTER_TXT), "*.txt" },
+ { SwResId(STR_FILTER_CSV), "*.csv" },
+#ifdef _WIN32
+ { SwResId(STR_FILTER_MDB), "*.mdb;*.mde" },
+ { SwResId(STR_FILTER_ACCDB), "*.accdb;*.accde" },
+#endif
+ };
+
+ OUStringBuffer sAllDataFilter;
+ for (const auto& [name, filter] : filters)
+ {
+ (void)name;
+ if (!sAllDataFilter.isEmpty())
+ sAllDataFilter.append(';');
+ sAllDataFilter.append(filter);
+ }
+
+ xFP->appendFilter( sFilterAll, "*" );
+ xFP->appendFilter( sFilterAllData, sAllDataFilter.makeStringAndClear());
+
+ // Similar to sfx2::addExtension from sfx2/source/dialog/filtergrouping.cxx
+ for (const auto& [name, filter] : filters)
+ xFP->appendFilter(name + " (" + filter + ")", filter);
+
+ xFP->setCurrentFilter( sFilterAll ) ;
+ OUString sFind;
+ if( ERRCODE_NONE == aDlgHelper.Execute() )
+ {
+ uno::Reference< beans::XPropertySet > aSettings;
+ const INetURLObject aURL( xFP->getSelectedFiles()[0] );
+ const DBConnURIType type = GetDBunoType( aURL );
+
+ if( DBConnURIType::FLAT == type )
+ {
+ uno::Reference<uno::XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
+ uno::Reference < sdb::XTextConnectionSettings > xSettingsDlg = sdb::TextConnectionSettings::create(xContext);
+ if( xSettingsDlg->execute() )
+ aSettings.set( uno::Reference < beans::XPropertySet >( xSettingsDlg, uno::UNO_QUERY_THROW ) );
+ }
+ sFind = LoadAndRegisterDataSource_Impl( type, DBConnURIType::FLAT == type ? &aSettings : nullptr, aURL, nullptr, pDocShell );
+
+ s_aUncommittedRegistrations.push_back(std::pair<SwDocShell*, OUString>(pDocShell, sFind));
+ }
+ return sFind;
+}
+
+void SwDBManager::StoreEmbeddedDataSource(const uno::Reference<frame::XStorable>& xStorable,
+ const uno::Reference<embed::XStorage>& xStorage,
+ const OUString& rStreamRelPath,
+ const OUString& rOwnURL, bool bCopyTo)
+{
+ // Construct vnd.sun.star.pkg:// URL for later loading, and TargetStorage/StreamRelPath for storing.
+ OUString const sTmpName = ConstructVndSunStarPkgUrl(rOwnURL, rStreamRelPath);
+
+ uno::Sequence<beans::PropertyValue> aSequence = comphelper::InitPropertySequence(
+ {
+ {"TargetStorage", uno::Any(xStorage)},
+ {"StreamRelPath", uno::Any(rStreamRelPath)},
+ {"BaseURI", uno::Any(rOwnURL)}
+ });
+ if (bCopyTo)
+ xStorable->storeToURL(sTmpName, aSequence);
+ else
+ xStorable->storeAsURL(sTmpName, aSequence);
+}
+
+OUString SwDBManager::LoadAndRegisterDataSource(std::u16string_view rURI, const OUString *pDestDir)
+{
+ return LoadAndRegisterDataSource_Impl( DBConnURIType::UNKNOWN, nullptr, INetURLObject(rURI), pDestDir, nullptr );
+}
+
+namespace
+{
+ // tdf#117824 switch the embedded database away from using its current storage and point it to temporary storage
+ // which allows the original storage to be deleted
+ void switchEmbeddedDatabaseStorage(const uno::Reference<sdb::XDatabaseContext>& rDatabaseContext, const OUString& rName)
+ {
+ uno::Reference<sdb::XDocumentDataSource> xDS(rDatabaseContext->getByName(rName), uno::UNO_QUERY);
+ if (!xDS)
+ return;
+ uno::Reference<document::XStorageBasedDocument> xStorageDoc(xDS->getDatabaseDocument(), uno::UNO_QUERY);
+ if (!xStorageDoc)
+ return;
+ xStorageDoc->switchToStorage(comphelper::OStorageHelper::GetTemporaryStorage());
+ }
+}
+
+void SwDBManager::RevokeDataSource(const OUString& rName)
+{
+ uno::Reference<sdb::XDatabaseContext> xDatabaseContext = sdb::DatabaseContext::create(comphelper::getProcessComponentContext());
+ if (xDatabaseContext->hasByName(rName))
+ {
+ switchEmbeddedDatabaseStorage(xDatabaseContext, rName);
+ xDatabaseContext->revokeObject(rName);
+ }
+}
+
+void SwDBManager::LoadAndRegisterEmbeddedDataSource(const SwDBData& rData, const SwDocShell& rDocShell)
+{
+ uno::Reference<sdb::XDatabaseContext> xDatabaseContext = sdb::DatabaseContext::create(comphelper::getProcessComponentContext());
+
+ OUString sDataSource = rData.sDataSource;
+
+ // Fallback, just in case the document would contain an embedded data source, but no DB fields.
+ if (sDataSource.isEmpty())
+ sDataSource = "EmbeddedDatabase";
+
+ SwDBManager::RevokeDataSource( sDataSource );
+
+ // Encode the stream name and the real path into a single URL.
+ const INetURLObject& rURLObject = rDocShell.GetMedium()->GetURLObject();
+ OUString const aURL = ConstructVndSunStarPkgUrl(
+ rURLObject.GetMainURL(INetURLObject::DecodeMechanism::NONE),
+ m_sEmbeddedName);
+
+ uno::Reference<uno::XInterface> xDataSource(xDatabaseContext->getByName(aURL), uno::UNO_QUERY);
+ xDatabaseContext->registerObject( sDataSource, xDataSource );
+
+ // temp file - don't remember connection
+ if (rData.sDataSource.isEmpty())
+ s_aUncommittedRegistrations.push_back(std::pair<SwDocShell*, OUString>(nullptr, sDataSource));
+}
+
+void SwDBManager::ExecuteFormLetter( SwWrtShell& rSh,
+ const uno::Sequence<beans::PropertyValue>& rProperties)
+{
+ //prevent second call
+ if(m_pImpl->pMergeDialog)
+ return ;
+ OUString sDataSource, sDataTableOrQuery;
+ uno::Sequence<uno::Any> aSelection;
+
+ sal_Int32 nCmdType = sdb::CommandType::TABLE;
+ uno::Reference< sdbc::XConnection> xConnection;
+
+ svx::ODataAccessDescriptor aDescriptor(rProperties);
+ sDataSource = aDescriptor.getDataSource();
+ OSL_VERIFY(aDescriptor[svx::DataAccessDescriptorProperty::Command] >>= sDataTableOrQuery);
+ OSL_VERIFY(aDescriptor[svx::DataAccessDescriptorProperty::CommandType] >>= nCmdType);
+
+ if ( aDescriptor.has(svx::DataAccessDescriptorProperty::Selection) )
+ aDescriptor[svx::DataAccessDescriptorProperty::Selection] >>= aSelection;
+ if ( aDescriptor.has(svx::DataAccessDescriptorProperty::Connection) )
+ aDescriptor[svx::DataAccessDescriptorProperty::Connection] >>= xConnection;
+
+ if(sDataSource.isEmpty() || sDataTableOrQuery.isEmpty())
+ {
+ OSL_FAIL("PropertyValues missing or unset");
+ return;
+ }
+
+ //always create a connection for the dialog and dispose it after the dialog has been closed
+ SwDSParam* pFound = nullptr;
+ if(!xConnection.is())
+ {
+ xConnection = SwDBManager::RegisterConnection(sDataSource);
+ pFound = FindDSConnection(sDataSource, true);
+ }
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ m_pImpl->pMergeDialog = pFact->CreateMailMergeDlg(rSh.GetView().GetViewFrame().GetFrameWeld(), rSh,
+ sDataSource,
+ sDataTableOrQuery,
+ nCmdType,
+ xConnection);
+ if(m_pImpl->pMergeDialog->Execute() == RET_OK)
+ {
+ aDescriptor[svx::DataAccessDescriptorProperty::Selection] <<= m_pImpl->pMergeDialog->GetSelection();
+
+ uno::Reference<sdbc::XResultSet> xResSet = m_pImpl->pMergeDialog->GetResultSet();
+ if(xResSet.is())
+ aDescriptor[svx::DataAccessDescriptorProperty::Cursor] <<= xResSet;
+
+ // SfxObjectShellRef is ok, since there should be no control over the document lifetime here
+ SfxObjectShellRef xDocShell = rSh.GetView().GetViewFrame().GetObjectShell();
+
+ lcl_emitEvent(SfxEventHintId::SwMailMerge, STR_SW_EVENT_MAIL_MERGE, xDocShell.get());
+
+ // prepare mail merge descriptor
+ SwMergeDescriptor aMergeDesc( m_pImpl->pMergeDialog->GetMergeType(), rSh, aDescriptor );
+ aMergeDesc.sSaveToFilter = m_pImpl->pMergeDialog->GetSaveFilter();
+ aMergeDesc.bCreateSingleFile = m_pImpl->pMergeDialog->IsSaveSingleDoc();
+ aMergeDesc.bPrefixIsFilename = aMergeDesc.bCreateSingleFile;
+ aMergeDesc.sPrefix = m_pImpl->pMergeDialog->GetTargetURL();
+
+ if(!aMergeDesc.bCreateSingleFile)
+ {
+ if(m_pImpl->pMergeDialog->IsGenerateFromDataBase())
+ aMergeDesc.sDBcolumn = m_pImpl->pMergeDialog->GetColumnName();
+
+ if(m_pImpl->pMergeDialog->IsFileEncryptedFromDataBase())
+ aMergeDesc.sDBPasswordColumn = m_pImpl->pMergeDialog->GetPasswordColumnName();
+ }
+
+ Merge( aMergeDesc );
+
+ lcl_emitEvent(SfxEventHintId::SwMailMergeEnd, STR_SW_EVENT_MAIL_MERGE_END, xDocShell.get());
+
+ // reset the cursor inside
+ xResSet = nullptr;
+ aDescriptor[svx::DataAccessDescriptorProperty::Cursor] <<= xResSet;
+ }
+ if(pFound)
+ {
+ for (const auto & pParam : m_DataSourceParams)
+ {
+ if (pParam.get() == pFound)
+ {
+ try
+ {
+ uno::Reference<lang::XComponent> xComp(pParam->xConnection, uno::UNO_QUERY);
+ if(xComp.is())
+ xComp->dispose();
+ }
+ catch(const uno::RuntimeException&)
+ {
+ //may be disposed already since multiple entries may have used the same connection
+ }
+ break;
+ }
+ //pFound doesn't need to be removed/deleted -
+ //this has been done by the SwConnectionDisposedListener_Impl already
+ }
+ }
+ m_pImpl->pMergeDialog.disposeAndClear();
+}
+
+void SwDBManager::InsertText(SwWrtShell& rSh,
+ const uno::Sequence< beans::PropertyValue>& rProperties)
+{
+ OUString sDataSource, sDataTableOrQuery;
+ uno::Reference<sdbc::XResultSet> xResSet;
+ uno::Sequence<uno::Any> aSelection;
+ sal_Int16 nCmdType = sdb::CommandType::TABLE;
+ uno::Reference< sdbc::XConnection> xConnection;
+ for(const beans::PropertyValue& rValue : rProperties)
+ {
+ if ( rValue.Name == "DataSourceName" )
+ rValue.Value >>= sDataSource;
+ else if ( rValue.Name == "Command" )
+ rValue.Value >>= sDataTableOrQuery;
+ else if ( rValue.Name == "Cursor" )
+ rValue.Value >>= xResSet;
+ else if ( rValue.Name == "Selection" )
+ rValue.Value >>= aSelection;
+ else if ( rValue.Name == "CommandType" )
+ rValue.Value >>= nCmdType;
+ else if ( rValue.Name == "ActiveConnection" )
+ rValue.Value >>= xConnection;
+ }
+ if(sDataSource.isEmpty() || sDataTableOrQuery.isEmpty() || !xResSet.is())
+ {
+ OSL_FAIL("PropertyValues missing or unset");
+ return;
+ }
+ uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
+ uno::Reference<sdbc::XDataSource> xSource;
+ uno::Reference<container::XChild> xChild(xConnection, uno::UNO_QUERY);
+ if(xChild.is())
+ xSource.set(xChild->getParent(), uno::UNO_QUERY);
+ if(!xSource.is())
+ xSource = dbtools::getDataSource(sDataSource, xContext);
+ uno::Reference< sdbcx::XColumnsSupplier > xColSupp( xResSet, uno::UNO_QUERY );
+ SwDBData aDBData;
+ aDBData.sDataSource = sDataSource;
+ aDBData.sCommand = sDataTableOrQuery;
+ aDBData.nCommandType = nCmdType;
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractSwInsertDBColAutoPilot> pDlg(pFact->CreateSwInsertDBColAutoPilot( rSh.GetView(),
+ xSource,
+ xColSupp,
+ aDBData ));
+ if( RET_OK != pDlg->Execute() )
+ return;
+
+ OUString sDummy;
+ if(!xConnection.is())
+ xConnection = xSource->getConnection(sDummy, sDummy);
+ try
+ {
+ pDlg->DataToDoc( aSelection , xSource, xConnection, xResSet);
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("sw.mailmerge", "");
+ }
+}
+
+uno::Reference<sdbc::XDataSource> SwDBManager::getDataSourceAsParent(const uno::Reference< sdbc::XConnection>& _xConnection,const OUString& _sDataSourceName)
+{
+ uno::Reference<sdbc::XDataSource> xSource;
+ try
+ {
+ uno::Reference<container::XChild> xChild(_xConnection, uno::UNO_QUERY);
+ if ( xChild.is() )
+ xSource.set(xChild->getParent(), uno::UNO_QUERY);
+ if ( !xSource.is() )
+ xSource = dbtools::getDataSource(_sDataSourceName, ::comphelper::getProcessComponentContext());
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("sw.mailmerge", "getDataSourceAsParent()");
+ }
+ return xSource;
+}
+
+uno::Reference<sdbc::XResultSet> SwDBManager::createCursor(const OUString& _sDataSourceName,
+ const OUString& _sCommand,
+ sal_Int32 _nCommandType,
+ const uno::Reference<sdbc::XConnection>& _xConnection,
+ const SwView* pView)
+{
+ uno::Reference<sdbc::XResultSet> xResultSet;
+ try
+ {
+ uno::Reference< lang::XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
+ if( xMgr.is() )
+ {
+ uno::Reference<uno::XInterface> xInstance = xMgr->createInstance("com.sun.star.sdb.RowSet");
+ uno::Reference<beans::XPropertySet> xRowSetPropSet(xInstance, uno::UNO_QUERY);
+ if(xRowSetPropSet.is())
+ {
+ xRowSetPropSet->setPropertyValue("DataSourceName", uno::Any(_sDataSourceName));
+ xRowSetPropSet->setPropertyValue("ActiveConnection", uno::Any(_xConnection));
+ xRowSetPropSet->setPropertyValue("Command", uno::Any(_sCommand));
+ xRowSetPropSet->setPropertyValue("CommandType", uno::Any(_nCommandType));
+
+ uno::Reference< sdb::XCompletedExecution > xRowSet(xInstance, uno::UNO_QUERY);
+
+ if ( xRowSet.is() )
+ {
+ weld::Window* pWindow = pView ? pView->GetFrameWeld() : nullptr;
+ uno::Reference< task::XInteractionHandler > xHandler( task::InteractionHandler::createWithParent(comphelper::getComponentContext(xMgr), pWindow ? pWindow->GetXWindow() : nullptr), uno::UNO_QUERY_THROW );
+ xRowSet->executeWithCompletion(xHandler);
+ }
+ xResultSet.set(xRowSet, uno::UNO_QUERY);
+ }
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("sw.mailmerge", "Caught exception while creating a new RowSet");
+ }
+ return xResultSet;
+}
+
+void SwDBManager::setEmbeddedName(const OUString& rEmbeddedName, SwDocShell& rDocShell)
+{
+ bool bLoad = m_sEmbeddedName != rEmbeddedName && !rEmbeddedName.isEmpty();
+ bool bRegisterListener = m_sEmbeddedName.isEmpty() && !rEmbeddedName.isEmpty();
+
+ m_sEmbeddedName = rEmbeddedName;
+
+ if (bLoad)
+ {
+ uno::Reference<embed::XStorage> xStorage = rDocShell.GetStorage();
+ // It's OK that we don't have the named sub-storage yet, in case
+ // we're in the process of creating it.
+ if (xStorage->hasByName(rEmbeddedName))
+ LoadAndRegisterEmbeddedDataSource(rDocShell.GetDoc()->GetDBData(), rDocShell);
+ }
+
+ if (bRegisterListener)
+ // Register a remove listener, so we know when the embedded data source is removed.
+ m_pImpl->m_xDataSourceRemovedListener = new SwDataSourceRemovedListener(*this);
+}
+
+const OUString& SwDBManager::getEmbeddedName() const
+{
+ return m_sEmbeddedName;
+}
+
+SwDoc* SwDBManager::getDoc() const
+{
+ return m_pDoc;
+}
+
+void SwDBManager::releaseRevokeListener()
+{
+ if (m_pImpl->m_xDataSourceRemovedListener.is())
+ {
+ m_pImpl->m_xDataSourceRemovedListener->Dispose();
+ m_pImpl->m_xDataSourceRemovedListener.clear();
+ }
+}
+
+SwDBManager::ConnectionDisposedListener_Impl::ConnectionDisposedListener_Impl(SwDBManager& rManager)
+ : m_pDBManager(&rManager)
+{
+}
+
+void SwDBManager::ConnectionDisposedListener_Impl::disposing( const lang::EventObject& rSource )
+{
+ ::SolarMutexGuard aGuard;
+
+ if (!m_pDBManager) return; // we're disposed too!
+
+ uno::Reference<sdbc::XConnection> xSource(rSource.Source, uno::UNO_QUERY);
+ for (size_t nPos = m_pDBManager->m_DataSourceParams.size(); nPos; nPos--)
+ {
+ SwDSParam* pParam = m_pDBManager->m_DataSourceParams[nPos - 1].get();
+ if(pParam->xConnection.is() &&
+ (xSource == pParam->xConnection))
+ {
+ m_pDBManager->m_DataSourceParams.erase(
+ m_pDBManager->m_DataSourceParams.begin() + nPos - 1);
+ }
+ }
+}
+
+std::shared_ptr<SwMailMergeConfigItem> SwDBManager::PerformMailMerge(SwView const * pView)
+{
+ std::shared_ptr<SwMailMergeConfigItem> xConfigItem = pView->GetMailMergeConfigItem();
+ if (!xConfigItem)
+ return xConfigItem;
+
+ svx::ODataAccessDescriptor aDescriptor;
+ aDescriptor.setDataSource(xConfigItem->GetCurrentDBData().sDataSource);
+ aDescriptor[ svx::DataAccessDescriptorProperty::Connection ] <<= xConfigItem->GetConnection().getTyped();
+ aDescriptor[ svx::DataAccessDescriptorProperty::Cursor ] <<= xConfigItem->GetResultSet();
+ aDescriptor[ svx::DataAccessDescriptorProperty::Command ] <<= xConfigItem->GetCurrentDBData().sCommand;
+ aDescriptor[ svx::DataAccessDescriptorProperty::CommandType ] <<= xConfigItem->GetCurrentDBData().nCommandType;
+ aDescriptor[ svx::DataAccessDescriptorProperty::Selection ] <<= xConfigItem->GetSelection();
+
+ SwWrtShell& rSh = pView->GetWrtShell();
+ xConfigItem->SetTargetView(nullptr);
+
+ SwMergeDescriptor aMergeDesc(DBMGR_MERGE_SHELL, rSh, aDescriptor);
+ aMergeDesc.pMailMergeConfigItem = xConfigItem.get();
+ aMergeDesc.bCreateSingleFile = true;
+ rSh.GetDBManager()->Merge(aMergeDesc);
+
+ return xConfigItem;
+}
+
+void SwDBManager::RevokeLastRegistrations()
+{
+ if (s_aUncommittedRegistrations.empty())
+ return;
+
+ SwView* pView = ( m_pDoc && m_pDoc->GetDocShell() ) ? m_pDoc->GetDocShell()->GetView() : nullptr;
+ if (pView)
+ {
+ const std::shared_ptr<SwMailMergeConfigItem>& xConfigItem = pView->GetMailMergeConfigItem();
+ if (xConfigItem)
+ {
+ xConfigItem->DisposeResultSet();
+ xConfigItem->DocumentReloaded();
+ }
+ }
+
+ for (auto it = s_aUncommittedRegistrations.begin(); it != s_aUncommittedRegistrations.end();)
+ {
+ if ((m_pDoc && it->first == m_pDoc->GetDocShell()) || it->first == nullptr)
+ {
+ RevokeDataSource(it->second);
+ it = s_aUncommittedRegistrations.erase(it);
+ }
+ else
+ ++it;
+ }
+}
+
+void SwDBManager::CommitLastRegistrations()
+{
+ for (auto aIt = s_aUncommittedRegistrations.begin(); aIt != s_aUncommittedRegistrations.end();)
+ {
+ if (aIt->first == m_pDoc->GetDocShell() || aIt->first == nullptr)
+ {
+ m_aNotUsedConnections.push_back(aIt->second);
+ aIt = s_aUncommittedRegistrations.erase(aIt);
+ }
+ else
+ aIt++;
+ }
+}
+
+void SwDBManager::SetAsUsed(const OUString& rName)
+{
+ auto aFound = std::find(m_aNotUsedConnections.begin(), m_aNotUsedConnections.end(), rName);
+ if (aFound != m_aNotUsedConnections.end())
+ m_aNotUsedConnections.erase(aFound);
+}
+
+void SwDBManager::RevokeNotUsedConnections()
+{
+ for (auto aIt = m_aNotUsedConnections.begin(); aIt != m_aNotUsedConnections.end();)
+ {
+ RevokeDataSource(*aIt);
+ aIt = m_aNotUsedConnections.erase(aIt);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/dbui/dbtree.cxx b/sw/source/uibase/dbui/dbtree.cxx
new file mode 100644
index 0000000000..432a0a28e6
--- /dev/null
+++ b/sw/source/uibase/dbui/dbtree.cxx
@@ -0,0 +1,454 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/string.hxx>
+#include <com/sun/star/container/XContainerListener.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <osl/diagnose.h>
+
+#include <dbmgr.hxx>
+#include <wrtsh.hxx>
+#include <dbtree.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+
+#include <bitmaps.hlst>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+
+class SwDBTreeList_Impl : public cppu::WeakImplHelper < XContainerListener >
+{
+ Reference< XDatabaseContext > m_xDatabaseContext;
+ SwWrtShell* m_pWrtShell;
+
+ public:
+ explicit SwDBTreeList_Impl()
+ : m_pWrtShell(nullptr)
+ {
+ }
+ virtual ~SwDBTreeList_Impl() override;
+
+ virtual void SAL_CALL elementInserted( const ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementRemoved( const ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementReplaced( const ContainerEvent& Event ) override;
+ virtual void SAL_CALL disposing( const EventObject& Source ) override;
+
+ bool HasContext();
+ SwWrtShell* GetWrtShell() { return m_pWrtShell;}
+ void SetWrtShell(SwWrtShell& rSh) { m_pWrtShell = &rSh;}
+ const Reference<XDatabaseContext>& GetContext() const {return m_xDatabaseContext;}
+ Reference<XConnection> GetConnection(const OUString& rSourceName);
+};
+
+SwDBTreeList_Impl::~SwDBTreeList_Impl()
+{
+ if(m_xDatabaseContext.is())
+ {
+ osl_atomic_increment(&m_refCount);
+ //block necessary due to solaris' compiler behaviour to
+ //remove temporaries at the block's end
+ {
+ m_xDatabaseContext->removeContainerListener( this );
+ }
+ osl_atomic_decrement(&m_refCount);
+ }
+}
+
+void SwDBTreeList_Impl::elementInserted( const ContainerEvent& )
+{
+ // information not needed
+}
+
+void SwDBTreeList_Impl::elementRemoved( const ContainerEvent& )
+{
+}
+
+void SwDBTreeList_Impl::disposing( const EventObject& )
+{
+ m_xDatabaseContext = nullptr;
+}
+
+void SwDBTreeList_Impl::elementReplaced( const ContainerEvent& rEvent )
+{
+ elementRemoved(rEvent);
+}
+
+bool SwDBTreeList_Impl::HasContext()
+{
+ if(!m_xDatabaseContext.is())
+ {
+ Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
+ m_xDatabaseContext = DatabaseContext::create(xContext);
+ m_xDatabaseContext->addContainerListener( this );
+ }
+ return m_xDatabaseContext.is();
+}
+
+Reference<XConnection> SwDBTreeList_Impl::GetConnection(const OUString& rSourceName)
+{
+ Reference<XConnection> xRet;
+ if (m_xDatabaseContext.is() && m_pWrtShell)
+ {
+ xRet = m_pWrtShell->GetDBManager()->RegisterConnection(rSourceName);
+ }
+ return xRet;
+}
+
+SwDBTreeList::SwDBTreeList(std::unique_ptr<weld::TreeView> xTreeView)
+ : m_bInitialized(false)
+ , m_bShowColumns(false)
+ , m_pImpl(new SwDBTreeList_Impl)
+ , m_xTreeView(std::move(xTreeView))
+ , m_xScratchIter(m_xTreeView->make_iterator())
+{
+ m_xTreeView->connect_expanding(LINK(this, SwDBTreeList, RequestingChildrenHdl));
+}
+
+SwDBTreeList::~SwDBTreeList()
+{
+}
+
+void SwDBTreeList::InitTreeList()
+{
+ if (!m_pImpl->HasContext() && m_pImpl->GetWrtShell())
+ return;
+
+ Sequence< OUString > aDBNames = m_pImpl->GetContext()->getElementNames();
+ auto const sort = comphelper::string::NaturalStringSorter(
+ comphelper::getProcessComponentContext(),
+ Application::GetSettings().GetUILanguageTag().getLocale());
+ auto [begin, end] = asNonConstRange(aDBNames);
+ std::sort(
+ begin, end,
+ [&sort](OUString const & x, OUString const & y)
+ { return sort.compare(x, y) < 0; });
+
+ OUString aImg(RID_BMP_DB);
+ for (const OUString& rDBName : std::as_const(aDBNames))
+ {
+ // If this database has a password or a (missing) remote connection,
+ // then it might take a long time or spam for unnecessary credentials.
+ // Just check that it basically exists to weed out any broken/obsolete registrations.
+ if (SwDBManager::getDataSourceAsParent(Reference<sdbc::XConnection>(), rDBName).is())
+ {
+ m_xTreeView->insert(nullptr, -1, &rDBName, nullptr, nullptr, nullptr, true, m_xScratchIter.get());
+ m_xTreeView->set_image(*m_xScratchIter, aImg);
+ }
+ }
+ Select(u"", u"", u"");
+
+ m_bInitialized = true;
+}
+
+void SwDBTreeList::AddDataSource(const OUString& rSource)
+{
+ m_xTreeView->insert(nullptr, -1, &rSource, nullptr, nullptr, nullptr, true, m_xScratchIter.get());
+ m_xTreeView->set_image(*m_xScratchIter, RID_BMP_DB);
+ m_xTreeView->select(*m_xScratchIter);
+}
+
+IMPL_LINK(SwDBTreeList, RequestingChildrenHdl, const weld::TreeIter&, rParent, bool)
+{
+ if (!m_xTreeView->iter_has_child(rParent))
+ {
+ if (m_xTreeView->get_iter_depth(rParent)) // column names
+ {
+ try
+ {
+ std::unique_ptr<weld::TreeIter> xGrandParent(m_xTreeView->make_iterator(&rParent));
+ m_xTreeView->iter_parent(*xGrandParent);
+ OUString sSourceName = m_xTreeView->get_text(*xGrandParent);
+ OUString sTableName = m_xTreeView->get_text(rParent);
+
+ if(!m_pImpl->GetContext()->hasByName(sSourceName))
+ return true;
+ Reference<XConnection> xConnection = m_pImpl->GetConnection(sSourceName);
+ bool bTable = m_xTreeView->get_id(rParent).isEmpty();
+ Reference<XColumnsSupplier> xColsSupplier;
+ if(bTable)
+ {
+ Reference<XTablesSupplier> xTSupplier(xConnection, UNO_QUERY);
+ if(xTSupplier.is())
+ {
+ Reference<XNameAccess> xTables = xTSupplier->getTables();
+ OSL_ENSURE(xTables->hasByName(sTableName), "table not available anymore?");
+ try
+ {
+ Any aTable = xTables->getByName(sTableName);
+ Reference<XPropertySet> xPropSet;
+ aTable >>= xPropSet;
+ xColsSupplier.set(xPropSet, UNO_QUERY);
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+ }
+ else
+ {
+ Reference<XQueriesSupplier> xQSupplier(xConnection, UNO_QUERY);
+ if(xQSupplier.is())
+ {
+ Reference<XNameAccess> xQueries = xQSupplier->getQueries();
+ OSL_ENSURE(xQueries->hasByName(sTableName), "table not available anymore?");
+ try
+ {
+ Any aQuery = xQueries->getByName(sTableName);
+ Reference<XPropertySet> xPropSet;
+ aQuery >>= xPropSet;
+ xColsSupplier.set(xPropSet, UNO_QUERY);
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+ }
+
+ if(xColsSupplier.is())
+ {
+ Reference <XNameAccess> xCols = xColsSupplier->getColumns();
+ const Sequence< OUString> aColNames = xCols->getElementNames();
+ for (const OUString& rColName : aColNames)
+ {
+ m_xTreeView->append(&rParent, rColName);
+ }
+ }
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+ else // table names
+ {
+ try
+ {
+ OUString sSourceName = m_xTreeView->get_text(rParent);
+ if (!m_pImpl->GetContext()->hasByName(sSourceName))
+ return true;
+ Reference<XConnection> xConnection = m_pImpl->GetConnection(sSourceName);
+ if (xConnection.is())
+ {
+ Reference<XTablesSupplier> xTSupplier(xConnection, UNO_QUERY);
+ if(xTSupplier.is())
+ {
+ Reference<XNameAccess> xTables = xTSupplier->getTables();
+ const Sequence< OUString> aTableNames = xTables->getElementNames();
+ OUString aImg(RID_BMP_DBTABLE);
+ for (const OUString& rTableName : aTableNames)
+ {
+ m_xTreeView->insert(&rParent, -1, &rTableName, nullptr,
+ nullptr, nullptr, m_bShowColumns, m_xScratchIter.get());
+ m_xTreeView->set_image(*m_xScratchIter, aImg);
+ }
+ }
+
+ Reference<XQueriesSupplier> xQSupplier(xConnection, UNO_QUERY);
+ if(xQSupplier.is())
+ {
+ Reference<XNameAccess> xQueries = xQSupplier->getQueries();
+ const Sequence< OUString> aQueryNames = xQueries->getElementNames();
+ OUString aImg(RID_BMP_DBQUERY);
+ for (const OUString& rQueryName : aQueryNames)
+ {
+ //to discriminate between queries and tables the user data of query entries is set
+ OUString sId(OUString::number(1));
+ m_xTreeView->insert(&rParent, -1, &rQueryName, &sId,
+ nullptr, nullptr, m_bShowColumns, m_xScratchIter.get());
+ m_xTreeView->set_image(*m_xScratchIter, aImg);
+ }
+ }
+ }
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+ }
+ return true;
+}
+
+OUString SwDBTreeList::GetDBName(OUString& rTableName, OUString& rColumnName, sal_Bool* pbIsTable)
+{
+ OUString sDBName;
+ std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator());
+ if (m_xTreeView->get_selected(xIter.get()))
+ {
+ if (m_xTreeView->get_iter_depth(*xIter) == 2)
+ {
+ rColumnName = m_xTreeView->get_text(*xIter);
+ m_xTreeView->iter_parent(*xIter); // column name was selected
+ }
+ if (m_xTreeView->get_iter_depth(*xIter) == 1)
+ {
+ if (pbIsTable)
+ *pbIsTable = m_xTreeView->get_id(*xIter).isEmpty();
+ rTableName = m_xTreeView->get_text(*xIter);
+ m_xTreeView->iter_parent(*xIter);
+ }
+ sDBName = m_xTreeView->get_text(*xIter);
+ }
+ return sDBName;
+}
+
+// Format: database.table
+void SwDBTreeList::Select(std::u16string_view rDBName, std::u16string_view rTableName, std::u16string_view rColumnName)
+{
+ std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator());
+ if (!m_xTreeView->get_iter_first(*xParent))
+ return;
+
+ do
+ {
+ if (rDBName == m_xTreeView->get_text(*xParent))
+ {
+ if (rTableName.empty() && rColumnName.empty())
+ {
+ // Just select the database node, do not expand
+ m_xTreeView->scroll_to_row(*xParent);
+ m_xTreeView->select(*xParent);
+ return;
+ }
+ if (!m_xTreeView->iter_has_child(*xParent))
+ {
+ m_xTreeView->set_children_on_demand(*xParent, false); // tdf#142294 drop placeholder on-demand node
+ RequestingChildrenHdl(*xParent);
+ // If successful, it will be expanded in a call to scroll_to_row for its children
+ }
+ std::unique_ptr<weld::TreeIter> xChild(m_xTreeView->make_iterator(xParent.get()));
+ if (!m_xTreeView->iter_children(*xChild))
+ {
+ m_xTreeView->scroll_to_row(*xParent);
+ m_xTreeView->select(*xParent);
+ continue;
+ }
+ do
+ {
+ if (rTableName == m_xTreeView->get_text(*xChild))
+ {
+ m_xTreeView->copy_iterator(*xChild, *xParent);
+
+ bool bNoChild = false;
+ if (m_bShowColumns && !rColumnName.empty())
+ {
+ if (!m_xTreeView->iter_has_child(*xParent))
+ {
+ m_xTreeView->set_children_on_demand(*xParent, false); // tdf#142294 drop placeholder on-demand node
+ RequestingChildrenHdl(*xParent);
+ m_xTreeView->expand_row(*xParent);
+ }
+
+ bNoChild = true;
+ if (m_xTreeView->iter_children(*xChild))
+ {
+ do
+ {
+ if (rColumnName == m_xTreeView->get_text(*xChild))
+ {
+ bNoChild = false;
+ break;
+ }
+ }
+ while (m_xTreeView->iter_next_sibling(*xChild));
+ }
+ }
+
+ if (bNoChild)
+ m_xTreeView->copy_iterator(*xParent, *xChild);
+
+ m_xTreeView->scroll_to_row(*xChild);
+ m_xTreeView->select(*xChild);
+ return;
+ }
+ }
+ while (m_xTreeView->iter_next_sibling(*xChild));
+ }
+ } while (m_xTreeView->iter_next_sibling(*xParent));
+}
+
+void SwDBTreeList::SetWrtShell(SwWrtShell& rSh)
+{
+ m_pImpl->SetWrtShell(rSh);
+ if (m_xTreeView->get_visible() && !m_bInitialized)
+ InitTreeList();
+}
+
+namespace
+{
+ void GotoRootLevelParent(const weld::TreeView& rTreeView, weld::TreeIter& rEntry)
+ {
+ while (rTreeView.get_iter_depth(rEntry))
+ rTreeView.iter_parent(rEntry);
+ }
+}
+
+void SwDBTreeList::ShowColumns(bool bShowCol)
+{
+ if (bShowCol == m_bShowColumns)
+ return;
+
+ m_bShowColumns = bShowCol;
+ OUString sTableName;
+ OUString sColumnName;
+ const OUString sDBName(GetDBName(sTableName, sColumnName));
+
+ m_xTreeView->freeze();
+
+ std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator());
+ std::unique_ptr<weld::TreeIter> xChild(m_xTreeView->make_iterator());
+ if (m_xTreeView->get_iter_first(*xIter))
+ {
+ do
+ {
+ GotoRootLevelParent(*m_xTreeView, *xIter);
+ m_xTreeView->collapse_row(*xIter);
+ while (m_xTreeView->iter_has_child(*xIter))
+ {
+ m_xTreeView->copy_iterator(*xIter, *xChild);
+ (void)m_xTreeView->iter_children(*xChild);
+ m_xTreeView->remove(*xChild);
+ }
+ } while (m_xTreeView->iter_next(*xIter));
+ }
+
+ m_xTreeView->thaw();
+
+ if (!sDBName.isEmpty())
+ {
+ Select(sDBName, sTableName, sColumnName); // force RequestingChildren
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/dbui/dbui.cxx b/sw/source/uibase/dbui/dbui.cxx
new file mode 100644
index 0000000000..7b420d5f86
--- /dev/null
+++ b/sw/source/uibase/dbui/dbui.cxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dbui.hxx>
+
+SaveMonitor::SaveMonitor(weld::Window *pParent)
+ : GenericDialogController(pParent, "modules/swriter/ui/savemonitordialog.ui",
+ "SaveMonitorDialog")
+ , m_xDocName(m_xBuilder->weld_label("docname"))
+ , m_xPrinter(m_xBuilder->weld_label("printer"))
+ , m_xPrintInfo(m_xBuilder->weld_label("printinfo"))
+{
+}
+
+SaveMonitor::~SaveMonitor()
+{
+}
+
+PrintMonitor::PrintMonitor(weld::Window *pParent)
+ : GenericDialogController(pParent, "modules/swriter/ui/printmonitordialog.ui",
+ "PrintMonitorDialog")
+ , m_xPrinter(m_xBuilder->weld_label("printer"))
+ , m_xPrintInfo(m_xBuilder->weld_label("printinfo"))
+{
+}
+
+PrintMonitor::~PrintMonitor()
+{
+}
+
+// Progress Indicator for Creation of personalized Mail Merge documents:
+CreateMonitor::CreateMonitor(weld::Window *pParent)
+ : GenericDialogController(pParent, "modules/swriter/ui/mmcreatingdialog.ui",
+ "MMCreatingDialog")
+ , m_nTotalCount(0)
+ , m_nCurrentPosition(0)
+ , m_xCounting(m_xBuilder->weld_label("progress"))
+{
+ m_sCountingPattern = m_xCounting->get_label();
+ m_xCounting->set_label("...");
+}
+
+CreateMonitor::~CreateMonitor()
+{
+}
+
+void CreateMonitor::UpdateCountingText()
+{
+ constexpr OUStringLiteral sVariable_Total(u"%Y");
+ constexpr OUStringLiteral sVariable_Position(u"%X");
+
+ OUString sText(m_sCountingPattern);
+ sText = sText.replaceAll( sVariable_Total, OUString::number( m_nTotalCount ) );
+ sText = sText.replaceAll( sVariable_Position, OUString::number( m_nCurrentPosition ) );
+ m_xCounting->set_label(sText);
+}
+
+void CreateMonitor::SetTotalCount( sal_Int32 nTotal )
+{
+ m_nTotalCount = nTotal;
+ UpdateCountingText();
+}
+
+void CreateMonitor::SetCurrentPosition( sal_Int32 nCurrent )
+{
+ m_nCurrentPosition = nCurrent;
+ UpdateCountingText();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/dbui/maildispatcher.cxx b/sw/source/uibase/dbui/maildispatcher.cxx
new file mode 100644
index 0000000000..8af9b18007
--- /dev/null
+++ b/sw/source/uibase/dbui/maildispatcher.cxx
@@ -0,0 +1,249 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <maildispatcher.hxx>
+#include <imaildsplistener.hxx>
+
+#include <algorithm>
+
+#include <com/sun/star/mail/MailException.hpp>
+#include <utility>
+#include <osl/diagnose.h>
+
+using namespace ::com::sun::star;
+
+typedef std::vector< ::rtl::Reference<IMailDispatcherListener> > MailDispatcherListenerContainer_t;
+
+namespace /* private */
+{
+ class MailDeliveryNotifier
+ {
+ public:
+ MailDeliveryNotifier(uno::Reference<mail::XMailMessage> message) :
+ message_(std::move(message))
+ {}
+
+ void operator() (::rtl::Reference<IMailDispatcherListener> const & listener) const
+ { listener->mailDelivered(message_); }
+
+ private:
+ uno::Reference<mail::XMailMessage> message_;
+ };
+
+ class MailDeliveryErrorNotifier
+ {
+ public:
+ MailDeliveryErrorNotifier(
+ ::rtl::Reference<MailDispatcher> xMailDispatcher,
+ uno::Reference<mail::XMailMessage> message,
+ OUString error_message) :
+ m_mail_dispatcher(std::move(xMailDispatcher)),
+ m_message(std::move(message)),
+ m_error_message(std::move(error_message))
+ {}
+
+ void operator() (::rtl::Reference<IMailDispatcherListener> const & listener) const
+ { listener->mailDeliveryError(m_mail_dispatcher, m_message, m_error_message); }
+
+ private:
+ ::rtl::Reference<MailDispatcher> m_mail_dispatcher;
+ uno::Reference<mail::XMailMessage> m_message;
+ OUString m_error_message;
+ };
+
+} // namespace private
+
+MailDispatcher::MailDispatcher(uno::Reference<mail::XSmtpService> mailserver) :
+ m_xMailserver(std::move( mailserver )),
+ m_bActive( false ),
+ m_bShutdownRequested( false )
+{
+ m_aWakeupCondition.reset();
+ m_aRunCondition.reset();
+
+ if (!create())
+ throw uno::RuntimeException();
+
+ // wait until the mail dispatcher thread is really alive
+ // and has acquired a reference to this instance of the
+ // class
+ m_aRunCondition.wait();
+}
+
+MailDispatcher::~MailDispatcher()
+{
+}
+
+void MailDispatcher::enqueueMailMessage(uno::Reference<mail::XMailMessage> const & message)
+{
+ ::osl::MutexGuard thread_status_guard( m_aThreadStatusMutex );
+ ::osl::MutexGuard message_container_guard( m_aMessageContainerMutex );
+
+ OSL_PRECOND( !m_bShutdownRequested, "MailDispatcher thread is shutting down already" );
+
+ m_aXMessageList.push_back( message );
+ if ( m_bActive )
+ m_aWakeupCondition.set();
+}
+
+uno::Reference<mail::XMailMessage> MailDispatcher::dequeueMailMessage()
+{
+ ::osl::MutexGuard guard( m_aMessageContainerMutex );
+ uno::Reference<mail::XMailMessage> message;
+ if ( !m_aXMessageList.empty() )
+ {
+ message = m_aXMessageList.front();
+ m_aXMessageList.pop_front();
+ }
+ return message;
+}
+
+void MailDispatcher::start()
+{
+ OSL_PRECOND(!isStarted(), "MailDispatcher is already started!");
+
+ ::osl::ClearableMutexGuard thread_status_guard( m_aThreadStatusMutex );
+
+ OSL_PRECOND(!m_bShutdownRequested, "MailDispatcher thread is shutting down already");
+
+ if ( !m_bShutdownRequested )
+ {
+ m_bActive = true;
+ m_aWakeupCondition.set();
+ thread_status_guard.clear();
+ }
+}
+
+void MailDispatcher::stop()
+{
+ OSL_PRECOND(isStarted(), "MailDispatcher not started!");
+
+ ::osl::ClearableMutexGuard thread_status_guard( m_aThreadStatusMutex );
+
+ OSL_PRECOND(!m_bShutdownRequested, "MailDispatcher thread is shutting down already");
+
+ if (!m_bShutdownRequested)
+ {
+ m_bActive = false;
+ m_aWakeupCondition.reset();
+ thread_status_guard.clear();
+ }
+}
+
+void MailDispatcher::shutdown()
+{
+ ::osl::MutexGuard thread_status_guard( m_aThreadStatusMutex );
+
+ OSL_PRECOND(!m_bShutdownRequested, "MailDispatcher thread is shutting down already");
+
+ m_bShutdownRequested = true;
+ m_aWakeupCondition.set();
+}
+
+
+void MailDispatcher::addListener(::rtl::Reference<IMailDispatcherListener> const & listener)
+{
+ OSL_PRECOND(!m_bShutdownRequested, "MailDispatcher thread is shutting down already");
+
+ ::osl::MutexGuard guard( m_aListenerContainerMutex );
+ m_aListenerVector.push_back( listener );
+}
+
+std::vector< ::rtl::Reference<IMailDispatcherListener> > MailDispatcher::cloneListener()
+{
+ ::osl::MutexGuard guard( m_aListenerContainerMutex );
+ return m_aListenerVector;
+}
+
+void MailDispatcher::sendMailMessageNotifyListener(uno::Reference<mail::XMailMessage> const & message)
+{
+ try
+ {
+ m_xMailserver->sendMailMessage( message );
+ MailDispatcherListenerContainer_t aClonedListenerVector(cloneListener());
+ std::for_each( aClonedListenerVector.begin(), aClonedListenerVector.end(),
+ MailDeliveryNotifier(message) );
+ }
+ catch (const mail::MailException& ex)
+ {
+ MailDispatcherListenerContainer_t aClonedListenerVector(cloneListener());
+ std::for_each( aClonedListenerVector.begin(), aClonedListenerVector.end(),
+ MailDeliveryErrorNotifier(this, message, ex.Message) );
+ }
+ catch (const uno::RuntimeException& ex)
+ {
+ MailDispatcherListenerContainer_t aClonedListenerVector(cloneListener());
+ std::for_each( aClonedListenerVector.begin(), aClonedListenerVector.end(),
+ MailDeliveryErrorNotifier(this, message, ex.Message) );
+ }
+}
+
+void MailDispatcher::run()
+{
+ osl_setThreadName("MailDispatcher");
+
+ // acquire a self reference in order to avoid race
+ // conditions. The last client of this class must
+ // call shutdown before releasing his last reference
+ // to this class in order to shutdown this thread
+ // which will release his (the very last reference
+ // to the class and so force their destruction
+ m_xSelfReference = this;
+
+ // signal that the mail dispatcher thread is now alive
+ m_aRunCondition.set();
+
+ for(;;)
+ {
+ m_aWakeupCondition.wait();
+
+ ::osl::ClearableMutexGuard thread_status_guard( m_aThreadStatusMutex );
+ if ( m_bShutdownRequested )
+ break;
+
+ ::osl::ClearableMutexGuard message_container_guard( m_aMessageContainerMutex );
+
+ if ( !m_aXMessageList.empty() )
+ {
+ thread_status_guard.clear();
+ uno::Reference<mail::XMailMessage> message = m_aXMessageList.front();
+ m_aXMessageList.pop_front();
+ message_container_guard.clear();
+ sendMailMessageNotifyListener( message );
+ }
+ else // idle - put ourself to sleep
+ {
+ m_aWakeupCondition.reset();
+ message_container_guard.clear();
+ thread_status_guard.clear();
+ MailDispatcherListenerContainer_t aListenerListcloned( cloneListener() );
+ for( const auto & l : aListenerListcloned)
+ l->idle();
+ }
+ }
+}
+
+void MailDispatcher::onTerminated()
+{
+ //keep the reference until the end of onTerminated() because of the call order in the
+ //_threadFunc() from osl/thread.hxx
+ m_xSelfReference = nullptr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/dbui/mailmergehelper.cxx b/sw/source/uibase/dbui/mailmergehelper.cxx
new file mode 100644
index 0000000000..4e6f7534da
--- /dev/null
+++ b/sw/source/uibase/dbui/mailmergehelper.cxx
@@ -0,0 +1,832 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <swtypes.hxx>
+#include <mailmergehelper.hxx>
+#include <mmconfigitem.hxx>
+#include <docsh.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <sfx2/docfile.hxx>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdb/XColumn.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
+#include <com/sun/star/mail/MailServiceProvider.hpp>
+#include <com/sun/star/mail/XSmtpService.hpp>
+#include <comphelper/processfactory.hxx>
+#include <o3tl/safeint.hxx>
+#include <utility>
+#include <vcl/event.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/weldutils.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <sfx2/passwd.hxx>
+
+#include <dbui.hrc>
+#include <strings.hrc>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+
+namespace SwMailMergeHelper
+{
+
+OUString CallSaveAsDialog(weld::Window* pParent, OUString& rFilter)
+{
+ ::sfx2::FileDialogHelper aDialog( ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
+ FileDialogFlags::NONE,
+ SwDocShell::Factory().GetFactoryName(), SfxFilterFlags::NONE, SfxFilterFlags::NONE, pParent);
+ aDialog.SetContext(sfx2::FileDialogHelper::WriterMailMergeSaveAs);
+
+ if (aDialog.Execute()!=ERRCODE_NONE)
+ {
+ return OUString();
+ }
+
+ rFilter = aDialog.GetRealFilter();
+ uno::Reference < ui::dialogs::XFilePicker3 > xFP = aDialog.GetFilePicker();
+ return xFP->getSelectedFiles().getConstArray()[0];
+}
+
+/*
+ simple address check: check for '@'
+ for at least one '.' after the '@',
+ for at least one character before the dot
+ and for at least two characters after the dot
+*/
+bool CheckMailAddress( std::u16string_view aMailAddress )
+{
+ const size_t nPosAt = aMailAddress.find('@');
+ if (nPosAt == std::u16string_view::npos || aMailAddress.rfind('@')!=nPosAt)
+ return false;
+ const size_t nPosDot = aMailAddress.find('.', nPosAt);
+ return !(nPosDot==std::u16string_view::npos || nPosDot-nPosAt<2 || aMailAddress.size()-nPosDot<3);
+}
+
+uno::Reference< mail::XSmtpService > ConnectToSmtpServer(
+ SwMailMergeConfigItem const & rConfigItem,
+ uno::Reference< mail::XMailService >& rxInMailService,
+ const OUString& rInMailServerPassword,
+ const OUString& rOutMailServerPassword,
+ weld::Window* pDialogParentWindow )
+{
+ uno::Reference< mail::XSmtpService > xSmtpServer;
+ uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
+ try
+ {
+ uno::Reference< mail::XMailServiceProvider > xMailServiceProvider(
+ mail::MailServiceProvider::create( xContext ) );
+ xSmtpServer.set(xMailServiceProvider->create(mail::MailServiceType_SMTP), uno::UNO_QUERY);
+
+ uno::Reference< mail::XConnectionListener> xConnectionListener(new SwConnectionListener);
+
+ if(rConfigItem.IsAuthentication() && rConfigItem.IsSMTPAfterPOP())
+ {
+ uno::Reference< mail::XMailService > xInMailService =
+ xMailServiceProvider->create(
+ rConfigItem.IsInServerPOP() ?
+ mail::MailServiceType_POP3 : mail::MailServiceType_IMAP);
+ //authenticate at the POP or IMAP server first
+ OUString sPasswd = rConfigItem.GetInServerPassword();
+ if(!rInMailServerPassword.isEmpty())
+ sPasswd = rInMailServerPassword;
+ uno::Reference<mail::XAuthenticator> xAuthenticator =
+ new SwAuthenticator(
+ rConfigItem.GetInServerUserName(),
+ sPasswd,
+ pDialogParentWindow);
+
+ xInMailService->addConnectionListener(xConnectionListener);
+ //check connection
+ uno::Reference< uno::XCurrentContext> xConnectionContext =
+ new SwConnectionContext(
+ rConfigItem.GetInServerName(),
+ rConfigItem.GetInServerPort(),
+ "Insecure");
+ xInMailService->connect(xConnectionContext, xAuthenticator);
+ rxInMailService = xInMailService;
+ }
+ uno::Reference< mail::XAuthenticator> xAuthenticator;
+ if(rConfigItem.IsAuthentication() &&
+ !rConfigItem.IsSMTPAfterPOP() &&
+ !rConfigItem.GetMailUserName().isEmpty())
+ {
+ OUString sPasswd = rConfigItem.GetMailPassword();
+ if(!rOutMailServerPassword.isEmpty())
+ sPasswd = rOutMailServerPassword;
+ xAuthenticator =
+ new SwAuthenticator(rConfigItem.GetMailUserName(),
+ sPasswd,
+ pDialogParentWindow);
+ }
+ else
+ xAuthenticator = new SwAuthenticator();
+ //just to check if the server exists
+ xSmtpServer->getSupportedConnectionTypes();
+ //check connection
+
+ uno::Reference< uno::XCurrentContext> xConnectionContext =
+ new SwConnectionContext(
+ rConfigItem.GetMailServer(),
+ rConfigItem.GetMailPort(),
+ rConfigItem.IsSecureConnection() ? OUString("Ssl") : OUString("Insecure") );
+ xSmtpServer->connect(xConnectionContext, xAuthenticator);
+ rxInMailService = xSmtpServer;
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "sw", "");
+ }
+ return xSmtpServer;
+}
+
+} //namespace
+
+struct SwAddressPreview_Impl
+{
+ std::vector< OUString > aAddresses;
+ sal_uInt16 nRows;
+ sal_uInt16 nColumns;
+ sal_uInt16 nSelectedAddress;
+ bool bEnableScrollBar;
+
+ SwAddressPreview_Impl() :
+ nRows(1),
+ nColumns(1),
+ nSelectedAddress(0),
+ bEnableScrollBar(false)
+ {
+ }
+};
+
+OUString SwAddressPreview::FillData(
+ const OUString& rAddress,
+ SwMailMergeConfigItem const & rConfigItem,
+ const Sequence< OUString>* pAssignments)
+{
+ //find the column names in the address string (with name assignment!) and
+ //exchange the placeholder (like <Firstname>) with the database content
+ //unassigned columns are expanded to <not assigned>
+ Reference< XColumnsSupplier > xColsSupp( rConfigItem.GetResultSet(), UNO_QUERY);
+ Reference <XNameAccess> xColAccess = xColsSupp.is() ? xColsSupp->getColumns() : nullptr;
+ Sequence< OUString> aAssignment = pAssignments ?
+ *pAssignments :
+ rConfigItem.GetColumnAssignment(
+ rConfigItem.GetCurrentDBData() );
+ const OUString* pAssignment = aAssignment.getConstArray();
+ const std::vector<std::pair<OUString, int>>& rDefHeaders = rConfigItem.GetDefaultAddressHeaders();
+ OUString sNotAssigned = "<" + SwResId(STR_NOTASSIGNED) + ">";
+
+ bool bIncludeCountry = rConfigItem.IsIncludeCountry();
+ const OUString rExcludeCountry = rConfigItem.GetExcludeCountry();
+ bool bSpecialReplacementForCountry = (!bIncludeCountry || !rExcludeCountry.isEmpty());
+ OUString sCountryColumn;
+ if( bSpecialReplacementForCountry )
+ {
+ sCountryColumn = rDefHeaders[MM_PART_COUNTRY].first;
+ Sequence< OUString> aSpecialAssignment =
+ rConfigItem.GetColumnAssignment( rConfigItem.GetCurrentDBData() );
+ if(aSpecialAssignment.getLength() > MM_PART_COUNTRY && aSpecialAssignment[MM_PART_COUNTRY].getLength())
+ sCountryColumn = aSpecialAssignment[MM_PART_COUNTRY];
+ }
+
+ SwAddressIterator aIter(rAddress);
+ OUStringBuffer sAddress;
+ while(aIter.HasMore())
+ {
+ SwMergeAddressItem aItem = aIter.Next();
+ if(aItem.bIsColumn)
+ {
+ //get the default column name
+
+ //find the appropriate assignment
+ OUString sConvertedColumn = aItem.sText;
+ auto nSize = std::min(sal_uInt32(rDefHeaders.size()), sal_uInt32(aAssignment.getLength()));
+ for(sal_uInt32 nColumn = 0; nColumn < nSize; ++nColumn)
+ {
+ if (rDefHeaders[nColumn].first == aItem.sText &&
+ !pAssignment[nColumn].isEmpty())
+ {
+ sConvertedColumn = pAssignment[nColumn];
+ break;
+ }
+ }
+ if(!sConvertedColumn.isEmpty() &&
+ xColAccess.is() &&
+ xColAccess->hasByName(sConvertedColumn))
+ {
+ //get the content and exchange it in the address string
+ Any aCol = xColAccess->getByName(sConvertedColumn);
+ Reference< XColumn > xColumn;
+ aCol >>= xColumn;
+ if(xColumn.is())
+ {
+ try
+ {
+ OUString sReplace = xColumn->getString();
+
+ if( bSpecialReplacementForCountry && sCountryColumn == sConvertedColumn )
+ {
+ if( !rExcludeCountry.isEmpty() && sReplace != rExcludeCountry )
+ aItem.sText = sReplace;
+ else
+ aItem.sText.clear();
+ }
+ else
+ {
+ aItem.sText = sReplace;
+ }
+ }
+ catch (const sdbc::SQLException&)
+ {
+ TOOLS_WARN_EXCEPTION( "sw", "");
+ }
+ }
+ }
+ else
+ {
+ aItem.sText = sNotAssigned;
+ }
+
+ }
+ sAddress.append(aItem.sText);
+ }
+ return sAddress.makeStringAndClear();
+}
+
+SwAddressPreview::SwAddressPreview(std::unique_ptr<weld::ScrolledWindow> xWindow)
+ : m_pImpl(new SwAddressPreview_Impl())
+ , m_xVScrollBar(std::move(xWindow))
+{
+ m_xVScrollBar->connect_vadjustment_changed(LINK(this, SwAddressPreview, ScrollHdl));
+}
+
+SwAddressPreview::~SwAddressPreview()
+{
+}
+
+IMPL_LINK_NOARG(SwAddressPreview, ScrollHdl, weld::ScrolledWindow&, void)
+{
+ Invalidate();
+}
+
+void SwAddressPreview::AddAddress(const OUString& rAddress)
+{
+ m_pImpl->aAddresses.push_back(rAddress);
+ UpdateScrollBar();
+}
+
+void SwAddressPreview::SetAddress(const OUString& rAddress)
+{
+ m_pImpl->aAddresses.clear();
+ m_pImpl->aAddresses.push_back(rAddress);
+ m_xVScrollBar->set_vpolicy(VclPolicyType::NEVER);
+ Invalidate();
+}
+
+sal_uInt16 SwAddressPreview::GetSelectedAddress()const
+{
+ OSL_ENSURE(m_pImpl->nSelectedAddress < m_pImpl->aAddresses.size(), "selection invalid");
+ return m_pImpl->nSelectedAddress;
+}
+
+void SwAddressPreview::SelectAddress(sal_uInt16 nSelect)
+{
+ OSL_ENSURE(m_pImpl->nSelectedAddress < m_pImpl->aAddresses.size(), "selection invalid");
+ m_pImpl->nSelectedAddress = nSelect;
+ // now make it visible...
+ sal_uInt16 nSelectRow = nSelect / m_pImpl->nColumns;
+ sal_uInt16 nStartRow = m_xVScrollBar->vadjustment_get_value();
+ if( (nSelectRow < nStartRow) || (nSelectRow >= (nStartRow + m_pImpl->nRows) ))
+ m_xVScrollBar->vadjustment_set_value(nSelectRow);
+}
+
+void SwAddressPreview::Clear()
+{
+ m_pImpl->aAddresses.clear();
+ m_pImpl->nSelectedAddress = 0;
+ UpdateScrollBar();
+}
+
+void SwAddressPreview::ReplaceSelectedAddress(const OUString& rNew)
+{
+ m_pImpl->aAddresses[m_pImpl->nSelectedAddress] = rNew;
+ Invalidate();
+}
+
+void SwAddressPreview::RemoveSelectedAddress()
+{
+ m_pImpl->aAddresses.erase(m_pImpl->aAddresses.begin() + m_pImpl->nSelectedAddress);
+ if(m_pImpl->nSelectedAddress)
+ --m_pImpl->nSelectedAddress;
+ UpdateScrollBar();
+ Invalidate();
+}
+
+void SwAddressPreview::SetLayout(sal_uInt16 nRows, sal_uInt16 nColumns)
+{
+ m_pImpl->nRows = nRows;
+ m_pImpl->nColumns = nColumns;
+ UpdateScrollBar();
+}
+
+void SwAddressPreview::EnableScrollBar()
+{
+ m_pImpl->bEnableScrollBar = true;
+}
+
+void SwAddressPreview::UpdateScrollBar()
+{
+ if (m_pImpl->nColumns)
+ {
+ sal_uInt16 nResultingRows = o3tl::narrowing<sal_uInt16>(m_pImpl->aAddresses.size() + m_pImpl->nColumns - 1) / m_pImpl->nColumns;
+ ++nResultingRows;
+ auto nValue = m_xVScrollBar->vadjustment_get_value();
+ if (nValue > nResultingRows)
+ nValue = nResultingRows;
+ m_xVScrollBar->set_vpolicy(m_pImpl->bEnableScrollBar && nResultingRows > m_pImpl->nRows ? VclPolicyType::ALWAYS : VclPolicyType::NEVER);
+ m_xVScrollBar->vadjustment_configure(nValue, 0, nResultingRows, 1, 10, m_pImpl->nRows);
+ }
+}
+
+void SwAddressPreview::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
+{
+ const StyleSettings& rSettings = rRenderContext.GetSettings().GetStyleSettings();
+ rRenderContext.SetFillColor(rSettings.GetWindowColor());
+ rRenderContext.SetLineColor(COL_TRANSPARENT);
+ rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), GetOutputSizePixel()));
+ Color aPaintColor(IsEnabled() ? rSettings.GetWindowTextColor() : rSettings.GetDisableColor());
+ rRenderContext.SetLineColor(aPaintColor);
+
+ weld::SetPointFont(rRenderContext, GetDrawingArea()->get_font());
+ vcl::Font aFont(rRenderContext.GetFont());
+ aFont.SetColor(aPaintColor);
+ rRenderContext.SetFont(aFont);
+
+ Size aSize(GetOutputSizePixel());
+ sal_uInt16 nStartRow = 0;
+ if (m_xVScrollBar->get_vpolicy() != VclPolicyType::NEVER)
+ {
+ aSize.AdjustWidth(-m_xVScrollBar->get_scroll_thickness());
+ nStartRow = m_xVScrollBar->vadjustment_get_value();
+ }
+ Size aPartSize(aSize.Width() / m_pImpl->nColumns,
+ aSize.Height() / m_pImpl->nRows);
+ aPartSize.AdjustWidth( -2 );
+ aPartSize.AdjustHeight( -2 );
+
+ sal_uInt16 nAddress = nStartRow * m_pImpl->nColumns;
+ const sal_uInt16 nNumAddresses = o3tl::narrowing<sal_uInt16>(m_pImpl->aAddresses.size());
+ for (sal_uInt16 nRow = 0; nRow < m_pImpl->nRows ; ++nRow)
+ {
+ for (sal_uInt16 nCol = 0; nCol < m_pImpl->nColumns; ++nCol)
+ {
+ if (nAddress >= nNumAddresses)
+ break;
+ Point aPos(nCol * aPartSize.Width(),
+ nRow * aPartSize.Height());
+ aPos.Move(1, 1);
+ bool bIsSelected = nAddress == m_pImpl->nSelectedAddress;
+ if ((m_pImpl->nColumns * m_pImpl->nRows) == 1)
+ bIsSelected = false;
+ OUString adr(m_pImpl->aAddresses[nAddress]);
+ DrawText_Impl(rRenderContext, adr, aPos, aPartSize, bIsSelected);
+ ++nAddress;
+ }
+ }
+ rRenderContext.SetClipRegion();
+}
+
+bool SwAddressPreview::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if (rMEvt.IsLeft() && m_pImpl->nRows && m_pImpl->nColumns)
+ {
+ //determine the selected address
+ const Point& rMousePos = rMEvt.GetPosPixel();
+ Size aSize(GetOutputSizePixel());
+ Size aPartSize( aSize.Width()/m_pImpl->nColumns, aSize.Height()/m_pImpl->nRows );
+ sal_uInt32 nRow = rMousePos.Y() / aPartSize.Height() ;
+ if (m_xVScrollBar->get_vpolicy() != VclPolicyType::NEVER)
+ {
+ nRow += m_xVScrollBar->vadjustment_get_value();
+ }
+ sal_uInt32 nCol = rMousePos.X() / aPartSize.Width();
+ sal_uInt32 nSelect = nRow * m_pImpl->nColumns + nCol;
+
+ if( nSelect < m_pImpl->aAddresses.size() &&
+ m_pImpl->nSelectedAddress != o3tl::narrowing<sal_uInt16>(nSelect))
+ {
+ m_pImpl->nSelectedAddress = o3tl::narrowing<sal_uInt16>(nSelect);
+ m_aSelectHdl.Call(nullptr);
+ }
+ Invalidate();
+ }
+ return true;
+}
+
+bool SwAddressPreview::KeyInput( const KeyEvent& rKEvt )
+{
+ sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();
+ bool bHandled = false;
+ if (m_pImpl->nRows && m_pImpl->nColumns)
+ {
+ sal_uInt32 nSelectedRow = m_pImpl->nSelectedAddress / m_pImpl->nColumns;
+ sal_uInt32 nSelectedColumn = m_pImpl->nSelectedAddress - (nSelectedRow * m_pImpl->nColumns);
+ switch(nKey)
+ {
+ case KEY_UP:
+ if(nSelectedRow)
+ --nSelectedRow;
+ bHandled = true;
+ break;
+ case KEY_DOWN:
+ if(m_pImpl->aAddresses.size() > o3tl::make_unsigned(m_pImpl->nSelectedAddress + m_pImpl->nColumns))
+ ++nSelectedRow;
+ bHandled = true;
+ break;
+ case KEY_LEFT:
+ if(nSelectedColumn)
+ --nSelectedColumn;
+ bHandled = true;
+ break;
+ case KEY_RIGHT:
+ if(nSelectedColumn < o3tl::make_unsigned(m_pImpl->nColumns - 1) &&
+ m_pImpl->aAddresses.size() - 1 > m_pImpl->nSelectedAddress )
+ ++nSelectedColumn;
+ bHandled = true;
+ break;
+ }
+ sal_uInt32 nSelect = nSelectedRow * m_pImpl->nColumns + nSelectedColumn;
+ if( nSelect < m_pImpl->aAddresses.size() &&
+ m_pImpl->nSelectedAddress != o3tl::narrowing<sal_uInt16>(nSelect))
+ {
+ m_pImpl->nSelectedAddress = o3tl::narrowing<sal_uInt16>(nSelect);
+ m_aSelectHdl.Call(nullptr);
+ Invalidate();
+ }
+ }
+ return bHandled;
+}
+
+void SwAddressPreview::DrawText_Impl(vcl::RenderContext& rRenderContext, std::u16string_view rAddress,
+ const Point& rTopLeft, const Size& rSize, bool bIsSelected)
+{
+ rRenderContext.SetClipRegion(vcl::Region(tools::Rectangle(rTopLeft, rSize)));
+ if (bIsSelected)
+ {
+ //selection rectangle
+ rRenderContext.SetFillColor(COL_TRANSPARENT);
+ rRenderContext.DrawRect(tools::Rectangle(rTopLeft, rSize));
+ }
+ sal_Int32 nHeight = GetTextHeight();
+ Point aStart = rTopLeft;
+ //put it away from the border
+ aStart.Move(2, 2);
+ sal_Int32 nPos = 0;
+ do
+ {
+ rRenderContext.DrawText(aStart, OUString(o3tl::getToken(rAddress, 0, '\n', nPos)));
+ aStart.AdjustY(nHeight );
+ }
+ while (nPos >= 0);
+}
+
+SwMergeAddressItem SwAddressIterator::Next()
+{
+ //currently the string may either start with a '<' then it's a column
+ //otherwise it's simple text maybe containing a return
+ SwMergeAddressItem aRet;
+ if(!m_sAddress.isEmpty())
+ {
+ if(m_sAddress[0] == '<')
+ {
+ aRet.bIsColumn = true;
+ sal_Int32 nClose = m_sAddress.indexOf('>');
+ OSL_ENSURE(nClose != -1, "closing '>' not found");
+ if( nClose != -1 )
+ {
+ aRet.sText = m_sAddress.copy(1, nClose - 1);
+ m_sAddress = m_sAddress.copy(nClose + 1);
+ }
+ else
+ {
+ aRet.sText = m_sAddress.copy(1, 1);
+ m_sAddress = m_sAddress.copy(1);
+ }
+ }
+ else
+ {
+ sal_Int32 nOpen = m_sAddress.indexOf('<');
+ sal_Int32 nReturn = m_sAddress.indexOf('\n');
+ if(nReturn == 0)
+ {
+ aRet.bIsReturn = true;
+ aRet.sText = "\n";
+ m_sAddress = m_sAddress.copy(1);
+ }
+ else if(-1 == nOpen && -1 == nReturn)
+ {
+ aRet.sText = m_sAddress;
+ m_sAddress.clear();
+ }
+ else
+ {
+ if (nOpen == -1)
+ nOpen = m_sAddress.getLength();
+ if (nReturn == -1)
+ nReturn = m_sAddress.getLength();
+ sal_Int32 nTarget = std::min(nOpen, nReturn);
+ aRet.sText = m_sAddress.copy(0, nTarget);
+ m_sAddress = m_sAddress.copy(nTarget);
+ }
+ }
+ }
+ return aRet;
+
+}
+
+SwAuthenticator::~SwAuthenticator()
+{
+}
+
+OUString SwAuthenticator::getUserName( )
+{
+ return m_aUserName;
+}
+
+OUString SwAuthenticator::getPassword( )
+{
+ if(!m_aUserName.isEmpty() && m_aPassword.isEmpty() && m_pParentWindow)
+ {
+ SfxPasswordDialog aPasswdDlg(m_pParentWindow);
+ aPasswdDlg.SetMinLen(0);
+ if (RET_OK == aPasswdDlg.run())
+ m_aPassword = aPasswdDlg.GetPassword();
+ }
+ return m_aPassword;
+}
+
+SwConnectionContext::SwConnectionContext(
+ OUString aMailServer, sal_Int16 nPort,
+ OUString aConnectionType) :
+ m_sMailServer(std::move(aMailServer)),
+ m_nPort(nPort),
+ m_sConnectionType(std::move(aConnectionType))
+{
+}
+
+SwConnectionContext::~SwConnectionContext()
+{
+}
+
+uno::Any SwConnectionContext::getValueByName( const OUString& rName )
+{
+ uno::Any aRet;
+ if( rName == "ServerName" )
+ aRet <<= m_sMailServer;
+ else if( rName == "Port" )
+ aRet <<= static_cast<sal_Int32>(m_nPort);
+ else if( rName == "ConnectionType" )
+ aRet <<= m_sConnectionType;
+ return aRet;
+}
+
+SwConnectionListener::~SwConnectionListener()
+{
+}
+
+void SwConnectionListener::connected(const lang::EventObject& /*aEvent*/)
+{
+}
+
+void SwConnectionListener::disconnected(const lang::EventObject& /*aEvent*/)
+{
+}
+
+void SwConnectionListener::disposing(const lang::EventObject& /*aEvent*/)
+{
+}
+
+SwMailTransferable::SwMailTransferable(OUString aBody, OUString aMimeType) :
+ m_aMimeType(std::move( aMimeType )),
+ m_sBody(std::move( aBody )),
+ m_bIsBody( true )
+{
+}
+
+SwMailTransferable::SwMailTransferable(OUString aURL,
+ OUString aName, OUString aMimeType) :
+ m_aMimeType(std::move( aMimeType )),
+ m_aURL(std::move(aURL)),
+ m_aName(std::move( aName )),
+ m_bIsBody( false )
+{
+}
+
+SwMailTransferable::~SwMailTransferable()
+{
+}
+
+uno::Any SwMailTransferable::getTransferData( const datatransfer::DataFlavor& /*aFlavor*/ )
+{
+ uno::Any aRet;
+ if( m_bIsBody )
+ aRet <<= m_sBody;
+ else
+ {
+ Sequence<sal_Int8> aData;
+ SfxMedium aMedium( m_aURL, StreamMode::STD_READ );
+ SvStream* pStream = aMedium.GetInStream();
+ if ( aMedium.GetErrorCode() == ERRCODE_NONE && pStream)
+ {
+ aData.realloc(pStream->TellEnd());
+ pStream->Seek(0);
+ sal_Int8 * pData = aData.getArray();
+ pStream->ReadBytes( pData, aData.getLength() );
+ }
+ aRet <<= aData;
+ }
+ return aRet;
+}
+
+uno::Sequence< datatransfer::DataFlavor > SwMailTransferable::getTransferDataFlavors( )
+{
+ datatransfer::DataFlavor aRet;
+ aRet.MimeType = m_aMimeType;
+ if( m_bIsBody )
+ {
+ aRet.DataType = cppu::UnoType<OUString>::get();
+ }
+ else
+ {
+ aRet.HumanPresentableName = m_aName;
+ aRet.DataType = cppu::UnoType<uno::Sequence<sal_Int8>>::get();
+ }
+ return { aRet };
+}
+
+sal_Bool SwMailTransferable::isDataFlavorSupported(
+ const datatransfer::DataFlavor& aFlavor )
+{
+ return (aFlavor.MimeType == m_aMimeType);
+}
+
+uno::Reference< beans::XPropertySetInfo > SwMailTransferable::getPropertySetInfo( )
+{
+ return uno::Reference< beans::XPropertySetInfo >();
+}
+
+void SwMailTransferable::setPropertyValue( const OUString& , const uno::Any& )
+{
+}
+
+uno::Any SwMailTransferable::getPropertyValue( const OUString& rPropertyName )
+{
+ uno::Any aRet;
+ if ( rPropertyName == "URL" )
+ aRet <<= m_aURL;
+ return aRet;
+}
+
+void SwMailTransferable::addPropertyChangeListener(
+ const OUString&, const uno::Reference< beans::XPropertyChangeListener >& )
+{
+}
+
+void SwMailTransferable::removePropertyChangeListener(
+ const OUString&,
+ const uno::Reference< beans::XPropertyChangeListener >& )
+{
+}
+
+void SwMailTransferable::addVetoableChangeListener(
+ const OUString&,
+ const uno::Reference< beans::XVetoableChangeListener >& )
+{
+}
+
+void SwMailTransferable::removeVetoableChangeListener(
+ const OUString& ,
+ const uno::Reference< beans::XVetoableChangeListener >& )
+{
+}
+
+SwMailMessage::SwMailMessage()
+{
+}
+
+SwMailMessage::~SwMailMessage()
+{
+}
+
+OUString SwMailMessage::getSenderName()
+{
+ return m_sSenderName;
+}
+
+OUString SwMailMessage::getSenderAddress()
+{
+ return m_sSenderAddress;
+}
+
+OUString SwMailMessage::getReplyToAddress()
+{
+ return m_sReplyToAddress;
+}
+
+void SwMailMessage::setReplyToAddress( const OUString& _replytoaddress )
+{
+ m_sReplyToAddress = _replytoaddress;
+}
+
+OUString SwMailMessage::getSubject()
+{
+ return m_sSubject;
+}
+
+void SwMailMessage::setSubject( const OUString& _subject )
+{
+ m_sSubject = _subject;
+}
+
+uno::Reference< datatransfer::XTransferable > SwMailMessage::getBody()
+{
+ return m_xBody;
+}
+
+void SwMailMessage::setBody(
+ const uno::Reference< datatransfer::XTransferable >& rBody )
+{
+ m_xBody = rBody;
+}
+
+void SwMailMessage::addRecipient( const OUString& rRecipientAddress )
+{
+ m_aRecipients.realloc(m_aRecipients.getLength() + 1);
+ m_aRecipients.getArray()[m_aRecipients.getLength() - 1] = rRecipientAddress;
+}
+
+void SwMailMessage::addCcRecipient( const OUString& rRecipientAddress )
+{
+ m_aCcRecipients.realloc(m_aCcRecipients.getLength() + 1);
+ m_aCcRecipients.getArray()[m_aCcRecipients.getLength() - 1] = rRecipientAddress;
+
+}
+
+void SwMailMessage::addBccRecipient( const OUString& rRecipientAddress )
+{
+ m_aBccRecipients.realloc(m_aBccRecipients.getLength() + 1);
+ m_aBccRecipients.getArray()[m_aBccRecipients.getLength() - 1] = rRecipientAddress;
+}
+
+uno::Sequence< OUString > SwMailMessage::getRecipients( )
+{
+ return m_aRecipients;
+}
+
+uno::Sequence< OUString > SwMailMessage::getCcRecipients( )
+{
+ return m_aCcRecipients;
+}
+
+uno::Sequence< OUString > SwMailMessage::getBccRecipients( )
+{
+ return m_aBccRecipients;
+}
+
+void SwMailMessage::addAttachment( const mail::MailAttachment& rMailAttachment )
+{
+ m_aAttachments.realloc(m_aAttachments.getLength() + 1);
+ m_aAttachments.getArray()[m_aAttachments.getLength() - 1] = rMailAttachment;
+}
+
+uno::Sequence< mail::MailAttachment > SwMailMessage::getAttachments( )
+{
+ return m_aAttachments;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/dbui/mailmergetoolbarcontrols.cxx b/sw/source/uibase/dbui/mailmergetoolbarcontrols.cxx
new file mode 100644
index 0000000000..a6496a12c1
--- /dev/null
+++ b/sw/source/uibase/dbui/mailmergetoolbarcontrols.cxx
@@ -0,0 +1,370 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <svtools/toolboxcontroller.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/InterimItemWindow.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/toolbox.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <strings.hrc>
+#include <mmconfigitem.hxx>
+#include <swmodule.hxx>
+#include <view.hxx>
+
+using namespace css;
+
+namespace {
+
+class CurrentEdit final : public InterimItemWindow
+{
+private:
+ std::unique_ptr<weld::Entry> m_xWidget;
+
+ DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
+public:
+ CurrentEdit(vcl::Window* pParent)
+ : InterimItemWindow(pParent, "modules/swriter/ui/editbox.ui", "EditBox")
+ , m_xWidget(m_xBuilder->weld_entry("entry"))
+ {
+ InitControlBase(m_xWidget.get());
+
+ m_xWidget->connect_key_press(LINK(this, CurrentEdit, KeyInputHdl));
+ SetSizePixel(m_xWidget->get_preferred_size());
+ }
+
+ virtual void dispose() override
+ {
+ m_xWidget.reset();
+ InterimItemWindow::dispose();
+ }
+
+ void set_sensitive(bool bSensitive)
+ {
+ Enable(bSensitive);
+ m_xWidget->set_sensitive(bSensitive);
+ }
+
+ bool get_sensitive() const
+ {
+ return m_xWidget->get_sensitive();
+ }
+
+ void set_text(const OUString& rText)
+ {
+ m_xWidget->set_text(rText);
+ }
+
+ OUString get_text() const
+ {
+ return m_xWidget->get_text();
+ }
+
+ void connect_activate(const Link<weld::Entry&, bool>& rLink)
+ {
+ m_xWidget->connect_activate(rLink);
+ }
+
+ virtual ~CurrentEdit() override
+ {
+ disposeOnce();
+ }
+};
+
+IMPL_LINK(CurrentEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool)
+{
+ return ChildKeyInput(rKEvt);
+}
+
+/// Controller for .uno:MailMergeCurrentEntry toolbar checkbox: creates the checkbox & handles the value.
+typedef cppu::ImplInheritanceHelper< ::svt::ToolboxController, css::lang::XServiceInfo> MMCurrentEntryController_Base;
+class MMCurrentEntryController : public MMCurrentEntryController_Base
+{
+ VclPtr<CurrentEdit> m_xCurrentEdit;
+
+ DECL_LINK(CurrentEditUpdatedHdl, weld::Entry&, bool);
+
+public:
+ explicit MMCurrentEntryController(const uno::Reference<uno::XComponentContext>& rContext)
+ : MMCurrentEntryController_Base(rContext, uno::Reference<frame::XFrame>(), ".uno:MailMergeCurrentEntry")
+ , m_xCurrentEdit(nullptr)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override
+ {
+ return "lo.writer.MMCurrentEntryController";
+ }
+
+ virtual sal_Bool SAL_CALL supportsService(const OUString& rServiceName) override
+ {
+ return cppu::supportsService(this, rServiceName);
+ }
+
+ virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
+ {
+ return { "com.sun.star.frame.ToolbarController" };
+ }
+
+ // XComponent
+ virtual void SAL_CALL dispose() override;
+
+ // XToolbarController
+ virtual uno::Reference<awt::XWindow> SAL_CALL createItemWindow(const uno::Reference<awt::XWindow>& rParent) override;
+
+ // XStatusListener
+ virtual void SAL_CALL statusChanged(const frame::FeatureStateEvent& rEvent) override;
+};
+
+class ExcludeCheckBox final : public InterimItemWindow
+{
+private:
+ std::unique_ptr<weld::CheckButton> m_xWidget;
+
+ DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
+public:
+ ExcludeCheckBox(vcl::Window* pParent)
+ : InterimItemWindow(pParent, "modules/swriter/ui/checkbox.ui", "CheckBox")
+ , m_xWidget(m_xBuilder->weld_check_button("checkbutton"))
+ {
+ InitControlBase(m_xWidget.get());
+
+ m_xWidget->set_label(SwResId(ST_EXCLUDE));
+ m_xWidget->connect_key_press(LINK(this, ExcludeCheckBox, KeyInputHdl));
+ SetSizePixel(m_xWidget->get_preferred_size());
+ }
+
+ virtual void dispose() override
+ {
+ m_xWidget.reset();
+ InterimItemWindow::dispose();
+ }
+
+ void set_sensitive(bool bSensitive)
+ {
+ Enable(bSensitive);
+ m_xWidget->set_sensitive(bSensitive);
+ }
+
+ void set_active(bool bActive)
+ {
+ m_xWidget->set_active(bActive);
+ }
+
+ void connect_toggled(const Link<weld::Toggleable&, void>& rLink)
+ {
+ m_xWidget->connect_toggled(rLink);
+ }
+
+ virtual ~ExcludeCheckBox() override
+ {
+ disposeOnce();
+ }
+};
+
+IMPL_LINK(ExcludeCheckBox, KeyInputHdl, const KeyEvent&, rKEvt, bool)
+{
+ return ChildKeyInput(rKEvt);
+}
+
+/// Controller for .uno:MailMergeExcludeEntry toolbar checkbox: creates the checkbox & handles the value.
+typedef cppu::ImplInheritanceHelper< ::svt::ToolboxController, css::lang::XServiceInfo> MMExcludeEntryController_Base;
+class MMExcludeEntryController : public MMExcludeEntryController_Base
+{
+ VclPtr<ExcludeCheckBox> m_xExcludeCheckbox;
+
+ DECL_STATIC_LINK(MMExcludeEntryController, ExcludeHdl, weld::Toggleable&, void);
+
+public:
+ explicit MMExcludeEntryController(const uno::Reference<uno::XComponentContext>& rContext)
+ : MMExcludeEntryController_Base(rContext, uno::Reference<frame::XFrame>(), ".uno:MailMergeExcludeEntry")
+ , m_xExcludeCheckbox(nullptr)
+ {
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override
+ {
+ return "lo.writer.MMExcludeEntryController";
+ }
+
+ virtual sal_Bool SAL_CALL supportsService(const OUString& rServiceName) override
+ {
+ return cppu::supportsService(this, rServiceName);
+ }
+
+ virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
+ {
+ return { "com.sun.star.frame.ToolbarController" };
+ }
+
+ // XComponent
+ virtual void SAL_CALL dispose() override;
+
+ // XToolbarController
+ virtual uno::Reference<awt::XWindow> SAL_CALL createItemWindow(const uno::Reference<awt::XWindow>& rParent) override;
+
+ // XStatusListener
+ virtual void SAL_CALL statusChanged(const frame::FeatureStateEvent& rEvent) override;
+};
+
+void MMCurrentEntryController::dispose()
+{
+ SolarMutexGuard aSolarMutexGuard;
+
+ svt::ToolboxController::dispose();
+ m_xCurrentEdit.disposeAndClear();
+}
+
+uno::Reference<awt::XWindow> MMCurrentEntryController::createItemWindow(const uno::Reference<awt::XWindow>& rParent)
+{
+ VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow(rParent);
+ ToolBox* pToolbar = dynamic_cast<ToolBox*>(pParent.get());
+ if (pToolbar)
+ {
+ // make it visible
+ m_xCurrentEdit = VclPtr<CurrentEdit>::Create(pToolbar);
+ m_xCurrentEdit->connect_activate(LINK(this, MMCurrentEntryController, CurrentEditUpdatedHdl));
+ }
+
+ return VCLUnoHelper::GetInterface(m_xCurrentEdit);
+}
+
+IMPL_LINK(MMCurrentEntryController, CurrentEditUpdatedHdl, weld::Entry&, rEdit, bool)
+{
+ std::shared_ptr<SwMailMergeConfigItem> xConfigItem;
+ if (SwView* pView = GetActiveView())
+ xConfigItem = pView->GetMailMergeConfigItem();
+
+ if (!xConfigItem)
+ return true;
+
+ OUString aText(rEdit.get_text());
+ sal_Int32 nEntry = aText.toInt32();
+ if (!aText.isEmpty() && nEntry != xConfigItem->GetResultSetPosition())
+ {
+ xConfigItem->MoveResultSet(nEntry);
+ // notify about the change
+ dispatchCommand(".uno:MailMergeCurrentEntry", uno::Sequence<beans::PropertyValue>());
+ }
+ return true;
+};
+
+void MMCurrentEntryController::statusChanged(const frame::FeatureStateEvent& rEvent)
+{
+ if (!m_xCurrentEdit)
+ return;
+
+ std::shared_ptr<SwMailMergeConfigItem> xConfigItem;
+ if (SwView* pView = GetActiveView())
+ xConfigItem = pView->GetMailMergeConfigItem();
+
+ if (!xConfigItem || !rEvent.IsEnabled)
+ {
+ m_xCurrentEdit->set_sensitive(false);
+ m_xCurrentEdit->set_text("");
+ }
+ else
+ {
+ sal_Int32 nEntry = m_xCurrentEdit->get_text().toInt32();
+ if (!m_xCurrentEdit->get_sensitive() || nEntry != xConfigItem->GetResultSetPosition())
+ {
+ m_xCurrentEdit->set_sensitive(true);
+ m_xCurrentEdit->set_text(OUString::number(xConfigItem->GetResultSetPosition()));
+ }
+ }
+}
+
+void MMExcludeEntryController::dispose()
+{
+ SolarMutexGuard aSolarMutexGuard;
+
+ svt::ToolboxController::dispose();
+ m_xExcludeCheckbox.disposeAndClear();
+}
+
+uno::Reference<awt::XWindow> MMExcludeEntryController::createItemWindow(const uno::Reference<awt::XWindow>& rParent)
+{
+ VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow(rParent);
+ ToolBox* pToolbar = dynamic_cast<ToolBox*>(pParent.get());
+ if (pToolbar)
+ {
+ // make it visible
+ m_xExcludeCheckbox = VclPtr<ExcludeCheckBox>::Create(pToolbar);
+ m_xExcludeCheckbox->connect_toggled(LINK(this, MMExcludeEntryController, ExcludeHdl));
+ }
+
+ return VCLUnoHelper::GetInterface(m_xExcludeCheckbox);
+}
+
+IMPL_STATIC_LINK(MMExcludeEntryController, ExcludeHdl, weld::Toggleable&, rCheckbox, void)
+{
+ std::shared_ptr<SwMailMergeConfigItem> xConfigItem;
+ if (SwView* pView = GetActiveView())
+ xConfigItem = pView->GetMailMergeConfigItem();
+
+ if (xConfigItem)
+ xConfigItem->ExcludeRecord(xConfigItem->GetResultSetPosition(), rCheckbox.get_active());
+};
+
+void MMExcludeEntryController::statusChanged(const frame::FeatureStateEvent& rEvent)
+{
+ if (!m_xExcludeCheckbox)
+ return;
+
+ std::shared_ptr<SwMailMergeConfigItem> xConfigItem;
+ if (SwView* pView = GetActiveView())
+ xConfigItem = pView->GetMailMergeConfigItem();
+
+ if (!xConfigItem || !rEvent.IsEnabled)
+ {
+ m_xExcludeCheckbox->set_sensitive(false);
+ m_xExcludeCheckbox->set_active(false);
+ }
+ else
+ {
+ m_xExcludeCheckbox->set_sensitive(true);
+ m_xExcludeCheckbox->set_active(xConfigItem->IsRecordExcluded(xConfigItem->GetResultSetPosition()));
+ }
+}
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface *
+lo_writer_MMCurrentEntryController_get_implementation(
+ uno::XComponentContext *context,
+ uno::Sequence<uno::Any> const &)
+{
+ return cppu::acquire(new MMCurrentEntryController(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface *
+lo_writer_MMExcludeEntryController_get_implementation(
+ uno::XComponentContext *context,
+ uno::Sequence<uno::Any> const &)
+{
+ return cppu::acquire(new MMExcludeEntryController(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/dbui/mmconfigitem.cxx b/sw/source/uibase/dbui/mmconfigitem.cxx
new file mode 100644
index 0000000000..c8f89a44d4
--- /dev/null
+++ b/sw/source/uibase/dbui/mmconfigitem.cxx
@@ -0,0 +1,1708 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <mmconfigitem.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <vector>
+#include <swtypes.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdbc/XRowSet.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/types.hxx>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <comphelper/sequence.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <unotools/configitem.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <mailmergehelper.hxx>
+#include <swunohelper.hxx>
+#include <dbmgr.hxx>
+#include <view.hxx>
+#include <unodispatch.hxx>
+#include <wrtsh.hxx>
+#include <dbui.hrc>
+
+using namespace utl;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+
+constexpr OUString cAddressDataAssignments = u"AddressDataAssignments"_ustr;
+const char cDBColumnAssignments[] = "DBColumnAssignments";
+const char cDataSourceName[] = "DataSource/DataSourceName";
+const char cDataTableName[] = "DataSource/DataTableName" ;
+const char cDataCommandType[] = "DataSource/DataCommandType";
+
+#define SECURE_PORT 587
+#define DEFAULT_PORT 25
+#define POP_PORT 110
+#define POP_SECURE_PORT 995
+#define IMAP_PORT 143
+#define IMAP_SECURE_PORT 993
+
+namespace {
+
+struct DBAddressDataAssignment
+{
+ SwDBData aDBData;
+ Sequence< OUString> aDBColumnAssignments;
+ //if loaded the name of the node has to be saved
+ OUString sConfigNodeName;
+ //all created or changed assignments need to be stored
+ bool bColumnAssignmentsChanged;
+
+ DBAddressDataAssignment() :
+ bColumnAssignmentsChanged(false)
+ {}
+};
+
+}
+
+class SwMailMergeConfigItem_Impl : public utl::ConfigItem
+{
+ friend class SwMailMergeConfigItem;
+ Reference< XDataSource> m_xSource;
+ SharedConnection m_xConnection;
+ Reference< XColumnsSupplier> m_xColumnsSupplier;
+ Reference< XResultSet> m_xResultSet;
+ SwDBData m_aDBData;
+ OUString m_sFilter;
+ sal_Int32 m_nResultSetCursorPos;
+
+ std::vector<DBAddressDataAssignment> m_aAddressDataAssignments;
+ std::vector< OUString> m_aAddressBlocks;
+ sal_Int32 m_nCurrentAddressBlock;
+ bool m_bIsAddressBlock;
+ bool m_bIsHideEmptyParagraphs;
+
+ bool m_bIsOutputToLetter;
+ bool m_bIncludeCountry;
+ OUString m_sExcludeCountry;
+
+ bool m_bIsGreetingLine;
+ bool m_bIsIndividualGreetingLine;
+ std::vector< OUString> m_aFemaleGreetingLines;
+ sal_Int32 m_nCurrentFemaleGreeting;
+ std::vector< OUString> m_aMaleGreetingLines;
+ sal_Int32 m_nCurrentMaleGreeting;
+ std::vector< OUString> m_aNeutralGreetingLines;
+ sal_Int32 m_nCurrentNeutralGreeting;
+ OUString m_sFemaleGenderValue;
+ uno::Sequence< OUString> m_aSavedDocuments;
+
+ bool m_bIsGreetingLineInMail;
+ bool m_bIsIndividualGreetingLineInMail;
+
+ //mail settings
+ OUString m_sMailDisplayName;
+ OUString m_sMailAddress;
+ OUString m_sMailReplyTo;
+ OUString m_sMailServer;
+ OUString m_sMailUserName;
+ OUString m_sMailPassword;
+
+ bool m_bIsSMPTAfterPOP;
+ OUString m_sInServerName;
+ sal_Int16 m_nInServerPort;
+ bool m_bInServerPOP;
+ OUString m_sInServerUserName;
+ OUString m_sInServerPassword;
+
+ sal_Int16 m_nMailPort;
+ bool m_bIsMailReplyTo;
+ bool m_bIsSecureConnection;
+ bool m_bIsAuthentication;
+
+ bool m_bIsEMailSupported;
+
+ std::vector<std::pair<OUString, int>> m_AddressHeaderSA;
+
+ //these addresses are not stored in the configuration
+ std::vector< SwDocMergeInfo > m_aMergeInfos;
+
+ //we do overwrite the usersettings in a special case
+ //then we do remind the usersettings here
+ bool m_bUserSettingWereOverwritten;
+ bool m_bIsAddressBlock_LastUserSetting;
+ bool m_bIsGreetingLineInMail_LastUserSetting;
+ bool m_bIsGreetingLine_LastUserSetting;
+
+ static const Sequence< OUString>& GetPropertyNames();
+
+ virtual void ImplCommit() override;
+
+public:
+ SwMailMergeConfigItem_Impl();
+
+ virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+ Sequence< OUString> GetAddressBlocks(bool bConvertToConfig = false) const;
+ void SetAddressBlocks(
+ const Sequence< OUString>& rBlocks,
+ bool bConvertFromConfig = false);
+ uno::Sequence< OUString>
+ GetGreetings(SwMailMergeConfigItem::Gender eType,
+ bool bConvertToConfig = false) const;
+ void SetGreetings(SwMailMergeConfigItem::Gender eType,
+ const uno::Sequence< OUString>& rBlocks,
+ bool bConvertFromConfig = false);
+
+ void SetCurrentAddressBlockIndex( sal_Int32 nSet );
+ sal_Int32 GetCurrentAddressBlockIndex() const
+ { return m_nCurrentAddressBlock; }
+ sal_Int32 GetCurrentGreeting(SwMailMergeConfigItem::Gender eType) const;
+ void SetCurrentGreeting(SwMailMergeConfigItem::Gender eType, sal_Int32 nIndex);
+
+};
+
+SwMailMergeConfigItem_Impl::SwMailMergeConfigItem_Impl() :
+ ConfigItem("Office.Writer/MailMergeWizard", ConfigItemMode::NONE),
+ m_nResultSetCursorPos(-1),
+ m_nCurrentAddressBlock(0),
+ m_bIsAddressBlock(true),
+ m_bIsHideEmptyParagraphs(false),
+ m_bIsOutputToLetter(true),
+ m_bIncludeCountry(false),
+ m_bIsGreetingLine(true),
+ m_bIsIndividualGreetingLine(false),
+ m_nCurrentFemaleGreeting(0),
+ m_nCurrentMaleGreeting(0),
+ m_nCurrentNeutralGreeting(0),
+ m_bIsGreetingLineInMail(false),
+ m_bIsIndividualGreetingLineInMail(false),
+ m_bIsSMPTAfterPOP(false),
+ m_nInServerPort( POP_SECURE_PORT ),
+ m_bInServerPOP( true ),
+ m_nMailPort(SECURE_PORT),
+ m_bIsMailReplyTo(false),
+ m_bIsSecureConnection(true),
+ m_bIsAuthentication(false),
+
+ m_bIsEMailSupported(false),
+ m_bUserSettingWereOverwritten(false),
+ m_bIsAddressBlock_LastUserSetting(false),
+ m_bIsGreetingLineInMail_LastUserSetting(false),
+ m_bIsGreetingLine_LastUserSetting(false)
+{
+ for (auto const& [aName, aID] : SA_ADDRESS_HEADER)
+ {
+ m_AddressHeaderSA.emplace_back(SwResId(aName), aID);
+ }
+
+ const Sequence<OUString>& rNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(rNames);
+ const Any* pValues = aValues.getConstArray();
+ assert(aValues.getLength() == rNames.getLength());
+ if(aValues.getLength() == rNames.getLength())
+ {
+ for(int nProp = 0; nProp < rNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case 0: pValues[nProp] >>= m_bIsOutputToLetter; break;
+ case 1: pValues[nProp] >>= m_bIncludeCountry; break;
+ case 2: pValues[nProp] >>= m_sExcludeCountry; break;
+ case 3:
+ {
+ Sequence< OUString> aBlocks;
+ pValues[nProp] >>= aBlocks;
+ SetAddressBlocks(aBlocks, true);
+ }
+ break;
+ case 4: pValues[nProp] >>= m_bIsAddressBlock; break;
+ case 5: pValues[nProp] >>= m_bIsGreetingLine; break;
+ case 6: pValues[nProp] >>= m_bIsIndividualGreetingLine; break;
+ case 7 :
+ case 8 :
+ case 9 :
+ {
+ Sequence< OUString> aGreetings;
+ pValues[nProp] >>= aGreetings;
+ SetGreetings(SwMailMergeConfigItem::Gender(
+ SwMailMergeConfigItem::FEMALE + nProp - 7), aGreetings, true);
+ }
+ break;
+
+ case 10: pValues[nProp] >>= m_nCurrentFemaleGreeting; break;
+ case 11: pValues[nProp] >>= m_nCurrentMaleGreeting; break;
+ case 12: pValues[nProp] >>= m_nCurrentNeutralGreeting; break;
+ case 13: pValues[nProp] >>= m_sFemaleGenderValue; break;
+ case 14: pValues[nProp] >>= m_sMailDisplayName; break;
+ case 15: pValues[nProp] >>= m_sMailAddress; break;
+ case 16: pValues[nProp] >>= m_bIsMailReplyTo; break;
+ case 17: pValues[nProp] >>= m_sMailReplyTo; break;
+ case 18: pValues[nProp] >>= m_sMailServer; break;
+ case 19: pValues[nProp] >>= m_nMailPort; break;
+ case 20: pValues[nProp] >>= m_bIsSecureConnection; break;
+ case 21: pValues[nProp] >>= m_bIsAuthentication; break;
+ case 22: pValues[nProp] >>= m_sMailUserName; break;
+ case 23: pValues[nProp] >>= m_sMailPassword; break;
+ case 24 :pValues[nProp] >>= m_aDBData.sDataSource; break;
+ case 25 :pValues[nProp] >>= m_aDBData.sCommand; break;
+ case 26 :
+ {
+ short nTemp = 0;
+ if(pValues[nProp] >>= nTemp)
+ m_aDBData.nCommandType = nTemp;
+ }
+ break;
+ case 27: pValues[nProp] >>= m_sFilter; break;
+ case 28: pValues[nProp] >>= m_aSavedDocuments; break;
+ case 29:
+ pValues[nProp] >>= m_bIsEMailSupported;
+ break;
+ case 30: pValues[nProp] >>= m_bIsGreetingLineInMail; break;
+ case 31: pValues[nProp] >>= m_bIsIndividualGreetingLineInMail; break;
+ case 32: pValues[nProp] >>= m_bIsSMPTAfterPOP; break;
+ case 33: pValues[nProp] >>= m_sInServerName; break;
+ case 34: pValues[nProp] >>= m_nInServerPort; break;
+ case 35: pValues[nProp] >>= m_bInServerPOP; break;
+ case 36: pValues[nProp] >>= m_sInServerUserName; break;
+ case 37: pValues[nProp] >>= m_sInServerPassword; break;
+ case 38: pValues[nProp] >>= m_bIsHideEmptyParagraphs; break;
+ case 39: pValues[nProp] >>= m_nCurrentAddressBlock; break;
+ }
+ }
+ ClearModified();
+ }
+ //read the list of data base assignments
+ Sequence<OUString> aAssignments = GetNodeNames(cAddressDataAssignments);
+ if(aAssignments.hasElements())
+ {
+ //create a list of property names to load the URLs of all data bases
+ const OUString* pAssignments = aAssignments.getConstArray();
+ Sequence< OUString > aAssignProperties(4 * aAssignments.getLength());
+ OUString* pAssignProperties = aAssignProperties.getArray();
+ sal_Int32 nAssign;
+ for(nAssign = 0; nAssign < aAssignProperties.getLength(); nAssign += 4)
+ {
+ OUString sAssignPath = OUString::Concat(cAddressDataAssignments) +
+ "/" +
+ pAssignments[nAssign / 4] +
+ "/";
+ pAssignProperties[nAssign] = sAssignPath;
+ pAssignProperties[nAssign] += cDataSourceName;
+ pAssignProperties[nAssign + 1] = sAssignPath;
+ pAssignProperties[nAssign + 1] += cDataTableName;
+ pAssignProperties[nAssign + 2] = sAssignPath;
+ pAssignProperties[nAssign + 2] += cDataCommandType;
+ pAssignProperties[nAssign + 3] = sAssignPath;
+ pAssignProperties[nAssign + 3] += cDBColumnAssignments;
+ }
+ Sequence<Any> aAssignValues = GetProperties(aAssignProperties);
+ const Any* pAssignValues = aAssignValues.getConstArray();
+ for(nAssign = 0; nAssign < aAssignValues.getLength(); nAssign += 4 )
+ {
+ DBAddressDataAssignment aAssignment;
+ pAssignValues[nAssign] >>= aAssignment.aDBData.sDataSource;
+ pAssignValues[nAssign + 1] >>= aAssignment.aDBData.sCommand;
+ pAssignValues[nAssign + 2] >>= aAssignment.aDBData.nCommandType;
+ pAssignValues[nAssign + 3] >>= aAssignment.aDBColumnAssignments;
+ aAssignment.sConfigNodeName = pAssignments[nAssign / 4];
+ m_aAddressDataAssignments.push_back(aAssignment);
+ }
+ }
+ //check if the saved documents still exist
+ if(!m_aSavedDocuments.hasElements())
+ return;
+
+ uno::Sequence< OUString > aTempDocuments(m_aSavedDocuments.getLength());
+ auto begin = aTempDocuments.getArray();
+ OUString* pTempDocuments = std::copy_if(std::cbegin(m_aSavedDocuments), std::cend(m_aSavedDocuments), begin,
+ [](const OUString& rDoc) { return SWUnoHelper::UCB_IsFile( rDoc ); });
+ sal_Int32 nIndex = static_cast<sal_Int32>(std::distance(begin, pTempDocuments));
+ if(nIndex < m_aSavedDocuments.getLength())
+ {
+ m_aSavedDocuments.swap(aTempDocuments);
+ m_aSavedDocuments.realloc(nIndex);
+ }
+}
+
+void SwMailMergeConfigItem_Impl::SetCurrentAddressBlockIndex( sal_Int32 nSet )
+{
+ if(m_aAddressBlocks.size() >= sal::static_int_cast<sal_uInt32, sal_Int32>(nSet))
+ {
+ m_nCurrentAddressBlock = nSet;
+ SetModified();
+ }
+}
+
+static OUString lcl_CreateNodeName(Sequence<OUString>& rAssignments )
+{
+ sal_Int32 nStart = rAssignments.getLength();
+ OUString sNewName;
+ //search if the name exists
+ while(true)
+ {
+ sNewName = "_" + OUString::number(nStart++);
+ if(comphelper::findValue(rAssignments, sNewName) == -1)
+ break;
+ }
+ // add the new name to the array of existing names
+ rAssignments.realloc(rAssignments.getLength() + 1);
+ rAssignments.getArray()[rAssignments.getLength() - 1] = sNewName;
+ return sNewName;
+}
+
+static void lcl_ConvertToNumbers(OUString& rBlock, const std::vector<std::pair<OUString, int>>& rHeaders )
+{
+ //convert the strings used for UI to numbers used for the configuration
+ OUString sBlock(rBlock.replaceAll("\n", "\\n"));
+ for (size_t i = 0; i < rHeaders.size(); ++i)
+ {
+ OUString sHeader = "<" + rHeaders[i].first + ">";
+ OUString sReplace = "<" + OUStringChar(sal_Unicode('0' + i)) + ">";
+ sBlock = sBlock.replaceAll(sHeader, sReplace);
+ }
+ rBlock = sBlock;
+}
+
+static void lcl_ConvertFromNumbers(OUString& rBlock, const std::vector<std::pair<OUString, int>>& rHeaders)
+{
+ //convert the numbers used for the configuration to strings used for UI to numbers
+ //doesn't use ReplaceAll to prevent expansion of numbers inside of the headers
+ SwAddressIterator aGreetingIter(rBlock.replaceAll("\\n", "\n"));
+ OUStringBuffer sBlock;
+ while(aGreetingIter.HasMore())
+ {
+ SwMergeAddressItem aNext = aGreetingIter.Next();
+ if(aNext.bIsColumn)
+ {
+ //the text should be 1 characters long
+ sal_Unicode cChar = aNext.sText[0];
+ if(cChar >= '0' && cChar <= 'c')
+ {
+ sBlock.append("<");
+ sal_uInt16 nHeader = cChar - '0';
+ if(nHeader < rHeaders.size())
+ sBlock.append(rHeaders[nHeader].first);
+ sBlock.append(">");
+ }
+ else
+ {
+ SAL_WARN("sw.ui", "parse error in address block or greeting line");
+ }
+ }
+ else
+ sBlock.append(aNext.sText);
+ }
+ rBlock = sBlock.makeStringAndClear();
+}
+
+const Sequence<OUString>& SwMailMergeConfigItem_Impl::GetPropertyNames()
+{
+ static Sequence<OUString> aNames {
+ "OutputToLetter", // 0
+ "IncludeCountry", // 1
+ "ExcludeCountry", // 2
+ "AddressBlockSettings", // 3
+ "IsAddressBlock", // 4
+ "IsGreetingLine", // 5
+ "IsIndividualGreetingLine", // 6
+ "FemaleGreetingLines", // 7
+ "MaleGreetingLines", // 8
+ "NeutralGreetingLines", // 9
+ "CurrentFemaleGreeting", // 10
+ "CurrentMaleGreeting", // 11
+ "CurrentNeutralGreeting", // 12
+ "FemaleGenderValue", // 13
+ "MailDisplayName", // 14
+ "MailAddress", // 15
+ "IsMailReplyTo", // 16
+ "MailReplyTo", // 17
+ "MailServer", // 18
+ "MailPort", // 19
+ "IsSecureConnection", // 20
+ "IsAuthentication", // 21
+ "MailUserName", // 22
+ "MailPassword", // 23
+ "DataSource/DataSourceName", // 24
+ "DataSource/DataTableName", // 25
+ "DataSource/DataCommandType",// 26
+ "Filter", // 27
+ "SavedDocuments", // 28
+ "EMailSupported", // 29
+ "IsEMailGreetingLine", //30
+ "IsEMailIndividualGreetingLine", //31
+ "IsSMPTAfterPOP", //32
+ "InServerName", //33
+ "InServerPort", //34
+ "InServerIsPOP", //35
+ "InServerUserName", //36
+ "InServerPassword", //37
+ "IsHideEmptyParagraphs", //38
+ "CurrentAddressBlock" //39
+ };
+ return aNames;
+}
+
+void SwMailMergeConfigItem_Impl::Notify( const css::uno::Sequence< OUString >& ) {}
+
+void SwMailMergeConfigItem_Impl::ImplCommit()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case 0: pValues[nProp] <<= m_bIsOutputToLetter; break;
+ case 1: pValues[nProp] <<= m_bIncludeCountry; break;
+ case 2: pValues[nProp] <<= m_sExcludeCountry; break;
+ case 3: pValues[nProp] <<= GetAddressBlocks(true); break;
+ case 4:
+ {
+ if( m_bUserSettingWereOverwritten)
+ pValues[nProp] <<= m_bIsAddressBlock_LastUserSetting;
+ else
+ pValues[nProp] <<= m_bIsAddressBlock;
+ break;
+ }
+ case 5:
+ {
+ if( m_bUserSettingWereOverwritten)
+ pValues[nProp] <<= m_bIsGreetingLine_LastUserSetting;
+ else
+ pValues[nProp] <<= m_bIsGreetingLine;
+ break;
+ }
+ case 6: pValues[nProp] <<= m_bIsIndividualGreetingLine; break;
+ case 7:
+ case 8:
+ case 9:
+ pValues[nProp] <<= GetGreetings(
+ SwMailMergeConfigItem::Gender(
+ SwMailMergeConfigItem::FEMALE + nProp - 7), true);
+ break;
+ case 10: pValues[nProp] <<= m_nCurrentFemaleGreeting; break;
+ case 11: pValues[nProp] <<= m_nCurrentMaleGreeting; break;
+ case 12: pValues[nProp] <<= m_nCurrentNeutralGreeting; break;
+ case 13: pValues[nProp] <<= m_sFemaleGenderValue; break;
+ case 14: pValues[nProp] <<= m_sMailDisplayName; break;
+ case 15: pValues[nProp] <<= m_sMailAddress; break;
+ case 16: pValues[nProp] <<= m_bIsMailReplyTo; break;
+ case 17: pValues[nProp] <<= m_sMailReplyTo; break;
+ case 18: pValues[nProp] <<= m_sMailServer; break;
+ case 19: pValues[nProp] <<= m_nMailPort; break;
+ case 20: pValues[nProp] <<= m_bIsSecureConnection; break;
+ case 21: pValues[nProp] <<= m_bIsAuthentication; break;
+ case 22: pValues[nProp] <<= m_sMailUserName; break;
+ case 23: pValues[nProp] <<= m_sMailPassword; break;
+ case 24 :pValues[nProp] <<= m_aDBData.sDataSource; break;
+ case 25 :pValues[nProp] <<= m_aDBData.sCommand; break;
+ case 26 :pValues[nProp] <<= m_aDBData.nCommandType; break;
+ case 27 :pValues[nProp] <<= m_sFilter; break;
+ case 28 :pValues[nProp] <<= m_aSavedDocuments; break;
+ case 29: pValues[nProp] <<= m_bIsEMailSupported; break;
+ case 30:
+ {
+ if( m_bUserSettingWereOverwritten)
+ pValues[nProp] <<= m_bIsGreetingLineInMail_LastUserSetting;
+ else
+ pValues[nProp] <<= m_bIsGreetingLineInMail;
+ break;
+ }
+ case 31: pValues[nProp] <<= m_bIsIndividualGreetingLineInMail; break;
+ case 32: pValues[nProp] <<= m_bIsSMPTAfterPOP; break;
+ case 33: pValues[nProp] <<= m_sInServerName; break;
+ case 34: pValues[nProp] <<= m_nInServerPort; break;
+ case 35: pValues[nProp] <<= m_bInServerPOP; break;
+ case 36: pValues[nProp] <<= m_sInServerUserName; break;
+ case 37: pValues[nProp] <<= m_sInServerPassword; break;
+ case 38: pValues[nProp] <<= m_bIsHideEmptyParagraphs; break;
+ case 39: pValues[nProp] <<= m_nCurrentAddressBlock; break;
+ }
+ }
+ PutProperties(aNames, aValues);
+ //store the changed / new assignments
+
+ //load the existing node names to find new names
+ Sequence<OUString> aAssignments = GetNodeNames(cAddressDataAssignments);
+
+ for(const auto& rAssignment : m_aAddressDataAssignments)
+ {
+ if(rAssignment.bColumnAssignmentsChanged)
+ {
+ //create a new node name
+ OUString sNewNode = !rAssignment.sConfigNodeName.isEmpty() ?
+ rAssignment.sConfigNodeName :
+ lcl_CreateNodeName(aAssignments);
+ OUString sSlash = "/";
+ OUString sNodePath = cAddressDataAssignments + sSlash + sNewNode + sSlash;
+ //only one new entry is written
+ Sequence< PropertyValue > aNewValues
+ {
+ comphelper::makePropertyValue(sNodePath + cDataSourceName, rAssignment.aDBData.sDataSource),
+ comphelper::makePropertyValue(sNodePath + cDataTableName, rAssignment.aDBData.sCommand),
+ comphelper::makePropertyValue(sNodePath + cDataCommandType, rAssignment.aDBData.nCommandType),
+ comphelper::makePropertyValue(sNodePath + cDBColumnAssignments, rAssignment.aDBColumnAssignments)
+ };
+ SetSetProperties(cAddressDataAssignments, aNewValues);
+ }
+ }
+
+ m_bUserSettingWereOverwritten = false;
+}
+
+Sequence< OUString> SwMailMergeConfigItem_Impl::GetAddressBlocks(
+ bool bConvertToConfig) const
+{
+ Sequence< OUString> aRet(m_aAddressBlocks.size());
+ std::transform(m_aAddressBlocks.begin(), m_aAddressBlocks.end(), aRet.getArray(),
+ [this, bConvertToConfig](const OUString& rBlock) -> OUString {
+ OUString sBlock = rBlock;
+ if(bConvertToConfig)
+ lcl_ConvertToNumbers(sBlock, m_AddressHeaderSA);
+ return sBlock;
+ });
+ return aRet;
+}
+
+void SwMailMergeConfigItem_Impl::SetAddressBlocks(
+ const Sequence< OUString>& rBlocks,
+ bool bConvertFromConfig)
+{
+ m_aAddressBlocks.clear();
+ std::transform(rBlocks.begin(), rBlocks.end(), std::back_inserter(m_aAddressBlocks),
+ [this, bConvertFromConfig](const OUString& rBlock) -> OUString {
+ OUString sBlock = rBlock;
+ if(bConvertFromConfig)
+ lcl_ConvertFromNumbers(sBlock, m_AddressHeaderSA);
+ return sBlock;
+ });
+ m_nCurrentAddressBlock = 0;
+ SetModified();
+}
+
+Sequence< OUString> SwMailMergeConfigItem_Impl::GetGreetings(
+ SwMailMergeConfigItem::Gender eType, bool bConvertToConfig) const
+{
+ const std::vector< OUString>& rGreetings =
+ eType == SwMailMergeConfigItem::FEMALE ? m_aFemaleGreetingLines :
+ eType == SwMailMergeConfigItem::MALE ? m_aMaleGreetingLines :
+ m_aNeutralGreetingLines;
+ Sequence< OUString> aRet(rGreetings.size());
+ std::transform(rGreetings.begin(), rGreetings.end(), aRet.getArray(),
+ [this, bConvertToConfig](const OUString& rGreeting) -> OUString {
+ OUString sGreeting = rGreeting;
+ if(bConvertToConfig)
+ lcl_ConvertToNumbers(sGreeting, m_AddressHeaderSA);
+ return sGreeting;
+ });
+ return aRet;
+}
+
+void SwMailMergeConfigItem_Impl::SetGreetings(
+ SwMailMergeConfigItem::Gender eType,
+ const Sequence< OUString>& rSetGreetings,
+ bool bConvertFromConfig)
+{
+ std::vector< OUString>& rGreetings =
+ eType == SwMailMergeConfigItem::FEMALE ? m_aFemaleGreetingLines :
+ eType == SwMailMergeConfigItem::MALE ? m_aMaleGreetingLines :
+ m_aNeutralGreetingLines;
+
+ rGreetings.clear();
+ std::transform(rSetGreetings.begin(), rSetGreetings.end(), std::back_inserter(rGreetings),
+ [this, bConvertFromConfig](const OUString& rGreeting) -> OUString {
+ OUString sGreeting = rGreeting;
+ if(bConvertFromConfig)
+ lcl_ConvertFromNumbers(sGreeting, m_AddressHeaderSA);
+ return sGreeting;
+ });
+ SetModified();
+}
+
+sal_Int32 SwMailMergeConfigItem_Impl::GetCurrentGreeting(
+ SwMailMergeConfigItem::Gender eType) const
+{
+ sal_Int32 nRet;
+ switch(eType)
+ {
+ case SwMailMergeConfigItem::FEMALE: nRet = m_nCurrentFemaleGreeting ; break;
+ case SwMailMergeConfigItem::MALE: nRet = m_nCurrentMaleGreeting ; break;
+ default: nRet = m_nCurrentNeutralGreeting; break;
+ }
+ return nRet;
+}
+
+void SwMailMergeConfigItem_Impl::SetCurrentGreeting(
+ SwMailMergeConfigItem::Gender eType, sal_Int32 nIndex)
+{
+ bool bChanged = false;
+ switch(eType)
+ {
+ case SwMailMergeConfigItem::FEMALE:
+ bChanged = m_nCurrentFemaleGreeting != nIndex;
+ m_nCurrentFemaleGreeting = nIndex;
+ break;
+ case SwMailMergeConfigItem::MALE:
+ bChanged = m_nCurrentMaleGreeting != nIndex;
+ m_nCurrentMaleGreeting = nIndex;
+ break;
+ default:
+ bChanged = m_nCurrentNeutralGreeting != nIndex;
+ m_nCurrentNeutralGreeting = nIndex;
+ }
+ if(bChanged)
+ SetModified();
+}
+
+SwMailMergeConfigItem::SwMailMergeConfigItem() :
+ m_pImpl(new SwMailMergeConfigItem_Impl),
+ m_bAddressInserted(false),
+ m_bGreetingInserted(false),
+ m_nGreetingMoves(0),
+ m_nBegin(0),
+ m_nEnd(0),
+ m_pSourceView(nullptr),
+ m_pTargetView(nullptr)
+{
+}
+
+void SwMailMergeConfigItem::stopDBChangeListening()
+{
+ if (m_xDBChangedListener.is())
+ {
+ uno::Reference<view::XSelectionSupplier> xSupplier = m_pSourceView->GetUNOObject();
+ xSupplier->removeSelectionChangeListener(m_xDBChangedListener);
+ m_xDBChangedListener.clear();
+ }
+}
+
+void SwMailMergeConfigItem::updateCurrentDBDataFromDocument()
+{
+ const SwDBData& rDBData = m_pSourceView->GetWrtShell().GetDBData();
+ SetCurrentDBData(rDBData);
+}
+
+SwMailMergeConfigItem::~SwMailMergeConfigItem()
+{
+ stopDBChangeListening();
+}
+
+void SwMailMergeConfigItem::Commit()
+{
+ if(m_pImpl->IsModified())
+ m_pImpl->Commit();
+}
+
+const std::vector<std::pair<OUString, int>>& SwMailMergeConfigItem::GetDefaultAddressHeaders() const
+{
+ return m_pImpl->m_AddressHeaderSA;
+}
+
+void SwMailMergeConfigItem::SetAddressBlocks(
+ const Sequence< OUString>& rBlocks)
+{
+ m_pImpl->SetAddressBlocks(rBlocks);
+}
+
+Sequence< OUString> SwMailMergeConfigItem::GetAddressBlocks() const
+{
+ return m_pImpl->GetAddressBlocks();
+}
+
+bool SwMailMergeConfigItem::IsAddressBlock()const
+{
+ return m_pImpl->m_bIsAddressBlock && IsOutputToLetter();
+}
+
+void SwMailMergeConfigItem::SetAddressBlock(bool bSet)
+{
+ m_pImpl->m_bUserSettingWereOverwritten = false;
+ if(m_pImpl->m_bIsAddressBlock != bSet)
+ {
+ m_pImpl->m_bIsAddressBlock = bSet;
+ m_pImpl->SetModified();
+ }
+}
+
+bool SwMailMergeConfigItem::IsHideEmptyParagraphs() const
+{
+ return m_pImpl->m_bIsHideEmptyParagraphs;
+}
+
+void SwMailMergeConfigItem::SetHideEmptyParagraphs(bool bSet)
+{
+ if(m_pImpl->m_bIsHideEmptyParagraphs != bSet)
+ {
+ m_pImpl->m_bIsHideEmptyParagraphs = bSet;
+ m_pImpl->SetModified();
+ }
+}
+
+bool SwMailMergeConfigItem::IsIncludeCountry() const
+{
+ return m_pImpl->m_bIncludeCountry;
+}
+
+OUString& SwMailMergeConfigItem::GetExcludeCountry() const
+{
+ return m_pImpl->m_sExcludeCountry;
+}
+
+void SwMailMergeConfigItem::SetCountrySettings(bool bSet, const OUString& rCountry)
+{
+ if(m_pImpl->m_sExcludeCountry != rCountry ||
+ m_pImpl->m_bIncludeCountry != bSet)
+ {
+ m_pImpl->m_bIncludeCountry = bSet;
+ m_pImpl->m_sExcludeCountry = bSet ? rCountry : OUString();
+ m_pImpl->SetModified();
+ }
+}
+
+void SwMailMergeConfigItem::SetCurrentConnection(
+ Reference< XDataSource> const & xSource,
+ const SharedConnection& rConnection,
+ Reference< XColumnsSupplier> const & xColumnsSupplier,
+ const SwDBData& rDBData)
+{
+ m_pImpl->m_xSource = xSource ;
+ m_pImpl->m_xConnection = rConnection ;
+ m_pImpl->m_xColumnsSupplier = xColumnsSupplier;
+ m_pImpl->m_aDBData = rDBData;
+ m_pImpl->m_xResultSet = nullptr;
+ m_pImpl->m_nResultSetCursorPos = 0;
+ m_pImpl->SetModified();
+}
+
+Reference< XDataSource> const & SwMailMergeConfigItem::GetSource() const
+{
+ return m_pImpl->m_xSource;
+}
+
+SharedConnection const & SwMailMergeConfigItem::GetConnection() const
+{
+ return m_pImpl->m_xConnection;
+}
+
+Reference< XColumnsSupplier> const & SwMailMergeConfigItem::GetColumnsSupplier()
+{
+ if(!m_pImpl->m_xColumnsSupplier.is() && m_pImpl->m_xConnection.is())
+ {
+ m_pImpl->m_xColumnsSupplier = SwDBManager::GetColumnSupplier(m_pImpl->m_xConnection,
+ m_pImpl->m_aDBData.sCommand,
+ m_pImpl->m_aDBData.nCommandType == CommandType::TABLE ?
+ SwDBSelect::TABLE : SwDBSelect::QUERY );
+ }
+ return m_pImpl->m_xColumnsSupplier;
+}
+
+const SwDBData& SwMailMergeConfigItem::GetCurrentDBData() const
+{
+ return m_pImpl->m_aDBData;
+}
+
+void SwMailMergeConfigItem::SetCurrentDBData( const SwDBData& rDBData)
+{
+ if(m_pImpl->m_aDBData != rDBData)
+ {
+ m_pImpl->m_aDBData = rDBData;
+ m_pImpl->m_xConnection.clear();
+ m_pImpl->m_xSource = nullptr;
+ m_pImpl->m_xResultSet = nullptr;
+ m_pImpl->m_xColumnsSupplier = nullptr;
+ m_pImpl->SetModified();
+ }
+}
+
+Reference< XResultSet> const & SwMailMergeConfigItem::GetResultSet() const
+{
+ if(!m_pImpl->m_xConnection.is() && !m_pImpl->m_aDBData.sDataSource.isEmpty())
+ {
+ m_pImpl->m_xConnection.reset(
+ SwDBManager::GetConnection(m_pImpl->m_aDBData.sDataSource, m_pImpl->m_xSource, m_pSourceView),
+ SharedConnection::TakeOwnership
+ );
+ }
+ if(!m_pImpl->m_xResultSet.is() && m_pImpl->m_xConnection.is())
+ {
+ try
+ {
+ Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
+
+ Reference<XRowSet> xRowSet( xMgr->createInstance("com.sun.star.sdb.RowSet"), UNO_QUERY );
+ Reference<XPropertySet> xRowProperties(xRowSet, UNO_QUERY);
+ xRowProperties->setPropertyValue("DataSourceName", Any(m_pImpl->m_aDBData.sDataSource));
+ xRowProperties->setPropertyValue("Command", Any(m_pImpl->m_aDBData.sCommand));
+ xRowProperties->setPropertyValue("CommandType", Any(m_pImpl->m_aDBData.nCommandType));
+ xRowProperties->setPropertyValue("FetchSize", Any(sal_Int32(10)));
+ xRowProperties->setPropertyValue("ActiveConnection", Any(m_pImpl->m_xConnection.getTyped()));
+ try
+ {
+ xRowProperties->setPropertyValue("ApplyFilter", Any(!m_pImpl->m_sFilter.isEmpty()));
+ xRowProperties->setPropertyValue("Filter", Any(m_pImpl->m_sFilter));
+ }
+ catch (const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("sw.ui", "");
+ }
+ xRowSet->execute();
+ m_pImpl->m_xResultSet = xRowSet.get();
+ m_pImpl->m_xResultSet->first();
+ m_pImpl->m_nResultSetCursorPos = 1;
+ }
+ catch (const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("sw.ui", "SwMailMergeConfigItem::GetResultSet()");
+ }
+ }
+ return m_pImpl->m_xResultSet;
+}
+
+void SwMailMergeConfigItem::DisposeResultSet()
+{
+ m_pImpl->m_xConnection.clear();
+ if(m_pImpl->m_xResultSet.is())
+ {
+ ::comphelper::disposeComponent( m_pImpl->m_xResultSet );
+ }
+}
+
+OUString& SwMailMergeConfigItem::GetFilter() const
+{
+ return m_pImpl->m_sFilter;
+}
+
+void SwMailMergeConfigItem::SetFilter(OUString const & rFilter)
+{
+ if(m_pImpl->m_sFilter == rFilter)
+ return;
+
+ m_pImpl->m_sFilter = rFilter;
+ m_pImpl->SetModified();
+ Reference<XPropertySet> xRowProperties(m_pImpl->m_xResultSet, UNO_QUERY);
+ if(!xRowProperties.is())
+ return;
+
+ try
+ {
+ xRowProperties->setPropertyValue("ApplyFilter", Any(!m_pImpl->m_sFilter.isEmpty()));
+ xRowProperties->setPropertyValue("Filter", Any(m_pImpl->m_sFilter));
+ uno::Reference<XRowSet> xRowSet( m_pImpl->m_xResultSet, UNO_QUERY_THROW );
+ xRowSet->execute();
+ }
+ catch (const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("sw.ui", "SwMailMergeConfigItem::SetFilter()");
+ }
+}
+
+sal_Int32 SwMailMergeConfigItem::MoveResultSet(sal_Int32 nTarget)
+{
+ if(!m_pImpl->m_xResultSet.is())
+ GetResultSet();
+ if(m_pImpl->m_xResultSet.is())
+ {
+ try
+ {
+ //no action if the resultset is already at the right position
+ if(m_pImpl->m_xResultSet->getRow() != nTarget)
+ {
+ if(nTarget > 0)
+ {
+ bool bMoved = m_pImpl->m_xResultSet->absolute(nTarget);
+ if(!bMoved)
+ {
+ if(nTarget > 1)
+ m_pImpl->m_xResultSet->last();
+ else if(nTarget == 1)
+ m_pImpl->m_xResultSet->first();
+ }
+ }
+ else if(nTarget == -1)
+ m_pImpl->m_xResultSet->last();
+ m_pImpl->m_nResultSetCursorPos = m_pImpl->m_xResultSet->getRow();
+ }
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+ return m_pImpl->m_nResultSetCursorPos;
+}
+
+bool SwMailMergeConfigItem::IsResultSetFirstLast(bool& bIsFirst, bool& bIsLast)
+{
+ bool bRet = false;
+ if(!m_pImpl->m_xResultSet.is())
+ GetResultSet();
+ if(m_pImpl->m_xResultSet.is())
+ {
+ try
+ {
+ bIsFirst = m_pImpl->m_xResultSet->isFirst();
+ bIsLast = m_pImpl->m_xResultSet->isLast();
+ bRet = true;
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+ return bRet;
+}
+
+sal_Int32 SwMailMergeConfigItem::GetResultSetPosition() const
+{
+ return m_pImpl->m_nResultSetCursorPos;
+}
+
+bool SwMailMergeConfigItem::IsRecordIncluded(sal_uInt32 nRecord) const
+ { return nRecord > m_nBegin && nRecord <= m_nEnd; }
+
+bool SwMailMergeConfigItem::IsRecordExcluded(sal_uInt32 nRecord) const
+ { return m_aExcludedRecords.find(nRecord) != m_aExcludedRecords.end(); }
+
+void SwMailMergeConfigItem::ExcludeRecord(sal_Int32 nRecord, bool bExclude)
+{
+ if(bExclude)
+ m_aExcludedRecords.insert(nRecord);
+ else
+ m_aExcludedRecords.erase(nRecord);
+}
+
+uno::Sequence<uno::Any> SwMailMergeConfigItem::GetSelection() const
+{
+ if(!m_pImpl->m_xResultSet.is())
+ GetResultSet();
+ if(!m_pImpl->m_xResultSet.is())
+ return {};
+ m_pImpl->m_xResultSet->last();
+ sal_uInt32 nResultSetSize = m_pImpl->m_xResultSet->getRow()+1;
+ std::vector<uno::Any> vResult;
+ for(sal_uInt32 nIdx=1; nIdx<nResultSetSize;++nIdx)
+ if( !IsRecordExcluded(nIdx) && IsRecordIncluded(nIdx) )
+ vResult.push_back(uno::Any(sal_uInt32(nIdx)));
+ return comphelper::containerToSequence(vResult);
+}
+
+
+const uno::Sequence< OUString>&
+ SwMailMergeConfigItem::GetSavedDocuments() const
+{
+ return m_pImpl->m_aSavedDocuments;
+}
+
+bool SwMailMergeConfigItem::IsOutputToLetter()const
+{
+ return m_pImpl->m_bIsOutputToLetter || !IsMailAvailable();
+}
+
+void SwMailMergeConfigItem::SetOutputToLetter(bool bSet)
+{
+ if(m_pImpl->m_bIsOutputToLetter != bSet)
+ {
+ m_pImpl->m_bIsOutputToLetter = bSet;
+ m_pImpl->SetModified();
+ }
+}
+
+bool SwMailMergeConfigItem::IsIndividualGreeting(bool bInEMail) const
+{
+ return bInEMail ?
+ m_pImpl->m_bIsIndividualGreetingLineInMail :
+ m_pImpl->m_bIsIndividualGreetingLine;
+}
+
+void SwMailMergeConfigItem::SetIndividualGreeting(
+ bool bSet, bool bInEMail)
+{
+ if(bInEMail)
+ {
+ if(m_pImpl->m_bIsIndividualGreetingLineInMail != bSet)
+ {
+ m_pImpl->m_bIsIndividualGreetingLineInMail = bSet;
+ m_pImpl->SetModified();
+ }
+ }
+ else
+ {
+ if(m_pImpl->m_bIsIndividualGreetingLine != bSet)
+ {
+ m_pImpl->m_bIsIndividualGreetingLine = bSet;
+ m_pImpl->SetModified();
+ }
+ }
+}
+
+bool SwMailMergeConfigItem::IsGreetingLine(bool bInEMail) const
+{
+ return bInEMail ? m_pImpl->m_bIsGreetingLineInMail : m_pImpl->m_bIsGreetingLine;
+}
+
+void SwMailMergeConfigItem::SetGreetingLine(bool bSet, bool bInEMail)
+{
+ m_pImpl->m_bUserSettingWereOverwritten = false;
+ if(bInEMail)
+ {
+ if(m_pImpl->m_bIsGreetingLineInMail != bSet)
+ {
+ m_pImpl->m_bIsGreetingLineInMail = bSet;
+ m_pImpl->SetModified();
+ }
+ }
+ else
+ {
+ if(m_pImpl->m_bIsGreetingLine != bSet)
+ {
+ m_pImpl->m_bIsGreetingLine = bSet;
+ m_pImpl->SetModified();
+ }
+ }
+}
+
+Sequence< OUString> SwMailMergeConfigItem::GetGreetings(
+ Gender eType ) const
+{
+ return m_pImpl->GetGreetings(eType);
+}
+
+void SwMailMergeConfigItem::SetGreetings(
+ Gender eType, const Sequence< OUString>& rSetGreetings)
+{
+ m_pImpl->SetGreetings( eType, rSetGreetings);
+}
+
+sal_Int32 SwMailMergeConfigItem::GetCurrentGreeting(
+ SwMailMergeConfigItem::Gender eType) const
+{
+ return m_pImpl->GetCurrentGreeting(eType);
+}
+
+void SwMailMergeConfigItem::SetCurrentGreeting(Gender eType, sal_Int32 nIndex)
+{
+ m_pImpl->SetCurrentGreeting(eType, nIndex);
+}
+
+const OUString& SwMailMergeConfigItem::GetFemaleGenderValue() const
+{
+ return m_pImpl->m_sFemaleGenderValue;
+}
+
+void SwMailMergeConfigItem::SetFemaleGenderValue(const OUString& rValue)
+{
+ if( m_pImpl->m_sFemaleGenderValue != rValue )
+ {
+ m_pImpl->m_sFemaleGenderValue = rValue;
+ m_pImpl->SetModified();
+ }
+}
+
+Sequence< OUString> SwMailMergeConfigItem::GetColumnAssignment(
+ const SwDBData& rDBData ) const
+{
+ Sequence< OUString> aRet;
+ auto aAssignIter = std::find_if(m_pImpl->m_aAddressDataAssignments.begin(), m_pImpl->m_aAddressDataAssignments.end(),
+ [&rDBData](const DBAddressDataAssignment& rAssignment) { return rAssignment.aDBData == rDBData; });
+ if (aAssignIter != m_pImpl->m_aAddressDataAssignments.end())
+ {
+ aRet = aAssignIter->aDBColumnAssignments;
+ }
+ return aRet;
+}
+
+// returns the name that is assigned as e-mail column of the current data base
+OUString SwMailMergeConfigItem::GetAssignedColumn(sal_uInt32 nColumn) const
+{
+ OUString sRet;
+ Sequence< OUString> aAssignment = GetColumnAssignment( m_pImpl->m_aDBData );
+ if(aAssignment.getLength() > sal::static_int_cast< sal_Int32, sal_uInt32>(nColumn) && !aAssignment[nColumn].isEmpty())
+ sRet = aAssignment[nColumn];
+ else if(nColumn < m_pImpl->m_AddressHeaderSA.size())
+ sRet = m_pImpl->m_AddressHeaderSA[nColumn].first;
+ return sRet;
+}
+
+void SwMailMergeConfigItem::SetColumnAssignment( const SwDBData& rDBData,
+ const Sequence< OUString>& rList)
+{
+ auto aAssignIter = std::find_if(m_pImpl->m_aAddressDataAssignments.begin(), m_pImpl->m_aAddressDataAssignments.end(),
+ [&rDBData](const DBAddressDataAssignment& rAssignment) { return rAssignment.aDBData == rDBData; });
+ if (aAssignIter != m_pImpl->m_aAddressDataAssignments.end())
+ {
+ if(aAssignIter->aDBColumnAssignments != rList)
+ {
+ aAssignIter->aDBColumnAssignments = rList;
+ aAssignIter->bColumnAssignmentsChanged = true;
+ }
+ }
+ else
+ {
+ DBAddressDataAssignment aAssignment;
+ aAssignment.aDBData = rDBData;
+ aAssignment.aDBColumnAssignments = rList;
+ aAssignment.bColumnAssignmentsChanged = true;
+ m_pImpl->m_aAddressDataAssignments.push_back(aAssignment);
+ }
+ m_pImpl->SetModified();
+}
+
+bool SwMailMergeConfigItem::IsAddressFieldsAssigned() const
+{
+ bool bResult = true;
+ Reference< XResultSet> xResultSet = GetResultSet();
+ uno::Reference< XColumnsSupplier > xColsSupp( xResultSet, UNO_QUERY );
+ if(!xColsSupp.is())
+ return false;
+ uno::Reference<container::XNameAccess> xCols = xColsSupp->getColumns();
+
+ const std::vector<std::pair<OUString, int>>& rHeaders = GetDefaultAddressHeaders();
+ Sequence< OUString> aAssignment =
+ GetColumnAssignment( GetCurrentDBData() );
+ const OUString* pAssignment = aAssignment.getConstArray();
+ const Sequence< OUString> aBlocks = GetAddressBlocks();
+
+ if(aBlocks.getLength() <= m_pImpl->GetCurrentAddressBlockIndex())
+ return false;
+ SwAddressIterator aIter(aBlocks[m_pImpl->GetCurrentAddressBlockIndex()]);
+ while(aIter.HasMore())
+ {
+ SwMergeAddressItem aItem = aIter.Next();
+ if(aItem.bIsColumn)
+ {
+ OUString sConvertedColumn = aItem.sText;
+ auto nSize = std::min(sal_uInt32(rHeaders.size()), sal_uInt32(aAssignment.getLength()));
+ for(sal_uInt32 nColumn = 0; nColumn < nSize; ++nColumn)
+ {
+ if (rHeaders[nColumn].first == aItem.sText &&
+ !pAssignment[nColumn].isEmpty())
+ {
+ sConvertedColumn = pAssignment[nColumn];
+ break;
+ }
+ }
+ //find out if the column exists in the data base
+ if(!xCols->hasByName(sConvertedColumn))
+ {
+ bResult = false;
+ break;
+ }
+ }
+ }
+ return bResult;
+}
+
+bool SwMailMergeConfigItem::IsGreetingFieldsAssigned() const
+{
+ bool bResult = true;
+
+ if(!IsIndividualGreeting(false))
+ return true;
+
+ Reference< XResultSet> xResultSet = GetResultSet();
+ uno::Reference< XColumnsSupplier > xColsSupp( xResultSet, UNO_QUERY );
+ if(!xColsSupp.is())
+ return false;
+ const std::vector<std::pair<OUString, int>>& rHeaders = GetDefaultAddressHeaders();
+ uno::Reference<container::XNameAccess> xCols = xColsSupp->getColumns();
+
+ Sequence< OUString> aAssignment =
+ GetColumnAssignment( GetCurrentDBData() );
+ const OUString* pAssignment = aAssignment.getConstArray();
+
+ const Sequence< OUString> rFemaleEntries = GetGreetings(SwMailMergeConfigItem::FEMALE);
+ sal_Int32 nCurrentFemale = GetCurrentGreeting(SwMailMergeConfigItem::FEMALE);
+ const Sequence< OUString> rMaleEntries = GetGreetings(SwMailMergeConfigItem::MALE);
+ sal_Int32 nCurrentMale = GetCurrentGreeting(SwMailMergeConfigItem::MALE);
+ OUString sMale, sFemale;
+ if(rFemaleEntries.getLength() > nCurrentFemale)
+ sFemale = rFemaleEntries[nCurrentFemale];
+ if(rMaleEntries.getLength() > nCurrentMale)
+ sMale = rMaleEntries[nCurrentMale];
+
+ OUString sAddress = sFemale + sMale;
+ SwAddressIterator aIter(sAddress);
+ while(aIter.HasMore())
+ {
+ SwMergeAddressItem aItem = aIter.Next();
+ if(aItem.bIsColumn)
+ {
+ OUString sConvertedColumn = aItem.sText;
+ auto nSize = std::min(sal_uInt32(rHeaders.size()), sal_uInt32(aAssignment.getLength()));
+ for(sal_uInt32 nColumn = 0; nColumn < nSize; ++nColumn)
+ {
+ if (rHeaders[nColumn].first == aItem.sText &&
+ !pAssignment[nColumn].isEmpty())
+ {
+ sConvertedColumn = pAssignment[nColumn];
+ break;
+ }
+ }
+ //find out if the column exists in the data base
+ if(!xCols->hasByName(sConvertedColumn))
+ {
+ bResult = false;
+ break;
+ }
+ }
+ }
+ return bResult;
+}
+
+OUString const & SwMailMergeConfigItem::GetMailDisplayName() const
+{
+ return m_pImpl->m_sMailDisplayName;
+}
+
+void SwMailMergeConfigItem::SetMailDisplayName(const OUString& rName)
+{
+ if(m_pImpl->m_sMailDisplayName != rName)
+ {
+ m_pImpl->m_sMailDisplayName = rName;
+ m_pImpl->SetModified();
+ }
+}
+
+OUString const & SwMailMergeConfigItem::GetMailAddress() const
+{
+ return m_pImpl->m_sMailAddress;
+}
+
+void SwMailMergeConfigItem::SetMailAddress(const OUString& rAddress)
+{
+ if(m_pImpl->m_sMailAddress != rAddress )
+ {
+ m_pImpl->m_sMailAddress = rAddress;
+ m_pImpl->SetModified();
+ }
+}
+
+bool SwMailMergeConfigItem::IsMailReplyTo() const
+{
+ return m_pImpl->m_bIsMailReplyTo;
+}
+
+void SwMailMergeConfigItem::SetMailReplyTo(bool bSet)
+{
+ if(m_pImpl->m_bIsMailReplyTo != bSet)
+ {
+ m_pImpl->m_bIsMailReplyTo = bSet;
+ m_pImpl->SetModified();
+ }
+}
+
+OUString const & SwMailMergeConfigItem::GetMailReplyTo() const
+{
+ return m_pImpl->m_sMailReplyTo;
+}
+
+void SwMailMergeConfigItem::SetMailReplyTo(const OUString& rReplyTo)
+{
+ if(m_pImpl->m_sMailReplyTo != rReplyTo)
+ {
+ m_pImpl->m_sMailReplyTo = rReplyTo;
+ m_pImpl->SetModified();
+ }
+}
+
+OUString const & SwMailMergeConfigItem::GetMailServer() const
+{
+ return m_pImpl->m_sMailServer;
+}
+
+void SwMailMergeConfigItem::SetMailServer(const OUString& rAddress)
+{
+ if(m_pImpl->m_sMailServer != rAddress)
+ {
+ m_pImpl->m_sMailServer = rAddress;
+ m_pImpl->SetModified();
+ }
+}
+
+sal_Int16 SwMailMergeConfigItem::GetMailPort() const
+{
+ // provide appropriate TCP port, based on SSL/STARTTLS status, if current port is one of the defaults
+ switch (m_pImpl->m_nMailPort)
+ {
+ case SECURE_PORT:
+ case DEFAULT_PORT:
+ return m_pImpl->m_bIsSecureConnection ? SECURE_PORT : DEFAULT_PORT;
+ default:
+ return m_pImpl->m_nMailPort;
+ }
+}
+
+void SwMailMergeConfigItem::SetMailPort(sal_Int16 nSet)
+{
+ if(m_pImpl->m_nMailPort != nSet)
+ {
+ m_pImpl->m_nMailPort = nSet;
+ m_pImpl->SetModified();
+ }
+}
+
+bool SwMailMergeConfigItem::IsSecureConnection() const
+{
+ return m_pImpl->m_bIsSecureConnection;
+}
+
+void SwMailMergeConfigItem::SetSecureConnection(bool bSet)
+{
+ if(m_pImpl->m_bIsSecureConnection != bSet)
+ {
+ m_pImpl->m_bIsSecureConnection = bSet;
+ m_pImpl->SetModified();
+ }
+}
+
+bool SwMailMergeConfigItem::IsAuthentication() const
+{
+ return m_pImpl->m_bIsAuthentication;
+}
+
+void SwMailMergeConfigItem::SetAuthentication(bool bSet)
+{
+ if(m_pImpl->m_bIsAuthentication != bSet)
+ {
+ m_pImpl->m_bIsAuthentication = bSet;
+ m_pImpl->SetModified();
+ }
+}
+
+OUString const & SwMailMergeConfigItem::GetMailUserName() const
+{
+ return m_pImpl->m_sMailUserName;
+}
+
+void SwMailMergeConfigItem::SetMailUserName(const OUString& rName)
+{
+ if(m_pImpl->m_sMailUserName != rName)
+ {
+ m_pImpl->m_sMailUserName = rName;
+ m_pImpl->SetModified();
+ }
+}
+
+OUString const & SwMailMergeConfigItem::GetMailPassword() const
+{
+ return m_pImpl->m_sMailPassword;
+}
+
+void SwMailMergeConfigItem::SetMailPassword(const OUString& rPassword)
+{
+ if(m_pImpl->m_sMailPassword != rPassword)
+ {
+ m_pImpl->m_sMailPassword = rPassword;
+ m_pImpl->SetModified();
+ }
+}
+
+bool SwMailMergeConfigItem::IsSMTPAfterPOP() const
+{
+ return m_pImpl->m_bIsSMPTAfterPOP;
+}
+
+void SwMailMergeConfigItem::SetSMTPAfterPOP(bool bSet)
+{
+ if( m_pImpl->m_bIsSMPTAfterPOP != bSet)
+ {
+ m_pImpl->m_bIsSMPTAfterPOP = bSet;
+ m_pImpl->SetModified();
+ }
+}
+
+OUString const & SwMailMergeConfigItem::GetInServerName() const
+{
+ return m_pImpl->m_sInServerName;
+}
+
+void SwMailMergeConfigItem::SetInServerName(const OUString& rServer)
+{
+ if(m_pImpl->m_sInServerName != rServer)
+ {
+ m_pImpl->m_sInServerName = rServer;
+ m_pImpl->SetModified();
+ }
+}
+
+sal_Int16 SwMailMergeConfigItem::GetInServerPort() const
+{
+ // provide appropriate TCP port as user toggles between POP/IMAP if current port is one of the defaults
+ switch (m_pImpl->m_nInServerPort)
+ {
+ case POP_SECURE_PORT:
+ case POP_PORT:
+ case IMAP_SECURE_PORT:
+ case IMAP_PORT:
+ if ( m_pImpl->m_bInServerPOP )
+ return m_pImpl->m_bIsSecureConnection ? POP_SECURE_PORT : POP_PORT;
+ else
+ return m_pImpl->m_bIsSecureConnection ? IMAP_SECURE_PORT : IMAP_PORT;
+ default:
+ return m_pImpl->m_nInServerPort;
+ }
+}
+
+void SwMailMergeConfigItem::SetInServerPort(sal_Int16 nSet)
+{
+ if( m_pImpl->m_nInServerPort != nSet)
+ {
+ m_pImpl->m_nInServerPort = nSet;
+ m_pImpl->SetModified();
+ }
+}
+
+bool SwMailMergeConfigItem::IsInServerPOP() const
+{
+ return m_pImpl->m_bInServerPOP;
+}
+
+void SwMailMergeConfigItem::SetInServerPOP(bool bSet)
+{
+ if( m_pImpl->m_bInServerPOP != bSet)
+ {
+ m_pImpl->m_bInServerPOP = bSet;
+ m_pImpl->SetModified();
+ }
+}
+
+OUString const & SwMailMergeConfigItem::GetInServerUserName() const
+{
+ return m_pImpl->m_sInServerUserName;
+}
+
+void SwMailMergeConfigItem::SetInServerUserName(const OUString& rName)
+{
+ if( m_pImpl->m_sInServerUserName != rName)
+ {
+ m_pImpl->m_sInServerUserName = rName;
+ m_pImpl->SetModified();
+ }
+}
+
+OUString const & SwMailMergeConfigItem::GetInServerPassword() const
+{
+ return m_pImpl->m_sInServerPassword;
+}
+
+void SwMailMergeConfigItem::SetInServerPassword(const OUString& rPassword)
+{
+ if(m_pImpl->m_sInServerPassword != rPassword)
+ {
+ m_pImpl->m_sInServerPassword = rPassword;
+ m_pImpl->SetModified();
+ }
+}
+
+void SwMailMergeConfigItem::DocumentReloaded()
+{
+ m_bGreetingInserted = false;
+ m_bAddressInserted = false;
+}
+
+bool SwMailMergeConfigItem::IsMailAvailable() const
+{
+ return m_pImpl->m_bIsEMailSupported;
+}
+
+void SwMailMergeConfigItem::AddMergedDocument(SwDocMergeInfo const & rInfo)
+{
+ m_pImpl->m_aMergeInfos.push_back(rInfo);
+}
+
+SwDocMergeInfo& SwMailMergeConfigItem::GetDocumentMergeInfo(sal_uInt32 nDocument)
+{
+ assert(nDocument < m_pImpl->m_aMergeInfos.size());
+ return m_pImpl->m_aMergeInfos[nDocument];
+}
+
+
+sal_uInt32 SwMailMergeConfigItem::GetMergedDocumentCount()
+{
+ if(m_pTargetView)
+ return m_pImpl->m_aMergeInfos.size();
+ else
+ {
+ sal_Int32 nRestore = GetResultSetPosition();
+ MoveResultSet(-1);
+ sal_Int32 nRet = GetResultSetPosition();
+ MoveResultSet( nRestore );
+ nRet -= m_aExcludedRecords.size();
+ return nRet >= 0 ? nRet : 0;
+ }
+}
+
+static SwView* lcl_ExistsView(SwView* pView)
+{
+ SfxViewShell* pViewShell = SfxViewShell::GetFirst( false, checkSfxViewShell<SwView> );
+ while(pViewShell)
+ {
+ if(pViewShell == pView)
+ return pView;
+
+ pViewShell = SfxViewShell::GetNext( *pViewShell, false, checkSfxViewShell<SwView> );
+ }
+ return nullptr;
+}
+
+SwView* SwMailMergeConfigItem::GetTargetView()
+{
+ //make sure that the pointer is really valid - the document may have been closed manually
+ if(m_pTargetView)
+ {
+ m_pTargetView = lcl_ExistsView(m_pTargetView);
+ }
+ return m_pTargetView;
+}
+
+void SwMailMergeConfigItem::SetTargetView(SwView* pView)
+{
+ m_pTargetView = pView;
+ //reset the document merge counter
+ if(!m_pTargetView)
+ {
+ m_pImpl->m_aMergeInfos.clear();
+ }
+}
+
+SwView* SwMailMergeConfigItem::GetSourceView()
+{
+ m_pSourceView = lcl_ExistsView(m_pSourceView);
+ return m_pSourceView;
+}
+
+namespace {
+
+//This implements XSelectionChangeListener and XDispatch because the
+//broadcaster uses this combo to determine if to send the database-changed
+//update. Its probably that listening to statusChanged at some other level is
+//equivalent to this. See the other call to SwXDispatch::GetDBChangeURL for
+//the broadcaster of the event.
+class DBChangeListener : public cppu::WeakImplHelper<css::view::XSelectionChangeListener, css::frame::XDispatch>
+{
+ SwMailMergeConfigItem& m_rParent;
+public:
+ explicit DBChangeListener(SwMailMergeConfigItem& rParent)
+ : m_rParent(rParent)
+ {
+ }
+
+ virtual void SAL_CALL selectionChanged(const EventObject& /*rEvent*/) override
+ {
+ }
+
+ virtual void SAL_CALL disposing(const EventObject&) override
+ {
+ m_rParent.stopDBChangeListening();
+ }
+
+ virtual void SAL_CALL dispatch(const css::util::URL& rURL, const css::uno::Sequence< css::beans::PropertyValue >& /*rArgs*/) override
+ {
+ if (rURL.Complete.equalsAscii(SwXDispatch::GetDBChangeURL()))
+ m_rParent.updateCurrentDBDataFromDocument();
+ }
+
+ virtual void SAL_CALL addStatusListener(const css::uno::Reference< css::frame::XStatusListener >&, const css::util::URL&) override
+ {
+ }
+
+ virtual void SAL_CALL removeStatusListener(const css::uno::Reference< css::frame::XStatusListener >&, const css::util::URL&) override
+ {
+ }
+};
+
+}
+
+void SwMailMergeConfigItem::SetSourceView(SwView* pView)
+{
+ if (m_xDBChangedListener.is())
+ {
+ uno::Reference<view::XSelectionSupplier> xSupplier = m_pSourceView->GetUNOObject();
+ xSupplier->removeSelectionChangeListener(m_xDBChangedListener);
+ m_xDBChangedListener.clear();
+ }
+
+ m_pSourceView = pView;
+
+ if (!m_pSourceView)
+ return;
+
+ std::vector<OUString> aDBNameList;
+ std::vector<OUString> aAllDBNames;
+ m_pSourceView->GetWrtShell().GetAllUsedDB( aDBNameList, &aAllDBNames );
+ if(!aDBNameList.empty())
+ {
+ // if fields are available there is usually no need of an addressblock and greeting
+ if(!m_pImpl->m_bUserSettingWereOverwritten)
+ {
+ if( m_pImpl->m_bIsAddressBlock
+ || m_pImpl->m_bIsGreetingLineInMail
+ || m_pImpl->m_bIsGreetingLine )
+ {
+ //store user settings
+ m_pImpl->m_bUserSettingWereOverwritten = true;
+ m_pImpl->m_bIsAddressBlock_LastUserSetting = m_pImpl->m_bIsAddressBlock;
+ m_pImpl->m_bIsGreetingLineInMail_LastUserSetting = m_pImpl->m_bIsGreetingLineInMail;
+ m_pImpl->m_bIsGreetingLine_LastUserSetting = m_pImpl->m_bIsGreetingLine;
+
+ //set all to false
+ m_pImpl->m_bIsAddressBlock = false;
+ m_pImpl->m_bIsGreetingLineInMail = false;
+ m_pImpl->m_bIsGreetingLine = false;
+
+ m_pImpl->SetModified();
+ }
+ }
+ }
+ else if( m_pImpl->m_bUserSettingWereOverwritten )
+ {
+ //restore last user settings:
+ m_pImpl->m_bIsAddressBlock = m_pImpl->m_bIsAddressBlock_LastUserSetting;
+ m_pImpl->m_bIsGreetingLineInMail = m_pImpl->m_bIsGreetingLineInMail_LastUserSetting;
+ m_pImpl->m_bIsGreetingLine = m_pImpl->m_bIsGreetingLine_LastUserSetting;
+
+ m_pImpl->m_bUserSettingWereOverwritten = false;
+ }
+
+ if (!m_xDBChangedListener.is())
+ {
+ m_xDBChangedListener.set(new DBChangeListener(*this));
+ }
+
+ uno::Reference<view::XSelectionSupplier> xSupplier = m_pSourceView->GetUNOObject();
+ xSupplier->addSelectionChangeListener(m_xDBChangedListener);
+}
+
+void SwMailMergeConfigItem::SetCurrentAddressBlockIndex( sal_Int32 nSet )
+{
+ m_pImpl->SetCurrentAddressBlockIndex( nSet );
+}
+
+sal_Int32 SwMailMergeConfigItem::GetCurrentAddressBlockIndex() const
+{
+ return m_pImpl->GetCurrentAddressBlockIndex();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/dialog/SwSpellDialogChildWindow.cxx b/sw/source/uibase/dialog/SwSpellDialogChildWindow.cxx
new file mode 100644
index 0000000000..5af09a6adf
--- /dev/null
+++ b/sw/source/uibase/dialog/SwSpellDialogChildWindow.cxx
@@ -0,0 +1,828 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <SwSpellDialogChildWindow.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <editeng/svxacorr.hxx>
+#include <editeng/acorrcfg.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <wrtsh.hxx>
+#include <sfx2/printer.hxx>
+#include <svx/svdoutl.hxx>
+#include <svx/svdview.hxx>
+#include <unotools/linguprops.hxx>
+#include <unotools/lingucfg.hxx>
+#include <osl/diagnose.h>
+#include <doc.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <docsh.hxx>
+#include <drawdoc.hxx>
+#include <dcontact.hxx>
+#include <edtwin.hxx>
+#include <pam.hxx>
+#include <drawbase.hxx>
+#include <unotextrange.hxx>
+#include <strings.hrc>
+#include <cmdid.h>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::linguistic2;
+using namespace ::com::sun::star::beans;
+
+SFX_IMPL_CHILDWINDOW_WITHID(SwSpellDialogChildWindow, FN_SPELL_GRAMMAR_DIALOG)
+
+struct SpellState
+{
+ bool m_bInitialCall;
+ bool m_bLockFocus; // lock the focus notification while a modal dialog is active
+ bool m_bLostFocus;
+
+ // restart and progress information
+ bool m_bBodySpelled; // body already spelled
+ bool m_bOtherSpelled; // frames, footnotes, headers and footers spelled
+ bool m_bStartedInOther; // started the spelling inside of the _other_ area
+ bool m_bStartedInSelection; // there was an initial text selection
+ std::unique_ptr<SwPaM>
+ pOtherCursor; // position where the spelling inside the _other_ area started
+ bool m_bDrawingsSpelled; // all drawings spelled
+ rtl::Reference<SwXTextRange> m_xStartRange; // text range that marks the start of spelling
+ const SdrObject* m_pStartDrawing; // draw text object spelling started in
+ ESelection m_aStartDrawingSelection; // draw text start selection
+ bool m_bRestartDrawing; // the first selected drawing object is found again
+
+ // lose/get focus information to decide if spelling can be continued
+ ShellMode m_eSelMode;
+ const SwNode* m_pPointNode;
+ const SwNode* m_pMarkNode;
+ sal_Int32 m_nPointPos;
+ sal_Int32 m_nMarkPos;
+ const SdrOutliner* m_pOutliner;
+ ESelection m_aESelection;
+
+ // iterating over draw text objects
+ std::list<SdrTextObj*> m_aTextObjects;
+ bool m_bTextObjectsCollected;
+
+ SpellState() :
+ m_bInitialCall(true),
+ m_bLockFocus(false),
+ m_bLostFocus(false),
+ m_bBodySpelled(false),
+ m_bOtherSpelled(false),
+ m_bStartedInOther(false),
+ m_bStartedInSelection(false),
+ m_bDrawingsSpelled(false),
+ m_pStartDrawing(nullptr),
+ m_bRestartDrawing(false),
+
+ m_eSelMode(ShellMode::Object), // initially invalid
+ m_pPointNode(nullptr),
+ m_pMarkNode(nullptr),
+ m_nPointPos(0),
+ m_nMarkPos(0),
+ m_pOutliner(nullptr),
+ m_bTextObjectsCollected(false)
+ {}
+
+ // reset state in ::InvalidateSpellDialog
+ void Reset()
+ { m_bInitialCall = true;
+ m_bBodySpelled = m_bOtherSpelled = m_bDrawingsSpelled = false;
+ m_xStartRange = nullptr;
+ m_pStartDrawing = nullptr;
+ m_bRestartDrawing = false;
+ m_bTextObjectsCollected = false;
+ m_aTextObjects.clear();
+ m_bStartedInOther = false;
+ pOtherCursor.reset();
+ }
+};
+
+static void lcl_LeaveDrawText(SwWrtShell& rSh)
+{
+ if(rSh.GetDrawView())
+ {
+ rSh.GetDrawView()->SdrEndTextEdit( true );
+ Point aPt(LONG_MIN, LONG_MIN);
+ // go out of the frame
+ rSh.SelectObj(aPt, SW_LEAVE_FRAME);
+ rSh.EnterStdMode();
+ rSh.GetView().AttrChangedNotify(nullptr);
+ }
+}
+
+SwSpellDialogChildWindow::SwSpellDialogChildWindow (
+ vcl::Window* _pParent,
+ sal_uInt16 nId,
+ SfxBindings* pBindings,
+ SfxChildWinInfo* /*pInfo*/)
+ : svx::SpellDialogChildWindow (
+ _pParent, nId, pBindings)
+ , m_bIsGrammarCheckingOn(false)
+ , m_pSpellState(new SpellState)
+{
+ SvtLinguConfig().GetProperty( UPN_IS_GRAMMAR_INTERACTIVE ) >>= m_bIsGrammarCheckingOn;
+}
+
+SwSpellDialogChildWindow::~SwSpellDialogChildWindow ()
+{
+ SwWrtShell* pWrtShell = GetWrtShell_Impl();
+ if(!m_pSpellState->m_bInitialCall && pWrtShell)
+ pWrtShell->SpellEnd();
+ m_pSpellState.reset();
+}
+
+SfxChildWinInfo SwSpellDialogChildWindow::GetInfo() const
+{
+ SfxChildWinInfo aInfo = svx::SpellDialogChildWindow::GetInfo();
+ aInfo.bVisible = false;
+ return aInfo;
+}
+
+svx::SpellPortions SwSpellDialogChildWindow::GetNextWrongSentence(bool bRecheck)
+{
+ svx::SpellPortions aRet;
+ SwWrtShell* pWrtShell = GetWrtShell_Impl();
+ if(pWrtShell)
+ {
+ bool bNoDictionaryAvailable = pWrtShell->GetDoc()->IsDictionaryMissing();
+
+ if (!bRecheck)
+ {
+ // first set continuation point for spell/grammar check to the
+ // end of the current sentence
+ SwEditShell::MoveContinuationPosToEndOfCheckedSentence();
+ }
+
+ ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
+ bool bDrawText = ShellMode::DrawText == eSelMode;
+ bool bNormalText =
+ ShellMode::TableText == eSelMode ||
+ ShellMode::ListText == eSelMode ||
+ ShellMode::TableListText == eSelMode ||
+ ShellMode::Text == eSelMode;
+ // Writer text outside of the body
+ bool bOtherText = false;
+
+ if( m_pSpellState->m_bInitialCall )
+ {
+ // if no text selection exists the cursor has to be set into the text
+ if(!bDrawText && !bNormalText)
+ {
+ MakeTextSelection_Impl(*pWrtShell, eSelMode);
+ // the selection type has to be checked again - both text types are possible
+ if(pWrtShell->GetSelectionType() & SelectionType::DrawObjectEditMode)
+ bDrawText = true;
+ bNormalText = !bDrawText;
+ }
+ if(bNormalText)
+ {
+ // set cursor to the start of the sentence
+ if(!pWrtShell->HasSelection())
+ pWrtShell->GoStartSentence();
+ else
+ {
+ pWrtShell->ExpandToSentenceBorders();
+ m_pSpellState->m_bStartedInSelection = true;
+ }
+ // determine if the selection is outside of the body text
+ bOtherText = !(pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY);
+ if(bOtherText)
+ {
+ m_pSpellState->pOtherCursor.reset( new SwPaM(*pWrtShell->GetCursor()->GetPoint()) );
+ m_pSpellState->m_bStartedInOther = true;
+ pWrtShell->SpellStart( SwDocPositions::OtherStart, SwDocPositions::OtherEnd, SwDocPositions::Curr );
+ }
+ else
+ {
+ // mark the start position only if not at start of doc
+ if(!pWrtShell->IsStartOfDoc())
+ {
+ // Record the position *before* the current cursor, as
+ // the word at the current cursor can possibly be
+ // replaced by a spellcheck correction which invalidates
+ // an XTextRange at this position.
+ SwDoc *pDoc = pWrtShell->GetDoc();
+ auto pStart = pWrtShell->GetCursor()->Start();
+ auto pUnoCursor = pDoc->CreateUnoCursor(*pStart);
+ pUnoCursor->Left( 1 );
+ pStart = pUnoCursor->Start();
+ m_pSpellState->m_xStartRange
+ = SwXTextRange::CreateXTextRange(*pDoc, *pStart, nullptr);
+ }
+ pWrtShell->SpellStart( SwDocPositions::Start, SwDocPositions::End, SwDocPositions::Curr );
+ }
+ }
+ else
+ {
+ SdrView* pSdrView = pWrtShell->GetDrawView();
+ m_pSpellState->m_pStartDrawing = pSdrView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
+ OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
+ // start checking at the top of the drawing object
+ pOLV->SetSelection( ESelection() );
+ m_pSpellState->m_aStartDrawingSelection = ESelection();
+/*
+Note: spelling in a selection only, or starting in a mid of a drawing object requires
+further changes elsewhere. (Especially if it should work in sc and sd as well.)
+The code below would only be part of the solution.
+(Keeping it as a comment for the time being)
+ ESelection aCurSel( pOLV->GetSelection() );
+ ESelection aSentenceSel( pOLV->GetEditView().GetEditEngine()->SelectSentence( aCurSel ) );
+ if (!aCurSel.HasRange())
+ {
+ aSentenceSel.nEndPara = aSentenceSel.nStartPara;
+ aSentenceSel.nEndPos = aSentenceSel.nStartPos;
+ }
+ pOLV->SetSelection( aSentenceSel );
+ m_pSpellState->m_aStartDrawingSelection = aSentenceSel;
+*/
+ }
+
+ m_pSpellState->m_bInitialCall = false;
+ }
+ if( bDrawText )
+ {
+ // spell inside of the current draw text
+ if(!SpellDrawText_Impl(*pWrtShell, aRet))
+ {
+ if(!FindNextDrawTextError_Impl(*pWrtShell) || !SpellDrawText_Impl(*pWrtShell, aRet))
+ {
+ lcl_LeaveDrawText(*pWrtShell);
+ // now the drawings have been spelled
+ m_pSpellState->m_bDrawingsSpelled = true;
+ // the spelling continues at the other content
+ // if there's any that has not been spelled yet
+ if(!m_pSpellState->m_bOtherSpelled && pWrtShell->HasOtherCnt())
+ {
+ pWrtShell->SpellStart(SwDocPositions::OtherStart, SwDocPositions::OtherEnd, SwDocPositions::OtherStart );
+ if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
+ {
+ pWrtShell->SpellEnd();
+ m_pSpellState->m_bOtherSpelled = true;
+ }
+ }
+ else
+ m_pSpellState->m_bOtherSpelled = true;
+ // if no result has been found try at the body text - completely
+ if(!m_pSpellState->m_bBodySpelled && aRet.empty())
+ {
+ pWrtShell->SpellStart(SwDocPositions::Start, SwDocPositions::End, SwDocPositions::Start );
+ if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
+ {
+ m_pSpellState->m_bBodySpelled = true;
+ pWrtShell->SpellEnd();
+ }
+ }
+
+ }
+ }
+ }
+ else
+ {
+ // spell inside of the Writer text
+ if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
+ {
+ // if there is a selection (within body or header/footer text)
+ // then spell/grammar checking should not move outside of it.
+ if (!m_pSpellState->m_bStartedInSelection)
+ {
+ // find out which text has been spelled body or other
+ bOtherText = !(pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY);
+ if(bOtherText && m_pSpellState->m_bStartedInOther && m_pSpellState->pOtherCursor)
+ {
+ m_pSpellState->m_bStartedInOther = false;
+ pWrtShell->SetSelection(*m_pSpellState->pOtherCursor);
+ pWrtShell->SpellEnd();
+ m_pSpellState->pOtherCursor.reset();
+ pWrtShell->SpellStart(SwDocPositions::OtherStart, SwDocPositions::Curr, SwDocPositions::OtherStart );
+ (void)pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn);
+ }
+ if(aRet.empty())
+ {
+ // end spelling
+ pWrtShell->SpellEnd();
+ if(bOtherText)
+ {
+ m_pSpellState->m_bOtherSpelled = true;
+ // has the body been spelled?
+ if(!m_pSpellState->m_bBodySpelled)
+ {
+ pWrtShell->SpellStart(SwDocPositions::Start, SwDocPositions::End, SwDocPositions::Start );
+ if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
+ {
+ m_pSpellState->m_bBodySpelled = true;
+ pWrtShell->SpellEnd();
+ }
+ }
+ }
+ else
+ {
+ m_pSpellState->m_bBodySpelled = true;
+ if(!m_pSpellState->m_bOtherSpelled && pWrtShell->HasOtherCnt())
+ {
+ pWrtShell->SpellStart(SwDocPositions::OtherStart, SwDocPositions::OtherEnd, SwDocPositions::OtherStart );
+ if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
+ {
+ pWrtShell->SpellEnd();
+ m_pSpellState->m_bOtherSpelled = true;
+ }
+ }
+ else
+ m_pSpellState->m_bOtherSpelled = true;
+ }
+ }
+
+ // search for a draw text object that contains error and spell it
+ if(aRet.empty() &&
+ (m_pSpellState->m_bDrawingsSpelled ||
+ !FindNextDrawTextError_Impl(*pWrtShell) || !SpellDrawText_Impl(*pWrtShell, aRet)))
+ {
+ lcl_LeaveDrawText(*pWrtShell);
+ m_pSpellState->m_bDrawingsSpelled = true;
+ }
+ }
+ }
+ }
+ // now only the rest of the body text can be spelled -
+ // if the spelling started inside of the body
+ bool bCloseMessage = true;
+ if(aRet.empty() && !m_pSpellState->m_bStartedInSelection)
+ {
+ OSL_ENSURE(m_pSpellState->m_bDrawingsSpelled &&
+ m_pSpellState->m_bOtherSpelled && m_pSpellState->m_bBodySpelled,
+ "not all parts of the document are already spelled");
+ if( m_pSpellState->m_xStartRange.is() && !bNoDictionaryAvailable )
+ {
+ LockFocusNotification( true );
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetController()->getDialog(),
+ VclMessageType::Question, VclButtonsType::YesNo, SwResId(STR_QUERY_SPELL_CONTINUE)));
+ sal_uInt16 nRet = xBox->run();
+ if (RET_YES == nRet)
+ {
+ SwUnoInternalPaM aPam(*pWrtShell->GetDoc());
+ if (::sw::XTextRangeToSwPaM(aPam,
+ m_pSpellState->m_xStartRange))
+ {
+ pWrtShell->SetSelection(aPam);
+ pWrtShell->SpellStart(SwDocPositions::Start, SwDocPositions::Curr, SwDocPositions::Start);
+ if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
+ pWrtShell->SpellEnd();
+ }
+ m_pSpellState->m_xStartRange = nullptr;
+ LockFocusNotification( false );
+ // take care that the now valid selection is stored
+ LoseFocus();
+ }
+ else
+ bCloseMessage = false; // no closing message if a wrap around has been denied
+ }
+ }
+ if( aRet.empty() && bCloseMessage && !bNoDictionaryAvailable )
+ {
+ LockFocusNotification( true );
+ OUString sInfo( SwResId( bNoDictionaryAvailable ? STR_DICTIONARY_UNAVAILABLE : STR_SPELLING_COMPLETED ) );
+ auto xSpellController = GetController();
+ // #i84610#
+ std::unique_ptr<weld::MessageDialog> xBox(
+ Application::CreateMessageDialog( xSpellController->getDialog(),
+ VclMessageType::Info,
+ VclButtonsType::Ok,
+ sInfo ) );
+ xBox->run();
+ LockFocusNotification( false );
+ // take care that the now valid selection is stored
+ LoseFocus();
+ xSpellController->getDialog()->grab_focus();
+ }
+ }
+ return aRet;
+}
+
+void SwSpellDialogChildWindow::ApplyChangedSentence(const svx::SpellPortions& rChanged, bool bRecheck)
+{
+ SwWrtShell* pWrtShell = GetWrtShell_Impl();
+ OSL_ENSURE(!m_pSpellState->m_bInitialCall, "ApplyChangedSentence in initial call or after resume");
+ if(!pWrtShell || m_pSpellState->m_bInitialCall)
+ return;
+
+ ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
+ bool bDrawText = ShellMode::DrawText == eSelMode;
+ bool bNormalText =
+ ShellMode::TableText == eSelMode ||
+ ShellMode::ListText == eSelMode ||
+ ShellMode::TableListText == eSelMode ||
+ ShellMode::Text == eSelMode;
+
+ // evaluate if the same sentence should be rechecked or not.
+ // Sentences that got grammar checked should always be rechecked in order
+ // to detect possible errors that get introduced with the changes
+ bRecheck |= SwEditShell::HasLastSentenceGotGrammarChecked();
+
+ if(bNormalText)
+ pWrtShell->ApplyChangedSentence(rChanged, bRecheck);
+ else if(bDrawText )
+ {
+ SdrView* pDrView = pWrtShell->GetDrawView();
+ SdrOutliner *pOutliner = pDrView->GetTextEditOutliner();
+ pOutliner->ApplyChangedSentence(pDrView->GetTextEditOutlinerView()->GetEditView(), rChanged, bRecheck);
+ }
+}
+
+void SwSpellDialogChildWindow::AddAutoCorrection(
+ const OUString& rOld, const OUString& rNew, LanguageType eLanguage)
+{
+ SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get().GetAutoCorrect();
+ pACorr->PutText( rOld, rNew, eLanguage );
+}
+
+bool SwSpellDialogChildWindow::HasAutoCorrection()
+{
+ return true;
+}
+
+bool SwSpellDialogChildWindow::HasGrammarChecking()
+{
+ return SvtLinguConfig().HasGrammarChecker();
+}
+
+bool SwSpellDialogChildWindow::IsGrammarChecking()
+{
+ return m_bIsGrammarCheckingOn;
+}
+
+void SwSpellDialogChildWindow::SetGrammarChecking(bool bOn)
+{
+ uno::Any aVal;
+ aVal <<= bOn;
+ m_bIsGrammarCheckingOn = bOn;
+ SvtLinguConfig().SetProperty( UPN_IS_GRAMMAR_INTERACTIVE, aVal );
+ // set current spell position to the start of the current sentence to
+ // continue with this sentence after grammar checking state has been changed
+ SwWrtShell* pWrtShell = GetWrtShell_Impl();
+ if(!pWrtShell)
+ return;
+
+ ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
+ bool bDrawText = ShellMode::DrawText == eSelMode;
+ bool bNormalText =
+ ShellMode::TableText == eSelMode ||
+ ShellMode::ListText == eSelMode ||
+ ShellMode::TableListText == eSelMode ||
+ ShellMode::Text == eSelMode;
+ if( bNormalText )
+ SwEditShell::PutSpellingToSentenceStart();
+ else if( bDrawText )
+ {
+ SdrView* pSdrView = pWrtShell->GetDrawView();
+ SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : nullptr;
+ OSL_ENSURE(pOutliner, "No Outliner in SwSpellDialogChildWindow::SetGrammarChecking");
+ if(pOutliner)
+ {
+ pOutliner->PutSpellingToSentenceStart( pSdrView->GetTextEditOutlinerView()->GetEditView() );
+ }
+ }
+}
+
+void SwSpellDialogChildWindow::GetFocus()
+{
+ if(m_pSpellState->m_bLockFocus)
+ return;
+ bool bInvalidate = false;
+ SwWrtShell* pWrtShell = GetWrtShell_Impl();
+ if(pWrtShell && !m_pSpellState->m_bInitialCall)
+ {
+ ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
+ if(eSelMode != m_pSpellState->m_eSelMode)
+ {
+ // prevent initial invalidation
+ if(m_pSpellState->m_bLostFocus)
+ bInvalidate = true;
+ }
+ else
+ {
+ switch(m_pSpellState->m_eSelMode)
+ {
+ case ShellMode::Text:
+ case ShellMode::ListText:
+ case ShellMode::TableText:
+ case ShellMode::TableListText:
+ {
+ SwPaM* pCursor = pWrtShell->GetCursor();
+ if(m_pSpellState->m_pPointNode != &pCursor->GetPointNode() ||
+ m_pSpellState->m_pMarkNode != &pCursor->GetMarkNode()||
+ m_pSpellState->m_nPointPos != pCursor->GetPoint()->GetContentIndex()||
+ m_pSpellState->m_nMarkPos != pCursor->GetMark()->GetContentIndex())
+ bInvalidate = true;
+ }
+ break;
+ case ShellMode::DrawText:
+ {
+ SdrView* pSdrView = pWrtShell->GetDrawView();
+ SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : nullptr;
+ if(!pOutliner || m_pSpellState->m_pOutliner != pOutliner)
+ bInvalidate = true;
+ else
+ {
+ OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
+ OSL_ENSURE(pOLV, "no OutlinerView in SwSpellDialogChildWindow::GetFocus()");
+ if(!pOLV || m_pSpellState->m_aESelection != pOLV->GetSelection())
+ bInvalidate = true;
+ }
+ }
+ break;
+ default: bInvalidate = true;
+ }
+ }
+ }
+ else
+ {
+ bInvalidate = true;
+ }
+ if(bInvalidate)
+ InvalidateSpellDialog();
+}
+
+void SwSpellDialogChildWindow::LoseFocus()
+{
+ // prevent initial invalidation
+ m_pSpellState->m_bLostFocus = true;
+ if(m_pSpellState->m_bLockFocus)
+ return;
+ SwWrtShell* pWrtShell = GetWrtShell_Impl();
+ if(pWrtShell)
+ {
+ m_pSpellState->m_eSelMode = pWrtShell->GetView().GetShellMode();
+ m_pSpellState->m_pPointNode = m_pSpellState->m_pMarkNode = nullptr;
+ m_pSpellState->m_nPointPos = m_pSpellState->m_nMarkPos = 0;
+ m_pSpellState->m_pOutliner = nullptr;
+
+ switch(m_pSpellState->m_eSelMode)
+ {
+ case ShellMode::Text:
+ case ShellMode::ListText:
+ case ShellMode::TableText:
+ case ShellMode::TableListText:
+ {
+ // store a node pointer and a pam-position to be able to check on next GetFocus();
+ SwPaM* pCursor = pWrtShell->GetCursor();
+ m_pSpellState->m_pPointNode = &pCursor->GetPointNode();
+ m_pSpellState->m_pMarkNode = &pCursor->GetMarkNode();
+ m_pSpellState->m_nPointPos = pCursor->GetPoint()->GetContentIndex();
+ m_pSpellState->m_nMarkPos = pCursor->GetMark()->GetContentIndex();
+
+ }
+ break;
+ case ShellMode::DrawText:
+ {
+ SdrView* pSdrView = pWrtShell->GetDrawView();
+ SdrOutliner* pOutliner = pSdrView->GetTextEditOutliner();
+ m_pSpellState->m_pOutliner = pOutliner;
+ OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
+ OSL_ENSURE(pOutliner && pOLV, "no Outliner/OutlinerView in SwSpellDialogChildWindow::LoseFocus()");
+ if(pOLV)
+ {
+ m_pSpellState->m_aESelection = pOLV->GetSelection();
+ }
+ }
+ break;
+ default:;// prevent warning
+ }
+ }
+ else
+ m_pSpellState->m_eSelMode = ShellMode::Object;
+}
+
+void SwSpellDialogChildWindow::InvalidateSpellDialog()
+{
+ SwWrtShell* pWrtShell = GetWrtShell_Impl();
+ if(!m_pSpellState->m_bInitialCall && pWrtShell)
+ pWrtShell->SpellEnd(nullptr, false);
+ m_pSpellState->Reset();
+ svx::SpellDialogChildWindow::InvalidateSpellDialog();
+}
+
+SwWrtShell* SwSpellDialogChildWindow::GetWrtShell_Impl()
+{
+ SfxDispatcher* pDispatch = GetBindings().GetDispatcher();
+ SwView* pView = nullptr;
+ if(pDispatch)
+ {
+ sal_uInt16 nShellIdx = 0;
+ SfxShell* pShell;
+ while(nullptr != (pShell = pDispatch->GetShell(nShellIdx++)))
+ if(auto pSwView = dynamic_cast< SwView *>( pShell ))
+ {
+ pView = pSwView;
+ break;
+ }
+ }
+ return pView ? pView->GetWrtShellPtr(): nullptr;
+}
+
+// set the cursor into the body text - necessary if any object is selected
+// on start of the spelling dialog
+void SwSpellDialogChildWindow::MakeTextSelection_Impl(SwWrtShell& rShell, ShellMode eSelMode)
+{
+ SwView& rView = rShell.GetView();
+ switch(eSelMode)
+ {
+ case ShellMode::Text:
+ case ShellMode::ListText:
+ case ShellMode::TableText:
+ case ShellMode::TableListText:
+ case ShellMode::DrawText:
+ OSL_FAIL("text already active in SwSpellDialogChildWindow::MakeTextSelection_Impl()");
+ break;
+
+ case ShellMode::Frame:
+ {
+ rShell.UnSelectFrame();
+ rShell.LeaveSelFrameMode();
+ rView.AttrChangedNotify(nullptr);
+ }
+ break;
+
+ case ShellMode::Draw:
+ case ShellMode::DrawForm:
+ case ShellMode::Bezier:
+ if(FindNextDrawTextError_Impl(rShell))
+ {
+ rView.AttrChangedNotify(nullptr);
+ break;
+ }
+ [[fallthrough]]; // to deselect the object
+ case ShellMode::Graphic:
+ case ShellMode::Object:
+ {
+ if ( rShell.IsDrawCreate() )
+ {
+ rView.GetDrawFuncPtr()->BreakCreate();
+ rView.AttrChangedNotify(nullptr);
+ }
+ else if ( rShell.HasSelection() || rView.IsDrawMode() )
+ {
+ SdrView *pSdrView = rShell.GetDrawView();
+ if(pSdrView && pSdrView->AreObjectsMarked() &&
+ pSdrView->GetHdlList().GetFocusHdl())
+ {
+ const_cast<SdrHdlList&>(pSdrView->GetHdlList()).ResetFocusHdl();
+ }
+ else
+ {
+ rView.LeaveDrawCreate();
+ Point aPt(LONG_MIN, LONG_MIN);
+ // go out of the frame
+ rShell.SelectObj(aPt, SW_LEAVE_FRAME);
+ SfxBindings& rBind = rView.GetViewFrame().GetBindings();
+ rBind.Invalidate( SID_ATTR_SIZE );
+ rShell.EnterStdMode();
+ rView.AttrChangedNotify(nullptr);
+ }
+ }
+ }
+ break;
+ default:; // prevent warning
+ }
+}
+
+// select the next draw text object that has a spelling error
+bool SwSpellDialogChildWindow::FindNextDrawTextError_Impl(SwWrtShell& rSh)
+{
+ bool bNextDoc = false;
+ SdrView* pDrView = rSh.GetDrawView();
+ if(!pDrView)
+ return bNextDoc;
+ SwView& rView = rSh.GetView();
+ SwDoc* pDoc = rView.GetDocShell()->GetDoc();
+ const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
+ // start at the current draw object - if there is any selected
+ SdrTextObj* pCurrentTextObj = nullptr;
+ if ( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ if( auto pSdrTextObj = DynCastSdrTextObj( pObj ) )
+ pCurrentTextObj = pSdrTextObj;
+ }
+ // at first fill the list of drawing objects
+ if(!m_pSpellState->m_bTextObjectsCollected )
+ {
+ m_pSpellState->m_bTextObjectsCollected = true;
+ SwDrawContact::GetTextObjectsFromFormat(m_pSpellState->m_aTextObjects, *pDoc);
+ if(pCurrentTextObj)
+ {
+ m_pSpellState->m_aTextObjects.remove(pCurrentTextObj);
+ m_pSpellState->m_aTextObjects.push_back(pCurrentTextObj);
+ }
+ }
+ if(!m_pSpellState->m_aTextObjects.empty())
+ {
+ Reference< XSpellChecker1 > xSpell( GetSpellChecker() );
+ while(!bNextDoc && !m_pSpellState->m_aTextObjects.empty())
+ {
+ std::list<SdrTextObj*>::iterator aStart = m_pSpellState->m_aTextObjects.begin();
+ SdrTextObj* pTextObj = *aStart;
+ if(m_pSpellState->m_pStartDrawing == pTextObj)
+ m_pSpellState->m_bRestartDrawing = true;
+ m_pSpellState->m_aTextObjects.erase(aStart);
+ OutlinerParaObject* pParaObj = pTextObj->GetOutlinerParaObject();
+ if ( pParaObj )
+ {
+ bool bHasSpellError = false;
+ {
+ SdrOutliner aTmpOutliner(pDoc->getIDocumentDrawModelAccess().GetDrawModel()->
+ GetDrawOutliner().GetEmptyItemSet().GetPool(),
+ OutlinerMode::TextObject );
+ aTmpOutliner.SetRefDevice( pDoc->getIDocumentDeviceAccess().getPrinter( false ) );
+ MapMode aMapMode (MapUnit::MapTwip);
+ aTmpOutliner.SetRefMapMode(aMapMode);
+ aTmpOutliner.SetPaperSize( pTextObj->GetLogicRect().GetSize() );
+ aTmpOutliner.SetSpeller( xSpell );
+
+ OutlinerView aOutlView( &aTmpOutliner, &(rView.GetEditWin()) );
+ aOutlView.GetOutliner()->SetRefDevice( rSh.getIDocumentDeviceAccess().getPrinter( false ) );
+ aTmpOutliner.InsertView( &aOutlView );
+ Size aSize(1,1);
+ tools::Rectangle aRect( Point(), aSize );
+ aOutlView.SetOutputArea( aRect );
+ aTmpOutliner.SetText( *pParaObj );
+ aTmpOutliner.ClearModifyFlag();
+ bHasSpellError = EESpellState::Ok != aTmpOutliner.HasSpellErrors();
+ aTmpOutliner.RemoveView( &aOutlView );
+ }
+ if(bHasSpellError)
+ {
+ // now the current one has to be deselected
+ if(pCurrentTextObj)
+ pDrView->SdrEndTextEdit( true );
+ // and the found one should be activated
+ rSh.MakeVisible(SwRect(pTextObj->GetLogicRect()));
+ Point aTmp( 0,0 );
+ rSh.SelectObj( aTmp, 0, pTextObj );
+ SdrPageView* pPV = pDrView->GetSdrPageView();
+ rView.BeginTextEdit( pTextObj, pPV, &rView.GetEditWin(), false, true );
+ rView.AttrChangedNotify(nullptr);
+ bNextDoc = true;
+ }
+ }
+ }
+ }
+ return bNextDoc;
+}
+
+bool SwSpellDialogChildWindow::SpellDrawText_Impl(SwWrtShell& rSh, svx::SpellPortions& rPortions)
+{
+ bool bRet = false;
+ SdrView* pSdrView = rSh.GetDrawView();
+ SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : nullptr;
+ OSL_ENSURE(pOutliner, "No Outliner in SwSpellDialogChildWindow::SpellDrawText_Impl");
+ if(pOutliner)
+ {
+ bRet = pOutliner->SpellSentence(pSdrView->GetTextEditOutlinerView()->GetEditView(), rPortions);
+ // find out if the current selection is in the first spelled drawing object
+ // and behind the initial selection
+ if(bRet && m_pSpellState->m_bRestartDrawing)
+ {
+ OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
+ ESelection aCurrentSelection = pOLV->GetSelection();
+ if(m_pSpellState->m_aStartDrawingSelection.nEndPara < aCurrentSelection.nEndPara ||
+ (m_pSpellState->m_aStartDrawingSelection.nEndPara == aCurrentSelection.nEndPara &&
+ m_pSpellState->m_aStartDrawingSelection.nEndPos < aCurrentSelection.nEndPos))
+ {
+ bRet = false;
+ rPortions.clear();
+ }
+ }
+ }
+ return bRet;
+}
+
+void SwSpellDialogChildWindow::LockFocusNotification(bool bLock)
+{
+ OSL_ENSURE(m_pSpellState->m_bLockFocus != bLock, "invalid locking - no change of state");
+ m_pSpellState->m_bLockFocus = bLock;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/dialog/regionsw.cxx b/sw/source/uibase/dialog/regionsw.cxx
new file mode 100644
index 0000000000..9eaa64c894
--- /dev/null
+++ b/sw/source/uibase/dialog/regionsw.cxx
@@ -0,0 +1,234 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+#include <comphelper/string.hxx>
+#include <svl/stritem.hxx>
+#include <svl/eitem.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <editeng/sizeitem.hxx>
+#include <section.hxx>
+#include <basesh.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <fmtclds.hxx>
+#include <fmtfsize.hxx>
+#include <cmdid.h>
+#include <swabstdlg.hxx>
+#include <IDocumentContentOperations.hxx>
+#include <translatehelper.hxx>
+#include <IDocumentUndoRedo.hxx>
+
+void SwBaseShell::InsertRegionDialog(SfxRequest& rReq)
+{
+ SwWrtShell& rSh = GetShell();
+ const SfxItemSet *pSet = rReq.GetArgs();
+
+ SfxItemSetFixed<
+ RES_FRM_SIZE, RES_FRM_SIZE,
+ RES_LR_SPACE, RES_LR_SPACE,
+ RES_BACKGROUND, RES_BACKGROUND,
+ RES_COL, RES_COL,
+ RES_FTN_AT_TXTEND, RES_FRAMEDIR,
+ XATTR_FILL_FIRST, XATTR_FILL_LAST,
+ SID_ATTR_PAGE_SIZE, SID_ATTR_PAGE_SIZE>
+ aSet( GetPool() );
+
+ if (!pSet || pSet->Count()==0)
+ {
+ SwRect aRect;
+ rSh.CalcBoundRect(aRect, RndStdIds::FLY_AS_CHAR);
+
+ tools::Long nWidth = aRect.Width();
+ aSet.Put(SwFormatFrameSize(SwFrameSize::Variable, nWidth));
+
+ // height=width for more consistent preview (analog to edit region)
+ aSet.Put(SvxSizeItem(SID_ATTR_PAGE_SIZE, Size(nWidth, nWidth)));
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ VclPtr<AbstractInsertSectionTabDialog> aTabDlg(pFact->CreateInsertSectionTabDialog(
+ GetView().GetFrameWeld(), aSet , rSh));
+ aTabDlg->StartExecuteAsync([aTabDlg](sal_Int32 /*nResult*/){
+ aTabDlg->disposeOnce();
+ });
+ rReq.Ignore();
+ }
+ else
+ {
+ OUString aTmpStr;
+ if ( const SfxStringItem* pItem = pSet->GetItemIfSet(FN_PARAM_REGION_NAME) )
+ {
+ const OUString sRemoveWhenUniStringIsGone = pItem->GetValue();
+ aTmpStr = rSh.GetUniqueSectionName(&sRemoveWhenUniStringIsGone);
+ }
+ else
+ aTmpStr = rSh.GetUniqueSectionName();
+
+ SwSectionData aSection(SectionType::Content, aTmpStr);
+ rReq.SetReturnValue(SfxStringItem(FN_INSERT_REGION, aTmpStr));
+
+ aSet.Put( *pSet );
+ const SfxUInt16Item *pColRegionItem = nullptr;
+ if((pColRegionItem = pSet->GetItemIfSet(SID_ATTR_COLUMNS, false)) ||
+ (pColRegionItem = pSet->GetItemIfSet(FN_INSERT_REGION, false)))
+ {
+ SwFormatCol aCol;
+ SwRect aRect;
+ rSh.CalcBoundRect(aRect, RndStdIds::FLY_AS_CHAR);
+ tools::Long nWidth = aRect.Width();
+
+ sal_uInt16 nCol = pColRegionItem->GetValue();
+ if(nCol)
+ {
+ aCol.Init( nCol, 0, static_cast< sal_uInt16 >(nWidth) );
+ aSet.Put(aCol);
+ }
+ }
+ else if(const SwFormatCol* pFormatCol = pSet->GetItemIfSet(RES_COL, false))
+ {
+ aSet.Put(*pFormatCol);
+ }
+
+ const SfxBoolItem* pBoolItem;
+ const bool bHidden = (pBoolItem = pSet->GetItemIfSet(FN_PARAM_REGION_HIDDEN)) &&
+ pBoolItem->GetValue();
+ const bool bProtect = (pBoolItem = pSet->GetItemIfSet(FN_PARAM_REGION_PROTECT)) &&
+ pBoolItem->GetValue();
+ // #114856# edit in readonly sections
+ const bool bEditInReadonly = (pBoolItem = pSet->GetItemIfSet(FN_PARAM_REGION_EDIT_IN_READONLY)) &&
+ pBoolItem->GetValue();
+
+ aSection.SetProtectFlag(bProtect);
+ aSection.SetHidden(bHidden);
+ // #114856# edit in readonly sections
+ aSection.SetEditInReadonlyFlag(bEditInReadonly);
+
+ if(const SfxStringItem* pConditionItem =
+ pSet->GetItemIfSet(FN_PARAM_REGION_CONDITION))
+ aSection.SetCondition(pConditionItem->GetValue());
+
+ OUString aFile, aSub;
+ const SfxPoolItem* pItem;
+ if(SfxItemState::SET ==
+ pSet->GetItemState(FN_PARAM_1, true, &pItem))
+ aFile = static_cast<const SfxStringItem *>(pItem)->GetValue();
+
+ if(SfxItemState::SET ==
+ pSet->GetItemState(FN_PARAM_3, true, &pItem))
+ aSub = static_cast<const SfxStringItem *>(pItem)->GetValue();
+
+ if(!aFile.isEmpty() || !aSub.isEmpty())
+ {
+ OUString sLinkFileName = OUStringChar(sfx2::cTokenSeparator)
+ + OUStringChar(sfx2::cTokenSeparator);
+ sLinkFileName = comphelper::string::setToken(sLinkFileName, 0, sfx2::cTokenSeparator, aFile);
+
+ if(SfxItemState::SET ==
+ pSet->GetItemState(FN_PARAM_2, true, &pItem))
+ {
+ sLinkFileName = comphelper::string::setToken(sLinkFileName, 1, sfx2::cTokenSeparator,
+ static_cast<const SfxStringItem *>(pItem)->GetValue());
+ }
+
+ sLinkFileName += aSub;
+ aSection.SetType( SectionType::FileLink );
+ aSection.SetLinkFileName(sLinkFileName);
+ }
+ rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSSECTION, nullptr);
+ rSh.StartAction();
+ rSh.InsertSection(aSection, aSet.Count() ? &aSet : nullptr);
+
+ const SfxStringItem* pSectionContent = rReq.GetArg<SfxStringItem>(FN_PARAM_4);
+ if (pSectionContent)
+ {
+ OUString aSectionContent = pSectionContent->GetValue();
+ SwPaM* pCursorPos = rSh.GetCursor();
+ pCursorPos->Move(fnMoveBackward, GoInContent);
+ // Paste HTML content.
+ SwTranslateHelper::PasteHTMLToPaM(rSh, pCursorPos, aSectionContent.toUtf8());
+ if (pCursorPos->GetPoint()->GetContentIndex() == 0)
+ {
+ // The paste created a last empty text node, remove it.
+ SwPaM aPam(*pCursorPos->GetPoint());
+ aPam.SetMark();
+ aPam.Move(fnMoveBackward, GoInContent);
+ rSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(aPam);
+ }
+ }
+ rSh.EndAction();
+ rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSSECTION, nullptr);
+
+ rReq.Done();
+ }
+}
+
+void SwWrtShell::StartInsertRegionDialog(const SwSectionData& rSectionData)
+{
+ SfxItemSetFixed<
+ RES_FRM_SIZE, RES_FRM_SIZE,
+ RES_BACKGROUND, RES_BACKGROUND,
+ RES_COL, RES_COL,
+ XATTR_FILL_FIRST, XATTR_FILL_LAST,
+ SID_ATTR_PAGE_SIZE, SID_ATTR_PAGE_SIZE>
+ aSet( GetView().GetPool() );
+ SwRect aRect;
+ CalcBoundRect(aRect, RndStdIds::FLY_AS_CHAR);
+ tools::Long nWidth = aRect.Width();
+ aSet.Put(SwFormatFrameSize(SwFrameSize::Variable, nWidth));
+ // height=width for more consistent preview (analog to edit region)
+ aSet.Put(SvxSizeItem(SID_ATTR_PAGE_SIZE, Size(nWidth, nWidth)));
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ VclPtr<AbstractInsertSectionTabDialog> aTabDlg(pFact->CreateInsertSectionTabDialog(
+ GetView().GetFrameWeld(), aSet, *this));
+ aTabDlg->SetSectionData(rSectionData);
+ aTabDlg->StartExecuteAsync([aTabDlg](sal_Int32 /*nResult*/){
+ aTabDlg->disposeOnce();
+ });
+}
+
+void SwBaseShell::EditRegionDialog(SfxRequest const & rReq)
+{
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ sal_uInt16 nSlot = rReq.GetSlot();
+ const SfxPoolItem* pItem = nullptr;
+ if(pArgs)
+ pArgs->GetItemState(nSlot, false, &pItem);
+ SwWrtShell& rWrtShell = GetShell();
+
+ switch ( nSlot )
+ {
+ case FN_EDIT_REGION:
+ case FN_EDIT_CURRENT_REGION:
+ {
+ weld::Window* pParentWin = GetView().GetFrameWeld();
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractEditRegionDlg> pEditRegionDlg(pFact->CreateEditRegionDlg(pParentWin, rWrtShell));
+ if(auto pStringItem = dynamic_cast< const SfxStringItem *>( pItem ))
+ {
+ pEditRegionDlg->SelectSection(pStringItem->GetValue());
+ }
+ pEditRegionDlg->Execute();
+ }
+ }
+ break;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/dialog/swabstdlg.cxx b/sw/source/uibase/dialog/swabstdlg.cxx
new file mode 100644
index 0000000000..d5651d731c
--- /dev/null
+++ b/sw/source/uibase/dialog/swabstdlg.cxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <swabstdlg.hxx>
+
+#include <osl/module.hxx>
+
+typedef SwAbstractDialogFactory* (*SwFuncPtrCreateDialogFactory)();
+
+#ifndef DISABLE_DYNLOADING
+
+extern "C" { static void thisModule() {} }
+
+#else
+
+extern "C" SwAbstractDialogFactory* SwCreateDialogFactory();
+
+#endif
+
+SwAbstractDialogFactory* SwAbstractDialogFactory::Create()
+{
+ SwFuncPtrCreateDialogFactory fp = nullptr;
+#ifndef DISABLE_DYNLOADING
+ static ::osl::Module aDialogLibrary;
+ static constexpr OUStringLiteral sLibName(u"" SWUI_DLL_NAME);
+ if ( aDialogLibrary.is() || aDialogLibrary.loadRelative( &thisModule, sLibName,
+ SAL_LOADMODULE_GLOBAL | SAL_LOADMODULE_LAZY ) )
+ fp = reinterpret_cast<SwAbstractDialogFactory* (SAL_CALL*)()>(
+ aDialogLibrary.getFunctionSymbol( "SwCreateDialogFactory" ));
+#else
+ fp = SwCreateDialogFactory;
+#endif
+
+ if ( fp )
+ return fp();
+ return nullptr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/dialog/swwrtshitem.cxx b/sw/source/uibase/dialog/swwrtshitem.cxx
new file mode 100644
index 0000000000..d64f716b14
--- /dev/null
+++ b/sw/source/uibase/dialog/swwrtshitem.cxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <swwrtshitem.hxx>
+#include <globals.hrc>
+
+SwWrtShellItem::SwWrtShellItem( SwWrtShell* pSh )
+ : SfxPoolItem( SID_WRT_SHELL ), m_pWrtSh( pSh )
+{
+
+}
+
+bool SwWrtShellItem::operator==( const SfxPoolItem& rItem) const
+{
+ return SfxPoolItem::operator==(rItem)
+ && m_pWrtSh == static_cast<const SwWrtShellItem&>(rItem).m_pWrtSh;
+}
+
+SwWrtShellItem* SwWrtShellItem::Clone( SfxItemPool * /*pPool*/ ) const
+{
+ return new SwWrtShellItem( *this );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/dialog/watermarkdialog.cxx b/sw/source/uibase/dialog/watermarkdialog.cxx
new file mode 100644
index 0000000000..413d20f284
--- /dev/null
+++ b/sw/source/uibase/dialog/watermarkdialog.cxx
@@ -0,0 +1,119 @@
+/* -*- 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 <watermarkdialog.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/dispatchcommand.hxx>
+#include <editeng/editids.hrc>
+#include <editeng/flstitem.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/objsh.hxx>
+#include <vcl/svapp.hxx>
+#include <sfx2/watermarkitem.hxx>
+#include <svtools/ctrltool.hxx>
+#include <comphelper/lok.hxx>
+#include <sfx2/viewsh.hxx>
+#include <svl/itemset.hxx>
+
+#define IS_MOBILE (comphelper::LibreOfficeKit::isActive() && SfxViewShell::Current() && SfxViewShell::Current()->isLOKMobilePhone())
+
+SwWatermarkDialog::SwWatermarkDialog(weld::Window* pParent, SfxBindings& rBindings)
+ : SfxDialogController(pParent, "modules/swriter/ui/watermarkdialog.ui", "WatermarkDialog")
+ , m_rBindings(rBindings)
+ , m_xTextInput(m_xBuilder->weld_entry("TextInput"))
+ , m_xOKButton(m_xBuilder->weld_button("ok"))
+ , m_xFont(m_xBuilder->weld_combo_box("FontBox"))
+ , m_xAngle(m_xBuilder->weld_metric_spin_button("Angle", FieldUnit::DEGREE))
+ , m_xTransparency(m_xBuilder->weld_metric_spin_button("Transparency", FieldUnit::PERCENT))
+ , m_xColor(new ColorListBox(m_xBuilder->weld_menu_button("Color"), [this]{ return m_xDialog.get(); }))
+{
+ InitFields();
+
+ if (IS_MOBILE)
+ {
+ m_xBuilder->weld_label("ColorLabel")->hide();
+ m_xColor->hide();
+ m_xBuilder->weld_button("cancel")->hide();
+ m_xBuilder->weld_button("help")->hide();
+ }
+}
+
+SwWatermarkDialog::~SwWatermarkDialog()
+{
+}
+
+void SwWatermarkDialog::InitFields()
+{
+ // Update font list
+ SfxObjectShell* pDocSh = SfxObjectShell::Current();
+ const SfxPoolItem* pFontItem;
+ const FontList* pFontList = nullptr;
+ std::unique_ptr<FontList> xFontList;
+
+ if ( pDocSh && ( ( pFontItem = pDocSh->GetItem( SID_ATTR_CHAR_FONTLIST ) ) != nullptr ) )
+ pFontList = static_cast<const SvxFontListItem*>( pFontItem )->GetFontList();
+
+ if (!pFontList)
+ {
+ xFontList.reset(new FontList(Application::GetDefaultDevice(), nullptr));
+ pFontList = xFontList.get();
+ }
+
+ m_xFont->freeze();
+ sal_uInt16 nFontCount = pFontList->GetFontNameCount();
+ for (sal_uInt16 i = 0; i < nFontCount; ++i)
+ {
+ const FontMetric& rFontMetric = pFontList->GetFontName(i);
+ m_xFont->append_text(rFontMetric.GetFamilyName());
+ }
+ m_xFont->thaw();
+
+ m_xOKButton->connect_clicked(LINK(this, SwWatermarkDialog, OKButtonHdl));
+
+ // Get watermark properties
+ SfxPoolItemHolder aResult;
+ const SfxItemState eState(m_rBindings.GetDispatcher()->QueryState(SID_WATERMARK, aResult));
+ const SfxWatermarkItem* pWatermark(static_cast<const SfxWatermarkItem*>(aResult.getItem()));
+
+ if( !(eState >= SfxItemState::DEFAULT && pWatermark && pWatermark->Which() == SID_WATERMARK))
+ return;
+
+ const OUString& sText = pWatermark->GetText();
+ m_xTextInput->set_text(sText);
+ OUString sFontName = pWatermark->GetFont();
+ int nFontIndex = m_xFont->find_text(sFontName);
+ if (nFontIndex != -1)
+ m_xFont->set_active(nFontIndex);
+ else
+ m_xFont->set_entry_text(sFontName);
+ m_xAngle->set_value(pWatermark->GetAngle(), FieldUnit::DEGREE);
+ m_xColor->SelectEntry( pWatermark->GetColor() );
+ m_xTransparency->set_value(pWatermark->GetTransparency(), FieldUnit::PERCENT);
+}
+
+IMPL_LINK_NOARG(SwWatermarkDialog, OKButtonHdl, weld::Button&, void)
+{
+ OUString sText = m_xTextInput->get_text();
+
+ css::uno::Sequence<css::beans::PropertyValue> aPropertyValues( comphelper::InitPropertySequence(
+ {
+ { "Text", css::uno::Any( sText ) },
+ { "Font", css::uno::Any( m_xFont->get_active_text() ) },
+ { "Angle", css::uno::Any( static_cast<sal_Int16>( m_xAngle->get_value(FieldUnit::DEGREE) ) ) },
+ { "Transparency", css::uno::Any( static_cast<sal_Int16>( m_xTransparency->get_value(FieldUnit::PERCENT) ) ) },
+ { "Color", css::uno::Any( static_cast<sal_uInt32>( m_xColor->GetSelectEntryColor().GetRGBColor() ) ) }
+ } ) );
+ comphelper::dispatchCommand( ".uno:Watermark", aPropertyValues );
+
+ m_xDialog->response(RET_OK);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/source/uibase/dialog/wordcountwrapper.cxx b/sw/source/uibase/dialog/wordcountwrapper.cxx
new file mode 100644
index 0000000000..d7d4a14515
--- /dev/null
+++ b/sw/source/uibase/dialog/wordcountwrapper.cxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <wordcountdialog.hxx>
+#include <docstat.hxx>
+#include <cmdid.h>
+
+SFX_IMPL_CHILDWINDOW_WITHID(SwWordCountWrapper, FN_WORDCOUNT_DIALOG)
+
+SwWordCountWrapper::SwWordCountWrapper(vcl::Window *pParentWindow,
+ sal_uInt16 nId,
+ SfxBindings* pBindings,
+ SfxChildWinInfo* pInfo )
+ : SfxChildWindow(pParentWindow, nId)
+{
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ m_xAbstDlg.reset(pFact->CreateSwWordCountDialog(pBindings, this, pParentWindow->GetFrameWeld(), pInfo));
+ SetController(m_xAbstDlg->GetController());
+}
+
+SwWordCountWrapper::~SwWordCountWrapper()
+{
+ m_xAbstDlg.disposeAndClear();
+}
+
+SfxChildWinInfo SwWordCountWrapper::GetInfo() const
+{
+ SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
+ return aInfo;
+}
+
+void SwWordCountWrapper::UpdateCounts()
+{
+ m_xAbstDlg->UpdateCounts();
+}
+
+void SwWordCountWrapper::SetCounts(const SwDocStat &rCurrCnt, const SwDocStat &rDocStat)
+{
+ m_xAbstDlg->SetCounts(rCurrCnt, rDocStat);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/dochdl/gloshdl.cxx b/sw/source/uibase/dochdl/gloshdl.cxx
new file mode 100644
index 0000000000..e70ed7ffc4
--- /dev/null
+++ b/sw/source/uibase/dochdl/gloshdl.cxx
@@ -0,0 +1,725 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <utility>
+#include <vcl/errinf.hxx>
+#include <vcl/weld.hxx>
+#include <svl/macitem.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <unotools/transliterationwrapper.hxx>
+#include <o3tl/string_view.hxx>
+#include <docsh.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <gloshdl.hxx>
+#include <glosdoc.hxx>
+#include <shellio.hxx>
+#include <swundo.hxx>
+#include <expfld.hxx>
+#include <initui.hxx>
+#include <gloslst.hxx>
+#include <swdtflvr.hxx>
+
+#include <strings.hrc>
+#include <vcl/svapp.hxx>
+#include <osl/diagnose.h>
+
+#include <editeng/acorrcfg.hxx>
+#include <sfx2/event.hxx>
+#include <swabstdlg.hxx>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+
+const short RET_EDIT = 100;
+
+namespace {
+
+struct TextBlockInfo_Impl
+{
+ OUString sTitle;
+ OUString sLongName;
+ OUString sGroupName;
+ TextBlockInfo_Impl(OUString aTitle, OUString aLongName, OUString aGroupName)
+ : sTitle(std::move(aTitle)), sLongName(std::move(aLongName)), sGroupName(std::move(aGroupName)) {}
+};
+
+}
+
+// Dialog for edit templates
+void SwGlossaryHdl::GlossaryDlg()
+{
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractGlossaryDlg> pDlg(pFact->CreateGlossaryDlg(m_rViewFrame, this, m_pWrtShell));
+ OUString sName;
+ OUString sShortName;
+
+ if( RET_EDIT == pDlg->Execute() )
+ {
+ sName = pDlg->GetCurrGrpName();
+ sShortName = pDlg->GetCurrShortName();
+ }
+
+ pDlg.disposeAndClear();
+ m_pCurGrp.reset();
+ if(HasGlossaryList())
+ {
+ GetGlossaryList()->ClearGroups();
+ }
+
+ if( !sName.isEmpty() || !sShortName.isEmpty() )
+ m_rStatGlossaries.EditGroupDoc( sName, sShortName );
+}
+
+// set the default group; if called from the dialog
+// the group is created temporarily for faster access
+void SwGlossaryHdl::SetCurGroup(const OUString &rGrp, bool bApi, bool bAlwaysCreateNew )
+{
+ OUString sGroup(rGrp);
+ if (sGroup.indexOf(GLOS_DELIM)<0 && !FindGroupName(sGroup))
+ {
+ sGroup += OUStringChar(GLOS_DELIM) + "0";
+ }
+ if(m_pCurGrp)
+ {
+ bool bPathEqual = false;
+ if(!bAlwaysCreateNew)
+ {
+ INetURLObject aTemp( m_pCurGrp->GetFileName() );
+ const OUString sCurBase = aTemp.getBase();
+ aTemp.removeSegment();
+ const OUString sCurEntryPath = aTemp.GetMainURL(INetURLObject::DecodeMechanism::NONE);
+ const std::vector<OUString> & rPathArr = m_rStatGlossaries.GetPathArray();
+ sal_uInt16 nCurrentPath = USHRT_MAX;
+ for (size_t nPath = 0; nPath < rPathArr.size(); ++nPath)
+ {
+ if (sCurEntryPath == rPathArr[nPath])
+ {
+ nCurrentPath = o3tl::narrowing<sal_uInt16>(nPath);
+ break;
+ }
+ }
+ const std::u16string_view sPath = o3tl::getToken(sGroup, 1, GLOS_DELIM);
+ sal_uInt16 nComparePath = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(sPath));
+ if(nCurrentPath == nComparePath &&
+ o3tl::getToken(sGroup, 0, GLOS_DELIM) == sCurBase)
+ bPathEqual = true;
+ }
+
+ // When path changed, the name is not reliable
+ if(!bAlwaysCreateNew && bPathEqual)
+ return;
+ }
+ m_aCurGrp = sGroup;
+ if(!bApi)
+ {
+ m_pCurGrp = m_rStatGlossaries.GetGroupDoc(m_aCurGrp, true);
+ }
+}
+
+size_t SwGlossaryHdl::GetGroupCnt() const
+{
+ return m_rStatGlossaries.GetGroupCnt();
+}
+
+OUString SwGlossaryHdl::GetGroupName( size_t nId, OUString* pTitle )
+{
+ OUString sRet = m_rStatGlossaries.GetGroupName(nId);
+ if(pTitle)
+ {
+ std::unique_ptr<SwTextBlocks> pGroup = m_rStatGlossaries.GetGroupDoc(sRet);
+ if (pGroup && !pGroup->GetError())
+ {
+ *pTitle = pGroup->GetName();
+ if (pTitle->isEmpty())
+ {
+ *pTitle = sRet.getToken(0, GLOS_DELIM);
+ pGroup->SetName(*pTitle);
+ }
+ }
+ else
+ {
+ sRet.clear();
+ }
+ }
+ return sRet;
+}
+
+void SwGlossaryHdl::NewGroup(OUString &rGrpName, const OUString& rTitle)
+{
+ if (rGrpName.indexOf(GLOS_DELIM)<0)
+ FindGroupName(rGrpName);
+ m_rStatGlossaries.NewGroupDoc(rGrpName, rTitle);
+}
+
+void SwGlossaryHdl::RenameGroup(const OUString& rOld, OUString& rNew, const OUString& rNewTitle)
+{
+ OUString sOldGroup(rOld);
+ if (rOld.indexOf(GLOS_DELIM)<0)
+ FindGroupName(sOldGroup);
+ if(rOld == rNew)
+ {
+ std::unique_ptr<SwTextBlocks> pGroup = m_rStatGlossaries.GetGroupDoc(sOldGroup);
+ if(pGroup)
+ {
+ pGroup->SetName(rNewTitle);
+ }
+ }
+ else
+ {
+ OUString sNewGroup(rNew);
+ if (sNewGroup.indexOf(GLOS_DELIM)<0)
+ {
+ sNewGroup += OUStringChar(GLOS_DELIM) + "0";
+ }
+ m_rStatGlossaries.RenameGroupDoc(sOldGroup, sNewGroup, rNewTitle);
+ rNew = sNewGroup;
+ }
+}
+
+bool SwGlossaryHdl::CopyOrMove(const OUString& rSourceGroupName, OUString& rSourceShortName,
+ const OUString& rDestGroupName, const OUString& rLongName, bool bMove)
+{
+ std::unique_ptr<SwTextBlocks> pSourceGroup = m_rStatGlossaries.GetGroupDoc(rSourceGroupName);
+ std::unique_ptr<SwTextBlocks> pDestGroup = m_rStatGlossaries.GetGroupDoc(rDestGroupName);
+ if (pDestGroup->IsReadOnly() || (bMove && pSourceGroup->IsReadOnly()) )
+ {
+ return false;
+ }
+
+ //The index must be determined here because rSourceShortName maybe changed in CopyBlock
+ sal_uInt16 nDeleteIdx = pSourceGroup->GetIndex( rSourceShortName );
+ OSL_ENSURE(USHRT_MAX != nDeleteIdx, "entry not found");
+ ErrCode nRet = pSourceGroup->CopyBlock( *pDestGroup, rSourceShortName, rLongName );
+ if(!nRet && bMove)
+ {
+ // the index must be existing
+ nRet = pSourceGroup->Delete( nDeleteIdx ) ? ERRCODE_NONE : ErrCode(1);
+ }
+ return !nRet;
+}
+
+// delete an autotext-file-group
+bool SwGlossaryHdl::DelGroup(const OUString &rGrpName)
+{
+ OUString sGroup(rGrpName);
+ if (sGroup.indexOf(GLOS_DELIM)<0)
+ FindGroupName(sGroup);
+ if( m_rStatGlossaries.DelGroupDoc(sGroup) )
+ {
+ if(m_pCurGrp)
+ {
+ if (m_pCurGrp->GetName() == sGroup)
+ m_pCurGrp.reset();
+ }
+ return true;
+ }
+ return false;
+}
+
+// ask for number of autotexts
+sal_uInt16 SwGlossaryHdl::GetGlossaryCnt() const
+{
+ return m_pCurGrp ? m_pCurGrp->GetCount() : 0;
+}
+
+OUString SwGlossaryHdl::GetGlossaryName( sal_uInt16 nId )
+{
+ OSL_ENSURE(nId < GetGlossaryCnt(), "Text building block array over-indexed.");
+ return m_pCurGrp->GetLongName( nId );
+}
+
+OUString SwGlossaryHdl::GetGlossaryShortName(sal_uInt16 nId)
+{
+ OSL_ENSURE(nId < GetGlossaryCnt(), "Text building block array over-indexed.");
+ return m_pCurGrp->GetShortName( nId );
+}
+
+// ask for short name
+OUString SwGlossaryHdl::GetGlossaryShortName(std::u16string_view aName)
+{
+ OUString sReturn;
+ SwTextBlocks *pTmp =
+ m_pCurGrp ? m_pCurGrp.get() : m_rStatGlossaries.GetGroupDoc( m_aCurGrp ).release();
+ if(pTmp)
+ {
+ sal_uInt16 nIdx = pTmp->GetLongIndex( aName );
+ if( nIdx != sal_uInt16(-1) )
+ sReturn = pTmp->GetShortName( nIdx );
+ if( !m_pCurGrp )
+ delete pTmp;
+ }
+ return sReturn;
+}
+
+// short name for autotext already used?
+bool SwGlossaryHdl::HasShortName(const OUString& rShortName) const
+{
+ SwTextBlocks *pBlock = m_pCurGrp ? m_pCurGrp.get()
+ : m_rStatGlossaries.GetGroupDoc( m_aCurGrp ).release();
+ bool bRet = pBlock->GetIndex( rShortName ) != sal_uInt16(-1);
+ if( !m_pCurGrp )
+ delete pBlock;
+ return bRet;
+}
+
+// Create autotext
+bool SwGlossaryHdl::NewGlossary(const OUString& rName, const OUString& rShortName,
+ bool bCreateGroup, bool bNoAttr)
+{
+ SwTextBlocks *pTmp =
+ m_pCurGrp ? m_pCurGrp.get() : m_rStatGlossaries.GetGroupDoc( m_aCurGrp, bCreateGroup ).release();
+ //pTmp == 0 if the AutoText path setting is wrong
+ if(!pTmp)
+ {
+ if (!m_pCurGrp)
+ delete pTmp;
+ return false;
+ }
+
+ OUString sOnlyText;
+ OUString* pOnlyText = nullptr;
+ if( bNoAttr )
+ {
+ m_pWrtShell->GetSelectedText( sOnlyText, ParaBreakType::ToOnlyCR );
+ pOnlyText = &sOnlyText;
+ }
+
+ const SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get();
+
+ const sal_uInt16 nSuccess = m_pWrtShell->MakeGlossary( *pTmp, rName, rShortName,
+ rCfg.IsSaveRelFile(), pOnlyText );
+ if(nSuccess == sal_uInt16(-1) )
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_pWrtShell->GetView().GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok, SwResId(STR_ERR_INSERT_GLOS)));
+ xBox->run();
+ }
+ if( !m_pCurGrp )
+ delete pTmp;
+ return nSuccess != sal_uInt16(-1);
+}
+
+// Delete an autotext
+bool SwGlossaryHdl::DelGlossary(const OUString &rShortName)
+{
+ SwTextBlocks *pGlossary = m_pCurGrp ? m_pCurGrp.get()
+ : m_rStatGlossaries.GetGroupDoc(m_aCurGrp).release();
+ //pTmp == 0 if the AutoText path setting is wrong
+ if(!pGlossary)
+ {
+ if( !m_pCurGrp )
+ delete pGlossary;
+ return false;
+ }
+
+ sal_uInt16 nIdx = pGlossary->GetIndex( rShortName );
+ if( nIdx != sal_uInt16(-1) )
+ pGlossary->Delete( nIdx );
+ if( !m_pCurGrp )
+ delete pGlossary;
+ return true;
+}
+
+// expand short name
+bool SwGlossaryHdl::ExpandGlossary(weld::Window* pParent)
+{
+ OSL_ENSURE(m_pWrtShell->CanInsert(), "illegal");
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ::GlossaryGetCurrGroup fnGetCurrGroup = pFact->GetGlossaryCurrGroupFunc();
+ OUString sGroupName( (*fnGetCurrGroup)() );
+ if (sGroupName.indexOf(GLOS_DELIM)<0)
+ FindGroupName(sGroupName);
+ std::unique_ptr<SwTextBlocks> pGlossary = m_rStatGlossaries.GetGroupDoc(sGroupName);
+
+ OUString aShortName;
+
+ // use this at text selection
+ if(m_pWrtShell->SwCursorShell::HasSelection() && !m_pWrtShell->IsBlockMode())
+ {
+ aShortName = m_pWrtShell->GetSelText();
+ }
+ else
+ {
+ if(m_pWrtShell->IsAddMode())
+ m_pWrtShell->LeaveAddMode();
+ else if(m_pWrtShell->IsBlockMode())
+ m_pWrtShell->LeaveBlockMode();
+ else if(m_pWrtShell->IsExtMode())
+ m_pWrtShell->LeaveExtMode();
+ // select word (tdf#126589: part to the left of cursor)
+ if (m_pWrtShell->IsInWord() || m_pWrtShell->IsEndWrd())
+ m_pWrtShell->PrvWrd(true);
+ // ask for word
+ if(m_pWrtShell->IsSelection())
+ aShortName = m_pWrtShell->GetSelText();
+ }
+ return pGlossary && Expand(pParent, aShortName, &m_rStatGlossaries, std::move(pGlossary));
+}
+
+bool SwGlossaryHdl::Expand(weld::Window* pParent, const OUString& rShortName,
+ SwGlossaries *pGlossaries,
+ std::unique_ptr<SwTextBlocks> pGlossary)
+{
+ std::vector<TextBlockInfo_Impl> aFoundArr;
+ OUString aShortName( rShortName );
+ bool bCancel = false;
+ // search for text block
+ // - don't prefer current group depending on configuration setting
+ const SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get();
+ sal_uInt16 nFound = !rCfg.IsSearchInAllCategories() ? pGlossary->GetIndex( aShortName ) : -1;
+ // if not found then search in all groups
+ if( nFound == sal_uInt16(-1) )
+ {
+ const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
+ SwGlossaryList* pGlossaryList = ::GetGlossaryList();
+ const size_t nGroupCount = pGlossaryList->GetGroupCount();
+ for(size_t i = 0; i < nGroupCount; ++i)
+ {
+ // get group name with path-extension
+ const OUString sGroupName = pGlossaryList->GetGroupName(i);
+ if(sGroupName == pGlossary->GetName())
+ continue;
+ const sal_uInt16 nBlockCount = pGlossaryList->GetBlockCount(i);
+ if(nBlockCount)
+ {
+ const OUString sTitle = pGlossaryList->GetGroupTitle(i);
+ for(sal_uInt16 j = 0; j < nBlockCount; j++)
+ {
+ const OUString sLongName(pGlossaryList->GetBlockLongName(i, j));
+ const OUString sShortName(pGlossaryList->GetBlockShortName(i, j));
+ if( rSCmp.isEqual( rShortName, sShortName ))
+ {
+ aFoundArr.emplace_back(sTitle, sLongName, sGroupName);
+ }
+ }
+ }
+ }
+ if( !aFoundArr.empty() ) // one was found
+ {
+ pGlossary.reset();
+ if (1 == aFoundArr.size())
+ {
+ TextBlockInfo_Impl& rData = aFoundArr.front();
+ pGlossary = pGlossaries->GetGroupDoc(rData.sGroupName);
+ nFound = pGlossary->GetIndex( aShortName );
+ }
+ else
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractSwSelGlossaryDlg> pDlg(pFact->CreateSwSelGlossaryDlg(pParent, aShortName));
+ for(const TextBlockInfo_Impl & i : aFoundArr)
+ {
+ pDlg->InsertGlos(i.sTitle, i.sLongName);
+ }
+ pDlg->SelectEntryPos(0);
+ const sal_Int32 nRet = RET_OK == pDlg->Execute() ?
+ pDlg->GetSelectedIdx() :
+ -1;
+ pDlg.disposeAndClear();
+ if (nRet != -1)
+ {
+ TextBlockInfo_Impl& rData = aFoundArr[nRet];
+ pGlossary = pGlossaries->GetGroupDoc(rData.sGroupName);
+ nFound = pGlossary->GetIndex( aShortName );
+ }
+ else
+ {
+ nFound = sal_uInt16(-1);
+ bCancel = true;
+ }
+ }
+ }
+ }
+
+ // not found
+ if( nFound == sal_uInt16(-1) )
+ {
+ if( !bCancel )
+ {
+ pGlossary.reset();
+
+ const sal_Int32 nMaxLen = 50;
+ if(m_pWrtShell->IsSelection() && aShortName.getLength() > nMaxLen)
+ {
+ aShortName = OUString::Concat(aShortName.subView(0, nMaxLen)) + " ...";
+ }
+ OUString aTmp( SwResId(STR_NOGLOS));
+ aTmp = aTmp.replaceFirst("%1", aShortName);
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_pWrtShell->GetView().GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ aTmp));
+ xInfoBox->run();
+ }
+
+ return false;
+ }
+ else
+ {
+ SvxMacro aStartMacro(OUString(), OUString(), STARBASIC);
+ SvxMacro aEndMacro(OUString(), OUString(), STARBASIC);
+ GetMacros( aShortName, aStartMacro, aEndMacro, pGlossary.get() );
+
+ // StartAction must not be before HasSelection and DelRight,
+ // otherwise the possible Shell change gets delayed and
+ // API-programs would hang.
+ // Moreover the event macro must also not be called in an action
+ m_pWrtShell->StartUndo(SwUndoId::INSGLOSSARY);
+ if( aStartMacro.HasMacro() )
+ m_pWrtShell->ExecMacro( aStartMacro );
+ if(m_pWrtShell->HasSelection())
+ m_pWrtShell->DelLeft();
+ m_pWrtShell->StartAllAction();
+
+ // cache all InputFields
+ SwInputFieldList aFieldLst( m_pWrtShell, true );
+
+ m_pWrtShell->InsertGlossary(*pGlossary, aShortName);
+ m_pWrtShell->EndAllAction();
+ if( aEndMacro.HasMacro() )
+ {
+ m_pWrtShell->ExecMacro( aEndMacro );
+ }
+ m_pWrtShell->EndUndo(SwUndoId::INSGLOSSARY);
+
+ // demand input for all new InputFields
+ if( aFieldLst.BuildSortLst() )
+ m_pWrtShell->UpdateInputFields( &aFieldLst );
+ }
+ return true;
+}
+
+// add autotext
+bool SwGlossaryHdl::InsertGlossary(const OUString &rName)
+{
+ OSL_ENSURE(m_pWrtShell->CanInsert(), "illegal");
+
+ SwTextBlocks *pGlos =
+ m_pCurGrp ? m_pCurGrp.get() : m_rStatGlossaries.GetGroupDoc(m_aCurGrp).release();
+
+ if (!pGlos)
+ {
+ if (!m_pCurGrp)
+ delete pGlos;
+ return false;
+ }
+
+ SvxMacro aStartMacro(OUString(), OUString(), STARBASIC);
+ SvxMacro aEndMacro(OUString(), OUString(), STARBASIC);
+ GetMacros( rName, aStartMacro, aEndMacro, pGlos );
+
+ // StartAction must not be before HasSelection and DelRight,
+ // otherwise the possible Shell change gets delayed and
+ // API-programs would hang.
+ // Moreover the event macro must also not be called in an action
+ if( aStartMacro.HasMacro() )
+ m_pWrtShell->ExecMacro( aStartMacro );
+ if( m_pWrtShell->HasSelection() )
+ m_pWrtShell->DelRight();
+ m_pWrtShell->StartAllAction();
+
+ // cache all InputFields
+ SwInputFieldList aFieldLst( m_pWrtShell, true );
+
+ m_pWrtShell->InsertGlossary(*pGlos, rName);
+ m_pWrtShell->EndAllAction();
+ if( aEndMacro.HasMacro() )
+ {
+ m_pWrtShell->ExecMacro( aEndMacro );
+ }
+
+ // demand input for all new InputFields
+ if( aFieldLst.BuildSortLst() )
+ m_pWrtShell->UpdateInputFields( &aFieldLst );
+
+ if(!m_pCurGrp)
+ delete pGlos;
+ return true;
+}
+
+// set / ask for macro
+void SwGlossaryHdl::SetMacros(const OUString& rShortName,
+ const SvxMacro* pStart,
+ const SvxMacro* pEnd,
+ SwTextBlocks *pGlossary )
+{
+ SwTextBlocks *pGlos = pGlossary ? pGlossary :
+ m_pCurGrp ? m_pCurGrp.get()
+ : m_rStatGlossaries.GetGroupDoc( m_aCurGrp ).release();
+ SvxMacroTableDtor aMacroTable;
+ if( pStart )
+ aMacroTable.Insert( SvMacroItemId::SwStartInsGlossary, *pStart);
+ if( pEnd )
+ aMacroTable.Insert( SvMacroItemId::SwEndInsGlossary, *pEnd);
+ sal_uInt16 nIdx = pGlos->GetIndex( rShortName );
+ if( !pGlos->SetMacroTable( nIdx, aMacroTable ) && pGlos->GetError() )
+ ErrorHandler::HandleError( pGlos->GetError() );
+
+ if(!m_pCurGrp && !pGlossary)
+ delete pGlos;
+}
+
+void SwGlossaryHdl::GetMacros( const OUString &rShortName,
+ SvxMacro& rStart,
+ SvxMacro& rEnd,
+ SwTextBlocks *pGlossary )
+{
+ SwTextBlocks *pGlos = pGlossary ? pGlossary
+ : m_pCurGrp ? m_pCurGrp.get()
+ : m_rStatGlossaries.GetGroupDoc(m_aCurGrp).release();
+ sal_uInt16 nIndex = pGlos->GetIndex( rShortName );
+ if( nIndex != USHRT_MAX )
+ {
+ SvxMacroTableDtor aMacroTable;
+ if( pGlos->GetMacroTable( nIndex, aMacroTable ) )
+ {
+ SvxMacro *pMacro = aMacroTable.Get( SvMacroItemId::SwStartInsGlossary );
+ if( pMacro )
+ rStart = *pMacro;
+
+ pMacro = aMacroTable.Get( SvMacroItemId::SwEndInsGlossary );
+ if( pMacro )
+ rEnd = *pMacro;
+ }
+ }
+
+ if( !m_pCurGrp && !pGlossary )
+ delete pGlos;
+}
+
+// ctor, dtor
+SwGlossaryHdl::SwGlossaryHdl(SfxViewFrame& rVwFrame, SwWrtShell *pSh)
+ : m_rStatGlossaries( *::GetGlossaries() ),
+ m_aCurGrp( SwGlossaries::GetDefName() ),
+ m_rViewFrame(rVwFrame),
+ m_pWrtShell( pSh )
+{
+}
+
+SwGlossaryHdl::~SwGlossaryHdl()
+{
+}
+
+// rename an autotext
+bool SwGlossaryHdl::Rename(const OUString& rOldShort, const OUString& rNewShortName,
+ const OUString& rNewName )
+{
+ bool bRet = false;
+ SwTextBlocks *pGlossary = m_pCurGrp ? m_pCurGrp.get()
+ : m_rStatGlossaries.GetGroupDoc(m_aCurGrp).release();
+ if(pGlossary)
+ {
+ sal_uInt16 nIdx = pGlossary->GetIndex( rOldShort );
+ sal_uInt16 nOldLongIdx = pGlossary->GetLongIndex( rNewName );
+ sal_uInt16 nOldIdx = pGlossary->GetIndex( rNewShortName );
+
+ if( nIdx != USHRT_MAX &&
+ (nOldLongIdx == USHRT_MAX || nOldLongIdx == nIdx )&&
+ (nOldIdx == USHRT_MAX || nOldIdx == nIdx ))
+ {
+ pGlossary->Rename( nIdx, &rNewShortName, &rNewName );
+ bRet = pGlossary->GetError() == ERRCODE_NONE;
+ }
+ if( !m_pCurGrp )
+ delete pGlossary;
+ }
+ return bRet;
+}
+
+bool SwGlossaryHdl::IsReadOnly( const OUString* pGrpNm ) const
+{
+ SwTextBlocks *pGlossary = nullptr;
+
+ if (pGrpNm)
+ pGlossary = m_rStatGlossaries.GetGroupDoc( *pGrpNm ).release();
+ else if (m_pCurGrp)
+ pGlossary = m_pCurGrp.get();
+ else
+ pGlossary = m_rStatGlossaries.GetGroupDoc(m_aCurGrp).release();
+
+ const bool bRet = !pGlossary || pGlossary->IsReadOnly();
+ if( pGrpNm || !m_pCurGrp )
+ delete pGlossary;
+ return bRet;
+}
+
+bool SwGlossaryHdl::IsOld() const
+{
+ if( !m_pCurGrp )
+ m_rStatGlossaries.GetGroupDoc(m_aCurGrp).reset();
+ return false;
+}
+
+// find group without path index
+bool SwGlossaryHdl::FindGroupName(OUString& rGroup)
+{
+ return m_rStatGlossaries.FindGroupName(rGroup);
+}
+
+bool SwGlossaryHdl::CopyToClipboard(SwWrtShell& rSh, const OUString& rShortName)
+{
+ SwTextBlocks *pGlossary = m_pCurGrp ? m_pCurGrp.get()
+ : m_rStatGlossaries.GetGroupDoc(m_aCurGrp).release();
+
+ rtl::Reference<SwTransferable> pTransfer = new SwTransferable( rSh );
+
+ bool bRet = pTransfer->CopyGlossary( *pGlossary, rShortName );
+ if( !m_pCurGrp )
+ delete pGlossary;
+ return bRet;
+}
+
+bool SwGlossaryHdl::ImportGlossaries( const OUString& rName )
+{
+ bool bRet = false;
+ if( !rName.isEmpty() )
+ {
+ std::shared_ptr<const SfxFilter> pFilter;
+ SfxMedium aMed( rName, StreamMode::READ, nullptr, nullptr );
+ SfxFilterMatcher aMatcher( "swriter" );
+ aMed.UseInteractionHandler( true );
+ if (aMatcher.GuessFilter(aMed, pFilter, SfxFilterFlags::NONE) == ERRCODE_NONE)
+ {
+ assert(pFilter && "success means pFilter was set");
+ SwTextBlocks *pGlossary = nullptr;
+ aMed.SetFilter( pFilter );
+ Reader* pR = SwReaderWriter::GetReader( pFilter->GetUserData() );
+ if( pR && nullptr != ( pGlossary = m_pCurGrp ? m_pCurGrp.get()
+ : m_rStatGlossaries.GetGroupDoc(m_aCurGrp).release()) )
+ {
+ SwReader aReader( aMed, rName );
+ if( aReader.HasGlossaries( *pR ) )
+ {
+ const SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get();
+ bRet = aReader.ReadGlossaries( *pR, *pGlossary,
+ rCfg.IsSaveRelFile() );
+ }
+
+ if (!m_pCurGrp)
+ delete pGlossary;
+ }
+ }
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx b/sw/source/uibase/dochdl/swdtflvr.cxx
new file mode 100644
index 0000000000..cb96c08527
--- /dev/null
+++ b/sw/source/uibase/dochdl/swdtflvr.cxx
@@ -0,0 +1,4597 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/embed/XEmbedObjectClipboardCreator.hpp>
+#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
+#include <com/sun/star/embed/MSOLEObjectSystemCreator.hpp>
+#include <com/sun/star/text/XPasteListener.hpp>
+
+#include <svtools/embedtransfer.hxx>
+#include <svtools/insdlg.hxx>
+#include <unotools/tempfile.hxx>
+#include <comphelper/fileformat.h>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <comphelper/string.hxx>
+#include <o3tl/deleter.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <sot/filelist.hxx>
+#include <svx/svxdlg.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <osl/endian.h>
+#include <sfx2/linkmgr.hxx>
+#include <tools/urlobj.hxx>
+#include <vcl/weld.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/stritem.hxx>
+#include <vcl/imap.hxx>
+#include <sot/storage.hxx>
+#include <vcl/graph.hxx>
+#include <svl/urihelper.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/xmlexchg.hxx>
+#include <svx/dbaexchange.hxx>
+#include <svx/clipfmtitem.hxx>
+#include <sfx2/mieclip.hxx>
+#include <svl/urlbmk.hxx>
+#include <vcl/inetimg.hxx>
+#include <svx/fmview.hxx>
+#include <sfx2/docfilt.hxx>
+#include <vcl/imapobj.hxx>
+#include <sfx2/docfile.hxx>
+#include <unotools/transliterationwrapper.hxx>
+#include <unotools/streamwrap.hxx>
+#include <vcl/graphicfilter.hxx>
+
+#ifdef _WIN32
+#include <prewin.h>
+#include <postwin.h>
+#include <o3tl/char16_t2wchar_t.hxx>
+#include <osl/file.hxx>
+#endif
+
+#include <svx/unomodel.hxx>
+#include <fmturl.hxx>
+#include <fmtinfmt.hxx>
+#include <swdtflvr.hxx>
+#include <shellio.hxx>
+#include <ddefld.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentFieldsAccess.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <IDocumentState.hxx>
+#include <IMark.hxx>
+#include <section.hxx>
+#include <ndtxt.hxx>
+#include <edtdd.hxx>
+#include <edtwin.hxx>
+#include <navicont.hxx>
+#include <swcont.hxx>
+#include <wrtsh.hxx>
+#include <swmodule.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <wdocsh.hxx>
+#include <fldbas.hxx>
+#include <swundo.hxx>
+#include <pam.hxx>
+#include <ndole.hxx>
+#include <swwait.hxx>
+#include <viewopt.hxx>
+#include <SwCapObjType.hxx>
+#include <cmdid.h>
+#include <strings.hrc>
+#include <svx/svditer.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/prntitem.hxx>
+#include <svx/svdpage.hxx>
+#include <avmedia/mediawindow.hxx>
+#include <swcrsr.hxx>
+#include <SwRewriter.hxx>
+#include <vcl/svapp.hxx>
+#include <swserv.hxx>
+#include <fmtmeta.hxx>
+#include <itabenum.hxx>
+#include <iodetect.hxx>
+#include <unotextrange.hxx>
+#include <unoframe.hxx>
+#include <txatbase.hxx>
+#include <vcl/uitest/logger.hxx>
+#include <vcl/uitest/eventdescription.hxx>
+
+#include <vcl/GraphicNativeTransform.hxx>
+#include <vcl/GraphicNativeMetadata.hxx>
+#include <vcl/TypeSerializer.hxx>
+#include <comphelper/lok.hxx>
+#include <sfx2/classificationhelper.hxx>
+#include <sfx2/sfxdlg.hxx>
+#include <comphelper/classids.hxx>
+#include <osl/diagnose.h>
+
+#include <memory>
+
+/* default (A4 format) width of 210mm - 2 * border size (border on both sides) */
+constexpr tools::Long constOleWidthInMm = 210 - 2 * lMinBorderInMm;
+
+constexpr Size constOleSize100mm(
+ constOleWidthInMm * 100, // convert from mm to 100mm
+ 3000 // 3 cm
+);
+
+constexpr Size constOleSizeTwip = o3tl::convert(constOleSize100mm, o3tl::Length::mm100, o3tl::Length::twip);
+
+constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_DRAWMODEL = 0x00000001;
+constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_HTML = 0x00000002;
+constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_RTF = 0x00000004;
+constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_STRING = 0x00000008;
+constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_SWOLE = 0x00000010;
+constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_DDE = 0x00000020;
+constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_RICHTEXT = 0x00000040;
+
+using namespace ::svx;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::datatransfer;
+namespace {
+
+void collectUIInformation(const OUString& rAction, const OUString& aParameters)
+{
+ EventDescription aDescription;
+ aDescription.aAction = rAction;
+ aDescription.aParameters = {{"parameters", aParameters}};
+ aDescription.aID = "writer_edit";
+ aDescription.aKeyWord = "SwEditWinUIObject";
+ aDescription.aParent = "MainWindow";
+ UITestLogger::getInstance().logEvent(aDescription);
+}
+
+}
+
+class SwTransferDdeLink : public ::sfx2::SvBaseLink
+{
+ OUString m_sName;
+ ::sfx2::SvLinkSourceRef m_xRefObj;
+ SwTransferable& m_rTransfer;
+ SwDocShell* m_pDocShell;
+ sal_uLong m_nOldTimeOut;
+ bool m_bDelBookmark : 1;
+ bool m_bInDisconnect : 1;
+
+ bool FindDocShell();
+
+ using sfx2::SvBaseLink::Disconnect;
+
+protected:
+ virtual ~SwTransferDdeLink() override;
+
+public:
+ SwTransferDdeLink( SwTransferable& rTrans, SwWrtShell& rSh );
+
+ virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
+ const OUString& rMimeType, const css::uno::Any & rValue ) override;
+ virtual void Closed() override;
+
+ bool WriteData( SvStream& rStrm );
+
+ void Disconnect( bool bRemoveDataAdvise );
+};
+
+/// Tracks the boundaries of pasted content and notifies listeners.
+class SwPasteContext
+{
+public:
+ SwPasteContext(SwWrtShell& rWrtShell);
+ ~SwPasteContext();
+
+ void remember();
+ void forget();
+
+private:
+ SwWrtShell& m_rWrtShell;
+ std::optional<SwPaM> m_oPaM;
+ sal_Int32 m_nStartContent = 0;
+};
+
+namespace {
+
+// helper class for Action and Undo enclosing
+class SwTrnsfrActionAndUndo
+{
+ SwWrtShell *pSh;
+public:
+ SwTrnsfrActionAndUndo( SwWrtShell *pS, bool bDelSel = false, SwPasteContext* pContext = nullptr)
+ : pSh( pS )
+ {
+ pSh->StartUndo( SwUndoId::PASTE_CLIPBOARD );
+ if( bDelSel )
+ {
+ if (pContext)
+ pContext->forget();
+ pSh->DelRight();
+ if (pContext)
+ pContext->remember();
+ }
+ pSh->StartAllAction();
+ }
+ ~SwTrnsfrActionAndUndo() COVERITY_NOEXCEPT_FALSE
+ {
+ pSh->EndUndo();
+ pSh->EndAllAction();
+ }
+};
+
+}
+
+SwTransferable::SwTransferable( SwWrtShell& rSh )
+ : m_pWrtShell( &rSh ),
+ m_pCreatorView( nullptr ),
+ m_pOrigGraphic( nullptr ),
+ m_eBufferType( TransferBufferType::NONE ),
+ m_bOldIdle(false),
+ m_bCleanUp(false)
+{
+ rSh.GetView().AddTransferable(*this);
+ SwDocShell* pDShell = rSh.GetDoc()->GetDocShell();
+ if( !pDShell )
+ return;
+
+ pDShell->FillTransferableObjectDescriptor( m_aObjDesc );
+ if( pDShell->GetMedium() )
+ {
+ const INetURLObject& rURLObj = pDShell->GetMedium()->GetURLObject();
+ m_aObjDesc.maDisplayName = URIHelper::removePassword(
+ rURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
+ INetURLObject::EncodeMechanism::WasEncoded,
+ INetURLObject::DecodeMechanism::Unambiguous );
+ }
+
+ PrepareOLE( m_aObjDesc );
+}
+
+SwTransferable::~SwTransferable()
+{
+ SolarMutexGuard aSolarGuard;
+
+ // the DDELink still needs the WrtShell!
+ DisconnectDDE();
+
+ m_pWrtShell = nullptr;
+
+ // release reference to the document so that aDocShellRef will delete
+ // it (if aDocShellRef is set). Otherwise, the OLE nodes keep references
+ // to their sub-storage when the storage is already dead.
+ m_pClpDocFac.reset();
+
+ // first close, then the Ref. can be cleared as well, so that
+ // the DocShell really gets deleted!
+ if( m_aDocShellRef.Is() )
+ {
+ SfxObjectShell * pObj = m_aDocShellRef;
+ SwDocShell* pDocSh = static_cast<SwDocShell*>(pObj);
+ pDocSh->DoClose();
+ }
+ m_aDocShellRef.Clear();
+
+ SwModule* pMod = SW_MOD();
+ if(pMod)
+ {
+ if ( pMod->m_pDragDrop == this )
+ pMod->m_pDragDrop = nullptr;
+ else if ( pMod->m_pXSelection == this )
+ pMod->m_pXSelection = nullptr;
+ }
+
+ m_eBufferType = TransferBufferType::NONE;
+}
+
+static SwDoc& lcl_GetDoc(SwDocFac & rDocFac)
+{
+ SwDoc& rDoc = rDocFac.GetDoc();
+ rDoc.SetClipBoard( true );
+ return rDoc;
+}
+
+void SwTransferable::ObjectReleased()
+{
+ SwModule *pMod = SW_MOD();
+ if (!pMod)
+ return;
+ if( this == pMod->m_pDragDrop )
+ pMod->m_pDragDrop = nullptr;
+ else if( this == pMod->m_pXSelection )
+ pMod->m_pXSelection = nullptr;
+}
+
+void SwTransferable::AddSupportedFormats()
+{
+ // only need if we are the current XSelection Object
+ SwModule *pMod = SW_MOD();
+ if( this == pMod->m_pXSelection || comphelper::LibreOfficeKit::isActive())
+ {
+ SetDataForDragAndDrop( Point( 0,0) );
+ }
+}
+
+void SwTransferable::InitOle( SfxObjectShell* pDoc )
+{
+ //set OleVisArea. Upper left corner of the page and size of
+ //RealSize in Twips.
+ const Size aSz(constOleSizeTwip);
+ SwRect aVis( Point( DOCUMENTBORDER, DOCUMENTBORDER ), aSz );
+ pDoc->SetVisArea( aVis.SVRect() );
+}
+
+uno::Reference < embed::XEmbeddedObject > SwTransferable::FindOLEObj( sal_Int64& nAspect ) const
+{
+ uno::Reference < embed::XEmbeddedObject > xObj;
+ if( m_pClpDocFac )
+ {
+ SwIterator<SwContentNode,SwFormatColl> aIter( *m_pClpDocFac->GetDoc().GetDfltGrfFormatColl() );
+ for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() )
+ if( SwNodeType::Ole == pNd->GetNodeType() )
+ {
+ xObj = static_cast<SwOLENode*>(pNd)->GetOLEObj().GetOleRef();
+ nAspect = static_cast<SwOLENode*>(pNd)->GetAspect();
+ break;
+ }
+ }
+ return xObj;
+}
+
+const Graphic* SwTransferable::FindOLEReplacementGraphic() const
+{
+ if( m_pClpDocFac )
+ {
+ SwIterator<SwContentNode,SwFormatColl> aIter( *m_pClpDocFac->GetDoc().GetDfltGrfFormatColl() );
+ for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() )
+ if( SwNodeType::Ole == pNd->GetNodeType() )
+ {
+ return static_cast<SwOLENode*>(pNd)->GetGraphic();
+ }
+ }
+
+ return nullptr;
+}
+
+void SwTransferable::RemoveDDELinkFormat(vcl::Window& rWin)
+{
+ RemoveFormat( SotClipboardFormatId::LINK );
+ CopyToClipboard(&rWin);
+}
+
+void SwTransferable::DisconnectDDE()
+{
+ if( m_xDdeLink.is() )
+ {
+ m_xDdeLink->Disconnect( true );
+ m_xDdeLink.clear();
+ }
+}
+
+namespace
+{
+ //Resolves: fdo#40717 surely when we create a clipboard document we should
+ //overwrite the clipboard documents styles and settings with that of the
+ //source, so that we can WYSIWYG paste. If we want that the destinations
+ //styles are used over the source styles, that's a matter of the
+ //destination paste code to handle, not the source paste code.
+ void lclOverWriteDoc(SwWrtShell &rSrcWrtShell, SwDoc &rDest)
+ {
+ const SwDoc &rSrc = *rSrcWrtShell.GetDoc();
+
+ rDest.ReplaceCompatibilityOptions(rSrc);
+ rDest.ReplaceDefaults(rSrc);
+
+ //It would probably make most sense here to only insert the styles used
+ //by the selection, e.g. apply SwDoc::IsUsed on styles ?
+ rDest.ReplaceStyles(rSrc, false);
+
+ rSrcWrtShell.Copy(rDest);
+
+ rDest.GetMetaFieldManager().copyDocumentProperties(rSrc);
+ }
+
+ void lclCheckAndPerformRotation(Graphic& aGraphic)
+ {
+ GraphicNativeMetadata aMetadata;
+ if ( !aMetadata.read(aGraphic) )
+ return;
+
+ Degree10 aRotation = aMetadata.getRotation();
+ if (aRotation)
+ {
+ GraphicNativeTransform aTransform( aGraphic );
+ aTransform.rotate( aRotation );
+ }
+ }
+}
+
+sal_Bool SAL_CALL SwTransferable::isComplex()
+{
+ sal_Int32 nTextLength = 0;
+ SwNodes& aNodes = m_pWrtShell->GetDoc()->GetNodes();
+ for (SwPaM& rPaM : m_pWrtShell->GetCursor()->GetRingContainer())
+ {
+ for (SwNodeOffset nIndex = rPaM.GetMark()->GetNodeIndex();
+ nIndex <= rPaM.GetPoint()->GetNodeIndex(); ++nIndex)
+ {
+ SwNode& rNd = *aNodes[nIndex];
+
+ SwTextNode* pTextNode = rNd.GetTextNode();
+ if (pTextNode)
+ {
+ if (pTextNode->HasHints())
+ {
+ for (size_t nHint = 0; nHint < pTextNode->GetSwpHints().Count(); ++nHint)
+ {
+ SwTextAttr* pHint = pTextNode->GetSwpHints().Get(nHint);
+ if (pHint->Which() == RES_TXTATR_FLYCNT)
+ {
+ return true; // Complex
+ }
+ }
+ }
+
+ nTextLength += pTextNode->GetText().getLength();
+ if (nTextLength >= 1024 * 512)
+ return true; // Complex
+ }
+ }
+ }
+
+ if (m_pWrtShell->GetSelectionType() == SelectionType::DrawObject)
+ return true; // Complex
+
+ // Simple
+ return false;
+}
+
+bool SwTransferable::GetData( const DataFlavor& rFlavor, const OUString& rDestDoc )
+{
+ SotClipboardFormatId nFormat = SotExchange::GetFormat( rFlavor );
+
+ // we can only fulfil the request if
+ // 1) we have data for this format
+ // 2) we have either a clipboard document (pClpDocFac), or
+ // we have a SwWrtShell (so we can generate a new clipboard document)
+ if( !HasFormat( nFormat ) || ( m_pClpDocFac == nullptr && m_pWrtShell == nullptr ) )
+ return false;
+
+ if( !m_pClpDocFac )
+ {
+ SelectionType nSelectionType = m_pWrtShell->GetSelectionType();
+
+ // when pending we will not get the correct type, but SelectionType::Text
+ // as fallback. This *happens* during D&D, so we need to check if we are in
+ // the fallback and just try to get a graphic
+ const bool bPending(m_pWrtShell->ActionPend());
+
+ // SEL_GRF is from ContentType of editsh
+ if(bPending || ((SelectionType::Graphic | SelectionType::DrawObject | SelectionType::DbForm) & nSelectionType))
+ {
+ m_oClpGraphic.emplace();
+ if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_oClpGraphic ))
+ m_pOrigGraphic = &*m_oClpGraphic;
+ m_oClpBitmap.emplace();
+ if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_oClpBitmap ))
+ m_pOrigGraphic = &*m_oClpBitmap;
+
+ // is it a URL-Button ?
+ OUString sURL;
+ OUString sDesc;
+ if( m_pWrtShell->GetURLFromButton( sURL, sDesc ) )
+ {
+ m_oBookmark.emplace( sURL, sDesc );
+ m_eBufferType = TransferBufferType::InetField;
+ }
+ }
+
+ m_pClpDocFac.reset(new SwDocFac);
+ SwDoc& rTmpDoc = lcl_GetDoc(*m_pClpDocFac);
+
+ rTmpDoc.getIDocumentFieldsAccess().LockExpFields(); // never update fields - leave text as it is
+ lclOverWriteDoc(*m_pWrtShell, rTmpDoc);
+
+ // in CORE a new one was created (OLE-objects copied!)
+ m_aDocShellRef = rTmpDoc.GetTmpDocShell();
+ if( m_aDocShellRef.Is() )
+ SwTransferable::InitOle( m_aDocShellRef );
+ rTmpDoc.SetTmpDocShell( nullptr );
+
+ if( nSelectionType & SelectionType::Text && !m_pWrtShell->HasMark() )
+ {
+ SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );
+
+ Point aPos( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY());
+
+ bool bSelect = g_bExecuteDrag &&
+ m_pWrtShell->GetView().GetDocShell() &&
+ !m_pWrtShell->GetView().GetDocShell()->IsReadOnly();
+ if( m_pWrtShell->GetContentAtPos( aPos, aContentAtPos, bSelect ) )
+ {
+ m_oBookmark.emplace(
+ static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr)->GetValue(),
+ aContentAtPos.sStr );
+ m_eBufferType = TransferBufferType::InetField;
+ if( bSelect )
+ m_pWrtShell->SelectTextAttr( RES_TXTATR_INETFMT );
+ }
+ }
+ if( m_pWrtShell->IsFrameSelected() )
+ {
+ SfxItemSetFixed<RES_URL, RES_URL> aSet( m_pWrtShell->GetAttrPool() );
+ m_pWrtShell->GetFlyFrameAttr( aSet );
+ const SwFormatURL& rURL = aSet.Get( RES_URL );
+ if( rURL.GetMap() )
+ m_pImageMap.reset(new ImageMap( *rURL.GetMap() ));
+ else if( !rURL.GetURL().isEmpty() )
+ m_pTargetURL.reset(new INetImage(OUString(), rURL.GetURL(),
+ rURL.GetTargetFrameName() ));
+ }
+ }
+
+ bool bOK = false;
+ if( TransferBufferType::Ole == m_eBufferType )
+ {
+ //TODO/MBA: testing - is this the "single OLE object" case?!
+ // get OLE-Object from ClipDoc and get the data from that.
+ sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT; // will be set in the next statement
+ uno::Reference < embed::XEmbeddedObject > xObj = FindOLEObj( nAspect );
+ const Graphic* pOLEGraph = FindOLEReplacementGraphic();
+ if( xObj.is() )
+ {
+ TransferableDataHelper aD( new SvEmbedTransferHelper( xObj, pOLEGraph, nAspect ) );
+ uno::Any aAny = aD.GetAny(rFlavor, rDestDoc);
+ if( aAny.hasValue() )
+ bOK = SetAny( aAny );
+ }
+
+ // the following solution will be used in the case when the object can not generate the image
+ // TODO/LATER: in future the transferhelper must probably be created based on object and the replacement stream
+ // TODO: Block not required now, SvEmbedTransferHelper should be able to handle GDIMetaFile format
+ if ( nFormat == SotClipboardFormatId::GDIMETAFILE )
+ {
+ pOLEGraph = FindOLEReplacementGraphic();
+ if ( pOLEGraph )
+ bOK = SetGDIMetaFile( pOLEGraph->GetGDIMetaFile() );
+ }
+ }
+ else
+ {
+ switch( nFormat )
+ {
+ case SotClipboardFormatId::LINK:
+ if( m_xDdeLink.is() )
+ bOK = SetObject( m_xDdeLink.get(), SWTRANSFER_OBJECTTYPE_DDE, rFlavor );
+ break;
+
+ case SotClipboardFormatId::OBJECTDESCRIPTOR:
+ case SotClipboardFormatId::LINKSRCDESCRIPTOR:
+ bOK = SetTransferableObjectDescriptor( m_aObjDesc );
+ break;
+
+ case SotClipboardFormatId::DRAWING:
+ {
+ SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
+ bOK = SetObject( rDoc.getIDocumentDrawModelAccess().GetDrawModel(),
+ SWTRANSFER_OBJECTTYPE_DRAWMODEL, rFlavor );
+ }
+ break;
+
+ case SotClipboardFormatId::STRING:
+ {
+ SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
+ bOK = SetObject( &rDoc, SWTRANSFER_OBJECTTYPE_STRING, rFlavor );
+ }
+ break;
+ case SotClipboardFormatId::RTF:
+ {
+ SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
+ bOK = SetObject( &rDoc, SWTRANSFER_OBJECTTYPE_RTF, rFlavor );
+ }
+ break;
+ case SotClipboardFormatId::RICHTEXT:
+ {
+ SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
+ bOK = SetObject( &rDoc, SWTRANSFER_OBJECTTYPE_RICHTEXT, rFlavor );
+ }
+ break;
+
+ case SotClipboardFormatId::HTML:
+ {
+ SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
+ bOK = SetObject( &rDoc, SWTRANSFER_OBJECTTYPE_HTML, rFlavor );
+ }
+ break;
+
+ case SotClipboardFormatId::SVXB:
+ if( m_eBufferType & TransferBufferType::Graphic && m_pOrigGraphic )
+ bOK = SetGraphic( *m_pOrigGraphic );
+ break;
+
+ case SotClipboardFormatId::GDIMETAFILE:
+ if( m_eBufferType & TransferBufferType::Graphic )
+ bOK = SetGDIMetaFile( m_oClpGraphic->GetGDIMetaFile() );
+ break;
+ case SotClipboardFormatId::BITMAP:
+ case SotClipboardFormatId::PNG:
+ // Neither pClpBitmap nor pClpGraphic are necessarily set
+ if( (m_eBufferType & TransferBufferType::Graphic) && (m_oClpBitmap || m_oClpGraphic))
+ bOK = SetBitmapEx( (m_oClpBitmap ? m_oClpBitmap : m_oClpGraphic)->GetBitmapEx(), rFlavor );
+ break;
+
+ case SotClipboardFormatId::SVIM:
+ if( m_pImageMap )
+ bOK = SetImageMap( *m_pImageMap );
+ break;
+
+ case SotClipboardFormatId::INET_IMAGE:
+ if( m_pTargetURL )
+ bOK = SetINetImage( *m_pTargetURL, rFlavor );
+ break;
+
+ case SotClipboardFormatId::SOLK:
+ case SotClipboardFormatId::NETSCAPE_BOOKMARK:
+ case SotClipboardFormatId::FILEGRPDESCRIPTOR:
+ case SotClipboardFormatId::FILECONTENT:
+ case SotClipboardFormatId::UNIFORMRESOURCELOCATOR:
+ case SotClipboardFormatId::SIMPLE_FILE:
+ if( (TransferBufferType::InetField & m_eBufferType) && m_oBookmark )
+ bOK = SetINetBookmark( *m_oBookmark, rFlavor );
+ break;
+
+ case SotClipboardFormatId::EMBED_SOURCE:
+ if( !m_aDocShellRef.Is() )
+ {
+ SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
+ SwDocShell* pNewDocSh = new SwDocShell( rDoc,
+ SfxObjectCreateMode::EMBEDDED );
+ m_aDocShellRef = pNewDocSh;
+ m_aDocShellRef->DoInitNew();
+ SwTransferable::InitOle( m_aDocShellRef );
+ }
+ bOK = SetObject( &m_aDocShellRef, SWTRANSFER_OBJECTTYPE_SWOLE,
+ rFlavor );
+ break;
+ default: break;
+ }
+ }
+ return bOK;
+}
+
+bool SwTransferable::WriteObject( tools::SvRef<SotTempStream>& xStream,
+ void* pObject, sal_uInt32 nObjectType,
+ const DataFlavor& /*rFlavor*/ )
+{
+ bool bRet = false;
+ WriterRef xWrt;
+
+ switch( nObjectType )
+ {
+ case SWTRANSFER_OBJECTTYPE_DRAWMODEL:
+ {
+ // don't change the sequence of commands
+ SdrModel *pModel = static_cast<SdrModel*>(pObject);
+ xStream->SetBufferSize( 16348 );
+
+ // for the changed pool defaults from drawing layer pool set those
+ // attributes as hard attributes to preserve them for saving
+ const SfxItemPool& rItemPool = pModel->GetItemPool();
+ const SvxFontHeightItem& rDefaultFontHeight = rItemPool.GetDefaultItem(EE_CHAR_FONTHEIGHT);
+
+ // SW should have no MasterPages
+ OSL_ENSURE(0 == pModel->GetMasterPageCount(), "SW with MasterPages (!)");
+
+ for(sal_uInt16 a(0); a < pModel->GetPageCount(); a++)
+ {
+ const SdrPage* pPage = pModel->GetPage(a);
+ SdrObjListIter aIter(pPage, SdrIterMode::DeepNoGroups);
+
+ while(aIter.IsMore())
+ {
+ SdrObject* pObj = aIter.Next();
+ const SvxFontHeightItem& rItem = pObj->GetMergedItem(EE_CHAR_FONTHEIGHT);
+
+ if(rItem.GetHeight() == rDefaultFontHeight.GetHeight())
+ {
+ pObj->SetMergedItem(rDefaultFontHeight);
+ }
+ }
+ }
+
+ {
+ uno::Reference<io::XOutputStream> xDocOut( new utl::OOutputStreamWrapper( *xStream ) );
+ SvxDrawingLayerExport( pModel, xDocOut );
+ }
+
+ bRet = ERRCODE_NONE == xStream->GetError();
+ }
+ break;
+
+ case SWTRANSFER_OBJECTTYPE_SWOLE:
+ {
+ SfxObjectShell* pEmbObj = static_cast<SfxObjectShell*>(pObject);
+ try
+ {
+ ::utl::TempFileFast aTempFile;
+ SvStream* pTempStream = aTempFile.GetStream(StreamMode::READWRITE);
+ uno::Reference< embed::XStorage > xWorkStore =
+ ::comphelper::OStorageHelper::GetStorageFromStream( new utl::OStreamWrapper(*pTempStream), embed::ElementModes::READWRITE );
+
+ // write document storage
+ pEmbObj->SetupStorage( xWorkStore, SOFFICE_FILEFORMAT_CURRENT, false );
+ // mba: no BaseURL for clipboard
+ SfxMedium aMedium( xWorkStore, OUString() );
+ pEmbObj->DoSaveObjectAs( aMedium, false );
+ pEmbObj->DoSaveCompleted();
+
+ uno::Reference< embed::XTransactedObject > xTransact( xWorkStore, uno::UNO_QUERY );
+ if ( xTransact.is() )
+ xTransact->commit();
+
+ xStream->SetBufferSize( 0xff00 );
+ xStream->WriteStream( *pTempStream );
+
+ xWorkStore->dispose();
+ xWorkStore.clear();
+ }
+ catch (const uno::Exception&)
+ {
+ }
+
+ bRet = ( xStream->GetError() == ERRCODE_NONE );
+ }
+ break;
+
+ case SWTRANSFER_OBJECTTYPE_DDE:
+ {
+ xStream->SetBufferSize( 1024 );
+ SwTransferDdeLink* pDdeLnk = static_cast<SwTransferDdeLink*>(pObject);
+ if( pDdeLnk->WriteData( *xStream ) )
+ {
+ bRet = ERRCODE_NONE == xStream->GetError();
+ }
+ }
+ break;
+
+ case SWTRANSFER_OBJECTTYPE_HTML:
+ {
+ // LOK is interested in getting images embedded for copy/paste support.
+ GetHTMLWriter( comphelper::LibreOfficeKit::isActive() ? OUString("EmbedImages;NoPrettyPrint") : OUString(), OUString(), xWrt );
+ break;
+ }
+
+ case SWTRANSFER_OBJECTTYPE_RTF:
+ case SWTRANSFER_OBJECTTYPE_RICHTEXT:
+ GetRTFWriter(std::u16string_view(), OUString(), xWrt);
+ break;
+
+ case SWTRANSFER_OBJECTTYPE_STRING:
+ GetASCWriter(std::u16string_view(), OUString(), xWrt);
+ if( xWrt.is() )
+ {
+ SwAsciiOptions aAOpt;
+ aAOpt.SetCharSet( RTL_TEXTENCODING_UTF8 );
+ xWrt->SetAsciiOptions( aAOpt );
+
+ // no start char for clipboard
+ xWrt->m_bUCS2_WithStartChar = false;
+ }
+ break;
+ default: break;
+ }
+
+ if( xWrt.is() )
+ {
+ SwDoc* pDoc = static_cast<SwDoc*>(pObject);
+ xWrt->m_bWriteClipboardDoc = true;
+ xWrt->m_bWriteOnlyFirstTable = bool(TransferBufferType::Table & m_eBufferType);
+ xWrt->SetShowProgress(false);
+
+#if defined(DEBUGPASTE)
+ SvFileStream aPasteDebug(OUString(
+ "PASTEBUFFER.debug"), StreamMode::WRITE|StreamMode::TRUNC);
+ SwWriter aDbgWrt( aPasteDebug, *pDoc );
+ aDbgWrt.Write( xWrt );
+#endif
+
+ SwWriter aWrt( *xStream, *pDoc );
+ if( ! aWrt.Write( xWrt ).IsError() )
+ {
+ xStream->WriteChar( '\0' ); // terminate with a zero
+ bRet = true;
+ }
+ }
+
+ return bRet;
+}
+
+int SwTransferable::Cut()
+{
+ int nRet = Copy( true );
+ if( nRet )
+ DeleteSelection();
+ collectUIInformation("CUT", "parameter");
+ return nRet;
+}
+
+void SwTransferable::DeleteSelection()
+{
+ if(!m_pWrtShell)
+ return;
+ // ask for type of selection before action-bracketing
+ const SelectionType nSelection = m_pWrtShell->GetSelectionType();
+ // cut rows or columns selected by enhanced table selection and wholly selected tables
+ bool bCutMode = ( SelectionType::TableCell & nSelection ) && ( (SelectionType::TableRow | SelectionType::TableCol) & nSelection ||
+ m_pWrtShell->HasWholeTabSelection() );
+
+ m_pWrtShell->StartUndo( SwUndoId::START );
+ if( bCutMode )
+ {
+ if( !(SelectionType::TableCol & nSelection) )
+ m_pWrtShell->DeleteTable();
+ else
+ {
+ SfxDispatcher* pDispatch = m_pWrtShell->GetView().GetViewFrame().GetDispatcher();
+ pDispatch->Execute(FN_TABLE_DELETE_COL, SfxCallMode::SYNCHRON);
+ }
+ }
+ else
+ {
+ if( ( SelectionType::Text | SelectionType::Table ) & nSelection )
+ m_pWrtShell->IntelligentCut( nSelection );
+ m_pWrtShell->DelRight();
+ }
+ m_pWrtShell->EndUndo( SwUndoId::END );
+}
+
+static void DeleteDDEMarks(SwDoc & rDest)
+{
+ IDocumentMarkAccess *const pMarkAccess = rDest.getIDocumentMarkAccess();
+ std::vector< ::sw::mark::IMark* > vDdeMarks;
+ // find all DDE-Bookmarks
+ for (IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getAllMarksBegin();
+ ppMark != pMarkAccess->getAllMarksEnd();
+ ++ppMark)
+ {
+ if (IDocumentMarkAccess::MarkType::DDE_BOOKMARK == IDocumentMarkAccess::GetType(**ppMark))
+ {
+ vDdeMarks.push_back(*ppMark);
+ }
+ }
+ // remove all DDE-Bookmarks, they are invalid inside the clipdoc!
+ for (const auto& rpMark : vDdeMarks)
+ {
+ pMarkAccess->deleteMark(rpMark);
+ }
+}
+
+void SwTransferable::PrepareForCopyTextRange(SwPaM & rPaM)
+{
+ std::optional<SwWait> oWait;
+ if (m_pWrtShell->ShouldWait())
+ {
+ oWait.emplace( *m_pWrtShell->GetView().GetDocShell(), true );
+ }
+
+ m_pClpDocFac.reset(new SwDocFac);
+
+ SwDoc& rDest(lcl_GetDoc(*m_pClpDocFac));
+ rDest.getIDocumentFieldsAccess().LockExpFields(); // Never update fields - leave text as is
+ {
+ SwDoc const& rSrc(*m_pWrtShell->GetDoc());
+ assert(&rSrc == &rPaM.GetDoc());
+
+ rDest.ReplaceCompatibilityOptions(rSrc);
+ rDest.ReplaceDefaults(rSrc);
+
+ //It would probably make most sense here to only insert the styles used
+ //by the selection, e.g. apply SwDoc::IsUsed on styles ?
+ rDest.ReplaceStyles(rSrc, false);
+
+ // relevant bits of rSrcWrtShell.Copy(rDest);
+ rDest.GetIDocumentUndoRedo().DoUndo(false); // always false!
+ rDest.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines );
+
+ SwNodeIndex const aIdx(rDest.GetNodes().GetEndOfContent(), -1);
+ SwContentNode *const pContentNode(aIdx.GetNode().GetContentNode());
+ SwPosition aPos(aIdx, pContentNode, pContentNode ? pContentNode->Len() : 0);
+
+ rSrc.getIDocumentContentOperations().CopyRange(rPaM, aPos, SwCopyFlags::CheckPosInFly);
+
+ rDest.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::NONE );
+
+ rDest.GetMetaFieldManager().copyDocumentProperties(rSrc);
+ }
+
+ DeleteDDEMarks(rDest);
+
+ // a new one was created in core (OLE objects copied!)
+ m_aDocShellRef = rDest.GetTmpDocShell();
+ if (m_aDocShellRef.Is())
+ SwTransferable::InitOle( m_aDocShellRef );
+ rDest.SetTmpDocShell( nullptr );
+
+ // let's add some formats
+ AddFormat( SotClipboardFormatId::EMBED_SOURCE );
+ AddFormat( SotClipboardFormatId::RTF );
+#if HAVE_FEATURE_DESKTOP
+ AddFormat( SotClipboardFormatId::RICHTEXT );
+ AddFormat( SotClipboardFormatId::HTML );
+#endif
+ AddFormat( SotClipboardFormatId::STRING );
+}
+
+int SwTransferable::PrepareForCopy( bool bIsCut )
+{
+ int nRet = 1;
+ if(!m_pWrtShell)
+ return 0;
+
+ if ( m_pWrtShell->GetTableInsertMode() != SwTable::SEARCH_NONE )
+ m_pWrtShell->SetTableInsertMode( SwTable::SEARCH_NONE );
+
+ if ( m_pWrtShell->GetTableCopied() )
+ m_pWrtShell->SetTableCopied( false );
+
+ OUString sGrfNm;
+ const SelectionType nSelection = m_pWrtShell->GetSelectionType();
+ if( nSelection == SelectionType::Graphic )
+ {
+ m_oClpGraphic.emplace();
+ if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_oClpGraphic ))
+ m_pOrigGraphic = &*m_oClpGraphic;
+ m_oClpBitmap.emplace();
+ if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_oClpBitmap ))
+ m_pOrigGraphic = &*m_oClpBitmap;
+
+ m_pClpDocFac.reset(new SwDocFac);
+ SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
+ m_pWrtShell->Copy(rDoc);
+
+#if HAVE_FEATURE_DESKTOP
+ if (m_pOrigGraphic && !m_pOrigGraphic->GetBitmapEx().IsEmpty())
+ AddFormat( SotClipboardFormatId::SVXB );
+#endif
+
+ PrepareOLE( m_aObjDesc );
+ AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
+
+ const Graphic* pGrf = m_pWrtShell->GetGraphic();
+ if( pGrf && pGrf->IsSupportedGraphic() )
+ {
+ AddFormat( SotClipboardFormatId::PNG );
+#if HAVE_FEATURE_DESKTOP
+ AddFormat( SotClipboardFormatId::GDIMETAFILE );
+ AddFormat( SotClipboardFormatId::BITMAP );
+#endif
+ }
+ m_eBufferType = TransferBufferType::Graphic;
+ m_pWrtShell->GetGrfNms( &sGrfNm, nullptr );
+ }
+ else if ( nSelection == SelectionType::Ole )
+ {
+ m_pClpDocFac.reset(new SwDocFac);
+ SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
+ m_aDocShellRef = new SwDocShell(rDoc, SfxObjectCreateMode::EMBEDDED);
+ m_aDocShellRef->DoInitNew();
+ m_pWrtShell->Copy(rDoc);
+
+ AddFormat( SotClipboardFormatId::EMBED_SOURCE );
+
+ // --> OD #i98753#
+ // set size of embedded object at the object description structure
+ m_aObjDesc.maSize = o3tl::convert(m_pWrtShell->GetObjSize(), o3tl::Length::twip, o3tl::Length::mm100);
+
+ // <--
+ PrepareOLE( m_aObjDesc );
+
+#if HAVE_FEATURE_DESKTOP
+ AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
+ AddFormat( SotClipboardFormatId::GDIMETAFILE );
+
+ // Fetch the formats supported via embedtransferhelper as well
+ sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
+ uno::Reference < embed::XEmbeddedObject > xObj = FindOLEObj( nAspect );
+ const Graphic* pOLEGraph = FindOLEReplacementGraphic();
+ if( xObj.is() )
+ {
+ TransferableDataHelper aD( new SvEmbedTransferHelper( xObj, pOLEGraph, nAspect ) );
+ if ( aD.GetTransferable().is() )
+ {
+ DataFlavorExVector aVector( aD.GetDataFlavorExVector() );
+
+ for( const auto& rItem : aVector )
+ AddFormat( rItem );
+ }
+ }
+#endif
+ m_eBufferType = TransferBufferType::Ole;
+ }
+ // Is there anything to provide anyway?
+ else if ( m_pWrtShell->IsSelection() || m_pWrtShell->IsFrameSelected() ||
+ m_pWrtShell->IsObjSelected() )
+ {
+ std::optional<SwWait> oWait;
+ if( m_pWrtShell->ShouldWait() )
+ oWait.emplace( *m_pWrtShell->GetView().GetDocShell(), true );
+
+ m_pClpDocFac.reset(new SwDocFac);
+
+ // create additional cursor so that equal treatment of keyboard
+ // and mouse selection is possible.
+ // In AddMode with keyboard selection, the new cursor is not created
+ // before the cursor is moved after end of selection.
+ if( m_pWrtShell->IsAddMode() && m_pWrtShell->SwCursorShell::HasSelection() )
+ m_pWrtShell->CreateCursor();
+
+ SwDoc& rTmpDoc = lcl_GetDoc(*m_pClpDocFac);
+
+ rTmpDoc.getIDocumentFieldsAccess().LockExpFields(); // Never update fields - leave text as is
+ lclOverWriteDoc(*m_pWrtShell, rTmpDoc);
+
+ DeleteDDEMarks(rTmpDoc);
+
+ // a new one was created in CORE (OLE objects copied!)
+ m_aDocShellRef = rTmpDoc.GetTmpDocShell();
+ if( m_aDocShellRef.Is() )
+ SwTransferable::InitOle( m_aDocShellRef );
+ rTmpDoc.SetTmpDocShell( nullptr );
+
+ if( m_pWrtShell->IsObjSelected() )
+ m_eBufferType = TransferBufferType::Drawing;
+ else
+ {
+ m_eBufferType = TransferBufferType::Document;
+ if (m_pWrtShell->IntelligentCut(nSelection, false) != SwWrtShell::NO_WORD)
+ m_eBufferType = TransferBufferType::DocumentWord | m_eBufferType;
+ }
+
+ bool bDDELink = m_pWrtShell->IsSelection();
+ if( nSelection & SelectionType::TableCell )
+ {
+ m_eBufferType = TransferBufferType::Table | m_eBufferType;
+ bDDELink = m_pWrtShell->HasWholeTabSelection();
+
+ m_pWrtShell->SetTableCopied(true);
+
+ if ( bIsCut && (SelectionType::TableRow | SelectionType::TableCol) & nSelection )
+ m_pWrtShell->SetTableInsertMode( (SelectionType::TableRow & nSelection) ? SwTable::SEARCH_ROW : SwTable::SEARCH_COL );
+ }
+
+#if HAVE_FEATURE_DESKTOP
+ //When someone needs it, we 'OLE' him something
+ AddFormat( SotClipboardFormatId::EMBED_SOURCE );
+#endif
+
+ //put RTF ahead of the OLE's Metafile to have less loss
+ if( !m_pWrtShell->IsObjSelected() )
+ {
+ AddFormat( SotClipboardFormatId::RTF );
+#if HAVE_FEATURE_DESKTOP
+ AddFormat( SotClipboardFormatId::RICHTEXT );
+ AddFormat( SotClipboardFormatId::HTML );
+#endif
+ }
+ if( m_pWrtShell->IsSelection() )
+ AddFormat( SotClipboardFormatId::STRING );
+
+ if( nSelection & ( SelectionType::DrawObject | SelectionType::DbForm ))
+ {
+ AddFormat( SotClipboardFormatId::DRAWING );
+ if ( nSelection & SelectionType::DrawObject )
+ {
+#if HAVE_FEATURE_DESKTOP
+ AddFormat( SotClipboardFormatId::GDIMETAFILE );
+ AddFormat( SotClipboardFormatId::BITMAP );
+#endif
+ AddFormat( SotClipboardFormatId::PNG );
+ }
+ m_eBufferType = static_cast<TransferBufferType>( TransferBufferType::Graphic | m_eBufferType );
+
+ m_oClpGraphic.emplace();
+ if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_oClpGraphic ))
+ m_pOrigGraphic = &*m_oClpGraphic;
+ m_oClpBitmap.emplace();
+ if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_oClpBitmap ))
+ m_pOrigGraphic = &*m_oClpBitmap;
+
+ // is it a URL-Button ?
+ OUString sURL;
+ OUString sDesc;
+ if( m_pWrtShell->GetURLFromButton( sURL, sDesc ) )
+ {
+ AddFormat( SotClipboardFormatId::STRING );
+#if HAVE_FEATURE_DESKTOP
+ AddFormat( SotClipboardFormatId::SOLK );
+ AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
+ AddFormat( SotClipboardFormatId::FILECONTENT );
+ AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR );
+#endif
+ AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR );
+ m_eBufferType = TransferBufferType::InetField | m_eBufferType;
+ nRet = 1;
+ }
+ }
+
+ // at Cut, DDE-Link doesn't make sense!!
+ SwDocShell* pDShell;
+ if( !bIsCut && bDDELink &&
+ nullptr != ( pDShell = m_pWrtShell->GetDoc()->GetDocShell()) &&
+ SfxObjectCreateMode::STANDARD == pDShell->GetCreateMode() )
+ {
+#if HAVE_FEATURE_DESKTOP
+ AddFormat( SotClipboardFormatId::LINK );
+#endif
+ m_xDdeLink = new SwTransferDdeLink( *this, *m_pWrtShell );
+ }
+
+ //ObjectDescriptor was already filly from the old DocShell.
+ //Now adjust it. Thus in GetData the first query can still
+ //be answered with delayed rendering.
+ m_aObjDesc.maSize = constOleSize100mm;
+
+ PrepareOLE( m_aObjDesc );
+#if HAVE_FEATURE_DESKTOP
+ AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
+#endif
+ }
+ else
+ nRet = 0;
+
+ if( m_pWrtShell->IsFrameSelected() )
+ {
+ SfxItemSetFixed<RES_URL, RES_URL> aSet( m_pWrtShell->GetAttrPool() );
+ m_pWrtShell->GetFlyFrameAttr( aSet );
+ const SwFormatURL& rURL = aSet.Get( RES_URL );
+ if( rURL.GetMap() )
+ {
+ m_pImageMap.reset( new ImageMap( *rURL.GetMap() ) );
+ AddFormat( SotClipboardFormatId::SVIM );
+ }
+ else if( !rURL.GetURL().isEmpty() )
+ {
+ m_pTargetURL.reset(new INetImage( sGrfNm, rURL.GetURL(),
+ rURL.GetTargetFrameName() ));
+ AddFormat( SotClipboardFormatId::INET_IMAGE );
+ }
+ }
+
+ return nRet;
+}
+
+int SwTransferable::Copy( bool bIsCut )
+{
+ if (m_pWrtShell->GetView().GetObjectShell()->isContentExtractionLocked())
+ return 0;
+
+ int nRet = PrepareForCopy( bIsCut );
+ if ( nRet )
+ {
+ CopyToClipboard( &m_pWrtShell->GetView().GetEditWin() );
+ }
+
+ if( !bIsCut ){
+ collectUIInformation("COPY", "parameter");
+ }
+
+ return nRet;
+}
+
+void SwTransferable::CalculateAndCopy()
+{
+ if(!m_pWrtShell)
+ return;
+ SwWait aWait( *m_pWrtShell->GetView().GetDocShell(), true );
+
+ OUString aStr( m_pWrtShell->Calculate() );
+
+ m_pClpDocFac.reset(new SwDocFac);
+ SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
+ m_pWrtShell->Copy(rDoc, &aStr);
+ m_eBufferType = TransferBufferType::Document;
+ AddFormat( SotClipboardFormatId::STRING );
+
+ CopyToClipboard( &m_pWrtShell->GetView().GetEditWin() );
+}
+
+bool SwTransferable::CopyGlossary( SwTextBlocks& rGlossary, const OUString& rStr )
+{
+ if(!m_pWrtShell)
+ return false;
+ SwWait aWait( *m_pWrtShell->GetView().GetDocShell(), true );
+
+ m_pClpDocFac.reset(new SwDocFac);
+ SwDoc& rCDoc = lcl_GetDoc(*m_pClpDocFac);
+
+ SwNodes& rNds = rCDoc.GetNodes();
+ SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() );
+ SwContentNode* pCNd = rNds.GoNext( &aNodeIdx ); // go to 1st ContentNode
+ SwPaM aPam( *pCNd );
+
+ rCDoc.getIDocumentFieldsAccess().LockExpFields(); // never update fields - leave text as it is
+
+ rCDoc.InsertGlossary( rGlossary, rStr, aPam );
+
+ // a new one was created in CORE (OLE-Objects copied!)
+ m_aDocShellRef = rCDoc.GetTmpDocShell();
+ if( m_aDocShellRef.Is() )
+ SwTransferable::InitOle( m_aDocShellRef );
+ rCDoc.SetTmpDocShell( nullptr );
+
+ m_eBufferType = TransferBufferType::Document;
+
+ //When someone needs it, we 'OLE' her something.
+ AddFormat( SotClipboardFormatId::EMBED_SOURCE );
+ AddFormat( SotClipboardFormatId::RTF );
+ AddFormat( SotClipboardFormatId::RICHTEXT );
+ AddFormat( SotClipboardFormatId::HTML );
+ AddFormat( SotClipboardFormatId::STRING );
+
+ //ObjectDescriptor was already filled from the old DocShell.
+ //Now adjust it. Thus in GetData the first query can still
+ //be answered with delayed rendering.
+ m_aObjDesc.maSize = constOleSize100mm;
+
+ PrepareOLE( m_aObjDesc );
+ AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
+
+ CopyToClipboard( &m_pWrtShell->GetView().GetEditWin() );
+
+ return true;
+}
+
+static uno::Reference < XTransferable > * lcl_getTransferPointer ( uno::Reference < XTransferable > &xRef )
+{
+ return &xRef;
+}
+
+SwPasteContext::SwPasteContext(SwWrtShell& rWrtShell)
+ : m_rWrtShell(rWrtShell)
+{
+ remember();
+}
+
+void SwPasteContext::remember()
+{
+ if (m_rWrtShell.GetPasteListeners().getLength() == 0)
+ return;
+
+ SwPaM* pCursor = m_rWrtShell.GetCursor();
+ if (!pCursor)
+ return;
+
+ // Set point to the previous node, so it is not moved.
+ const SwNode& rNode = pCursor->GetPoint()->GetNode();
+ m_oPaM.emplace(rNode, rNode, SwNodeOffset(0), SwNodeOffset(-1));
+ m_nStartContent = pCursor->GetPoint()->GetContentIndex();
+}
+
+void SwPasteContext::forget() { m_oPaM.reset(); }
+
+SwPasteContext::~SwPasteContext()
+{
+ try
+ {
+ if (m_rWrtShell.GetPasteListeners().getLength() == 0)
+ return;
+
+ beans::PropertyValue aPropertyValue;
+
+ switch (m_rWrtShell.GetView().GetShellMode())
+ {
+ case ShellMode::Graphic:
+ {
+ SwFrameFormat* pFormat = m_rWrtShell.GetFlyFrameFormat();
+ if (!pFormat)
+ return;
+
+ aPropertyValue.Name = "TextGraphicObject";
+ aPropertyValue.Value
+ <<= uno::Reference<text::XTextContent>(SwXTextGraphicObject::CreateXTextGraphicObject(*pFormat->GetDoc(), pFormat));
+ break;
+ }
+
+ default:
+ {
+ if (!m_oPaM)
+ return;
+
+ SwPaM* pCursor = m_rWrtShell.GetCursor();
+ if (!pCursor)
+ return;
+
+ if (!pCursor->GetPoint()->GetNode().IsTextNode())
+ // Non-text was pasted.
+ return;
+
+ // Update mark after paste.
+ *m_oPaM->GetMark() = *pCursor->GetPoint();
+
+ // Restore point.
+ m_oPaM->GetPoint()->Adjust(SwNodeOffset(1));
+ SwNode& rNode = m_oPaM->GetPointNode();
+ if (!rNode.IsTextNode())
+ // Starting point is no longer text.
+ return;
+
+ m_oPaM->GetPoint()->SetContent(m_nStartContent);
+
+ aPropertyValue.Name = "TextRange";
+ const rtl::Reference<SwXTextRange> xTextRange = SwXTextRange::CreateXTextRange(
+ m_oPaM->GetDoc(), *m_oPaM->GetPoint(), m_oPaM->GetMark());
+ aPropertyValue.Value <<= uno::Reference<text::XTextRange>(xTextRange);
+ break;
+ }
+ }
+
+ if (aPropertyValue.Name.isEmpty())
+ return;
+
+ // Invoke the listeners.
+ uno::Sequence<beans::PropertyValue> aEvent{ aPropertyValue };
+ m_rWrtShell.GetPasteListeners().notifyEach( &css::text::XPasteListener::notifyPasteEvent, aEvent );
+ }
+ catch (const uno::Exception& rException)
+ {
+ SAL_WARN("sw",
+ "SwPasteContext::~SwPasteContext: uncaught exception: " << rException.Message);
+ }
+}
+
+bool SwTransferable::IsPaste( const SwWrtShell& rSh,
+ const TransferableDataHelper& rData )
+{
+ // Check the common case first: We can always paste our own data!
+ // If _only_ the internal format can be pasted, this check will
+ // yield 'true', while the one below would give a (wrong) result 'false'.
+
+ bool bIsPaste = ( GetSwTransferable( rData ) != nullptr );
+
+ // if it's not our own data, we need to have a closer look:
+ if( ! bIsPaste )
+ {
+ // determine the proper paste action, and return true if we find one
+ uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );
+
+ SotExchangeDest nDestination = SwTransferable::GetSotDestination( rSh );
+ sal_uInt16 nSourceOptions =
+ (( SotExchangeDest::DOC_TEXTFRAME == nDestination ||
+ SotExchangeDest::SWDOC_FREE_AREA == nDestination ||
+ SotExchangeDest::DOC_TEXTFRAME_WEB == nDestination ||
+ SotExchangeDest::SWDOC_FREE_AREA_WEB == nDestination )
+ ? EXCHG_IN_ACTION_COPY
+ : EXCHG_IN_ACTION_MOVE);
+
+ SotClipboardFormatId nFormat; // output param for GetExchangeAction
+ sal_uInt8 nEventAction; // output param for GetExchangeAction
+ sal_uInt8 nAction = SotExchange::GetExchangeAction(
+ rData.GetDataFlavorExVector(),
+ nDestination,
+ nSourceOptions, /* ?? */
+ EXCHG_IN_ACTION_DEFAULT, /* ?? */
+ nFormat, nEventAction, SotClipboardFormatId::NONE,
+ lcl_getTransferPointer ( xTransferable ) );
+
+ // if we find a suitable action, we can paste!
+ bIsPaste = (EXCHG_INOUT_ACTION_NONE != nAction);
+ }
+
+ return bIsPaste;
+}
+
+void SwTransferable::SelectPasteFormat(TransferableDataHelper& rData, sal_uInt8& nAction,
+ SotClipboardFormatId& nFormat)
+{
+ if (nFormat != SotClipboardFormatId::RICHTEXT)
+ {
+ return;
+ }
+
+ if (!rData.HasFormat(SotClipboardFormatId::EMBED_SOURCE))
+ {
+ return;
+ }
+
+ if (!rData.HasFormat(SotClipboardFormatId::OBJECTDESCRIPTOR))
+ {
+ return;
+ }
+
+ TransferableObjectDescriptor aObjDesc;
+ if (!rData.GetTransferableObjectDescriptor(SotClipboardFormatId::OBJECTDESCRIPTOR, aObjDesc))
+ {
+ return;
+ }
+
+ if (aObjDesc.maClassName != SvGlobalName(SO3_SW_CLASSID))
+ {
+ return;
+ }
+
+ // At this point we know that we paste from Writer to Writer and the clipboard has the content
+ // in both RTF and ODF formats. Prefer ODF in this case.
+ nAction = EXCHG_OUT_ACTION_INSERT_OLE;
+ nFormat = SotClipboardFormatId::EMBED_SOURCE;
+}
+
+// get HTML indentation level by counting tabulator characters before the index
+// (also index value -1 returns with 0)
+static sal_Int32 lcl_getLevel(OUString& sText, sal_Int32 nIdx)
+{
+ sal_Int32 nRet = 0;
+ while ( nIdx-- > 0 && sText[nIdx] == '\t' )
+ {
+ nRet++;
+ }
+ return nRet;
+}
+
+bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndStdIds nAnchorType, bool bIgnoreComments, PasteTableType ePasteTable)
+{
+ SwPasteContext aPasteContext(rSh);
+
+ sal_uInt8 nAction=0;
+ SotExchangeDest nDestination = SwTransferable::GetSotDestination( rSh );
+ SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
+ SotExchangeActionFlags nActionFlags = SotExchangeActionFlags::NONE;
+ bool bSingleCellTable = false;
+
+ if( GetSwTransferable( rData ) )
+ {
+ nAction = EXCHG_OUT_ACTION_INSERT_PRIVATE;
+ }
+ else
+ {
+ sal_uInt16 nSourceOptions =
+ (( SotExchangeDest::DOC_TEXTFRAME == nDestination ||
+ SotExchangeDest::SWDOC_FREE_AREA == nDestination ||
+ SotExchangeDest::DOC_TEXTFRAME_WEB == nDestination ||
+ SotExchangeDest::SWDOC_FREE_AREA_WEB == nDestination )
+ ? EXCHG_IN_ACTION_COPY
+ : EXCHG_IN_ACTION_MOVE);
+ uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );
+ sal_uInt8 nEventAction;
+ nAction = SotExchange::GetExchangeAction(
+ rData.GetDataFlavorExVector(),
+ nDestination,
+ nSourceOptions, /* ?? */
+ EXCHG_IN_ACTION_DEFAULT, /* ?? */
+ nFormat, nEventAction, SotClipboardFormatId::NONE,
+ lcl_getTransferPointer ( xTransferable ),
+ &nActionFlags );
+ }
+
+ // when HTML is just an image don't generate new section
+ if (rData.HasFormat(SotClipboardFormatId::HTML_SIMPLE) && rData.HasFormat(SotClipboardFormatId::HTML_NO_COMMENT)
+ && rData.HasFormat(SotClipboardFormatId::BITMAP) && nFormat == SotClipboardFormatId::FILE_LIST)
+ nFormat = SotClipboardFormatId::BITMAP;
+
+ // tdf#37223 avoid non-native insertion of Calc worksheets in the following cases:
+ // content of 1-cell worksheets are inserted as simple text using RTF format,
+ // bigger worksheets within native (Writer) table cells are inserted as native tables,
+ // ie. cell by cell instead of embedding the worksheet in a single cell of the Writer table
+ if ( EXCHG_IN_ACTION_COPY == nAction && ( rData.HasFormat( SotClipboardFormatId::SYLK ) ||
+ rData.HasFormat( SotClipboardFormatId::SYLK_BIGCAPS ) ) )
+ {
+ // is it a 1-cell worksheet?
+ OUString aExpand;
+ if( rData.GetString( SotClipboardFormatId::STRING, aExpand ))
+ {
+ const sal_Int32 nNewlines{comphelper::string::getTokenCount(aExpand, '\n')};
+ const sal_Int32 nRows = nNewlines ? nNewlines-1 : 0;
+ if ( nRows == 1 )
+ {
+ const sal_Int32 nCols = comphelper::string::getTokenCount(o3tl::getToken(aExpand, 0, '\n'), '\t');
+ if (nCols == 1)
+ bSingleCellTable = true;
+ }
+ }
+
+ // convert the worksheet to a temporary native table using HTML format, and copy that into the original native table
+ if (!bSingleCellTable && rData.HasFormat( SotClipboardFormatId::HTML ) &&
+ SwDoc::IsInTable(rSh.GetCursor()->GetPointNode()) != nullptr && rSh.DoesUndo())
+ {
+ SfxDispatcher* pDispatch = rSh.GetView().GetViewFrame().GetDispatcher();
+ sal_uInt32 nLevel = 0;
+
+ // within Writer table cells, inserting worksheets using HTML format results only plain text, not a native table,
+ // so remove all outer nested tables temporary to get a working insertion point
+ // (RTF format has no such problem, but that inserts the hidden rows of the original Calc worksheet, too)
+
+ // For this, switch off change tracking temporarily, if needed
+ RedlineFlags eOld = rSh.GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags();
+ if ( eOld & RedlineFlags::On )
+ rSh.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eOld & ~RedlineFlags::On );
+
+ OUString sPreviousTableName;
+ do
+ {
+ // tdf#152245 add a limit to the loop, if it's not possible to delete the table
+ const SwTableNode* pNode = rSh.GetCursor()->GetPointNode().FindTableNode();
+ const OUString sTableName = pNode->GetTable().GetFrameFormat()->GetName();
+ if ( sTableName == sPreviousTableName )
+ break;
+ sPreviousTableName = sTableName;
+ // insert a random character to redo the place of the insertion at the end
+ pDispatch->Execute(FN_INSERT_NNBSP, SfxCallMode::SYNCHRON);
+ pDispatch->Execute(FN_TABLE_DELETE_TABLE, SfxCallMode::SYNCHRON);
+ nLevel++;
+ } while (SwDoc::IsInTable(rSh.GetCursor()->GetPointNode()) != nullptr);
+
+ // restore change tracking settings
+ if ( eOld & RedlineFlags::On )
+ rSh.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eOld );
+
+ if ( SwTransferable::PasteData( rData, rSh, EXCHG_OUT_ACTION_INSERT_STRING, nActionFlags, SotClipboardFormatId::HTML,
+ nDestination, false, false, nullptr, 0, false, nAnchorType, bIgnoreComments, &aPasteContext, ePasteTable) )
+ {
+ bool bFoundTemporaryTable = false;
+ pDispatch->Execute(FN_LINE_UP, SfxCallMode::SYNCHRON);
+ if (SwDoc::IsInTable(rSh.GetCursor()->GetPointNode()) != nullptr)
+ {
+ bFoundTemporaryTable = true;
+ pDispatch->Execute(FN_TABLE_SELECT_ALL, SfxCallMode::SYNCHRON);
+ pDispatch->Execute(SID_COPY, SfxCallMode::SYNCHRON);
+ }
+ for(sal_uInt32 a = 0; a < 1 + (nLevel * 2); a++)
+ pDispatch->Execute(SID_UNDO, SfxCallMode::SYNCHRON);
+ // clipboard content hasn't changed (limit potential infinite
+ // recursion with the same non-native table, as was in tdf#138688)
+ if (!bFoundTemporaryTable)
+ return false;
+ if (ePasteTable == PasteTableType::PASTE_TABLE)
+ pDispatch->Execute(FN_PASTE_NESTED_TABLE, SfxCallMode::SYNCHRON);
+ else if (ePasteTable == PasteTableType::PASTE_ROW)
+ pDispatch->Execute(FN_TABLE_PASTE_ROW_BEFORE, SfxCallMode::SYNCHRON);
+ else if (ePasteTable == PasteTableType::PASTE_COLUMN)
+ pDispatch->Execute(FN_TABLE_PASTE_COL_BEFORE, SfxCallMode::SYNCHRON);
+ else
+ pDispatch->Execute(SID_PASTE, SfxCallMode::SYNCHRON);
+ return true;
+ } else {
+ for(sal_uInt32 a = 0; a < (nLevel * 2); a++)
+ pDispatch->Execute(SID_UNDO, SfxCallMode::SYNCHRON);
+ }
+ }
+ }
+ // insert clipboard content as new table rows/columns before the actual row/column instead of overwriting it
+ else if ( (rSh.GetTableInsertMode() != SwTable::SEARCH_NONE || ePasteTable == PasteTableType::PASTE_ROW || ePasteTable == PasteTableType::PASTE_COLUMN) &&
+ rData.HasFormat( SotClipboardFormatId::HTML ) &&
+ SwDoc::IsInTable(rSh.GetCursor()->GetPointNode()) != nullptr )
+ {
+ OUString aExpand;
+ sal_Int32 nIdx;
+ bool bRowMode = rSh.GetTableInsertMode() == SwTable::SEARCH_ROW || ePasteTable == PasteTableType::PASTE_ROW;
+ if( rData.GetString( SotClipboardFormatId::HTML, aExpand ) && (nIdx = aExpand.indexOf("<table")) > -1 )
+ {
+ // calculate table row/column count by analysing indentation of the HTML table extract
+
+ // calculate indentation level of <table>, which is the base of the next calculations
+ // (tdf#148791 table alignment can enlarge it using first level <center>, <div> or <dl>)
+ sal_Int32 nTableLevel = lcl_getLevel(aExpand, nIdx);
+ // table rows repeated heading use extra indentation, too:
+ // <thead> is always used here, and the first table with <thead> is not nested,
+ // if its indentation level is greater only by 1, than indentation level of the table
+ bool bShifted = lcl_getLevel(aExpand, aExpand.indexOf("<thead")) == nTableLevel + 1;
+ // calculate count of selected rows or columns
+ sal_Int32 nSelectedRowsOrCols = 0;
+ const OUString sSearchRowOrCol = bRowMode ? OUString("</tr>") : OUString("<col ");
+ while((nIdx = aExpand.indexOf(sSearchRowOrCol, nIdx)) > -1)
+ {
+ // skip rows/columns of nested tables, based on HTML indentation
+ if ( lcl_getLevel(aExpand, nIdx) == nTableLevel + (bShifted ? 2 : 1) &&
+ // skip also strange hidden empty rows <tr></tr>
+ !aExpand.match("<tr></tr>", nIdx - 4) )
+ {
+ ++nSelectedRowsOrCols;
+ }
+ ++nIdx;
+ }
+ // are we at the beginning of the cell?
+ bool bStartTableBoxNode =
+ // first paragraph of the cell?
+ rSh.GetCursor()->GetPointNode().GetIndex() == rSh.GetCursor()->GetPointNode().FindTableBoxStartNode()->GetIndex()+1 &&
+ // beginning of the paragraph?
+ !rSh.GetCursor()->GetPoint()->GetContentIndex();
+ SfxDispatcher* pDispatch = rSh.GetView().GetViewFrame().GetDispatcher();
+
+ // go start of the cell
+ if (!bStartTableBoxNode)
+ pDispatch->Execute(FN_START_OF_DOCUMENT, SfxCallMode::SYNCHRON);
+
+ // store cursor position in row mode
+ ::sw::mark::IMark* pMark = (!bRowMode || nSelectedRowsOrCols == 0) ? nullptr : rSh.SetBookmark(
+ vcl::KeyCode(),
+ OUString(),
+ IDocumentMarkAccess::MarkType::UNO_BOOKMARK );
+
+ // add a new empty row/column before the actual table row/column and go there
+ const sal_uInt16 nDispatchSlot = bRowMode ? FN_TABLE_INSERT_ROW_BEFORE : FN_TABLE_INSERT_COL_BEFORE;
+ pDispatch->Execute(nDispatchSlot, SfxCallMode::SYNCHRON);
+ pDispatch->Execute(bRowMode ? FN_LINE_UP : FN_CHAR_LEFT, SfxCallMode::SYNCHRON);
+
+ // add the other new empty rows/columns after the actual table row/column
+ if ( nSelectedRowsOrCols > 1 )
+ {
+ SfxInt16Item aCountItem( nDispatchSlot, nSelectedRowsOrCols-1 );
+ SfxBoolItem aAfter( FN_PARAM_INSERT_AFTER, true );
+ pDispatch->ExecuteList(nDispatchSlot,
+ SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
+ { &aCountItem, &aAfter });
+ }
+
+ // paste rows
+ bool bResult = SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat,
+ nDestination, false, false, nullptr, 0, false, nAnchorType, bIgnoreComments, &aPasteContext );
+
+ // restore cursor position
+ if (pMark != nullptr)
+ {
+ rSh.GotoMark( pMark );
+ rSh.getIDocumentMarkAccess()->deleteMark( pMark );
+ }
+
+ return bResult;
+ }
+ }
+
+ // special case for tables from draw application or 1-cell tables
+ if( EXCHG_OUT_ACTION_INSERT_DRAWOBJ == nAction || bSingleCellTable )
+ {
+ if( rData.HasFormat( SotClipboardFormatId::RTF ) )
+ {
+ nAction = EXCHG_OUT_ACTION_INSERT_STRING;
+ nFormat = SotClipboardFormatId::RTF;
+ }
+ else if( rData.HasFormat( SotClipboardFormatId::RICHTEXT ) )
+ {
+ nAction = EXCHG_OUT_ACTION_INSERT_STRING;
+ nFormat = SotClipboardFormatId::RICHTEXT;
+ }
+ }
+
+ // Tweak the format if necessary: the source application can be considered in this context,
+ // while not in sot/ code.
+ SwTransferable::SelectPasteFormat(rData, nAction, nFormat);
+
+ collectUIInformation("PASTE", "parameter");
+
+ return EXCHG_INOUT_ACTION_NONE != nAction &&
+ SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat,
+ nDestination, false, false, nullptr, 0, false, nAnchorType, bIgnoreComments, &aPasteContext, ePasteTable);
+}
+
+bool SwTransferable::PasteData( TransferableDataHelper& rData,
+ SwWrtShell& rSh, sal_uInt8 nAction, SotExchangeActionFlags nActionFlags,
+ SotClipboardFormatId nFormat,
+ SotExchangeDest nDestination, bool bIsPasteFormat,
+ bool bIsDefault,
+ const Point* pPt, sal_Int8 nDropAction,
+ bool bPasteSelection, RndStdIds nAnchorType,
+ bool bIgnoreComments,
+ SwPasteContext* pContext,
+ PasteTableType ePasteTable )
+{
+ SwWait aWait( *rSh.GetView().GetDocShell(), false );
+ std::unique_ptr<SwTrnsfrActionAndUndo, o3tl::default_delete<SwTrnsfrActionAndUndo>> pAction;
+ SwModule* pMod = SW_MOD();
+
+ bool bRet = false;
+ bool bCallAutoCaption = false;
+
+ if( pPt )
+ {
+ // external Drop
+ if ((bPasteSelection ? !pMod->m_pXSelection : !pMod->m_pDragDrop) &&
+ // The following condition is used for tdf#156111 to prevent a selection from being
+ // cleared by the default case of the nDestination switch.
+ !(rSh.GetCursorCnt() == 1 && rSh.TestCurrPam(*pPt) &&
+ nDestination == SotExchangeDest::SWDOC_FREE_AREA &&
+ nFormat == SotClipboardFormatId::SONLK))
+ {
+ switch( nDestination )
+ {
+ case SotExchangeDest::DOC_LNKD_GRAPH_W_IMAP:
+ case SotExchangeDest::DOC_LNKD_GRAPHOBJ:
+ case SotExchangeDest::DOC_GRAPH_W_IMAP:
+ case SotExchangeDest::DOC_GRAPHOBJ:
+ case SotExchangeDest::DOC_OLEOBJ:
+ case SotExchangeDest::DOC_DRAWOBJ:
+ case SotExchangeDest::DOC_URLBUTTON:
+ case SotExchangeDest::DOC_GROUPOBJ:
+ // select frames/objects
+ SwTransferable::SetSelInShell( rSh, true, pPt );
+ break;
+
+ default:
+ SwTransferable::SetSelInShell( rSh, false, pPt );
+ break;
+ }
+ }
+ }
+ else if( ( !GetSwTransferable( rData ) || bIsPasteFormat ) &&
+ !rSh.IsTableMode() && rSh.HasSelection() )
+ {
+ // then delete the selections
+
+ //don't delete selected content
+ // - at table-selection
+ // - at ReRead of a graphic/DDEData
+ // - at D&D, for the right selection was taken care of
+ // in Drop-Handler
+ bool bDelSel = false;
+ switch( nDestination )
+ {
+ case SotExchangeDest::DOC_TEXTFRAME:
+ case SotExchangeDest::SWDOC_FREE_AREA:
+ case SotExchangeDest::DOC_TEXTFRAME_WEB:
+ case SotExchangeDest::SWDOC_FREE_AREA_WEB:
+ bDelSel = true;
+ break;
+ default:
+ break;
+ }
+
+ if( bDelSel )
+ // #i34830#
+ pAction.reset(new SwTrnsfrActionAndUndo(&rSh, true, pContext));
+ }
+
+ SwTransferable *pTrans=nullptr, *pTunneledTrans=GetSwTransferable( rData );
+
+ // check for private drop
+ bool bPrivateDrop(pPt);
+ if (bPrivateDrop)
+ {
+ if (bPasteSelection)
+ pTrans = pMod->m_pXSelection;
+ else
+ pTrans = pMod->m_pDragDrop;
+ bPrivateDrop = nullptr != pTrans;
+ }
+ bool bNeedToSelectBeforePaste(false);
+
+ if(bPrivateDrop && DND_ACTION_LINK == nDropAction)
+ {
+ // internal drop on object, suppress bPrivateDrop to change internal fill
+ bPrivateDrop = false;
+ bNeedToSelectBeforePaste = true;
+ }
+
+ if(bPrivateDrop && pPt && DND_ACTION_MOVE == nDropAction)
+ {
+ // check if dragged over a useful target. If yes, use as content exchange
+ // drop as if from external
+ const SwFrameFormat* pSwFrameFormat = rSh.GetFormatFromObj(*pPt);
+
+ if(dynamic_cast< const SwDrawFrameFormat* >(pSwFrameFormat))
+ {
+ bPrivateDrop = false;
+ bNeedToSelectBeforePaste = true;
+ }
+ }
+
+ if(bPrivateDrop)
+ {
+ // then internal Drag & Drop or XSelection
+ bRet = pTrans->PrivateDrop( rSh, *pPt, DND_ACTION_MOVE == nDropAction,
+ bPasteSelection );
+ }
+ else if( !pPt && pTunneledTrans &&
+ EXCHG_OUT_ACTION_INSERT_PRIVATE == nAction )
+ {
+ // then internal paste
+ bRet = pTunneledTrans->PrivatePaste(rSh, pContext, ePasteTable);
+ }
+ else if( EXCHG_INOUT_ACTION_NONE != nAction )
+ {
+ if( !pAction )
+ {
+ pAction.reset(new SwTrnsfrActionAndUndo( &rSh ));
+ }
+
+ // in Drag&Drop MessageBoxes must not be showed
+ bool bMsg = nullptr == pPt;
+
+ // delete selections
+
+ switch( nAction )
+ {
+ case EXCHG_OUT_ACTION_INSERT_PRIVATE:
+ OSL_ENSURE( pPt, "EXCHG_OUT_ACTION_INSERT_PRIVATE: what should happen here?" );
+ break;
+
+ case EXCHG_OUT_ACTION_MOVE_PRIVATE:
+ OSL_ENSURE( pPt, "EXCHG_OUT_ACTION_MOVE_PRIVATE: what should happen here?" );
+ break;
+
+ case EXCHG_IN_ACTION_MOVE:
+ case EXCHG_IN_ACTION_COPY:
+ case EXCHG_IN_ACTION_LINK:
+ case EXCHG_OUT_ACTION_INSERT_HTML:
+ case EXCHG_OUT_ACTION_INSERT_STRING:
+ case EXCHG_OUT_ACTION_INSERT_IMAGEMAP:
+ case EXCHG_OUT_ACTION_REPLACE_IMAGEMAP:
+
+ // then we have to use the format
+ switch( nFormat )
+ {
+ case SotClipboardFormatId::DRAWING:
+ bRet = SwTransferable::PasteSdrFormat( rData, rSh,
+ SwPasteSdr::Insert, pPt,
+ nActionFlags, bNeedToSelectBeforePaste);
+ break;
+
+ case SotClipboardFormatId::HTML:
+ case SotClipboardFormatId::HTML_SIMPLE:
+ case SotClipboardFormatId::HTML_NO_COMMENT:
+ case SotClipboardFormatId::RTF:
+ case SotClipboardFormatId::RICHTEXT:
+ case SotClipboardFormatId::STRING:
+ bRet = SwTransferable::PasteFileContent( rData, rSh,
+ nFormat, bMsg, bIgnoreComments );
+ break;
+
+ case SotClipboardFormatId::NETSCAPE_BOOKMARK:
+ {
+ INetBookmark aBkmk;
+ if( rData.GetINetBookmark( nFormat, aBkmk ) )
+ {
+ SwFormatINetFormat aFormat( aBkmk.GetURL(), OUString() );
+ rSh.InsertURL( aFormat, aBkmk.GetDescription() );
+ bRet = true;
+ }
+ }
+ break;
+
+ case SotClipboardFormatId::SD_OLE:
+ bRet = SwTransferable::PasteOLE( rData, rSh, nFormat,
+ nActionFlags, bMsg );
+ break;
+
+ case SotClipboardFormatId::SVIM:
+ bRet = SwTransferable::PasteImageMap( rData, rSh );
+ break;
+
+ case SotClipboardFormatId::SVXB:
+ case SotClipboardFormatId::BITMAP:
+ case SotClipboardFormatId::PNG:
+ case SotClipboardFormatId::GDIMETAFILE:
+ bRet = SwTransferable::PasteGrf( rData, rSh, nFormat,
+ SwPasteSdr::Insert,pPt,
+ nActionFlags, nDropAction, bNeedToSelectBeforePaste);
+ break;
+
+ case SotClipboardFormatId::XFORMS:
+ case SotClipboardFormatId::SBA_FIELDDATAEXCHANGE:
+ case SotClipboardFormatId::SBA_DATAEXCHANGE:
+ case SotClipboardFormatId::SBA_CTRLDATAEXCHANGE:
+ bRet = SwTransferable::PasteDBData( rData, rSh, nFormat,
+ EXCHG_IN_ACTION_LINK == nAction,
+ pPt, bMsg );
+ break;
+
+ case SotClipboardFormatId::SIMPLE_FILE:
+ bRet = SwTransferable::PasteFileName( rData, rSh, nFormat,
+ ( EXCHG_IN_ACTION_MOVE == nAction
+ ? SwPasteSdr::Replace
+ : EXCHG_IN_ACTION_LINK == nAction
+ ? SwPasteSdr::SetAttr
+ : SwPasteSdr::Insert),
+ pPt, nActionFlags, nullptr );
+ break;
+
+ case SotClipboardFormatId::FILE_LIST:
+ // then insert as graphics only
+ bRet = SwTransferable::PasteFileList( rData, rSh,
+ EXCHG_IN_ACTION_LINK == nAction,
+ pPt, bMsg );
+ break;
+
+ case SotClipboardFormatId::SONLK:
+ if( pPt )
+ {
+ NaviContentBookmark aBkmk;
+ if (aBkmk.Paste(rData, rSh.GetSelText()))
+ {
+ if(bIsDefault)
+ {
+ switch(aBkmk.GetDefaultDragType())
+ {
+ case RegionMode::NONE: nAction = EXCHG_IN_ACTION_COPY; break;
+ case RegionMode::EMBEDDED: nAction = EXCHG_IN_ACTION_MOVE; break;
+ case RegionMode::LINK: nAction = EXCHG_IN_ACTION_LINK; break;
+ }
+ }
+ rSh.NavigatorPaste( aBkmk, nAction );
+ bRet = true;
+ }
+ }
+ break;
+
+ case SotClipboardFormatId::INET_IMAGE:
+ case SotClipboardFormatId::NETSCAPE_IMAGE:
+ bRet = SwTransferable::PasteTargetURL( rData, rSh,
+ SwPasteSdr::Insert,
+ pPt, true );
+ break;
+
+ default:
+ OSL_ENSURE( pPt, "unknown format" );
+ }
+ break;
+
+ case EXCHG_OUT_ACTION_INSERT_FILE:
+ {
+ bool graphicInserted;
+ bRet = SwTransferable::PasteFileName( rData, rSh, nFormat,
+ SwPasteSdr::Insert, pPt,
+ nActionFlags,
+ &graphicInserted );
+ if( graphicInserted )
+ bCallAutoCaption = true;
+ }
+ break;
+
+ case EXCHG_OUT_ACTION_INSERT_OLE:
+ bRet = SwTransferable::PasteOLE( rData, rSh, nFormat,
+ nActionFlags,bMsg );
+ break;
+
+ case EXCHG_OUT_ACTION_INSERT_DDE:
+ {
+ bool bReRead = 0 != CNT_HasGrf( rSh.GetCntType() );
+ bRet = SwTransferable::PasteDDE( rData, rSh, bReRead, bMsg );
+ }
+ break;
+
+ case EXCHG_OUT_ACTION_INSERT_HYPERLINK:
+ {
+ OUString sURL, sDesc;
+ if( SotClipboardFormatId::SIMPLE_FILE == nFormat )
+ {
+ if( rData.GetString( nFormat, sURL ) && !sURL.isEmpty() )
+ {
+ SwTransferable::CheckForURLOrLNKFile( rData, sURL, &sDesc );
+ if( sDesc.isEmpty() )
+ sDesc = sURL;
+ bRet = true;
+ }
+ }
+ else
+ {
+ INetBookmark aBkmk;
+ if( rData.GetINetBookmark( nFormat, aBkmk ) )
+ {
+ sURL = aBkmk.GetURL();
+ sDesc = aBkmk.GetDescription();
+ bRet = true;
+ }
+ }
+
+ if( bRet )
+ {
+ SwFormatINetFormat aFormat( sURL, OUString() );
+ rSh.InsertURL( aFormat, sDesc );
+ }
+ }
+ break;
+
+ case EXCHG_OUT_ACTION_GET_ATTRIBUTES:
+ switch( nFormat )
+ {
+ case SotClipboardFormatId::DRAWING:
+ bRet = SwTransferable::PasteSdrFormat( rData, rSh,
+ SwPasteSdr::SetAttr, pPt,
+ nActionFlags, bNeedToSelectBeforePaste);
+ break;
+ case SotClipboardFormatId::SVXB:
+ case SotClipboardFormatId::GDIMETAFILE:
+ case SotClipboardFormatId::BITMAP:
+ case SotClipboardFormatId::PNG:
+ case SotClipboardFormatId::NETSCAPE_BOOKMARK:
+ case SotClipboardFormatId::SIMPLE_FILE:
+ case SotClipboardFormatId::FILEGRPDESCRIPTOR:
+ case SotClipboardFormatId::UNIFORMRESOURCELOCATOR:
+ bRet = SwTransferable::PasteGrf( rData, rSh, nFormat,
+ SwPasteSdr::SetAttr, pPt,
+ nActionFlags, nDropAction, bNeedToSelectBeforePaste);
+ break;
+ default:
+ OSL_FAIL( "unknown format" );
+ }
+
+ break;
+
+ case EXCHG_OUT_ACTION_INSERT_DRAWOBJ:
+ bRet = SwTransferable::PasteSdrFormat( rData, rSh,
+ SwPasteSdr::Insert, pPt,
+ nActionFlags, bNeedToSelectBeforePaste);
+ break;
+ case EXCHG_OUT_ACTION_INSERT_SVXB:
+ case EXCHG_OUT_ACTION_INSERT_GDIMETAFILE:
+ case EXCHG_OUT_ACTION_INSERT_BITMAP:
+ case EXCHG_OUT_ACTION_INSERT_GRAPH:
+ bRet = SwTransferable::PasteGrf( rData, rSh, nFormat,
+ SwPasteSdr::Insert, pPt,
+ nActionFlags, nDropAction, bNeedToSelectBeforePaste, nAnchorType );
+ break;
+
+ case EXCHG_OUT_ACTION_REPLACE_DRAWOBJ:
+ bRet = SwTransferable::PasteSdrFormat( rData, rSh,
+ SwPasteSdr::Replace, pPt,
+ nActionFlags, bNeedToSelectBeforePaste);
+ break;
+
+ case EXCHG_OUT_ACTION_REPLACE_SVXB:
+ case EXCHG_OUT_ACTION_REPLACE_GDIMETAFILE:
+ case EXCHG_OUT_ACTION_REPLACE_BITMAP:
+ case EXCHG_OUT_ACTION_REPLACE_GRAPH:
+ bRet = SwTransferable::PasteGrf( rData, rSh, nFormat,
+ SwPasteSdr::Replace,pPt,
+ nActionFlags, nDropAction, bNeedToSelectBeforePaste);
+ break;
+
+ case EXCHG_OUT_ACTION_INSERT_INTERACTIVE:
+ bRet = SwTransferable::PasteAsHyperlink( rData, rSh, nFormat );
+ break;
+
+ default:
+ OSL_FAIL("unknown action" );
+ }
+ }
+
+ if( !bPasteSelection && rSh.IsFrameSelected() )
+ {
+ rSh.EnterSelFrameMode();
+ //force ::SelectShell
+ rSh.GetView().StopShellTimer();
+ }
+
+ pAction.reset();
+ if( bCallAutoCaption )
+ rSh.GetView().AutoCaption( GRAPHIC_CAP );
+
+ return bRet;
+}
+
+SotExchangeDest SwTransferable::GetSotDestination( const SwWrtShell& rSh )
+{
+ SotExchangeDest nRet = SotExchangeDest::NONE;
+
+ ObjCntType eOType = rSh.GetObjCntTypeOfSelection();
+
+ switch( eOType )
+ {
+ case OBJCNT_GRF:
+ {
+ bool bIMap, bLink;
+ bIMap = nullptr != rSh.GetFlyFrameFormat()->GetURL().GetMap();
+ OUString aDummy;
+ rSh.GetGrfNms( &aDummy, nullptr );
+ bLink = !aDummy.isEmpty();
+
+ if( bLink && bIMap )
+ nRet = SotExchangeDest::DOC_LNKD_GRAPH_W_IMAP;
+ else if( bLink )
+ nRet = SotExchangeDest::DOC_LNKD_GRAPHOBJ;
+ else if( bIMap )
+ nRet = SotExchangeDest::DOC_GRAPH_W_IMAP;
+ else
+ nRet = SotExchangeDest::DOC_GRAPHOBJ;
+ }
+ break;
+
+ case OBJCNT_FLY:
+ if( dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) != nullptr )
+ nRet = SotExchangeDest::DOC_TEXTFRAME_WEB;
+ else
+ nRet = SotExchangeDest::DOC_TEXTFRAME;
+ break;
+ case OBJCNT_OLE: nRet = SotExchangeDest::DOC_OLEOBJ; break;
+
+ case OBJCNT_CONTROL: /* no Action avail */
+ case OBJCNT_SIMPLE: nRet = SotExchangeDest::DOC_DRAWOBJ; break;
+ case OBJCNT_URLBUTTON: nRet = SotExchangeDest::DOC_URLBUTTON; break;
+ case OBJCNT_GROUPOBJ: nRet = SotExchangeDest::DOC_GROUPOBJ; break;
+
+ // what do we do at multiple selections???
+ default:
+ {
+ if( dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) != nullptr )
+ nRet = SotExchangeDest::SWDOC_FREE_AREA_WEB;
+ else
+ nRet = SotExchangeDest::SWDOC_FREE_AREA;
+ }
+ }
+
+ return nRet;
+}
+
+bool SwTransferable::PasteFileContent( const TransferableDataHelper& rData,
+ SwWrtShell& rSh, SotClipboardFormatId nFormat, bool bMsg, bool bIgnoreComments )
+{
+ TranslateId pResId = STR_CLPBRD_FORMAT_ERROR;
+ bool bRet = false;
+
+ MSE40HTMLClipFormatObj aMSE40ClpObj;
+
+ tools::SvRef<SotTempStream> xStrm;
+ SvStream* pStream = nullptr;
+ Reader* pRead = nullptr;
+ OUString sData;
+ switch( nFormat )
+ {
+ case SotClipboardFormatId::STRING:
+ {
+ pRead = ReadAscii;
+ if( rData.GetString( nFormat, sData ) )
+ {
+ pStream = new SvMemoryStream( const_cast<sal_Unicode *>(sData.getStr()),
+ sData.getLength() * sizeof( sal_Unicode ),
+ StreamMode::READ );
+#ifdef OSL_BIGENDIAN
+ pStream->SetEndian( SvStreamEndian::BIG );
+#else
+ pStream->SetEndian( SvStreamEndian::LITTLE );
+#endif
+
+ SwAsciiOptions aAOpt;
+ aAOpt.SetCharSet( RTL_TEXTENCODING_UCS2 );
+ pRead->GetReaderOpt().SetASCIIOpts( aAOpt );
+ break;
+ }
+ }
+ [[fallthrough]]; // because then test if we get a stream
+
+ default:
+ if( rData.GetSotStorageStream( nFormat, xStrm ) )
+ {
+ if( ( SotClipboardFormatId::HTML_SIMPLE == nFormat ) ||
+ ( SotClipboardFormatId::HTML_NO_COMMENT == nFormat ) )
+ {
+ pStream = aMSE40ClpObj.IsValid( *xStrm );
+ pRead = ReadHTML;
+ pRead->SetReadUTF8( true );
+
+ bool bNoComments =
+ ( nFormat == SotClipboardFormatId::HTML_NO_COMMENT );
+ pRead->SetIgnoreHTMLComments( bNoComments );
+ }
+ else
+ {
+ pStream = xStrm.get();
+ if( SotClipboardFormatId::RTF == nFormat || SotClipboardFormatId::RICHTEXT == nFormat)
+ pRead = SwReaderWriter::GetRtfReader();
+ else if( !pRead )
+ {
+ pRead = ReadHTML;
+ pRead->SetReadUTF8( true );
+ }
+ }
+ }
+ break;
+ }
+
+ if( pStream && pRead )
+ {
+ Link<LinkParamNone*,void> aOldLink( rSh.GetChgLnk() );
+ rSh.SetChgLnk( Link<LinkParamNone*,void>() );
+
+ const SwPosition& rInsPos = *rSh.GetCursor()->Start();
+ SwReader aReader(*pStream, OUString(), OUString(), *rSh.GetCursor());
+ rSh.SaveTableBoxContent( &rInsPos );
+
+ if (bIgnoreComments)
+ pRead->SetIgnoreHTMLComments(true);
+
+ if( aReader.Read( *pRead ).IsError() )
+ pResId = STR_ERROR_CLPBRD_READ;
+ else
+ {
+ pResId = TranslateId();
+ bRet = true;
+ }
+
+ rSh.SetChgLnk( aOldLink );
+ if( bRet )
+ rSh.CallChgLnk();
+ }
+ else
+ pResId = STR_CLPBRD_FORMAT_ERROR;
+
+ // Exist a SvMemoryStream? (data in the OUString and xStrm is empty)
+ if( pStream && !xStrm.is() )
+ delete pStream;
+
+ if (bMsg && pResId)
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(pResId)));
+ xBox->run();
+ }
+ return bRet;
+}
+
+bool SwTransferable::PasteOLE( TransferableDataHelper& rData, SwWrtShell& rSh,
+ SotClipboardFormatId nFormat, SotExchangeActionFlags nActionFlags, bool bMsg )
+{
+ bool bRet = false;
+ TransferableObjectDescriptor aObjDesc;
+ uno::Reference < io::XInputStream > xStrm;
+ uno::Reference < embed::XStorage > xStore;
+ Reader* pRead = nullptr;
+
+ // Get the preferred format
+ SotClipboardFormatId nId;
+ if( rData.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ ) )
+ nId = SotClipboardFormatId::EMBEDDED_OBJ;
+ else if( rData.HasFormat( SotClipboardFormatId::EMBED_SOURCE ) &&
+ rData.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR ))
+ nId = SotClipboardFormatId::EMBED_SOURCE;
+ else
+ nId = SotClipboardFormatId::NONE;
+
+ if (nId != SotClipboardFormatId::NONE)
+ {
+ SwDocShell* pDocSh = rSh.GetDoc()->GetDocShell();
+ xStrm = rData.GetInputStream(nId, SfxObjectShell::CreateShellID(pDocSh));
+ }
+
+ if (xStrm.is())
+ {
+ // if there is an embedded object, first try if it's a writer object
+ // this will be inserted into the document by using a Reader
+ try
+ {
+ xStore = comphelper::OStorageHelper::GetStorageFromInputStream( xStrm );
+ switch( SotStorage::GetFormatID( xStore ) )
+ {
+ case SotClipboardFormatId::STARWRITER_60:
+ case SotClipboardFormatId::STARWRITERWEB_60:
+ case SotClipboardFormatId::STARWRITERGLOB_60:
+ case SotClipboardFormatId::STARWRITER_8:
+ case SotClipboardFormatId::STARWRITERWEB_8:
+ case SotClipboardFormatId::STARWRITERGLOB_8:
+ pRead = ReadXML;
+ break;
+ default:
+ try
+ {
+ xStore->dispose();
+ xStore = nullptr;
+ }
+ catch (const uno::Exception&)
+ {
+ }
+
+ break;
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ // it wasn't a storage, but maybe it's a useful stream
+ }
+ }
+
+ if( pRead )
+ {
+ SwPaM &rPAM = *rSh.GetCursor();
+ SwReader aReader(xStore, OUString(), rPAM);
+ if( ! aReader.Read( *pRead ).IsError() )
+ bRet = true;
+ else if( bMsg )
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_ERROR_CLPBRD_READ)));
+ xBox->run();
+ }
+ }
+ else
+ {
+ // temporary storage until the object is inserted
+ uno::Reference< embed::XStorage > xTmpStor;
+ uno::Reference < embed::XEmbeddedObject > xObj;
+ OUString aName;
+ comphelper::EmbeddedObjectContainer aCnt;
+
+ if ( xStrm.is() )
+ {
+ if ( !rData.GetTransferableObjectDescriptor( SotClipboardFormatId::OBJECTDESCRIPTOR, aObjDesc ) )
+ {
+ OSL_ENSURE( !xStrm.is(), "An object without descriptor in clipboard!");
+ }
+ }
+ else
+ {
+ if( rData.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR_OLE ) && rData.GetTransferableObjectDescriptor( nFormat, aObjDesc ) )
+ {
+ xStrm = rData.GetInputStream(SotClipboardFormatId::EMBED_SOURCE_OLE, OUString());
+ if (!xStrm.is())
+ xStrm = rData.GetInputStream(SotClipboardFormatId::EMBEDDED_OBJ_OLE, OUString());
+
+ if ( !xStrm.is() )
+ {
+ // This is MSOLE object that should be created by direct using of system clipboard
+ try
+ {
+ xTmpStor = ::comphelper::OStorageHelper::GetTemporaryStorage();
+ uno::Reference < embed::XEmbedObjectClipboardCreator > xClipboardCreator =
+ embed::MSOLEObjectSystemCreator::create( ::comphelper::getProcessComponentContext() );
+
+ embed::InsertedObjectInfo aInfo = xClipboardCreator->createInstanceInitFromClipboard(
+ xTmpStor,
+ "DummyName",
+ uno::Sequence< beans::PropertyValue >() );
+
+ // TODO/LATER: in future InsertedObjectInfo will be used to get container related information
+ // for example whether the object should be an iconified one
+ xObj = aInfo.Object;
+ }
+ catch (const uno::Exception&)
+ {
+ }
+ }
+ }
+ else if (rData.HasFormat(SotClipboardFormatId::SIMPLE_FILE))
+ {
+ OUString sFile;
+ if (rData.GetString(nFormat, sFile) && !sFile.isEmpty())
+ {
+ // Copied from sd::View::DropInsertFileHdl
+ uno::Sequence< beans::PropertyValue > aMedium{ comphelper::makePropertyValue(
+ "URL", sFile) };
+ SwDocShell* pDocSh = rSh.GetDoc()->GetDocShell();
+ xObj = pDocSh->GetEmbeddedObjectContainer().InsertEmbeddedObject(aMedium, aName);
+ }
+ }
+ }
+
+ if ( xStrm.is() && !xObj.is() )
+ xObj = aCnt.InsertEmbeddedObject( xStrm, aName );
+
+ if( xObj.is() )
+ {
+ svt::EmbeddedObjectRef xObjRef( xObj, aObjDesc.mnViewAspect );
+
+ // try to get the replacement image from the clipboard
+ Graphic aGraphic;
+ SotClipboardFormatId nGrFormat = SotClipboardFormatId::NONE;
+
+ // limit the size of the preview metafile to 100000 actions
+ GDIMetaFile aMetafile;
+ if (rData.GetGDIMetaFile(SotClipboardFormatId::GDIMETAFILE, aMetafile, 100000))
+ {
+ nGrFormat = SotClipboardFormatId::GDIMETAFILE;
+ aGraphic = aMetafile;
+ }
+
+ // insert replacement image ( if there is one ) into the object helper
+ if ( nGrFormat != SotClipboardFormatId::NONE )
+ {
+ DataFlavor aDataFlavor;
+ SotExchange::GetFormatDataFlavor( nGrFormat, aDataFlavor );
+ xObjRef.SetGraphic( aGraphic, aDataFlavor.MimeType );
+ }
+ else if ( aObjDesc.mnViewAspect == embed::Aspects::MSOLE_ICON )
+ {
+ // it is important to have an icon, let an empty graphic be used
+ // if no other graphic is provided
+ // TODO/LATER: in future a default bitmap could be used
+ MapMode aMapMode( MapUnit::Map100thMM );
+ aGraphic.SetPrefSize( Size( 2500, 2500 ) );
+ aGraphic.SetPrefMapMode( aMapMode );
+ xObjRef.SetGraphic( aGraphic, OUString() );
+ }
+
+ //set size. This is a hack because of handing over, size should be
+ //passed to the InsertOle!!!!!!!!!!
+ Size aSize;
+ if ( aObjDesc.mnViewAspect == embed::Aspects::MSOLE_ICON )
+ {
+ if( aObjDesc.maSize.Width() && aObjDesc.maSize.Height() )
+ aSize = aObjDesc.maSize;
+ else
+ {
+ MapMode aMapMode( MapUnit::Map100thMM );
+ aSize = xObjRef.GetSize( &aMapMode );
+ }
+ }
+ else if( aObjDesc.maSize.Width() && aObjDesc.maSize.Height() )
+ {
+ aSize = aObjDesc.maSize; //always 100TH_MM
+ MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( aObjDesc.mnViewAspect ) );
+ aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(aUnit));
+ awt::Size aSz;
+ try
+ {
+ aSz = xObj->getVisualAreaSize( aObjDesc.mnViewAspect );
+ }
+ catch (const embed::NoVisualAreaSizeException&)
+ {
+ // in this case the provided size is used
+ }
+
+ if ( aSz.Width != aSize.Width() || aSz.Height != aSize.Height() )
+ {
+ aSz.Width = aSize.Width();
+ aSz.Height = aSize.Height();
+ xObj->setVisualAreaSize( aObjDesc.mnViewAspect, aSz );
+ }
+ }
+ else
+ {
+ // the descriptor contains the wrong object size
+ // the following call will let the MSOLE objects cache the size if it is possible
+ // it should be done while the object is running
+ try
+ {
+ xObj->getVisualAreaSize( aObjDesc.mnViewAspect );
+ }
+ catch (const uno::Exception&)
+ {
+ }
+ }
+ //End of Hack!
+
+ rSh.InsertOleObject( xObjRef );
+ bRet = true;
+
+ if( bRet && ( nActionFlags & SotExchangeActionFlags::InsertTargetUrl) )
+ SwTransferable::PasteTargetURL( rData, rSh, SwPasteSdr::NONE, nullptr, false );
+
+ // let the object be unloaded if possible
+ SwOLEObj::UnloadObject( xObj, rSh.GetDoc(), embed::Aspects::MSOLE_CONTENT );
+ }
+ }
+ return bRet;
+}
+
+bool SwTransferable::PasteTargetURL( const TransferableDataHelper& rData,
+ SwWrtShell& rSh, SwPasteSdr nAction,
+ const Point* pPt, bool bInsertGRF )
+{
+ bool bRet = false;
+ INetImage aINetImg;
+ if( ( rData.HasFormat( SotClipboardFormatId::INET_IMAGE ) &&
+ rData.GetINetImage( SotClipboardFormatId::INET_IMAGE, aINetImg )) ||
+ ( rData.HasFormat( SotClipboardFormatId::NETSCAPE_IMAGE ) &&
+ rData.GetINetImage( SotClipboardFormatId::NETSCAPE_IMAGE, aINetImg )) )
+ {
+ if( !aINetImg.GetImageURL().isEmpty() && bInsertGRF )
+ {
+ OUString sURL( aINetImg.GetImageURL() );
+ SwTransferable::CheckForURLOrLNKFile( rData, sURL );
+
+ //!!! check at FileSystem - only then it makes sense to test graphics !!!
+ Graphic aGraphic;
+ GraphicFilter &rFlt = GraphicFilter::GetGraphicFilter();
+ bRet = ERRCODE_NONE == GraphicFilter::LoadGraphic(sURL, OUString(), aGraphic, &rFlt);
+
+ if( bRet )
+ {
+ //Check and Perform rotation if needed
+ lclCheckAndPerformRotation(aGraphic);
+
+ switch( nAction )
+ {
+ case SwPasteSdr::Insert:
+ SwTransferable::SetSelInShell( rSh, false, pPt );
+ rSh.InsertGraphic(sURL, OUString(), aGraphic);
+ break;
+
+ case SwPasteSdr::Replace:
+ if( rSh.IsObjSelected() )
+ {
+ rSh.ReplaceSdrObj( sURL, &aGraphic );
+ Point aPt( pPt ? *pPt : rSh.GetCursorDocPos() );
+ SwTransferable::SetSelInShell( rSh, true, &aPt );
+ }
+ else
+ rSh.ReRead(sURL, OUString(), &aGraphic);
+ break;
+
+ case SwPasteSdr::SetAttr:
+ if( rSh.IsObjSelected() )
+ rSh.Paste( aGraphic, OUString() );
+ else if( OBJCNT_GRF == rSh.GetObjCntTypeOfSelection() )
+ rSh.ReRead(sURL, OUString(), &aGraphic);
+ else
+ {
+ SwTransferable::SetSelInShell( rSh, false, pPt );
+ rSh.InsertGraphic(sURL, OUString(), aGraphic);
+ }
+ break;
+ default:
+ bRet = false;
+ }
+ }
+ }
+ else
+ bRet = true;
+ }
+
+ if( bRet )
+ {
+ SfxItemSetFixed<RES_URL, RES_URL> aSet( rSh.GetAttrPool() );
+ rSh.GetFlyFrameAttr( aSet );
+ SwFormatURL aURL( aSet.Get( RES_URL ) );
+
+ if( aURL.GetURL() != aINetImg.GetTargetURL() ||
+ aURL.GetTargetFrameName() != aINetImg.GetTargetFrame() )
+ {
+ aURL.SetURL( aINetImg.GetTargetURL(), false );
+ aURL.SetTargetFrameName( aINetImg.GetTargetFrame() );
+ aSet.Put( aURL );
+ rSh.SetFlyFrameAttr( aSet );
+ }
+ }
+ return bRet;
+}
+
+void SwTransferable::SetSelInShell( SwWrtShell& rSh, bool bSelectFrame,
+ const Point* pPt )
+{
+ if( bSelectFrame )
+ {
+ // select frames/objects
+ if( pPt && !rSh.GetView().GetViewFrame().GetDispatcher()->IsLocked() )
+ {
+ rSh.GetView().NoRotate();
+ if( rSh.SelectObj( *pPt ))
+ {
+ rSh.HideCursor();
+ rSh.EnterSelFrameMode( pPt );
+ g_bFrameDrag = true;
+ }
+ }
+ }
+ else
+ {
+ if( rSh.IsFrameSelected() || rSh.IsObjSelected() )
+ {
+ rSh.UnSelectFrame();
+ rSh.LeaveSelFrameMode();
+ rSh.GetView().GetEditWin().StopInsFrame();
+ g_bFrameDrag = false;
+ }
+ else if( rSh.GetView().GetDrawFuncPtr() )
+ rSh.GetView().GetEditWin().StopInsFrame();
+
+ rSh.EnterStdMode();
+ if( pPt )
+ rSh.SwCursorShell::SetCursor( *pPt, true );
+ }
+}
+
+bool SwTransferable::PasteDDE( const TransferableDataHelper& rData,
+ SwWrtShell& rWrtShell, bool bReReadGrf,
+ bool bMsg )
+{
+ // data from Clipboardformat
+ OUString aApp, aTopic, aItem;
+
+ {
+ tools::SvRef<SotTempStream> xStrm;
+ if( !rData.GetSotStorageStream( SotClipboardFormatId::LINK, xStrm ))
+ {
+ OSL_ENSURE( false, "DDE Data not found." );
+ return false;
+ } // report useful error!!
+
+ rtl_TextEncoding eEncoding = osl_getThreadTextEncoding();
+ aApp = read_zeroTerminated_uInt8s_ToOUString(*xStrm, eEncoding);
+ aTopic = read_zeroTerminated_uInt8s_ToOUString(*xStrm, eEncoding);
+ aItem = read_zeroTerminated_uInt8s_ToOUString(*xStrm, eEncoding);
+ }
+
+ OUString aCmd;
+ sfx2::MakeLnkName( aCmd, &aApp, aTopic, aItem );
+
+ // do we want to read in a graphic now?
+ SotClipboardFormatId nFormat;
+ if( !rData.HasFormat( SotClipboardFormatId::RTF ) &&
+ !rData.HasFormat( SotClipboardFormatId::RICHTEXT ) &&
+ !rData.HasFormat( SotClipboardFormatId::HTML ) &&
+ !rData.HasFormat( SotClipboardFormatId::STRING ) &&
+ (rData.HasFormat( nFormat = SotClipboardFormatId::GDIMETAFILE ) ||
+ rData.HasFormat( nFormat = SotClipboardFormatId::BITMAP )) )
+ {
+ Graphic aGrf;
+ bool bRet = rData.GetGraphic( nFormat, aGrf );
+ if( bRet )
+ {
+ OUString sLnkTyp("DDE");
+ if ( bReReadGrf )
+ rWrtShell.ReRead( aCmd, sLnkTyp, &aGrf );
+ else
+ rWrtShell.InsertGraphic( aCmd, sLnkTyp, aGrf );
+ }
+ return bRet;
+ }
+
+ SwFieldType* pTyp = nullptr;
+ size_t i = 1;
+ size_t j;
+ OUString aName;
+ bool bDoublePaste = false;
+ const size_t nSize = rWrtShell.GetFieldTypeCount();
+ const ::utl::TransliterationWrapper& rColl = ::GetAppCmpStrIgnore();
+
+ do {
+ aName = aApp + OUString::number( i );
+ for( j = INIT_FLDTYPES; j < nSize; j++ )
+ {
+ pTyp = rWrtShell.GetFieldType( j );
+ if( SwFieldIds::Dde == pTyp->Which() )
+ {
+ if( rColl.isEqual( static_cast<SwDDEFieldType*>(pTyp)->GetCmd(), aCmd ) &&
+ SfxLinkUpdateMode::ALWAYS == static_cast<SwDDEFieldType*>(pTyp)->GetType() )
+ {
+ aName = pTyp->GetName();
+ bDoublePaste = true;
+ break;
+ }
+ else if( rColl.isEqual( aName, pTyp->GetName() ) )
+ break;
+ }
+ }
+ if( j == nSize )
+ break;
+ ++i;
+ }
+ while( !bDoublePaste );
+
+ if( !bDoublePaste )
+ {
+ SwDDEFieldType aType( aName, aCmd, SfxLinkUpdateMode::ALWAYS );
+ pTyp = rWrtShell.InsertFieldType( aType );
+ }
+
+ SwDDEFieldType* pDDETyp = static_cast<SwDDEFieldType*>(pTyp);
+
+ OUString aExpand;
+ if( rData.GetString( SotClipboardFormatId::STRING, aExpand ))
+ {
+ do { // middle checked loop
+
+ const sal_Int32 nNewlines{comphelper::string::getTokenCount(aExpand, '\n')};
+ // When data comes from a spreadsheet, we add a DDE-table
+ if( !aExpand.isEmpty() &&
+ ( rData.HasFormat( SotClipboardFormatId::SYLK ) ||
+ rData.HasFormat( SotClipboardFormatId::SYLK_BIGCAPS ) ) )
+ {
+ sal_Int32 nRows = nNewlines ? nNewlines-1 : 0;
+ if (!aExpand.endsWith("\n"))
+ ++nRows; // last row has no newline, e.g. one single cell
+ const sal_Int32 nCols = comphelper::string::getTokenCount(o3tl::getToken(aExpand, 0, '\n'), '\t');
+
+ // don't try to insert tables that are too large for writer
+ if (nRows > SAL_MAX_UINT16 || nCols > SAL_MAX_UINT16)
+ {
+ if( bMsg )
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_TABLE_TOO_LARGE)));
+ xBox->run();
+ }
+ pDDETyp = nullptr;
+ break;
+ }
+
+ // at least one column & row must be there
+ if( !nRows || !nCols )
+ {
+ if( bMsg )
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_NO_TABLE)));
+ xBox->run();
+ }
+ pDDETyp = nullptr;
+ break;
+ }
+
+ rWrtShell.InsertDDETable(
+ SwInsertTableOptions( SwInsertTableFlags::SplitLayout, 1 ), // TODO MULTIHEADER
+ pDDETyp, nRows, nCols );
+ }
+ else if( nNewlines > 1 )
+ {
+ // multiple paragraphs -> insert a protected section
+ if( rWrtShell.HasSelection() )
+ rWrtShell.DelRight();
+
+ SwSectionData aSect( SectionType::DdeLink, aName );
+ aSect.SetLinkFileName( aCmd );
+ aSect.SetProtectFlag(true);
+ rWrtShell.InsertSection( aSect );
+
+ pDDETyp = nullptr; // remove FieldTypes again
+ }
+ else
+ {
+ // insert
+ SwDDEField aSwDDEField( pDDETyp );
+ rWrtShell.InsertField2( aSwDDEField );
+ }
+
+ } while( false );
+ }
+ else
+ pDDETyp = nullptr; // remove FieldTypes again
+
+ if( !pDDETyp && !bDoublePaste )
+ {
+ // remove FieldType again - error occurred!
+ for( j = nSize; j >= INIT_FLDTYPES; --j )
+ if( pTyp == rWrtShell.GetFieldType( j ) )
+ {
+ rWrtShell.RemoveFieldType( j );
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool SwTransferable::PasteSdrFormat( const TransferableDataHelper& rData,
+ SwWrtShell& rSh, SwPasteSdr nAction,
+ const Point* pPt, SotExchangeActionFlags nActionFlags, bool bNeedToSelectBeforePaste)
+{
+ bool bRet = false;
+ tools::SvRef<SotTempStream> xStrm;
+ if( rData.GetSotStorageStream( SotClipboardFormatId::DRAWING, xStrm ))
+ {
+ xStrm->SetVersion( SOFFICE_FILEFORMAT_50 );
+
+ if(bNeedToSelectBeforePaste && pPt)
+ {
+ // if this is an internal drag, need to set the target right (select it), else
+ // still the source will be selected
+ SwTransferable::SetSelInShell( rSh, true, pPt );
+ }
+
+ rSh.Paste( *xStrm, nAction, pPt );
+ bRet = true;
+
+ if( bRet && ( nActionFlags & SotExchangeActionFlags::InsertTargetUrl ))
+ SwTransferable::PasteTargetURL( rData, rSh, SwPasteSdr::NONE, nullptr, false );
+ }
+ return bRet;
+}
+
+bool SwTransferable::PasteGrf( const TransferableDataHelper& rData, SwWrtShell& rSh,
+ SotClipboardFormatId nFormat, SwPasteSdr nAction, const Point* pPt,
+ SotExchangeActionFlags nActionFlags, sal_Int8 nDropAction, bool bNeedToSelectBeforePaste, RndStdIds nAnchorType )
+{
+ bool bRet = false;
+
+ Graphic aGraphic;
+ INetBookmark aBkmk;
+ bool bCheckForGrf = false, bCheckForImageMap = false;
+
+ switch( nFormat )
+ {
+ case SotClipboardFormatId::BITMAP:
+ case SotClipboardFormatId::PNG:
+ case SotClipboardFormatId::GDIMETAFILE:
+ bRet = rData.GetGraphic( nFormat, aGraphic );
+ break;
+
+ case SotClipboardFormatId::SVXB:
+ {
+ tools::SvRef<SotTempStream> xStm;
+
+ if(rData.GetSotStorageStream(SotClipboardFormatId::SVXB, xStm))
+ {
+ TypeSerializer aSerializer(*xStm);
+ aSerializer.readGraphic(aGraphic);
+ bRet = (GraphicType::NONE != aGraphic.GetType() && GraphicType::Default != aGraphic.GetType());
+ }
+
+ break;
+ }
+
+ case SotClipboardFormatId::NETSCAPE_BOOKMARK:
+ case SotClipboardFormatId::FILEGRPDESCRIPTOR:
+ case SotClipboardFormatId::UNIFORMRESOURCELOCATOR:
+ bRet = rData.GetINetBookmark( nFormat, aBkmk );
+ if( bRet )
+ {
+ if( SwPasteSdr::SetAttr == nAction )
+ nFormat = SotClipboardFormatId::NETSCAPE_BOOKMARK;
+ else
+ bCheckForGrf = true;
+ }
+ break;
+
+ case SotClipboardFormatId::SIMPLE_FILE:
+ {
+ OUString sText;
+ bRet = rData.GetString( nFormat, sText );
+ if( bRet )
+ {
+ OUString sDesc;
+ SwTransferable::CheckForURLOrLNKFile( rData, sText, &sDesc );
+
+ sText = URIHelper::SmartRel2Abs(INetURLObject(), sText, Link<OUString*, bool>(),
+ false);
+
+#ifdef _WIN32
+ // Now that the path could be modified after SwTransferable::CheckForURLOrLNKFile,
+ // where it could have been converted to URL, and made sure it's actually converted
+ // to URL in URIHelper::SmartRel2Abs, we can finally convert file: URL back to
+ // system path to make sure we don't use short path.
+ // It looks not optimal, when we could apply GetLongPathNameW right to the original
+ // pasted filename. But I don't know if (1) all arriving strings are system paths;
+ // and (2) if SwTransferable::CheckForURLOrLNKFile could result in a different short
+ // path, so taking a safe route.
+ if (sText.startsWithIgnoreAsciiCase("file:"))
+ {
+ // tdf#124500: Convert short path to long path which should be used in links
+ OUString sSysPath;
+ osl::FileBase::getSystemPathFromFileURL(sText, sSysPath);
+ std::unique_ptr<sal_Unicode[]> aBuf(new sal_Unicode[32767]);
+ DWORD nCopied = GetLongPathNameW(o3tl::toW(sSysPath.getStr()),
+ o3tl::toW(aBuf.get()), 32767);
+ if (nCopied && nCopied < 32767)
+ sText = URIHelper::SmartRel2Abs(INetURLObject(), OUString(aBuf.get()),
+ Link<OUString*, bool>(), false);
+ }
+#endif
+
+ aBkmk = INetBookmark(sText, sDesc);
+ bCheckForGrf = true;
+ bCheckForImageMap = SwPasteSdr::Replace == nAction;
+ }
+ }
+ break;
+
+ default:
+ bRet = rData.GetGraphic( nFormat, aGraphic );
+ break;
+ }
+
+ if( bCheckForGrf )
+ {
+ //!!! check at FileSystem - only then it makes sense to test the graphics !!!
+ GraphicFilter &rFlt = GraphicFilter::GetGraphicFilter();
+ bRet = ERRCODE_NONE == GraphicFilter::LoadGraphic(aBkmk.GetURL(), OUString(),
+ aGraphic, &rFlt );
+
+ if( !bRet && SwPasteSdr::SetAttr == nAction &&
+ SotClipboardFormatId::SIMPLE_FILE == nFormat &&
+ // only at frame selection
+ rSh.IsFrameSelected() )
+ {
+ // then set as hyperlink after the graphic
+ nFormat = SotClipboardFormatId::NETSCAPE_BOOKMARK;
+ bRet = true;
+ }
+ }
+
+ if(pPt && bNeedToSelectBeforePaste)
+ {
+ // when using internal D&Ds, still the source object is selected and
+ // this is necessary to get the correct source data which is also
+ // dependent from selection. After receiving the drag data it is
+ // now time to select the correct target object
+ SwTransferable::SetSelInShell( rSh, true, pPt );
+ }
+
+ if( bRet )
+ {
+ //Check and Perform rotation if needed
+ lclCheckAndPerformRotation(aGraphic);
+
+ OUString sURL;
+ if( dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) != nullptr
+ // #i123922# if link action is noted, also take URL
+ || DND_ACTION_LINK == nDropAction)
+ {
+ sURL = aBkmk.GetURL();
+ }
+
+ switch( nAction )
+ {
+ case SwPasteSdr::Insert:
+ {
+ SwTransferable::SetSelInShell( rSh, false, pPt );
+ rSh.InsertGraphic(sURL, OUString(), aGraphic, nullptr, nAnchorType);
+ break;
+ }
+
+ case SwPasteSdr::Replace:
+ {
+ if( rSh.IsObjSelected() )
+ {
+ // #i123922# for D&D on draw objects, do for now the same for
+ // SwPasteSdr::Replace (D&D) as for SwPasteSdr::SetAttr (D&D and
+ // CTRL+SHIFT). The code below replaces the draw object with
+ // a writer graphic; maybe this is an option later again if wanted
+ rSh.Paste( aGraphic, sURL );
+
+ // rSh.ReplaceSdrObj(sURL, OUString(), &aGraphic);
+ // Point aPt( pPt ? *pPt : rSh.GetCursorDocPos() );
+ // SwTransferable::SetSelInShell( rSh, true, &aPt );
+ }
+ else
+ {
+ // set graphic at writer graphic without link
+ rSh.ReRead(sURL, OUString(), &aGraphic);
+ }
+
+ break;
+ }
+
+ case SwPasteSdr::SetAttr:
+ {
+ if( SotClipboardFormatId::NETSCAPE_BOOKMARK == nFormat )
+ {
+ if( rSh.IsFrameSelected() )
+ {
+ SfxItemSetFixed<RES_URL, RES_URL> aSet( rSh.GetAttrPool() );
+ rSh.GetFlyFrameAttr( aSet );
+ SwFormatURL aURL( aSet.Get( RES_URL ) );
+ aURL.SetURL( aBkmk.GetURL(), false );
+ aSet.Put( aURL );
+ rSh.SetFlyFrameAttr( aSet );
+ }
+ }
+ else if( rSh.IsObjSelected() )
+ {
+ // set as attribute at DrawObject
+ rSh.Paste( aGraphic, sURL );
+ }
+ else if( OBJCNT_GRF == rSh.GetObjCntTypeOfSelection() )
+ {
+ // set as linked graphic at writer graphic frame
+ rSh.ReRead(sURL, OUString(), &aGraphic);
+ }
+ else
+ {
+ SwTransferable::SetSelInShell( rSh, false, pPt );
+ rSh.InsertGraphic(aBkmk.GetURL(), OUString(), aGraphic);
+ }
+ break;
+ }
+ default:
+ {
+ bRet = false;
+ break;
+ }
+ }
+ }
+
+ if( bRet )
+ {
+
+ if( nActionFlags &
+ ( SotExchangeActionFlags::InsertImageMap | SotExchangeActionFlags::ReplaceImageMap ) )
+ SwTransferable::PasteImageMap( rData, rSh );
+
+ if( nActionFlags & SotExchangeActionFlags::InsertTargetUrl )
+ SwTransferable::PasteTargetURL( rData, rSh, SwPasteSdr::NONE, nullptr, false );
+ }
+ else if( bCheckForImageMap )
+ {
+ // or should the file be an ImageMap-File?
+ ImageMap aMap;
+ SfxMedium aMed( INetURLObject(aBkmk.GetURL()).GetFull(),
+ StreamMode::STD_READ );
+ SvStream* pStream = aMed.GetInStream();
+ if( pStream != nullptr &&
+ !pStream->GetError() &&
+ // mba: no BaseURL for clipboard functionality
+ aMap.Read( *pStream, IMapFormat::Detect ) == IMAP_ERR_OK &&
+ aMap.GetIMapObjectCount() )
+ {
+ SfxItemSetFixed<RES_URL, RES_URL> aSet( rSh.GetAttrPool() );
+ rSh.GetFlyFrameAttr( aSet );
+ SwFormatURL aURL( aSet.Get( RES_URL ) );
+ aURL.SetMap( &aMap );
+ aSet.Put( aURL );
+ rSh.SetFlyFrameAttr( aSet );
+ bRet = true;
+ }
+ }
+
+ return bRet;
+}
+
+bool SwTransferable::PasteImageMap( const TransferableDataHelper& rData,
+ SwWrtShell& rSh )
+{
+ bool bRet = false;
+ if( rData.HasFormat( SotClipboardFormatId::SVIM ))
+ {
+ SfxItemSetFixed<RES_URL, RES_URL> aSet( rSh.GetAttrPool() );
+ rSh.GetFlyFrameAttr( aSet );
+ SwFormatURL aURL( aSet.Get( RES_URL ) );
+ const ImageMap* pOld = aURL.GetMap();
+
+ // set or replace, that is the question
+ ImageMap aImageMap;
+ if( rData.GetImageMap( SotClipboardFormatId::SVIM, aImageMap ) &&
+ ( !pOld || aImageMap != *pOld ))
+ {
+ aURL.SetMap( &aImageMap );
+ aSet.Put( aURL );
+ rSh.SetFlyFrameAttr( aSet );
+ }
+ bRet = true;
+ }
+ return bRet;
+}
+
+bool SwTransferable::PasteAsHyperlink( const TransferableDataHelper& rData,
+ SwWrtShell& rSh, SotClipboardFormatId nFormat )
+{
+ bool bRet = false;
+ OUString sFile;
+ if( rData.GetString( nFormat, sFile ) && !sFile.isEmpty() )
+ {
+ OUString sDesc;
+ SwTransferable::CheckForURLOrLNKFile( rData, sFile, &sDesc );
+
+ // first, make the URL absolute
+ INetURLObject aURL;
+ aURL.SetSmartProtocol( INetProtocol::File );
+ aURL.SetSmartURL( sFile );
+ sFile = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ switch( rSh.GetObjCntTypeOfSelection() )
+ {
+ case OBJCNT_FLY:
+ case OBJCNT_GRF:
+ case OBJCNT_OLE:
+ {
+ SfxItemSetFixed<RES_URL, RES_URL> aSet( rSh.GetAttrPool() );
+ rSh.GetFlyFrameAttr( aSet );
+ SwFormatURL aURL2( aSet.Get( RES_URL ) );
+ aURL2.SetURL( sFile, false );
+ if( aURL2.GetName().isEmpty() )
+ aURL2.SetName( sFile );
+ aSet.Put( aURL2 );
+ rSh.SetFlyFrameAttr( aSet );
+ }
+ break;
+
+ default:
+ {
+ rSh.InsertURL( SwFormatINetFormat( sFile, OUString() ),
+ sDesc.isEmpty() ? sFile : sDesc);
+ }
+ }
+ bRet = true;
+ }
+ return bRet;
+}
+
+bool SwTransferable::PasteFileName( TransferableDataHelper& rData,
+ SwWrtShell& rSh, SotClipboardFormatId nFormat,
+ SwPasteSdr nAction, const Point* pPt,
+ SotExchangeActionFlags nActionFlags,
+ bool * graphicInserted)
+{
+ bool bRet = SwTransferable::PasteGrf( rData, rSh, nFormat, nAction,
+ pPt, nActionFlags, 0, false);
+ if (graphicInserted != nullptr) {
+ *graphicInserted = bRet;
+ }
+ if( !bRet )
+ {
+ OUString sFile, sDesc;
+ if( rData.GetString( nFormat, sFile ) && !sFile.isEmpty() )
+ {
+#if HAVE_FEATURE_AVMEDIA
+ INetURLObject aMediaURL;
+
+ aMediaURL.SetSmartURL( sFile );
+ const OUString aMediaURLStr( aMediaURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
+
+ if( ::avmedia::MediaWindow::isMediaURL( aMediaURLStr, ""/*TODO?*/ ) )
+ {
+ const SfxStringItem aMediaURLItem( SID_INSERT_AVMEDIA, aMediaURLStr );
+ rSh.GetView().GetViewFrame().GetDispatcher()->ExecuteList(
+ SID_INSERT_AVMEDIA, SfxCallMode::SYNCHRON,
+ { &aMediaURLItem });
+ }
+#else
+ if (false)
+ {
+ }
+#endif
+ else
+ {
+ bool bIsURLFile = SwTransferable::CheckForURLOrLNKFile( rData, sFile, &sDesc );
+
+ //Own FileFormat? --> insert, not for StarWriter/Web
+ OUString sFileURL = URIHelper::SmartRel2Abs(INetURLObject(), sFile, Link<OUString *, bool>(), false );
+ std::shared_ptr<const SfxFilter> pFlt = SwPasteSdr::SetAttr == nAction
+ ? nullptr : SwIoSystem::GetFileFilter(sFileURL);
+ if( pFlt && dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) == nullptr )
+ {
+ // and then pull up the insert-region-dialog
+ SwSectionData aSect(
+ SectionType::FileLink,
+ rSh.GetDoc()->GetUniqueSectionName() );
+ aSect.SetLinkFileName( sFileURL );
+ aSect.SetProtectFlag( true );
+
+ rSh.StartInsertRegionDialog( aSect ); // starts dialog asynchronously
+ bRet = true;
+ }
+ else if (SwPasteSdr::Insert == nAction && rData.HasFormat(SotClipboardFormatId::SIMPLE_FILE))
+ {
+ // insert file as OLE
+ PasteOLE(rData, rSh, nFormat, nActionFlags, nullptr == pPt);
+ }
+ else if( SwPasteSdr::SetAttr == nAction ||
+ ( bIsURLFile && SwPasteSdr::Insert == nAction ))
+ {
+ //we can insert foreign files as links after all
+
+ // first, make the URL absolute
+ INetURLObject aURL;
+ aURL.SetSmartProtocol( INetProtocol::File );
+ aURL.SetSmartURL( sFile );
+ sFile = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ switch( rSh.GetObjCntTypeOfSelection() )
+ {
+ case OBJCNT_FLY:
+ case OBJCNT_GRF:
+ case OBJCNT_OLE:
+ {
+ SfxItemSetFixed<RES_URL, RES_URL> aSet( rSh.GetAttrPool() );
+ rSh.GetFlyFrameAttr( aSet );
+ SwFormatURL aURL2( aSet.Get( RES_URL ) );
+ aURL2.SetURL( sFile, false );
+ if( aURL2.GetName().isEmpty() )
+ aURL2.SetName( sFile );
+ aSet.Put( aURL2 );
+ rSh.SetFlyFrameAttr( aSet );
+ }
+ break;
+
+ default:
+ {
+ rSh.InsertURL( SwFormatINetFormat( sFile, OUString() ),
+ sDesc.isEmpty() ? sFile : sDesc );
+ }
+ }
+ bRet = true;
+ }
+ }
+ }
+ }
+ return bRet;
+}
+
+bool SwTransferable::PasteDBData( const TransferableDataHelper& rData,
+ SwWrtShell& rSh, SotClipboardFormatId nFormat, bool bLink,
+ const Point* pDragPt, bool bMsg )
+{
+ bool bRet = false;
+ OUString sText;
+ if( rData.GetString( nFormat, sText ) && !sText.isEmpty() )
+ {
+ sal_uInt16 nWh = SotClipboardFormatId::SBA_CTRLDATAEXCHANGE == nFormat
+ ? 0
+ : SotClipboardFormatId::SBA_DATAEXCHANGE == nFormat
+ ? (bLink
+ ? FN_QRY_MERGE_FIELD
+ : FN_QRY_INSERT)
+ : (bLink
+ ? 0
+ : FN_QRY_INSERT_FIELD );
+ const DataFlavorExVector& rVector = rData.GetDataFlavorExVector();
+ bool bHaveColumnDescriptor = OColumnTransferable::canExtractColumnDescriptor(rVector, ColumnTransferFormatFlags::COLUMN_DESCRIPTOR | ColumnTransferFormatFlags::CONTROL_EXCHANGE);
+ if ( SotClipboardFormatId::XFORMS == nFormat )
+ {
+ rSh.MakeDrawView();
+ FmFormView* pFmView = dynamic_cast<FmFormView*>( rSh.GetDrawView() );
+ if (pFmView && pDragPt)
+ {
+ OXFormsDescriptor aDesc = OXFormsTransferable::extractDescriptor(rData);
+ rtl::Reference<SdrObject> pObj = pFmView->CreateXFormsControl(aDesc);
+ if(pObj)
+ {
+ rSh.SwFEShell::InsertDrawObj( *pObj, *pDragPt );
+ }
+ }
+ }
+ else if( nWh )
+ {
+ std::unique_ptr<SfxUnoAnyItem> pConnectionItem;
+ std::unique_ptr<SfxUnoAnyItem> pCursorItem;
+ std::unique_ptr<SfxUnoAnyItem> pColumnItem;
+ std::unique_ptr<SfxUnoAnyItem> pSourceItem;
+ std::unique_ptr<SfxUnoAnyItem> pCommandItem;
+ std::unique_ptr<SfxUnoAnyItem> pCommandTypeItem;
+ std::unique_ptr<SfxUnoAnyItem> pColumnNameItem;
+ std::unique_ptr<SfxUnoAnyItem> pSelectionItem;
+
+ bool bDataAvailable = true;
+ ODataAccessDescriptor aDesc;
+ if(bHaveColumnDescriptor)
+ aDesc = OColumnTransferable::extractColumnDescriptor(rData);
+ else if(ODataAccessObjectTransferable::canExtractObjectDescriptor(rVector) )
+ aDesc = ODataAccessObjectTransferable::extractObjectDescriptor(rData);
+ else
+ bDataAvailable = false;
+
+ if ( bDataAvailable )
+ {
+ pConnectionItem.reset(new SfxUnoAnyItem(FN_DB_CONNECTION_ANY, aDesc[DataAccessDescriptorProperty::Connection]));
+ pColumnItem.reset(new SfxUnoAnyItem(FN_DB_COLUMN_ANY, aDesc[DataAccessDescriptorProperty::ColumnObject]));
+ pSourceItem.reset(new SfxUnoAnyItem(FN_DB_DATA_SOURCE_ANY, Any(aDesc.getDataSource())));
+ pCommandItem.reset(new SfxUnoAnyItem(FN_DB_DATA_COMMAND_ANY, aDesc[DataAccessDescriptorProperty::Command]));
+ pCommandTypeItem.reset(new SfxUnoAnyItem(FN_DB_DATA_COMMAND_TYPE_ANY, aDesc[DataAccessDescriptorProperty::CommandType]));
+ pColumnNameItem.reset(new SfxUnoAnyItem(FN_DB_DATA_COLUMN_NAME_ANY, aDesc[DataAccessDescriptorProperty::ColumnName]));
+ pSelectionItem.reset(new SfxUnoAnyItem(FN_DB_DATA_SELECTION_ANY, aDesc[DataAccessDescriptorProperty::Selection]));
+ pCursorItem.reset(new SfxUnoAnyItem(FN_DB_DATA_CURSOR_ANY, aDesc[DataAccessDescriptorProperty::Cursor]));
+ }
+
+ SwView& rView = rSh.GetView();
+ //force ::SelectShell
+ rView.StopShellTimer();
+
+ SfxStringItem aDataDesc( nWh, sText );
+ rView.GetViewFrame().GetDispatcher()->ExecuteList(
+ nWh, SfxCallMode::ASYNCHRON,
+ { &aDataDesc, pConnectionItem.get(), pColumnItem.get(),
+ pSourceItem.get(), pCommandItem.get(), pCommandTypeItem.get(),
+ pColumnNameItem.get(), pSelectionItem.get(),
+ pCursorItem.get() });
+ }
+ else
+ {
+ rSh.MakeDrawView();
+ FmFormView* pFmView = dynamic_cast<FmFormView*>( rSh.GetDrawView() );
+ if (pFmView && bHaveColumnDescriptor && pDragPt)
+ {
+ rtl::Reference<SdrObject> pObj = pFmView->CreateFieldControl( OColumnTransferable::extractColumnDescriptor(rData) );
+ if (pObj)
+ rSh.SwFEShell::InsertDrawObj( *pObj, *pDragPt );
+ }
+ }
+ bRet = true;
+ }
+ else if( bMsg )
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_CLPBRD_FORMAT_ERROR)));
+ xBox->run();
+ }
+ return bRet;
+}
+
+bool SwTransferable::PasteFileList( const TransferableDataHelper& rData,
+ SwWrtShell& rSh, bool bLink,
+ const Point* pPt, bool bMsg )
+{
+ bool bRet = false;
+ FileList aFileList;
+ if( rData.GetFileList( SotClipboardFormatId::FILE_LIST, aFileList ) &&
+ aFileList.Count() )
+ {
+ SwPasteSdr nAct = bLink ? SwPasteSdr::SetAttr : SwPasteSdr::Insert;
+ OUString sFlyNm;
+ // iterate over the filelist
+ for( sal_uLong n = 0, nEnd = aFileList.Count(); n < nEnd; ++n )
+ {
+ rtl::Reference<TransferDataContainer> pHlp = new TransferDataContainer;
+ pHlp->CopyString( SotClipboardFormatId::SIMPLE_FILE, aFileList.GetFile( n ));
+ TransferableDataHelper aData( pHlp );
+
+ if( SwTransferable::PasteFileName( aData, rSh, SotClipboardFormatId::SIMPLE_FILE, nAct,
+ pPt, SotExchangeActionFlags::NONE, nullptr ))
+ {
+ if( bLink )
+ {
+ sFlyNm = rSh.GetFlyName();
+ SwTransferable::SetSelInShell( rSh, false, pPt );
+ }
+ bRet = true;
+ }
+ }
+ if( !sFlyNm.isEmpty() )
+ rSh.GotoFly( sFlyNm );
+ }
+ else if( bMsg )
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_CLPBRD_FORMAT_ERROR)));
+ xBox->run();
+ }
+ return bRet;
+}
+
+bool SwTransferable::CheckForURLOrLNKFile( const TransferableDataHelper& rData,
+ OUString& rFileName, OUString* pTitle )
+{
+ bool bIsURLFile = false;
+ INetBookmark aBkmk;
+ if( rData.GetINetBookmark( SotClipboardFormatId::SOLK, aBkmk ) )
+ {
+ rFileName = aBkmk.GetURL();
+ if( pTitle )
+ *pTitle = aBkmk.GetDescription();
+ bIsURLFile = true;
+ }
+ else
+ {
+ if( rFileName.getLength()>4 && rFileName.endsWithIgnoreAsciiCase(".url") )
+ {
+ OSL_ENSURE( false, "how do we read today .URL - Files?" );
+ }
+ }
+ return bIsURLFile;
+}
+
+bool SwTransferable::IsPasteSpecial( const SwWrtShell& rWrtShell,
+ const TransferableDataHelper& rData )
+{
+ // we can paste-special if there's an entry in the paste-special-format list
+ SvxClipboardFormatItem aClipboardFormatItem(TypedWhichId<SvxClipboardFormatItem>(0));
+ FillClipFormatItem( rWrtShell, rData, aClipboardFormatItem);
+ return aClipboardFormatItem.Count() > 0;
+}
+
+bool SwTransferable::IsPasteOwnFormat( const TransferableDataHelper& rData )
+{
+ return ( GetSwTransferable( rData ) != nullptr );
+}
+
+bool SwTransferable::PasteFormat( SwWrtShell& rSh,
+ TransferableDataHelper& rData,
+ SotClipboardFormatId nFormat )
+{
+ SwWait aWait( *rSh.GetView().GetDocShell(), false );
+ bool bRet = false;
+
+ SotClipboardFormatId nPrivateFormat = SotClipboardFormatId::PRIVATE;
+ SwTransferable *pClipboard = GetSwTransferable( rData );
+ if( pClipboard &&
+ ((TransferBufferType::Document|TransferBufferType::Graphic|TransferBufferType::Ole) & pClipboard->m_eBufferType ))
+ nPrivateFormat = SotClipboardFormatId::EMBED_SOURCE;
+
+ if( pClipboard && nPrivateFormat == nFormat )
+ bRet = pClipboard->PrivatePaste( rSh );
+ else if( rData.HasFormat( nFormat ) )
+ {
+ uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );
+ sal_uInt8 nEventAction;
+ SotExchangeDest nDestination = SwTransferable::GetSotDestination( rSh );
+ sal_uInt16 nSourceOptions =
+ (( SotExchangeDest::DOC_TEXTFRAME == nDestination ||
+ SotExchangeDest::SWDOC_FREE_AREA == nDestination ||
+ SotExchangeDest::DOC_TEXTFRAME_WEB == nDestination ||
+ SotExchangeDest::SWDOC_FREE_AREA_WEB == nDestination )
+ ? EXCHG_IN_ACTION_COPY
+ : EXCHG_IN_ACTION_MOVE);
+ SotExchangeActionFlags nActionFlags;
+ sal_uInt8 nAction = SotExchange::GetExchangeAction(
+ rData.GetDataFlavorExVector(),
+ nDestination,
+ nSourceOptions, /* ?? */
+ EXCHG_IN_ACTION_DEFAULT, /* ?? */
+ nFormat, nEventAction, nFormat,
+ lcl_getTransferPointer ( xTransferable ),
+ &nActionFlags );
+
+ if( EXCHG_INOUT_ACTION_NONE != nAction )
+ bRet = SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat,
+ nDestination, true, false );
+ }
+ return bRet;
+}
+
+bool SwTransferable::TestAllowedFormat( const TransferableDataHelper& rData,
+ SotClipboardFormatId nFormat, SotExchangeDest nDestination )
+{
+ sal_uInt8 nAction = EXCHG_INOUT_ACTION_NONE;
+ if( rData.HasFormat( nFormat )) {
+ uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );
+ sal_uInt8 nEventAction;
+ nAction = SotExchange::GetExchangeAction(
+ rData.GetDataFlavorExVector(),
+ nDestination, EXCHG_IN_ACTION_COPY,
+ EXCHG_IN_ACTION_COPY, nFormat,
+ nEventAction, nFormat,
+ lcl_getTransferPointer ( xTransferable ) );
+ }
+ return EXCHG_INOUT_ACTION_NONE != nAction;
+}
+
+/**
+ * the list of formats which will be offered to the user in the 'Paste
+ * Special...' dialog and the paste button menu
+ */
+static SotClipboardFormatId aPasteSpecialIds[] =
+{
+ SotClipboardFormatId::HTML,
+ SotClipboardFormatId::HTML_SIMPLE,
+ SotClipboardFormatId::HTML_NO_COMMENT,
+ SotClipboardFormatId::RTF,
+ SotClipboardFormatId::RICHTEXT,
+ SotClipboardFormatId::STRING,
+ SotClipboardFormatId::SONLK,
+ SotClipboardFormatId::NETSCAPE_BOOKMARK,
+ SotClipboardFormatId::DRAWING,
+ SotClipboardFormatId::SVXB,
+ SotClipboardFormatId::GDIMETAFILE,
+ SotClipboardFormatId::BITMAP,
+ SotClipboardFormatId::SVIM,
+ SotClipboardFormatId::FILEGRPDESCRIPTOR,
+ SotClipboardFormatId::NONE
+};
+
+bool SwTransferable::PasteUnformatted( SwWrtShell& rSh, TransferableDataHelper& rData )
+{
+ // Plain text == unformatted
+ return SwTransferable::PasteFormat( rSh, rData, SotClipboardFormatId::STRING );
+}
+
+void SwTransferable::PrePasteSpecial( const SwWrtShell& rSh, TransferableDataHelper& rData, const VclPtr<SfxAbstractPasteDialog>& pDlg )
+{
+ DataFlavorExVector aFormats( rData.GetDataFlavorExVector() );
+ TransferableObjectDescriptor aDesc;
+
+ SotExchangeDest nDest = SwTransferable::GetSotDestination( rSh );
+
+ SwTransferable *pClipboard = GetSwTransferable( rData );
+ if( pClipboard )
+ {
+ aDesc = pClipboard->m_aObjDesc;
+ TranslateId pResId;
+ if( pClipboard->m_eBufferType & TransferBufferType::Document )
+ pResId = STR_PRIVATETEXT;
+ else if( pClipboard->m_eBufferType & TransferBufferType::Graphic )
+ pResId = STR_PRIVATEGRAPHIC;
+ else if( pClipboard->m_eBufferType == TransferBufferType::Ole )
+ pResId = STR_PRIVATEOLE;
+
+ if (pResId)
+ {
+ if (STR_PRIVATEOLE == pResId || STR_PRIVATEGRAPHIC == pResId)
+ {
+ // add SotClipboardFormatId::EMBED_SOURCE to the formats. This
+ // format display then the private format name.
+ DataFlavorEx aFlavorEx;
+ aFlavorEx.mnSotId = SotClipboardFormatId::EMBED_SOURCE;
+ aFormats.insert( aFormats.begin(), aFlavorEx );
+ }
+ pDlg->SetObjName( pClipboard->m_aObjDesc.maClassName,
+ SwResId(pResId) );
+ pDlg->Insert( SotClipboardFormatId::EMBED_SOURCE, OUString() );
+ }
+ }
+ else
+ {
+ if( rData.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR ) )
+ {
+ (void)rData.GetTransferableObjectDescriptor(
+ SotClipboardFormatId::OBJECTDESCRIPTOR, aDesc );
+ }
+
+ if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::EMBED_SOURCE, nDest ))
+ pDlg->Insert( SotClipboardFormatId::EMBED_SOURCE, OUString() );
+ if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::LINK_SOURCE, nDest ))
+ pDlg->Insert( SotClipboardFormatId::LINK_SOURCE, OUString() );
+ }
+
+ if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::LINK, nDest ))
+ pDlg->Insert( SotClipboardFormatId::LINK, SwResId(STR_DDEFORMAT) );
+
+ for( SotClipboardFormatId* pIds = aPasteSpecialIds; *pIds != SotClipboardFormatId::NONE; ++pIds )
+ if( SwTransferable::TestAllowedFormat( rData, *pIds, nDest ))
+ pDlg->Insert( *pIds, OUString() );
+}
+
+void SwTransferable::FillClipFormatItem( const SwWrtShell& rSh,
+ const TransferableDataHelper& rData,
+ SvxClipboardFormatItem & rToFill )
+{
+ SotExchangeDest nDest = SwTransferable::GetSotDestination( rSh );
+
+ SwTransferable *pClipboard = GetSwTransferable( rData );
+ if( pClipboard )
+ {
+ TranslateId pResId;
+ if( pClipboard->m_eBufferType & TransferBufferType::Document )
+ pResId = STR_PRIVATETEXT;
+ else if( pClipboard->m_eBufferType & TransferBufferType::Graphic )
+ pResId = STR_PRIVATEGRAPHIC;
+ else if( pClipboard->m_eBufferType == TransferBufferType::Ole )
+ pResId = STR_PRIVATEOLE;
+
+ if (pResId)
+ rToFill.AddClipbrdFormat(SotClipboardFormatId::EMBED_SOURCE,
+ SwResId(pResId));
+ }
+ else
+ {
+ TransferableObjectDescriptor aDesc;
+ if (rData.HasFormat(SotClipboardFormatId::OBJECTDESCRIPTOR))
+ {
+ (void)rData.GetTransferableObjectDescriptor(
+ SotClipboardFormatId::OBJECTDESCRIPTOR, aDesc);
+ }
+
+ if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::EMBED_SOURCE, nDest ))
+ rToFill.AddClipbrdFormat( SotClipboardFormatId::EMBED_SOURCE,
+ aDesc.maTypeName );
+ if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::LINK_SOURCE, nDest ))
+ rToFill.AddClipbrdFormat( SotClipboardFormatId::LINK_SOURCE );
+
+ SotClipboardFormatId nFormat;
+ if ( rData.HasFormat(nFormat = SotClipboardFormatId::EMBED_SOURCE_OLE) || rData.HasFormat(nFormat = SotClipboardFormatId::EMBEDDED_OBJ_OLE) )
+ {
+ OUString sName,sSource;
+ if ( SvPasteObjectHelper::GetEmbeddedName(rData,sName,sSource,nFormat) )
+ rToFill.AddClipbrdFormat( nFormat, sName );
+ }
+ }
+
+ if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::LINK, nDest ))
+ rToFill.AddClipbrdFormat( SotClipboardFormatId::LINK, SwResId(STR_DDEFORMAT) );
+
+ for( SotClipboardFormatId* pIds = aPasteSpecialIds; *pIds != SotClipboardFormatId::NONE; ++pIds )
+ if( SwTransferable::TestAllowedFormat( rData, *pIds, nDest ))
+ rToFill.AddClipbrdFormat(*pIds, OUString());
+}
+
+void SwTransferable::SetDataForDragAndDrop( const Point& rSttPos )
+{
+ if(!m_pWrtShell)
+ return;
+ OUString sGrfNm;
+ const SelectionType nSelection = m_pWrtShell->GetSelectionType();
+ if( SelectionType::Graphic == nSelection)
+ {
+ AddFormat( SotClipboardFormatId::SVXB );
+ const Graphic* pGrf = m_pWrtShell->GetGraphic();
+ if ( pGrf && pGrf->IsSupportedGraphic() )
+ {
+ AddFormat( SotClipboardFormatId::GDIMETAFILE );
+ AddFormat( SotClipboardFormatId::PNG );
+ AddFormat( SotClipboardFormatId::BITMAP );
+ }
+ m_eBufferType = TransferBufferType::Graphic;
+ m_pWrtShell->GetGrfNms( &sGrfNm, nullptr );
+ }
+ else if( SelectionType::Ole == nSelection )
+ {
+ AddFormat( SotClipboardFormatId::EMBED_SOURCE );
+ PrepareOLE( m_aObjDesc );
+ AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
+ AddFormat( SotClipboardFormatId::GDIMETAFILE );
+ m_eBufferType = TransferBufferType::Ole;
+ }
+ //Is there anything to provide anyway?
+ else if ( m_pWrtShell->IsSelection() || m_pWrtShell->IsFrameSelected() ||
+ m_pWrtShell->IsObjSelected() )
+ {
+ if( m_pWrtShell->IsObjSelected() )
+ m_eBufferType = TransferBufferType::Drawing;
+ else
+ {
+ m_eBufferType = TransferBufferType::Document;
+ if( SwWrtShell::NO_WORD !=
+ m_pWrtShell->IntelligentCut( nSelection, false ))
+ m_eBufferType = TransferBufferType::DocumentWord | m_eBufferType;
+ }
+
+ if( nSelection & SelectionType::TableCell )
+ m_eBufferType = TransferBufferType::Table | m_eBufferType;
+
+ AddFormat( SotClipboardFormatId::EMBED_SOURCE );
+
+ //put RTF ahead of the OLE's Metafile for less loss
+ if( !m_pWrtShell->IsObjSelected() )
+ {
+ AddFormat( SotClipboardFormatId::RTF );
+ AddFormat( SotClipboardFormatId::RICHTEXT );
+ AddFormat( SotClipboardFormatId::HTML );
+ }
+ if( m_pWrtShell->IsSelection() )
+ AddFormat( SotClipboardFormatId::STRING );
+
+ if( nSelection & ( SelectionType::DrawObject | SelectionType::DbForm ))
+ {
+ AddFormat( SotClipboardFormatId::DRAWING );
+ if ( nSelection & SelectionType::DrawObject )
+ {
+ AddFormat( SotClipboardFormatId::GDIMETAFILE );
+ AddFormat( SotClipboardFormatId::PNG );
+ AddFormat( SotClipboardFormatId::BITMAP );
+ }
+ m_eBufferType = TransferBufferType::Graphic | m_eBufferType;
+
+ // is it a URL-Button ?
+ OUString sURL;
+ OUString sDesc;
+ if( m_pWrtShell->GetURLFromButton( sURL, sDesc ) )
+ {
+ AddFormat( SotClipboardFormatId::STRING );
+ AddFormat( SotClipboardFormatId::SOLK );
+ AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
+ AddFormat( SotClipboardFormatId::FILECONTENT );
+ AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR );
+ AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR );
+ m_eBufferType = TransferBufferType::InetField | m_eBufferType;
+ }
+ }
+
+ //ObjectDescriptor was already filled from the old DocShell.
+ //Now adjust it. Thus in GetData the first query can still
+ //be answered with delayed rendering.
+ m_aObjDesc.maDragStartPos = rSttPos;
+ m_aObjDesc.maSize = constOleSize100mm;
+
+ PrepareOLE( m_aObjDesc );
+ AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
+ }
+ else if( nSelection & SelectionType::Text && !m_pWrtShell->HasMark() )
+ {
+ // is only one field - selected?
+ SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );
+ Point aPos( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY());
+
+ if( m_pWrtShell->GetContentAtPos( aPos, aContentAtPos ) )
+ {
+ AddFormat( SotClipboardFormatId::STRING );
+ AddFormat( SotClipboardFormatId::SOLK );
+ AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
+ AddFormat( SotClipboardFormatId::FILECONTENT );
+ AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR );
+ AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR );
+ m_eBufferType = TransferBufferType::InetField;
+ }
+ }
+
+ if( !m_pWrtShell->IsFrameSelected() )
+ return;
+
+ SfxItemSetFixed<RES_URL, RES_URL> aSet( m_pWrtShell->GetAttrPool() );
+ m_pWrtShell->GetFlyFrameAttr( aSet );
+ const SwFormatURL& rURL = aSet.Get( RES_URL );
+ if( rURL.GetMap() )
+ {
+ m_pImageMap.reset( new ImageMap( *rURL.GetMap() ) );
+ AddFormat( SotClipboardFormatId::SVIM );
+ }
+ else if( !rURL.GetURL().isEmpty() )
+ {
+ m_pTargetURL.reset(new INetImage( sGrfNm, rURL.GetURL(),
+ rURL.GetTargetFrameName() ));
+ AddFormat( SotClipboardFormatId::INET_IMAGE );
+ }
+}
+
+void SwTransferable::StartDrag( vcl::Window* pWin, const Point& rPos )
+{
+ if(!m_pWrtShell)
+ return;
+ m_bOldIdle = m_pWrtShell->GetViewOptions()->IsIdle();
+ m_bCleanUp = true;
+
+ m_pWrtShell->GetViewOptions()->SetIdle( false );
+
+ if( m_pWrtShell->IsSelFrameMode() )
+ m_pWrtShell->ShowCursor();
+
+ SW_MOD()->m_pDragDrop = this;
+
+ SetDataForDragAndDrop( rPos );
+
+ sal_Int8 nDragOptions = DND_ACTION_COPYMOVE | DND_ACTION_LINK;
+ SwDocShell* pDShell = m_pWrtShell->GetView().GetDocShell();
+ if( ( pDShell && pDShell->IsReadOnly() ) || m_pWrtShell->HasReadonlySel() )
+ nDragOptions &= ~DND_ACTION_MOVE;
+
+ TransferableHelper::StartDrag( pWin, nDragOptions );
+}
+
+void SwTransferable::DragFinished( sal_Int8 nAction )
+{
+ //And the last finishing work so that all statuses are right
+ if( DND_ACTION_MOVE == nAction )
+ {
+ if( m_bCleanUp )
+ {
+ //It was dropped outside of Writer. We still have to
+ //delete.
+
+ m_pWrtShell->StartAllAction();
+ m_pWrtShell->StartUndo( SwUndoId::UI_DRAG_AND_MOVE );
+ if ( m_pWrtShell->IsTableMode() )
+ m_pWrtShell->DeleteTableSel();
+ else
+ {
+ if ( !(m_pWrtShell->IsSelFrameMode() || m_pWrtShell->IsObjSelected()) )
+ //SmartCut, take one of the blanks along
+ m_pWrtShell->IntelligentCut( m_pWrtShell->GetSelectionType() );
+ m_pWrtShell->DelRight();
+ }
+ m_pWrtShell->EndUndo( SwUndoId::UI_DRAG_AND_MOVE );
+ m_pWrtShell->EndAllAction();
+ }
+ else
+ {
+ const SelectionType nSelection = m_pWrtShell->GetSelectionType();
+ if( ( SelectionType::Frame | SelectionType::Graphic |
+ SelectionType::Ole | SelectionType::DrawObject ) & nSelection )
+ {
+ m_pWrtShell->EnterSelFrameMode();
+ }
+ }
+ }
+ m_pWrtShell->GetView().GetEditWin().DragFinished();
+
+ if( m_pWrtShell->IsSelFrameMode() )
+ m_pWrtShell->HideCursor();
+ else
+ m_pWrtShell->ShowCursor();
+
+ m_pWrtShell->GetViewOptions()->SetIdle( m_bOldIdle );
+}
+
+namespace
+{
+
+bool lcl_checkClassification(SwDoc* pSourceDoc, SwDoc* pDestinationDoc)
+{
+ if (!pSourceDoc || !pDestinationDoc)
+ return true;
+
+ SwDocShell* pSourceShell = pSourceDoc->GetDocShell();
+ SwDocShell* pDestinationShell = pDestinationDoc->GetDocShell();
+ if (!pSourceShell || !pDestinationShell)
+ return true;
+
+ SfxClassificationCheckPasteResult eResult = SfxClassificationHelper::CheckPaste(pSourceShell->getDocProperties(), pDestinationShell->getDocProperties());
+ return SfxClassificationHelper::ShowPasteInfo(eResult);
+}
+
+}
+
+bool SwTransferable::PrivatePaste(SwWrtShell& rShell, SwPasteContext* pContext, PasteTableType ePasteTable)
+{
+ // first, ask for the SelectionType, then action-bracketing !!!!
+ // (otherwise it's not pasted into a TableSelection!!!)
+ OSL_ENSURE( !rShell.ActionPend(), "Paste must never have an ActionPend" );
+ if ( !m_pClpDocFac )
+ return false; // the return value of the SwFEShell::Paste also is bool!
+
+ const SelectionType nSelection = rShell.GetSelectionType();
+
+ SwTrnsfrActionAndUndo aAction( &rShell );
+
+ bool bKillPaMs = false;
+
+ //Delete selected content, not at table-selection and table in Clipboard, and don't delete hovering graphics.
+ if( rShell.HasSelection() && !( nSelection & SelectionType::TableCell) && !( nSelection & SelectionType::DrawObject))
+ {
+ if (!(nSelection & SelectionType::NumberList))
+ {
+ bKillPaMs = true;
+ rShell.SetRetainSelection( true );
+ }
+ if (pContext)
+ pContext->forget();
+ rShell.DelRight();
+ if (pContext)
+ pContext->remember();
+ // when a Fly was selected, a valid cursor position has to be found now
+ // (parked Cursor!)
+ if( ( SelectionType::Frame | SelectionType::Graphic |
+ SelectionType::Ole | SelectionType::DrawObject |
+ SelectionType::DbForm ) & nSelection )
+ {
+ // position the cursor again
+ Point aPt( rShell.GetCharRect().Pos() );
+ rShell.SwCursorShell::SetCursor( aPt, true );
+ }
+ if (!(nSelection & SelectionType::NumberList))
+ {
+ rShell.SetRetainSelection( false );
+ }
+ }
+ if ( nSelection & SelectionType::DrawObject) //unselect hovering graphics
+ {
+ rShell.ResetSelect(nullptr,false);
+ }
+
+ bool bInWrd = false, bEndWrd = false, bSttWrd = false,
+ bSmart(TransferBufferType::DocumentWord & m_eBufferType);
+ if( bSmart )
+ {
+ // Why not for other Scripts? If TransferBufferType::DocumentWord is set, we have a word
+ // in the buffer, word in this context means 'something with spaces at beginning
+ // and end'. In this case we definitely want these spaces to be inserted here.
+ bInWrd = rShell.IsInWord();
+ bEndWrd = rShell.IsEndWrd();
+ bSmart = bInWrd || bEndWrd;
+ if( bSmart )
+ {
+ bSttWrd = rShell.IsStartWord();
+ if (!bSttWrd && (bInWrd || bEndWrd))
+ rShell.SwEditShell::Insert(' ');
+ }
+ }
+
+ bool bRet = true;
+ // m_pWrtShell is nullptr when the source document is closed already.
+ if (!m_pWrtShell || lcl_checkClassification(m_pWrtShell->GetDoc(), rShell.GetDoc()))
+ bRet = rShell.Paste(m_pClpDocFac->GetDoc(), ePasteTable == PasteTableType::PASTE_TABLE);
+
+ if( bKillPaMs )
+ rShell.KillPams();
+
+ // If Smart Paste then insert blank
+ if( bRet && bSmart && ((bInWrd && !bEndWrd )|| bSttWrd) )
+ rShell.SwEditShell::Insert(' ');
+
+ return bRet;
+}
+
+bool SwTransferable::PrivateDrop( SwWrtShell& rSh, const Point& rDragPt,
+ bool bMove, bool bIsXSelection )
+{
+ int cWord = 0;
+ bool bInWrd = false;
+ bool bEndWrd = false;
+ bool bSttWrd = false;
+ bool bSttPara = false;
+ bool bTableSel = false;
+ bool bTableMove = false;
+ bool bFrameSel = false;
+
+ SwWrtShell& rSrcSh = *GetShell();
+
+ rSh.UnSetVisibleCursor();
+
+ if( TransferBufferType::InetField == m_eBufferType )
+ {
+ if( rSh.GetFormatFromObj( rDragPt ) )
+ {
+ INetBookmark aTmp;
+ if( (TransferBufferType::InetField & m_eBufferType) && m_oBookmark )
+ aTmp = *m_oBookmark;
+
+ // select target graphic
+ if( rSh.SelectObj( rDragPt ) )
+ {
+ rSh.HideCursor();
+ rSh.EnterSelFrameMode( &rDragPt );
+ g_bFrameDrag = true;
+ }
+
+ const SelectionType nSelection = rSh.GetSelectionType();
+
+ // not yet consider Draw objects
+ if( SelectionType::Graphic & nSelection )
+ {
+ SfxItemSetFixed<RES_URL, RES_URL> aSet( rSh.GetAttrPool() );
+ rSh.GetFlyFrameAttr( aSet );
+ SwFormatURL aURL( aSet.Get( RES_URL ) );
+ aURL.SetURL( aTmp.GetURL(), false );
+ aSet.Put( aURL );
+ rSh.SetFlyFrameAttr( aSet );
+ return true;
+ }
+
+ if( SelectionType::DrawObject & nSelection )
+ {
+ rSh.LeaveSelFrameMode();
+ rSh.UnSelectFrame();
+ rSh.ShowCursor();
+ g_bFrameDrag = false;
+ }
+ }
+ }
+
+ if( &rSh != &rSrcSh && (SelectionType::Graphic & rSh.GetSelectionType()) &&
+ TransferBufferType::Graphic == m_eBufferType )
+ {
+ // ReRead the graphic
+ OUString sGrfNm;
+ OUString sFltNm;
+ rSrcSh.GetGrfNms( &sGrfNm, &sFltNm );
+ rSh.ReRead( sGrfNm, sFltNm, rSrcSh.GetGraphic() );
+ return true;
+ }
+
+ //not in selections or selected frames
+ if( rSh.TestCurrPam( rDragPt ) ||
+ ( rSh.IsSelFrameMode() && rSh.IsInsideSelectedObj( rDragPt )) )
+ return false;
+
+ if( rSrcSh.IsTableMode() )
+ {
+ bTableSel = true;
+ const SelectionType nSelection = rSrcSh.GetSelectionType();
+ // at enhanced table row/column selection or wholly selected tables,
+ // paste rows above or columns before, and in the case of moving, remove the selection
+ // (limit only to the single document case temporarily)
+ if( rSrcSh.GetDoc() == rSh.GetDoc() &&
+ ( (( SelectionType::TableRow | SelectionType::TableCol) & nSelection ) || rSrcSh.HasWholeTabSelection() ) )
+ {
+ bool bTableCol(SelectionType::TableCol & nSelection);
+
+ ::sw::mark::IMark* pMarkMoveFrom = bMove
+ ? rSh.SetBookmark(
+ vcl::KeyCode(),
+ OUString(),
+ IDocumentMarkAccess::MarkType::UNO_BOOKMARK )
+ : nullptr;
+
+ // row count and direction of the table selection:
+ // up to down, if the cursor is there in its last table row
+ const SwSelBoxes& rBoxes = rSrcSh.GetTableCursor()->GetSelectedBoxes();
+ const SwTableNode* pTableNd = rSh.IsCursorInTable();
+ if (!pTableNd)
+ {
+ SAL_WARN("sw", "presumably this case can't arise in practice");
+ return false;
+ }
+ const SwTableLines& rLines = pTableNd->GetTable().GetTabLines();
+ const SwStartNode& rDelPos = rBoxes.back()
+ ? *rBoxes.front()->GetSttNd()
+ : *pTableNd->GetStartNode();
+
+ // count selected rows or columns
+ sal_Int32 nSelRowOrCols = 0;
+ if ( rBoxes.back() )
+ {
+ if ( bTableCol )
+ {
+ // selected column count is the count of the cells
+ // in the first row of the selection
+ auto nLine = rLines.GetPos( rBoxes.front()->GetUpper() );
+ for (auto pBox : rBoxes)
+ {
+ // cell is in the next row
+ if ( nLine != rLines.GetPos( pBox->GetUpper() ) )
+ break;
+ ++nSelRowOrCols;
+ }
+ }
+ else
+ {
+ // selected row count is the difference of the row number of the
+ // first and the last cell of the selection
+ nSelRowOrCols = rLines.GetPos( rBoxes.back()->GetUpper() ) -
+ rLines.GetPos( rBoxes.front()->GetUpper() ) + 1;
+ }
+ }
+
+ bool bSelUpToDown = rBoxes.back() && rBoxes.back()->GetUpper() ==
+ rSh.GetCursor()->GetPointNode().GetTableBox()->GetUpper();
+
+ SwUndoId eUndoId = bMove ? SwUndoId::UI_DRAG_AND_MOVE : SwUndoId::UI_DRAG_AND_COPY;
+
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UndoArg1, rSrcSh.GetSelDescr());
+
+ if(rSrcSh.GetDoc() != rSh.GetDoc())
+ rSrcSh.StartUndo( eUndoId, &aRewriter );
+ rSh.StartUndo( eUndoId, &aRewriter );
+
+ rSh.StartAction();
+ rSrcSh.StartAction();
+
+ SfxDispatcher* pDispatch = rSrcSh.GetView().GetViewFrame().GetDispatcher();
+ pDispatch->Execute(SID_COPY, SfxCallMode::SYNCHRON);
+
+ rSrcSh.Push(); // save selection for later restoration
+ rSh.EnterStdMode();
+ rSh.SwCursorShell::SetCursor(rDragPt, false);
+
+ bool bPasteIntoTable = rSh.GetCursor()->GetPointNode().GetTableBox() != nullptr;
+
+ // store cursor
+ ::sw::mark::IMark* pMark = rSh.SetBookmark(
+ vcl::KeyCode(),
+ OUString(),
+ IDocumentMarkAccess::MarkType::UNO_BOOKMARK );
+
+ // paste rows above/columns before
+ pDispatch->Execute(bTableCol ? FN_TABLE_PASTE_COL_BEFORE : FN_TABLE_PASTE_ROW_BEFORE, SfxCallMode::SYNCHRON);
+
+ // go to the previously inserted table rows and set them to tracked insertion, if needed
+ bool bNeedTrack = !bTableCol && rSh.getIDocumentRedlineAccess().IsRedlineOn();
+
+ // restore cursor position
+ if (bNeedTrack && pMark != nullptr)
+ rSh.GotoMark( pMark );
+
+ if ( !bNeedTrack && !bPasteIntoTable )
+ {
+ rSrcSh.Pop(SwCursorShell::PopMode::DeleteCurrent); // restore selection...
+
+ // delete source rows/columns
+ if (bMove)
+ pDispatch->Execute(bTableCol
+ ? FN_TABLE_DELETE_COL
+ : FN_TABLE_DELETE_ROW, SfxCallMode::SYNCHRON);
+ }
+ else
+ {
+ const SwTableBox* pBoxStt = rSh.GetCursor()->GetPointNode().GetTableBox();
+ SwTableLine* pLine = pBoxStt ? const_cast<SwTableLine*>( pBoxStt->GetUpper()): nullptr;
+
+ for (sal_Int32 nDeleted = 0; bNeedTrack && nDeleted < nSelRowOrCols;)
+ {
+ // move up text cursor (note: "true" is important for the layout level)
+ if ( !rSh.Up(false) )
+ break;
+
+ const SwTableBox* pBox = rSh.GetCursor()->GetPointNode().GetTableBox();
+
+ if ( !pBox )
+ break;
+
+ // Up() reaches a new row
+ if ( pBox->GetUpper() != pLine )
+ {
+ //rSh.SelTableRow();
+ SvxPrintItem aTracked(RES_PRINT, false);
+ rSh.GetDoc()->SetRowNotTracked( *rSh.GetCursor(), aTracked );
+ ++nDeleted;
+ pLine = const_cast<SwTableLine*>(pBox->GetUpper());
+ }
+ }
+
+ rSrcSh.Pop(SwCursorShell::PopMode::DeleteCurrent); // restore selection...
+
+ // delete source rows/columns
+ if (bMove)
+ {
+ // restore cursor position
+ if (pMarkMoveFrom != nullptr)
+ {
+ rSh.GotoMark( pMarkMoveFrom );
+ rSh.getIDocumentMarkAccess()->deleteMark( pMarkMoveFrom );
+ }
+
+ // tracked table row moving: set original rows as tracked deletion,
+ // otherwise delete original rows/columns (tracking column deletion
+ // and insertion is not supported yet)
+ if ( !bTableCol && bNeedTrack )
+ {
+ pLine = nullptr;
+
+ for (sal_Int32 nDeleted = 0; nDeleted < nSelRowOrCols;)
+ {
+ const SwTableBox* pBox = rSh.GetCursor()->GetPointNode().GetTableBox();
+
+ if ( !pBox )
+ break;
+
+ if ( pBox->GetUpper() != pLine )
+ {
+ pLine = const_cast<SwTableLine*>(pBox->GetUpper());
+ pDispatch->Execute(FN_TABLE_DELETE_ROW, SfxCallMode::SYNCHRON);
+ ++nDeleted;
+ }
+
+ bool bMoved = false;
+ if (bSelUpToDown)
+ bMoved = rSh.Up(false);
+ else
+ bMoved = rSh.Down(false);
+ if (!bMoved)
+ break;
+ }
+ }
+ else
+ {
+ // set cursor in the first cell of the original selection
+ rSh.GetCursor()->DeleteMark();
+ rSh.GetCursor()->GetPoint()->Assign( rDelPos.GetIndex() + 1);
+
+ for (sal_Int32 nDeleted = 0; nDeleted < nSelRowOrCols; ++nDeleted)
+ {
+ pDispatch->Execute(bTableCol
+ ? FN_TABLE_DELETE_COL
+ : FN_TABLE_DELETE_ROW, SfxCallMode::SYNCHRON);
+ }
+ }
+ }
+ }
+
+ // restore cursor position
+ if (pMark != nullptr)
+ {
+ rSh.GotoMark( pMark );
+ rSh.getIDocumentMarkAccess()->deleteMark( pMark );
+ }
+
+ rSh.DestroyCursor();
+ rSh.EndUndo();
+ rSh.EndAction();
+ rSh.EndAction();
+ return true;
+ }
+
+ if ( bMove && rSrcSh.HasWholeTabSelection() )
+ bTableMove = true;
+ }
+ else if( rSrcSh.IsSelFrameMode() || rSrcSh.IsObjSelected() )
+ {
+ // don't move position-protected objects!
+ if( bMove && rSrcSh.IsSelObjProtected( FlyProtectFlags::Pos ) != FlyProtectFlags::NONE )
+ return false;
+
+ bFrameSel = true;
+ }
+
+ const SelectionType nSel = rSrcSh.GetSelectionType();
+
+ SwUndoId eUndoId = bMove ? SwUndoId::UI_DRAG_AND_MOVE : SwUndoId::UI_DRAG_AND_COPY;
+
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UndoArg1, rSrcSh.GetSelDescr());
+
+ if(rSrcSh.GetDoc() != rSh.GetDoc())
+ rSrcSh.StartUndo( eUndoId, &aRewriter );
+ rSh.StartUndo( eUndoId, &aRewriter );
+
+ rSh.StartAction();
+ rSrcSh.StartAction();
+
+ if( &rSrcSh != &rSh )
+ {
+ rSh.EnterStdMode();
+ rSh.SwCursorShell::SetCursor( rDragPt, true );
+ cWord = rSrcSh.IntelligentCut( nSel, false );
+ }
+ else if( !bTableSel && !bFrameSel )
+ {
+ if( !rSh.IsAddMode() )
+ {
+ // #i87233#
+ if ( rSh.IsBlockMode() )
+ {
+ // preserve order of cursors for block mode
+ rSh.GoPrevCursor();
+ }
+
+ rSh.SwCursorShell::CreateCursor();
+ }
+ rSh.SwCursorShell::SetCursor( rDragPt, true, false );
+ rSh.GoPrevCursor();
+ cWord = rSh.IntelligentCut( rSh.GetSelectionType(), false );
+ rSh.GoNextCursor();
+ }
+
+ bInWrd = rSh.IsInWord();
+ bEndWrd = rSh.IsEndWrd();
+ bSttWrd = !bEndWrd && rSh.IsStartWord();
+ bSttPara= rSh.IsSttPara();
+
+ Point aSttPt( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY() );
+
+ // at first, select InetFields!
+ if( TransferBufferType::InetField == m_eBufferType )
+ {
+ if( &rSrcSh == &rSh )
+ {
+ rSh.GoPrevCursor();
+ rSh.SwCursorShell::SetCursor( aSttPt, true );
+ rSh.SelectTextAttr( RES_TXTATR_INETFMT );
+ if( rSh.TestCurrPam( rDragPt ) )
+ {
+ // don't copy/move inside of yourself
+ rSh.DestroyCursor();
+ rSh.EndUndo();
+ rSh.EndAction();
+ rSh.EndAction();
+ return false;
+ }
+ rSh.GoNextCursor();
+ }
+ else
+ {
+ rSrcSh.SwCursorShell::SetCursor( aSttPt, true );
+ rSrcSh.SelectTextAttr( RES_TXTATR_INETFMT );
+ }
+
+ // is there a URL attribute at the insert point? Then replace that,
+ // so simply put up a selection?
+ rSh.DelINetAttrWithText();
+ g_bDDINetAttr = true;
+ }
+
+ if ( rSrcSh.IsSelFrameMode() )
+ {
+ //Hack: fool the special treatment
+ aSttPt = rSrcSh.GetObjRect().Pos();
+ }
+
+ bool bRet = rSrcSh.SwFEShell::Copy(rSh, aSttPt, rDragPt, bMove,
+ !bIsXSelection);
+
+ if( !bIsXSelection )
+ {
+ rSrcSh.Push();
+ if ( bRet && bMove && !bFrameSel )
+ {
+ if ( bTableSel )
+ {
+ /* delete table contents not cells */
+ rSrcSh.Delete(false);
+ }
+ else
+ {
+ //SmartCut, take one of the blanks along.
+ rSh.SwCursorShell::DestroyCursor();
+ if ( cWord == SwWrtShell::WORD_SPACE_BEFORE )
+ rSh.ExtendSelection( false );
+ else if ( cWord == SwWrtShell::WORD_SPACE_AFTER )
+ rSh.ExtendSelection();
+ rSrcSh.DelRight();
+ }
+ }
+ rSrcSh.KillPams();
+ rSrcSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+
+ /* after dragging a table selection inside one shell
+ set cursor to the drop position. */
+ if( &rSh == &rSrcSh && ( bTableSel || rSh.IsBlockMode() ) )
+ {
+ rSrcSh.CalcLayout();
+ rSrcSh.SwCursorShell::SetCursor(rDragPt);
+ rSrcSh.GetCursor()->SetMark();
+ }
+ }
+
+ if( bRet && !bTableSel && !bFrameSel )
+ {
+ if( (bInWrd || bEndWrd) &&
+ (cWord == SwWrtShell::WORD_SPACE_AFTER ||
+ cWord == SwWrtShell::WORD_SPACE_BEFORE) )
+ {
+ if ( bSttWrd || (bInWrd && !bEndWrd))
+ rSh.SwEditShell::Insert(' ', bIsXSelection);
+ if ( !bSttWrd || (bInWrd && !bSttPara) )
+ {
+ rSh.SwapPam();
+ if ( !bSttWrd )
+ rSh.SwEditShell::Insert(' ', bIsXSelection);
+ rSh.SwapPam();
+ }
+ }
+
+ if( bIsXSelection )
+ {
+ if( &rSrcSh == &rSh && !rSh.IsAddMode() )
+ {
+ rSh.SwCursorShell::DestroyCursor();
+ rSh.GoPrevCursor();
+ }
+ else
+ {
+ rSh.SwapPam();
+ rSh.SwCursorShell::ClearMark();
+ }
+ }
+ else
+ {
+ if( rSh.IsAddMode() )
+ rSh.SwCursorShell::CreateCursor();
+ else
+ {
+ // turn on selection mode
+ rSh.SttSelect();
+ rSh.EndSelect();
+ }
+ }
+ }
+ else if ( bRet && bTableMove )
+ {
+ SfxDispatcher* pDispatch = rSrcSh.GetView().GetViewFrame().GetDispatcher();
+ pDispatch->Execute(FN_TABLE_DELETE_TABLE, SfxCallMode::SYNCHRON);
+ }
+
+ if( bRet && bMove && bFrameSel )
+ rSrcSh.LeaveSelFrameMode();
+
+ if( rSrcSh.GetDoc() != rSh.GetDoc() )
+ rSrcSh.EndUndo();
+ rSh.EndUndo();
+
+ // put the shell in the right state
+ if( &rSrcSh != &rSh && ( rSh.IsFrameSelected() || rSh.IsObjSelected() ))
+ rSh.EnterSelFrameMode();
+
+ rSrcSh.EndAction();
+ rSh.EndAction();
+ return true;
+}
+
+// Interfaces for Selection
+void SwTransferable::CreateSelection( SwWrtShell& rSh,
+ const SwFrameShell * _pCreatorView )
+{
+ SwModule *pMod = SW_MOD();
+ rtl::Reference<SwTransferable> pNew = new SwTransferable( rSh );
+
+ pNew->m_pCreatorView = _pCreatorView;
+
+ pMod->m_pXSelection = pNew.get();
+ pNew->CopyToPrimarySelection();
+}
+
+void SwTransferable::ClearSelection( const SwWrtShell& rSh,
+ const SwFrameShell * _pCreatorView)
+{
+ SwModule *pMod = SW_MOD();
+ if( pMod->m_pXSelection &&
+ ((!pMod->m_pXSelection->m_pWrtShell) || (pMod->m_pXSelection->m_pWrtShell == &rSh)) &&
+ (!_pCreatorView || (pMod->m_pXSelection->m_pCreatorView == _pCreatorView)) )
+ {
+ TransferableHelper::ClearPrimarySelection();
+ }
+}
+
+SwTransferable* SwTransferable::GetSwTransferable( const TransferableDataHelper& rData )
+{
+ return dynamic_cast<SwTransferable*>(rData.GetTransferable().get());
+}
+
+SwTransferDdeLink::SwTransferDdeLink( SwTransferable& rTrans, SwWrtShell& rSh )
+ : m_rTransfer(rTrans)
+ , m_pDocShell(nullptr)
+ , m_nOldTimeOut(0)
+ , m_bDelBookmark(false)
+ , m_bInDisconnect(false)
+{
+ // we only end up here with table- or text selection
+ if( SelectionType::TableCell & rSh.GetSelectionType() )
+ {
+ SwFrameFormat* pFormat = rSh.GetTableFormat();
+ if( pFormat )
+ m_sName = pFormat->GetName();
+ }
+ else
+ {
+ // creating a temp. bookmark without undo
+ bool bUndo = rSh.DoesUndo();
+ rSh.DoUndo( false );
+ bool bIsModified = rSh.IsModified();
+
+ ::sw::mark::IMark* pMark = rSh.SetBookmark(
+ vcl::KeyCode(),
+ OUString(),
+ IDocumentMarkAccess::MarkType::DDE_BOOKMARK);
+ if(pMark)
+ {
+ m_sName = pMark->GetName();
+ m_bDelBookmark = true;
+ if( !bIsModified )
+ rSh.ResetModified();
+ }
+ else
+ m_sName.clear();
+ rSh.DoUndo( bUndo );
+ }
+
+ if( m_sName.isEmpty() ||
+ nullptr == ( m_pDocShell = rSh.GetDoc()->GetDocShell() ))
+ return;
+
+ // then we create our "server" and connect to it
+ m_xRefObj = m_pDocShell->DdeCreateLinkSource( m_sName );
+ if( m_xRefObj.is() )
+ {
+ m_xRefObj->AddConnectAdvise( this );
+ m_xRefObj->AddDataAdvise( this,
+ OUString(),
+ ADVISEMODE_NODATA | ADVISEMODE_ONLYONCE );
+ m_nOldTimeOut = m_xRefObj->GetUpdateTimeout();
+ m_xRefObj->SetUpdateTimeout( 0 );
+ }
+}
+
+SwTransferDdeLink::~SwTransferDdeLink()
+{
+ if( m_xRefObj.is() )
+ Disconnect( true );
+}
+
+::sfx2::SvBaseLink::UpdateResult SwTransferDdeLink::DataChanged( const OUString& ,
+ const uno::Any& )
+{
+ // well, that's it with the link
+ if( !m_bInDisconnect )
+ {
+ if( FindDocShell() && m_pDocShell->GetView() )
+ m_rTransfer.RemoveDDELinkFormat( m_pDocShell->GetView()->GetEditWin() );
+ Disconnect( false );
+ }
+ return SUCCESS;
+}
+
+bool SwTransferDdeLink::WriteData( SvStream& rStrm )
+{
+ if( !m_xRefObj.is() || !FindDocShell() )
+ return false;
+
+ rtl_TextEncoding eEncoding = osl_getThreadTextEncoding();
+ const OString aAppNm(OUStringToOString(
+ Application::GetAppName(), eEncoding));
+ const OString aTopic(OUStringToOString(
+ m_pDocShell->GetTitle(SFX_TITLE_FULLNAME), eEncoding));
+ const OString aName(OUStringToOString(m_sName, eEncoding));
+
+ std::unique_ptr<char[]> pMem(new char[ aAppNm.getLength() + aTopic.getLength() + aName.getLength() + 4 ]);
+
+ sal_Int32 nLen = aAppNm.getLength();
+ memcpy( pMem.get(), aAppNm.getStr(), nLen );
+ pMem[ nLen++ ] = 0;
+ memcpy( pMem.get() + nLen, aTopic.getStr(), aTopic.getLength() );
+ nLen = nLen + aTopic.getLength();
+ pMem[ nLen++ ] = 0;
+ memcpy( pMem.get() + nLen, aName.getStr(), aName.getLength() );
+ nLen = nLen + aName.getLength();
+ pMem[ nLen++ ] = 0;
+ pMem[ nLen++ ] = 0;
+
+ rStrm.WriteBytes( pMem.get(), nLen );
+ pMem.reset();
+
+ IDocumentMarkAccess* const pMarkAccess = m_pDocShell->GetDoc()->getIDocumentMarkAccess();
+ IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->findMark(m_sName);
+ if(ppMark != pMarkAccess->getAllMarksEnd()
+ && IDocumentMarkAccess::GetType(**ppMark) != IDocumentMarkAccess::MarkType::BOOKMARK)
+ {
+ // the mark is still a DdeBookmark
+ // we replace it with a Bookmark, so it will get saved etc.
+ ::sw::mark::IMark* const pMark = *ppMark;
+ ::sfx2::SvLinkSource* p = m_xRefObj.get();
+ SwServerObject& rServerObject = dynamic_cast<SwServerObject&>(*p);
+
+ // collecting state of old mark
+ SwPaM aPaM(pMark->GetMarkStart());
+ *aPaM.GetPoint() = pMark->GetMarkStart();
+ if(pMark->IsExpanded())
+ {
+ aPaM.SetMark();
+ *aPaM.GetMark() = pMark->GetMarkEnd();
+ }
+ OUString sMarkName = pMark->GetName();
+
+ // remove mark
+ rServerObject.SetNoServer(); // this removes the connection between SwServerObject and mark
+ // N.B. ppMark was not loaded from file and cannot have xml:id
+ pMarkAccess->deleteMark(ppMark, false);
+
+ // recreate as Bookmark
+ ::sw::mark::IMark* const pNewMark = pMarkAccess->makeMark(
+ aPaM,
+ sMarkName,
+ IDocumentMarkAccess::MarkType::BOOKMARK,
+ ::sw::mark::InsertMode::New);
+ rServerObject.SetDdeBookmark(*pNewMark);
+ }
+
+ m_bDelBookmark = false;
+ return true;
+}
+
+void SwTransferDdeLink::Disconnect( bool bRemoveDataAdvise )
+{
+ // don't accept DataChanged anymore, when already in Disconnect!
+ // (DTOR from Bookmark sends a DataChanged!)
+ bool bOldDisconnect = m_bInDisconnect;
+ m_bInDisconnect = true;
+
+ // destroy the unused bookmark again (without Undo!)?
+ if( m_bDelBookmark && m_xRefObj.is() && FindDocShell() )
+ {
+ SwDoc* pDoc = m_pDocShell->GetDoc();
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ // #i58448#
+ Link<bool,void> aSavedOle2Link( pDoc->GetOle2Link() );
+ pDoc->SetOle2Link( Link<bool,void>() );
+
+ bool bIsModified = pDoc->getIDocumentState().IsModified();
+
+ IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ pMarkAccess->deleteMark(pMarkAccess->findMark(m_sName), false);
+
+ if( !bIsModified )
+ pDoc->getIDocumentState().ResetModified();
+ // #i58448#
+ pDoc->SetOle2Link( aSavedOle2Link );
+
+ m_bDelBookmark = false;
+ }
+
+ if( m_xRefObj.is() )
+ {
+ m_xRefObj->SetUpdateTimeout( m_nOldTimeOut );
+ m_xRefObj->RemoveConnectAdvise( this );
+ if( bRemoveDataAdvise )
+ // in a DataChanged the SelectionObject must NEVER be deleted
+ // is already handled by the base class
+ // (ADVISEMODE_ONLYONCE!!!!)
+ // but always in normal Disconnect!
+ m_xRefObj->RemoveAllDataAdvise( this );
+ m_xRefObj.clear();
+ }
+ m_bInDisconnect = bOldDisconnect;
+}
+
+bool SwTransferDdeLink::FindDocShell()
+{
+ SfxObjectShell* pTmpSh = SfxObjectShell::GetFirst( checkSfxObjectShell<SwDocShell> );
+ while( pTmpSh )
+ {
+ if( pTmpSh == m_pDocShell ) // that's what we want to have
+ {
+ if( m_pDocShell->GetDoc() )
+ return true;
+ break; // the Doc is not there anymore, so leave!
+ }
+ pTmpSh = SfxObjectShell::GetNext( *pTmpSh, checkSfxObjectShell<SwDocShell> );
+ }
+
+ m_pDocShell = nullptr;
+ return false;
+}
+
+void SwTransferDdeLink::Closed()
+{
+ if( !m_bInDisconnect && m_xRefObj.is() )
+ {
+ m_xRefObj->RemoveAllDataAdvise( this );
+ m_xRefObj->RemoveConnectAdvise( this );
+ m_xRefObj.clear();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/AnchorOverlayObject.cxx b/sw/source/uibase/docvw/AnchorOverlayObject.cxx
new file mode 100644
index 0000000000..4cbb0e6ada
--- /dev/null
+++ b/sw/source/uibase/docvw/AnchorOverlayObject.cxx
@@ -0,0 +1,385 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "AnchorOverlayObject.hxx"
+#include <SidebarWindowsConsts.hxx>
+
+#include <swrect.hxx>
+#include <utility>
+#include <view.hxx>
+#include <svx/sdrpaintwindow.hxx>
+#include <svx/svdview.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <tools/long.hxx>
+
+#include <sw_primitivetypes2d.hxx>
+#include <drawinglayer/attribute/lineattribute.hxx>
+#include <drawinglayer/attribute/strokeattribute.hxx>
+#include <drawinglayer/primitive2d/primitivetools2d.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
+
+namespace sw::sidebarwindows {
+
+namespace {
+
+// helper class: Primitive for discrete visualisation
+class AnchorPrimitive : public drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D
+{
+private:
+ basegfx::B2DPolygon maTriangle;
+ basegfx::B2DPolygon maLine;
+ basegfx::B2DPolygon maLineTop;
+ const AnchorState maAnchorState;
+ basegfx::BColor maColor;
+
+ // discrete line width
+ double mfDiscreteLineWidth;
+
+ bool mbLineSolid : 1;
+
+protected:
+ virtual void create2DDecomposition(
+ drawinglayer::primitive2d::Primitive2DContainer& rContainer,
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation) const override;
+
+public:
+ AnchorPrimitive( basegfx::B2DPolygon aTriangle,
+ basegfx::B2DPolygon aLine,
+ basegfx::B2DPolygon aLineTop,
+ AnchorState aAnchorState,
+ const basegfx::BColor& rColor,
+ double fDiscreteLineWidth,
+ bool bLineSolid )
+ : maTriangle(std::move(aTriangle)),
+ maLine(std::move(aLine)),
+ maLineTop(std::move(aLineTop)),
+ maAnchorState(aAnchorState),
+ maColor(rColor),
+ mfDiscreteLineWidth(fDiscreteLineWidth),
+ mbLineSolid(bLineSolid)
+ {}
+
+ // data access
+ const basegfx::B2DPolygon& getLine() const { return maLine; }
+ const basegfx::BColor& getColor() const { return maColor; }
+ bool getLineSolid() const { return mbLineSolid; }
+
+ virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const override;
+
+ virtual sal_uInt32 getPrimitive2DID() const override;
+};
+
+}
+
+void AnchorPrimitive::create2DDecomposition(
+ drawinglayer::primitive2d::Primitive2DContainer& rContainer,
+ const drawinglayer::geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+ if ( AnchorState::Tri == maAnchorState ||
+ AnchorState::All == maAnchorState )
+ {
+ // create triangle
+ const drawinglayer::primitive2d::Primitive2DReference aTriangle(
+ new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
+ basegfx::B2DPolyPolygon(maTriangle),
+ getColor()));
+
+ rContainer.push_back(aTriangle);
+ }
+
+ // prepare view-independent LineWidth and color
+ const drawinglayer::attribute::LineAttribute aLineAttribute(
+ getColor(),
+ mfDiscreteLineWidth * getDiscreteUnit());
+
+ if ( AnchorState::All == maAnchorState )
+ {
+ // create line start
+ if(getLineSolid())
+ {
+ const drawinglayer::primitive2d::Primitive2DReference aSolidLine(
+ new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
+ getLine(),
+ aLineAttribute));
+
+ rContainer.push_back(aSolidLine);
+ }
+ else
+ {
+ std::vector< double > aDotDashArray;
+ const double fDistance(3.0 * 15.0);
+ const double fDashLen(5.0 * 15.0);
+
+ aDotDashArray.push_back(fDashLen);
+ aDotDashArray.push_back(fDistance);
+
+ drawinglayer::attribute::StrokeAttribute aStrokeAttribute(
+ std::move(aDotDashArray),
+ fDistance + fDashLen);
+
+ const drawinglayer::primitive2d::Primitive2DReference aStrokedLine(
+ new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
+ getLine(),
+ aLineAttribute,
+ std::move(aStrokeAttribute)));
+
+ rContainer.push_back(aStrokedLine);
+ }
+ }
+
+ if ( AnchorState::All == maAnchorState ||
+ AnchorState::End == maAnchorState )
+ {
+ // LineTop has to be created, too, but uses no shadow, so add after
+ // the other parts are created
+ const drawinglayer::primitive2d::Primitive2DReference aLineTop(
+ new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
+ maLineTop,
+ aLineAttribute));
+
+ rContainer.push_back(aLineTop);
+ }
+}
+
+bool AnchorPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const
+{
+ if(drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
+ {
+ const AnchorPrimitive& rCompare = static_cast< const AnchorPrimitive& >(rPrimitive);
+
+ return (maTriangle == rCompare.maTriangle
+ && getLine() == rCompare.getLine()
+ && maLineTop == rCompare.maLineTop
+ && maAnchorState == rCompare.maAnchorState
+ && getColor() == rCompare.getColor()
+ && mfDiscreteLineWidth == rCompare.mfDiscreteLineWidth
+ && getLineSolid() == rCompare.getLineSolid());
+ }
+
+ return false;
+}
+
+sal_uInt32 AnchorPrimitive::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_SWSIDEBARANCHORPRIMITIVE;
+}
+
+/*static*/ std::unique_ptr<AnchorOverlayObject> AnchorOverlayObject::CreateAnchorOverlayObject(
+ SwView const & rDocView,
+ const SwRect& aAnchorRect,
+ tools::Long aPageBorder,
+ const Point& aLineStart,
+ const Point& aLineEnd,
+ const Color& aColorAnchor )
+{
+ std::unique_ptr<AnchorOverlayObject> pAnchorOverlayObject;
+ if ( rDocView.GetDrawView() )
+ {
+ SdrPaintWindow* pPaintWindow = rDocView.GetDrawView()->GetPaintWindow(0);
+ if( pPaintWindow )
+ {
+ const rtl::Reference< sdr::overlay::OverlayManager >& xOverlayManager = pPaintWindow->GetOverlayManager();
+
+ if ( xOverlayManager.is() )
+ {
+ pAnchorOverlayObject.reset(new AnchorOverlayObject(
+ basegfx::B2DPoint( aAnchorRect.Left() , aAnchorRect.Bottom()-5*15),
+ basegfx::B2DPoint( aAnchorRect.Left()-5*15 , aAnchorRect.Bottom()+5*15),
+ basegfx::B2DPoint( aAnchorRect.Left()+5*15 , aAnchorRect.Bottom()+5*15),
+ basegfx::B2DPoint( aAnchorRect.Left(), aAnchorRect.Bottom()+2*15),
+ basegfx::B2DPoint( aPageBorder ,aAnchorRect.Bottom()+2*15),
+ basegfx::B2DPoint( aLineStart.X(),aLineStart.Y()),
+ basegfx::B2DPoint( aLineEnd.X(),aLineEnd.Y()) ,
+ aColorAnchor));
+ xOverlayManager->add(*pAnchorOverlayObject);
+ }
+ }
+ }
+
+ return pAnchorOverlayObject;
+}
+
+AnchorOverlayObject::AnchorOverlayObject( const basegfx::B2DPoint& rBasePos,
+ const basegfx::B2DPoint& rSecondPos,
+ const basegfx::B2DPoint& rThirdPos,
+ const basegfx::B2DPoint& rFourthPos,
+ const basegfx::B2DPoint& rFifthPos,
+ const basegfx::B2DPoint& rSixthPos,
+ const basegfx::B2DPoint& rSeventhPos,
+ const Color& rBaseColor)
+ : OverlayObjectWithBasePosition(rBasePos, rBaseColor)
+ , maSecondPosition(rSecondPos)
+ , maThirdPosition(rThirdPos)
+ , maFourthPosition(rFourthPos)
+ , maFifthPosition(rFifthPos)
+ , maSixthPosition(rSixthPos)
+ , maSeventhPosition(rSeventhPos)
+ , mAnchorState(AnchorState::All)
+ , mbLineSolid(false)
+{
+}
+
+AnchorOverlayObject::~AnchorOverlayObject()
+{
+ if ( getOverlayManager() )
+ {
+ // remove this object from the chain
+ getOverlayManager()->remove(*this);
+ }
+}
+
+void AnchorOverlayObject::implEnsureGeometry()
+{
+ if(!maTriangle.count())
+ {
+ maTriangle.append(getBasePosition());
+ maTriangle.append(GetSecondPosition());
+ maTriangle.append(GetThirdPosition());
+ maTriangle.setClosed(true);
+ }
+
+ if(!maLine.count())
+ {
+ maLine.append(GetFourthPosition());
+ maLine.append(GetFifthPosition());
+ maLine.append(GetSixthPosition());
+ }
+
+ if(!maLineTop.count())
+ {
+ maLineTop.append(GetSixthPosition());
+ maLineTop.append(GetSeventhPosition());
+ }
+}
+
+void AnchorOverlayObject::implResetGeometry()
+{
+ maTriangle.clear();
+ maLine.clear();
+ maLineTop.clear();
+}
+
+drawinglayer::primitive2d::Primitive2DContainer AnchorOverlayObject::createOverlayObjectPrimitive2DSequence()
+{
+ implEnsureGeometry();
+
+ static const double aDiscreteLineWidth(1.6);
+ const drawinglayer::primitive2d::Primitive2DReference aReference(
+ new AnchorPrimitive( maTriangle,
+ maLine,
+ maLineTop,
+ GetAnchorState(),
+ getBaseColor().getBColor(),
+ ANCHORLINE_WIDTH * aDiscreteLineWidth,
+ getLineSolid()) );
+
+ return drawinglayer::primitive2d::Primitive2DContainer { aReference };
+}
+
+void AnchorOverlayObject::SetAllPosition( const basegfx::B2DPoint& rPoint1,
+ const basegfx::B2DPoint& rPoint2,
+ const basegfx::B2DPoint& rPoint3,
+ const basegfx::B2DPoint& rPoint4,
+ const basegfx::B2DPoint& rPoint5,
+ const basegfx::B2DPoint& rPoint6,
+ const basegfx::B2DPoint& rPoint7)
+{
+ if ( !(rPoint1 != getBasePosition() ||
+ rPoint2 != GetSecondPosition() ||
+ rPoint3 != GetThirdPosition() ||
+ rPoint4 != GetFourthPosition() ||
+ rPoint5 != GetFifthPosition() ||
+ rPoint6 != GetSixthPosition() ||
+ rPoint7 != GetSeventhPosition()) )
+ return;
+
+ maBasePosition = rPoint1;
+ maSecondPosition = rPoint2;
+ maThirdPosition = rPoint3;
+ maFourthPosition = rPoint4;
+ maFifthPosition = rPoint5;
+ maSixthPosition = rPoint6;
+ maSeventhPosition = rPoint7;
+
+ implResetGeometry();
+ objectChange();
+}
+
+void AnchorOverlayObject::SetSixthPosition(const basegfx::B2DPoint& rNew)
+{
+ if(rNew != maSixthPosition)
+ {
+ maSixthPosition = rNew;
+ implResetGeometry();
+ objectChange();
+ }
+}
+
+void AnchorOverlayObject::SetSeventhPosition(const basegfx::B2DPoint& rNew)
+{
+ if(rNew != maSeventhPosition)
+ {
+ maSeventhPosition = rNew;
+ implResetGeometry();
+ objectChange();
+ }
+}
+
+void AnchorOverlayObject::SetTriPosition(const basegfx::B2DPoint& rPoint1,const basegfx::B2DPoint& rPoint2,const basegfx::B2DPoint& rPoint3,
+ const basegfx::B2DPoint& rPoint4,const basegfx::B2DPoint& rPoint5)
+{
+ if(rPoint1 != getBasePosition()
+ || rPoint2 != GetSecondPosition()
+ || rPoint3 != GetThirdPosition()
+ || rPoint4 != GetFourthPosition()
+ || rPoint5 != GetFifthPosition())
+ {
+ maBasePosition = rPoint1;
+ maSecondPosition = rPoint2;
+ maThirdPosition = rPoint3;
+ maFourthPosition = rPoint4;
+ maFifthPosition = rPoint5;
+
+ implResetGeometry();
+ objectChange();
+ }
+}
+
+void AnchorOverlayObject::setLineSolid( const bool bNew )
+{
+ if ( bNew != getLineSolid() )
+ {
+ mbLineSolid = bNew;
+ objectChange();
+ }
+}
+
+void AnchorOverlayObject::SetAnchorState( const AnchorState aState)
+{
+ if ( mAnchorState != aState)
+ {
+ mAnchorState = aState;
+ objectChange();
+ }
+}
+
+} // end of namespace sw::sidebarwindows
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/AnchorOverlayObject.hxx b/sw/source/uibase/docvw/AnchorOverlayObject.hxx
new file mode 100644
index 0000000000..744b2f0627
--- /dev/null
+++ b/sw/source/uibase/docvw/AnchorOverlayObject.hxx
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <svx/sdr/overlay/overlayobject.hxx>
+#include <tools/long.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+
+class SwView;
+class SwRect;
+class Point;
+
+namespace sw::sidebarwindows {
+
+enum class AnchorState
+{
+ All,
+ End,
+ Tri
+};
+
+class AnchorOverlayObject final : public sdr::overlay::OverlayObjectWithBasePosition
+{
+ public:
+ static std::unique_ptr<AnchorOverlayObject> CreateAnchorOverlayObject( SwView const & rDocView,
+ const SwRect& aAnchorRect,
+ tools::Long aPageBorder,
+ const Point& aLineStart,
+ const Point& aLineEnd,
+ const Color& aColorAnchor );
+
+ const basegfx::B2DPoint& GetSecondPosition() const { return maSecondPosition; }
+ const basegfx::B2DPoint& GetThirdPosition() const { return maThirdPosition; }
+ const basegfx::B2DPoint& GetFourthPosition() const { return maFourthPosition; }
+ const basegfx::B2DPoint& GetFifthPosition() const { return maFifthPosition; }
+ const basegfx::B2DPoint& GetSixthPosition() const { return maSixthPosition; }
+ const basegfx::B2DPoint& GetSeventhPosition() const { return maSeventhPosition; }
+
+ void SetAllPosition( const basegfx::B2DPoint& rPoint1,
+ const basegfx::B2DPoint& rPoint2,
+ const basegfx::B2DPoint& rPoint3,
+ const basegfx::B2DPoint& rPoint4,
+ const basegfx::B2DPoint& rPoint5,
+ const basegfx::B2DPoint& rPoint6,
+ const basegfx::B2DPoint& rPoint7 );
+ void SetTriPosition( const basegfx::B2DPoint& rPoint1,
+ const basegfx::B2DPoint& rPoint2,
+ const basegfx::B2DPoint& rPoint3,
+ const basegfx::B2DPoint& rPoint4,
+ const basegfx::B2DPoint& rPoint5 );
+ void SetSixthPosition( const basegfx::B2DPoint& rNew );
+ void SetSeventhPosition( const basegfx::B2DPoint& rNew );
+
+ void setLineSolid( const bool bNew );
+ bool getLineSolid() const { return mbLineSolid; }
+
+ void SetAnchorState( const AnchorState aState );
+ AnchorState GetAnchorState() const { return mAnchorState; }
+
+ private:
+ /* 6------------7
+ 1 /
+ /4\ ---------------5
+ 2 - 3
+ */
+
+ basegfx::B2DPoint maSecondPosition;
+ basegfx::B2DPoint maThirdPosition;
+ basegfx::B2DPoint maFourthPosition;
+ basegfx::B2DPoint maFifthPosition;
+ basegfx::B2DPoint maSixthPosition;
+ basegfx::B2DPoint maSeventhPosition;
+
+ // helpers to fill and reset geometry
+ void implEnsureGeometry();
+ void implResetGeometry();
+
+ // geometry creation for OverlayObject
+ virtual drawinglayer::primitive2d::Primitive2DContainer createOverlayObjectPrimitive2DSequence() override;
+
+ // object's geometry
+ basegfx::B2DPolygon maTriangle;
+ basegfx::B2DPolygon maLine;
+ basegfx::B2DPolygon maLineTop;
+ AnchorState mAnchorState;
+
+ bool mbLineSolid : 1;
+
+ AnchorOverlayObject( const basegfx::B2DPoint& rBasePos,
+ const basegfx::B2DPoint& rSecondPos,
+ const basegfx::B2DPoint& rThirdPos,
+ const basegfx::B2DPoint& rFourthPos,
+ const basegfx::B2DPoint& rFifthPos,
+ const basegfx::B2DPoint& rSixthPos,
+ const basegfx::B2DPoint& rSeventhPos,
+ const Color& rBaseColor );
+ public:
+ virtual ~AnchorOverlayObject() override;
+};
+
+} // end of namespace sw::annotation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/AnnotationMenuButton.cxx b/sw/source/uibase/docvw/AnnotationMenuButton.cxx
new file mode 100644
index 0000000000..5e42d15c87
--- /dev/null
+++ b/sw/source/uibase/docvw/AnnotationMenuButton.cxx
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <AnnotationWin.hxx>
+#include <strings.hrc>
+
+#include <unotools/useroptions.hxx>
+
+#include <vcl/event.hxx>
+
+#include <cmdid.h>
+
+#include <swtypes.hxx>
+
+namespace sw::annotation {
+
+IMPL_LINK(SwAnnotationWin, SelectHdl, const OUString&, rIdent, void)
+{
+ if (rIdent.isEmpty())
+ return;
+
+ // tdf#136682 ensure this is the currently active sidebar win so the command
+ // operates in an active sidebar context
+ bool bSwitchedFocus = SetActiveSidebarWin();
+
+ if (rIdent == "reply")
+ ExecuteCommand(FN_REPLY);
+ if (rIdent == "resolve" || rIdent == "unresolve")
+ ExecuteCommand(FN_RESOLVE_NOTE);
+ else if (rIdent == "resolvethread" || rIdent == "unresolvethread")
+ ExecuteCommand(FN_RESOLVE_NOTE_THREAD);
+ else if (rIdent == "delete")
+ ExecuteCommand(FN_DELETE_COMMENT);
+ else if (rIdent == "deletethread")
+ ExecuteCommand(FN_DELETE_COMMENT_THREAD);
+ else if (rIdent == "deleteby")
+ ExecuteCommand(FN_DELETE_NOTE_AUTHOR);
+ else if (rIdent == "deleteall")
+ ExecuteCommand(FN_DELETE_ALL_NOTES);
+ else if (rIdent == "formatall")
+ ExecuteCommand(FN_FORMAT_ALL_NOTES);
+
+ if (bSwitchedFocus)
+ UnsetActiveSidebarWin();
+ GrabFocusToDocument();
+}
+
+IMPL_LINK_NOARG(SwAnnotationWin, ToggleHdl, weld::Toggleable&, void)
+{
+ if (!mxMenuButton->get_active())
+ return;
+
+ bool bReadOnly = IsReadOnly();
+ if (bReadOnly)
+ {
+ mxMenuButton->set_item_visible("reply", false);
+ mxMenuButton->set_item_visible("sep1", false); // Separator after reply button.
+ mxMenuButton->set_item_visible("resolve", false);
+ mxMenuButton->set_item_visible("unresolve", false);
+ mxMenuButton->set_item_visible("resolvethread", false);
+ mxMenuButton->set_item_visible("unresolvethread", false);
+ mxMenuButton->set_item_visible("delete", false );
+ }
+ else
+ {
+ mxMenuButton->set_item_visible("reply", !IsReadOnlyOrProtected());
+ mxMenuButton->set_item_visible("sep1", !IsReadOnlyOrProtected());
+ mxMenuButton->set_item_visible("resolve", !IsResolved());
+ mxMenuButton->set_item_visible("unresolve", IsResolved());
+ mxMenuButton->set_item_visible("resolvethread", !IsThreadResolved());
+ mxMenuButton->set_item_visible("unresolvethread", IsThreadResolved());
+ mxMenuButton->set_item_visible("delete", !IsReadOnlyOrProtected());
+ }
+
+ mxMenuButton->set_item_visible("deletethread", !bReadOnly);
+ mxMenuButton->set_item_visible("deleteby", !bReadOnly);
+ mxMenuButton->set_item_visible("deleteall", !bReadOnly);
+ mxMenuButton->set_item_visible("formatall", !bReadOnly);
+}
+
+IMPL_LINK(SwAnnotationWin, KeyInputHdl, const KeyEvent&, rKeyEvt, bool)
+{
+ const vcl::KeyCode& rKeyCode = rKeyEvt.GetKeyCode();
+ if (rKeyCode.GetCode() == KEY_TAB)
+ {
+ ActivatePostIt();
+ GrabFocus();
+ return true;
+ }
+ return false;
+}
+
+} // end of namespace sw::annotation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/AnnotationWin.cxx b/sw/source/uibase/docvw/AnnotationWin.cxx
new file mode 100644
index 0000000000..714c1419d2
--- /dev/null
+++ b/sw/source/uibase/docvw/AnnotationWin.cxx
@@ -0,0 +1,495 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_wasm_strip.h>
+
+#include <AnnotationWin.hxx>
+
+#include <PostItMgr.hxx>
+
+#include <strings.hrc>
+
+#include <uiobject.hxx>
+
+#include <vcl/svapp.hxx>
+#include <vcl/uitest/logger.hxx>
+#include <vcl/uitest/eventdescription.hxx>
+
+#include <svl/undo.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <unotools/syslocale.hxx>
+#include <svl/languageoptions.hxx>
+#include <osl/diagnose.h>
+
+#include <editeng/eeitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/editund2.hxx>
+
+#include <editeng/editview.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/editobj.hxx>
+#include <editeng/outlobj.hxx>
+
+#include <comphelper/lok.hxx>
+#include <comphelper/random.hxx>
+#include <docufld.hxx>
+#include <txtfld.hxx>
+#include <ndtxt.hxx>
+#include <view.hxx>
+#include <viewopt.hxx>
+#include <wrtsh.hxx>
+#include <docsh.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <SwUndoField.hxx>
+#include <edtwin.hxx>
+#include "ShadowOverlayObject.hxx"
+#include "AnchorOverlayObject.hxx"
+#include "OverlayRanges.hxx"
+#include "SidebarTxtControl.hxx"
+#include "SidebarWinAcc.hxx"
+
+#include <memory>
+
+namespace{
+
+void collectUIInformation( const OUString& aevent , const OUString& aID )
+{
+ EventDescription aDescription;
+ aDescription.aID = aID;
+ aDescription.aParameters = {{"" , ""}};
+ aDescription.aAction = aevent;
+ aDescription.aParent = "MainWindow";
+ aDescription.aKeyWord = "SwEditWinUIObject";
+ UITestLogger::getInstance().logEvent(aDescription);
+}
+
+}
+
+namespace sw::annotation {
+
+// see AnnotationContents in sd for something similar
+SwAnnotationWin::SwAnnotationWin( SwEditWin& rEditWin,
+ SwPostItMgr& aMgr,
+ SwSidebarItem& rSidebarItem,
+ SwFormatField* aField )
+ : InterimItemWindow(&rEditWin, "modules/swriter/ui/annotation.ui", "Annotation")
+ , mrMgr(aMgr)
+ , mrView(rEditWin.GetView())
+ , mnDeleteEventId(nullptr)
+ , meSidebarPosition(sw::sidebarwindows::SidebarPosition::NONE)
+ , mPageBorder(0)
+ , mbAnchorRectChanged(false)
+ , mbResolvedStateUpdated(false)
+ , mbMouseOver(false)
+ , mLayoutStatus(SwPostItHelper::INVISIBLE)
+ , mbReadonly(false)
+ , mbIsFollow(false)
+ , mrSidebarItem(rSidebarItem)
+ , mpAnchorFrame(rSidebarItem.maLayoutInfo.mpAnchorFrame)
+ , mpFormatField(aField)
+ , mpField( static_cast<SwPostItField*>(aField->GetField()))
+{
+ set_id("Comment"+OUString::number(mpField->GetPostItId()));
+
+ m_xContainer->connect_mouse_move(LINK(this, SwAnnotationWin, MouseMoveHdl));
+
+ mpShadow = sidebarwindows::ShadowOverlayObject::CreateShadowOverlayObject( mrView );
+ if ( mpShadow )
+ {
+ mpShadow->setVisible(false);
+ }
+
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ mrMgr.ConnectSidebarWinToFrame( *(mrSidebarItem.maLayoutInfo.mpAnchorFrame),
+ mrSidebarItem.GetFormatField(),
+ *this );
+#endif
+
+ if (SupportsDoubleBuffering())
+ // When double-buffering, allow parents to paint on our area. That's
+ // necessary when parents paint the complete buffer.
+ SetParentClipMode(ParentClipMode::NoClip);
+}
+
+SwAnnotationWin::~SwAnnotationWin()
+{
+ disposeOnce();
+}
+
+void SwAnnotationWin::dispose()
+{
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ mrMgr.DisconnectSidebarWinFromFrame( *(mrSidebarItem.maLayoutInfo.mpAnchorFrame),
+ *this );
+#endif
+ Disable();
+
+ mxSidebarTextControlWin.reset();
+ mxSidebarTextControl.reset();
+
+ mxMetadataAuthor.reset();
+ mxMetadataResolved.reset();
+ mxMetadataDate.reset();
+ mxVScrollbar.reset();
+
+ mpAnchor.reset();
+ mpShadow.reset();
+
+ mpTextRangeOverlay.reset();
+
+ mxMenuButton.reset();
+
+ if (mnDeleteEventId)
+ Application::RemoveUserEvent(mnDeleteEventId);
+
+ mpOutliner.reset();
+ mpOutlinerView.reset();
+
+ InterimItemWindow::dispose();
+}
+
+void SwAnnotationWin::SetPostItText()
+{
+ //If the cursor was visible, then make it visible again after
+ //changing text, e.g. fdo#33599
+ vcl::Cursor *pCursor = GetOutlinerView()->GetEditView().GetCursor();
+ bool bCursorVisible = pCursor && pCursor->IsVisible();
+
+ //If the new text is the same as the old text, keep the same insertion
+ //point .e.g. fdo#33599
+ mpField = static_cast<SwPostItField*>(mpFormatField->GetField());
+ OUString sNewText = mpField->GetPar2();
+ bool bTextUnchanged = sNewText == mpOutliner->GetEditEngine().GetText();
+ ESelection aOrigSelection(GetOutlinerView()->GetEditView().GetSelection());
+
+ // get text from SwPostItField and insert into our textview
+ mpOutliner->SetModifyHdl( Link<LinkParamNone*,void>() );
+ mpOutliner->EnableUndo( false );
+ if( mpField->GetTextObject() )
+ mpOutliner->SetText( *mpField->GetTextObject() );
+ else
+ {
+ mpOutliner->Clear();
+ GetOutlinerView()->SetStyleSheet(SwResId(STR_POOLCOLL_COMMENT));
+ GetOutlinerView()->InsertText(sNewText);
+ }
+
+ mpOutliner->ClearModifyFlag();
+ mpOutliner->GetUndoManager().Clear();
+ mpOutliner->EnableUndo( true );
+ mpOutliner->SetModifyHdl( LINK( this, SwAnnotationWin, ModifyHdl ) );
+ if (bTextUnchanged)
+ GetOutlinerView()->GetEditView().SetSelection(aOrigSelection);
+ if (bCursorVisible)
+ GetOutlinerView()->ShowCursor();
+ Invalidate();
+}
+
+void SwAnnotationWin::GeneratePostItName()
+{
+ if (mpField && mpField->GetName().isEmpty())
+ {
+ mpField->SetName(sw::mark::MarkBase::GenerateNewName(u"__Annotation__"));
+ }
+}
+
+void SwAnnotationWin::SetResolved(bool resolved)
+{
+ bool oldState = IsResolved();
+ static_cast<SwPostItField*>(mpFormatField->GetField())->SetResolved(resolved);
+ if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
+ {
+ const SwViewOption* pVOpt = pWrtShell->GetViewOptions();
+ mrSidebarItem.mbShow = !IsResolved() || (pVOpt->IsResolvedPostIts());
+ }
+
+ mpTextRangeOverlay.reset();
+
+ if(IsResolved())
+ mxMetadataResolved->show();
+ else
+ mxMetadataResolved->hide();
+
+ if(IsResolved() != oldState)
+ mbResolvedStateUpdated = true;
+ UpdateData();
+ Invalidate();
+ collectUIInformation("SETRESOLVED",get_id());
+}
+
+void SwAnnotationWin::ToggleResolved()
+{
+ SetResolved(!IsResolved());
+}
+
+void SwAnnotationWin::ToggleResolvedForThread()
+{
+ auto pTop = GetTopReplyNote();
+ pTop->ToggleResolved();
+ mrMgr.UpdateResolvedStatus(pTop);
+ mrMgr.LayoutPostIts();
+}
+
+sal_uInt32 SwAnnotationWin::GetParaId()
+{
+ auto pField = static_cast<SwPostItField*>(mpFormatField->GetField());
+ auto nParaId = pField->GetParaId();
+ if (nParaId == 0)
+ {
+ // The parent annotation does not have a paraId. This happens when the annotation was just
+ // created, and not imported. paraIds are regenerated upon export, thus this new paraId
+ // is only generated so that children annotations can refer to it
+ nParaId = CreateUniqueParaId();
+ pField->SetParaId(nParaId);
+ }
+ return nParaId;
+}
+
+sal_uInt32 SwAnnotationWin::CreateUniqueParaId()
+{
+ return comphelper::rng::uniform_uint_distribution(0, std::numeric_limits<sal_uInt32>::max());
+}
+
+void SwAnnotationWin::DeleteThread()
+{
+ // Go to the top and delete each comment one by one
+ SwAnnotationWin* topNote = GetTopReplyNote();
+ for (SwAnnotationWin* current = topNote;;)
+ {
+ SwAnnotationWin* next = mrMgr.GetNextPostIt(KEY_PAGEDOWN, current);
+ current->mnDeleteEventId = Application::PostUserEvent( LINK( current, SwAnnotationWin, DeleteHdl), nullptr, true );
+ if (!next || next->GetTopReplyNote() != topNote)
+ return;
+ current = next;
+ }
+}
+
+bool SwAnnotationWin::IsResolved() const
+{
+ return static_cast<SwPostItField*>(mpFormatField->GetField())->GetResolved();
+}
+
+bool SwAnnotationWin::IsThreadResolved()
+{
+ /// First Get the top note
+ // then iterate downwards checking resolved status
+ SwAnnotationWin* topNote = GetTopReplyNote();
+ for (SwAnnotationWin* current = topNote;;)
+ {
+ if (!current->IsResolved())
+ return false;
+ current = mrMgr.GetNextPostIt(KEY_PAGEDOWN, current);
+ if (!current || current->GetTopReplyNote() != topNote)
+ return true;
+ }
+}
+
+void SwAnnotationWin::UpdateData()
+{
+ if ( mpOutliner->IsModified() || mbResolvedStateUpdated )
+ {
+ IDocumentUndoRedo & rUndoRedo(
+ mrView.GetDocShell()->GetDoc()->GetIDocumentUndoRedo());
+ std::unique_ptr<SwField> pOldField;
+ if (rUndoRedo.DoesUndo())
+ {
+ pOldField = mpField->Copy();
+ }
+ mpField->SetPar2(mpOutliner->GetEditEngine().GetText());
+ mpField->SetTextObject(mpOutliner->CreateParaObject());
+ if (rUndoRedo.DoesUndo())
+ {
+ SwTextField *const pTextField = mpFormatField->GetTextField();
+ SwPosition aPosition( pTextField->GetTextNode(), pTextField->GetStart() );
+ rUndoRedo.AppendUndo(
+ std::make_unique<SwUndoFieldFromDoc>(aPosition, *pOldField, *mpField, true));
+ }
+ // so we get a new layout of notes (anchor position is still the same and we would otherwise not get one)
+ mrMgr.SetLayout();
+ // #i98686# if we have several views, all notes should update their text
+ if(mbResolvedStateUpdated)
+ mpFormatField->Broadcast(SwFormatFieldHint( nullptr, SwFormatFieldHintWhich::RESOLVED));
+ else
+ mpFormatField->Broadcast(SwFormatFieldHint( nullptr, SwFormatFieldHintWhich::CHANGED));
+ mrView.GetDocShell()->SetModified();
+ }
+ mpOutliner->ClearModifyFlag();
+ mpOutliner->GetUndoManager().Clear();
+ mbResolvedStateUpdated = false;
+}
+
+void SwAnnotationWin::Delete()
+{
+ collectUIInformation("DELETE",get_id());
+ SwWrtShell* pWrtShell = mrView.GetWrtShellPtr();
+ if (!(pWrtShell && pWrtShell->GotoField(*mpFormatField)))
+ return;
+
+ if ( mrMgr.GetActiveSidebarWin() == this)
+ {
+ mrMgr.SetActiveSidebarWin(nullptr);
+ // if the note is empty, the previous line will send a delete event, but we are already there
+ if (mnDeleteEventId)
+ {
+ Application::RemoveUserEvent(mnDeleteEventId);
+ mnDeleteEventId = nullptr;
+ }
+ }
+ // we delete the field directly, the Mgr cleans up the PostIt by listening
+ GrabFocusToDocument();
+ pWrtShell->ClearMark();
+ pWrtShell->DelRight();
+}
+
+void SwAnnotationWin::GotoPos()
+{
+ mrView.GetDocShell()->GetWrtShell()->GotoField(*mpFormatField);
+}
+
+sal_uInt32 SwAnnotationWin::MoveCaret()
+{
+ // if this is an answer, do not skip over all following ones, but insert directly behind the current one
+ // but when just leaving a note, skip all following ones as well to continue typing
+ return mrMgr.IsAnswer()
+ ? 1
+ : 1 + CountFollowing();
+}
+
+// counts how many SwPostItField we have right after the current one
+sal_uInt32 SwAnnotationWin::CountFollowing()
+{
+ SwTextField* pTextField = mpFormatField->GetTextField();
+ SwPosition aPosition( pTextField->GetTextNode(), pTextField->GetStart() );
+
+ for (sal_Int32 n = 1;; ++n)
+ {
+ SwTextAttr * pTextAttr = pTextField->GetTextNode().GetTextAttrForCharAt(
+ aPosition.GetContentIndex() + n,
+ RES_TXTATR_ANNOTATION );
+ if (!pTextAttr)
+ return n - 1;
+ const SwField* pField = pTextAttr->GetFormatField().GetField();
+ if (!pField || pField->Which() != SwFieldIds::Postit)
+ return n - 1;
+ }
+}
+
+void SwAnnotationWin::InitAnswer(OutlinerParaObject const & rText)
+{
+ // If tiled annotations is off in lok case, skip adding additional reply text.
+ if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations())
+ return;
+
+ //collect our old meta data
+ SwAnnotationWin* pWin = mrMgr.GetNextPostIt(KEY_PAGEUP, this);
+ if (!pWin)
+ return;
+
+ const SvtSysLocale aSysLocale;
+ const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData();
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, pWin->GetAuthor());
+ const OUString aText = aRewriter.Apply(SwResId(STR_REPLY))
+ + " (" + rLocalData.getDate( pWin->GetDate())
+ + ", " + rLocalData.getTime( pWin->GetTime(), false)
+ + "): \"";
+ GetOutlinerView()->InsertText(aText);
+
+ // insert old, selected text or "..."
+ // TODO: iterate over all paragraphs, not only first one to find out if it is empty
+ if (!rText.GetTextObject().GetText(0).isEmpty())
+ GetOutlinerView()->GetEditView().InsertText(rText.GetTextObject());
+ else
+ GetOutlinerView()->InsertText("...");
+ GetOutlinerView()->InsertText("\"\n");
+
+ GetOutlinerView()->SetSelection(ESelection(0,0,EE_PARA_ALL,EE_TEXTPOS_ALL));
+ SfxItemSet aAnswerSet( mrView.GetDocShell()->GetPool() );
+ aAnswerSet.Put(SvxFontHeightItem(200,80,EE_CHAR_FONTHEIGHT));
+ aAnswerSet.Put(SvxPostureItem(ITALIC_NORMAL,EE_CHAR_ITALIC));
+ GetOutlinerView()->SetAttribs(aAnswerSet);
+ GetOutlinerView()->SetSelection(ESelection(EE_PARA_MAX_COUNT,EE_TEXTPOS_MAX_COUNT,EE_PARA_MAX_COUNT,EE_TEXTPOS_MAX_COUNT));
+
+ //remove all attributes and reset our standard ones
+ GetOutlinerView()->GetEditView().RemoveAttribsKeepLanguages(true);
+ // lets insert an undo step so the initial text can be easily deleted
+ // but do not use UpdateData() directly, would set modified state again and reentrance into Mgr
+ mpOutliner->SetModifyHdl( Link<LinkParamNone*,void>() );
+ IDocumentUndoRedo & rUndoRedo(
+ mrView.GetDocShell()->GetDoc()->GetIDocumentUndoRedo());
+ std::unique_ptr<SwField> pOldField;
+ if (rUndoRedo.DoesUndo())
+ {
+ pOldField = mpField->Copy();
+ }
+ mpField->SetPar2(mpOutliner->GetEditEngine().GetText());
+ mpField->SetTextObject(mpOutliner->CreateParaObject());
+ if (rUndoRedo.DoesUndo())
+ {
+ SwTextField *const pTextField = mpFormatField->GetTextField();
+ SwPosition aPosition( pTextField->GetTextNode(), pTextField->GetStart() );
+ rUndoRedo.AppendUndo(
+ std::make_unique<SwUndoFieldFromDoc>(aPosition, *pOldField, *mpField, true));
+ }
+ mpOutliner->SetModifyHdl( LINK( this, SwAnnotationWin, ModifyHdl ) );
+ mpOutliner->ClearModifyFlag();
+ mpOutliner->GetUndoManager().Clear();
+}
+
+void SwAnnotationWin::UpdateText(const OUString& aText)
+{
+ mpOutliner->Clear();
+ GetOutlinerView()->InsertText(aText);
+ UpdateData();
+}
+
+bool SwAnnotationWin::IsReadOnlyOrProtected() const
+{
+ return mbReadonly ||
+ GetLayoutStatus() == SwPostItHelper::DELETED ||
+ ( mpFormatField && mpFormatField->IsProtect() );
+}
+
+OUString SwAnnotationWin::GetAuthor() const
+{
+ return mpField->GetPar1();
+}
+
+Date SwAnnotationWin::GetDate() const
+{
+ return mpField->GetDate();
+}
+
+tools::Time SwAnnotationWin::GetTime() const
+{
+ return mpField->GetTime();
+}
+
+FactoryFunction SwAnnotationWin::GetUITestFactory() const
+{
+ return CommentUIObject::create;
+}
+
+} // end of namespace sw::annotation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/AnnotationWin2.cxx b/sw/source/uibase/docvw/AnnotationWin2.cxx
new file mode 100644
index 0000000000..a1780f9132
--- /dev/null
+++ b/sw/source/uibase/docvw/AnnotationWin2.cxx
@@ -0,0 +1,1436 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_wasm_strip.h>
+
+#include <sal/config.h>
+
+#include <cstddef>
+
+#include "SidebarWinAcc.hxx"
+#include <PostItMgr.hxx>
+#include <AnnotationWin.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include "SidebarTxtControl.hxx"
+#include "AnchorOverlayObject.hxx"
+#include "ShadowOverlayObject.hxx"
+#include "OverlayRanges.hxx"
+
+#include <strings.hrc>
+
+#include <viewopt.hxx>
+#include <cmdid.h>
+
+#include <editeng/fhgtitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/outlobj.hxx>
+#include <editeng/editund2.hxx>
+
+#include <svl/undo.hxx>
+#include <svl/stritem.hxx>
+
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+
+#include <vcl/decoview.hxx>
+#include <vcl/event.hxx>
+#include <vcl/gradient.hxx>
+#include <vcl/pdfextoutdevdata.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/ptrstyle.hxx>
+#include <vcl/uitest/logger.hxx>
+#include <vcl/uitest/eventdescription.hxx>
+
+#include <edtwin.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <wrtsh.hxx>
+#include <doc.hxx>
+#include <docstyle.hxx>
+#include <docufld.hxx>
+#include <swmodule.hxx>
+
+#include <SwRewriter.hxx>
+#include <txtannotationfld.hxx>
+#include <ndtxt.hxx>
+
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <drawinglayer/processor2d/processor2dtools.hxx>
+#include <osl/diagnose.h>
+#include <unotools/localedatawrapper.hxx>
+#include <unotools/syslocale.hxx>
+#include <memory>
+#include <comphelper/lok.hxx>
+
+using namespace sw::sidebarwindows;
+
+namespace
+{
+
+void collectUIInformation( const OUString& aevent , const OUString& aID )
+{
+ EventDescription aDescription;
+ aDescription.aID = aID;
+ aDescription.aParameters = {{"" , ""}};
+ aDescription.aAction = aevent;
+ aDescription.aParent = "MainWindow";
+ aDescription.aKeyWord = "SwEditWinUIObject";
+ UITestLogger::getInstance().logEvent(aDescription);
+}
+
+}
+
+namespace sw::annotation {
+
+#define METABUTTON_WIDTH 16
+#define METABUTTON_HEIGHT 18
+#define POSTIT_MINIMUMSIZE_WITHOUT_META 50
+
+void SwAnnotationWin::PaintTile(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ bool bMenuButtonVisible = mxMenuButton->get_visible();
+ // No point in showing this button till click on it are not handled.
+ if (bMenuButtonVisible)
+ mxMenuButton->hide();
+
+ // draw left over space
+ if (Application::GetSettings().GetStyleSettings().GetHighContrastMode())
+ rRenderContext.SetFillColor(COL_BLACK);
+ else
+ rRenderContext.SetFillColor(mColorDark);
+ rRenderContext.SetLineColor();
+ rRenderContext.DrawRect(rRect);
+
+ m_xContainer->draw(rRenderContext, rRect.TopLeft(), GetSizePixel());
+
+ const drawinglayer::geometry::ViewInformation2D aViewInformation;
+ std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(drawinglayer::processor2d::createProcessor2DFromOutputDevice(rRenderContext, aViewInformation));
+
+ // drawinglayer sets the map mode to pixels, not needed here.
+ rRenderContext.Pop();
+ // Work in document-global twips.
+ rRenderContext.Pop();
+ if (mpAnchor)
+ pProcessor->process(mpAnchor->getOverlayObjectPrimitive2DSequence());
+ if (mpTextRangeOverlay)
+ pProcessor->process(mpTextRangeOverlay->getOverlayObjectPrimitive2DSequence());
+
+ rRenderContext.Push(vcl::PushFlags::NONE);
+ pProcessor.reset();
+ rRenderContext.Push(vcl::PushFlags::NONE);
+
+ if (bMenuButtonVisible)
+ mxMenuButton->show();
+}
+
+bool SwAnnotationWin::IsHitWindow(const Point& rPointLogic)
+{
+ tools::Rectangle aRectangleLogic(EditWin().PixelToLogic(tools::Rectangle(GetPosPixel(),GetSizePixel())));
+ return aRectangleLogic.Contains(rPointLogic);
+}
+
+void SwAnnotationWin::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark)
+{
+ mxSidebarTextControl->SetCursorLogicPosition(rPosition, bPoint, bClearMark);
+}
+
+void SwAnnotationWin::DrawForPage(OutputDevice* pDev, const Point& rPt)
+{
+ // tdf#143511 unclip SysObj so get_extents_relative_to of children
+ // of the SysObj can provide meaningful results
+ UnclipVisibleSysObj();
+
+ vcl::PDFExtOutDevData *const pPDFExtOutDevData(
+ dynamic_cast<vcl::PDFExtOutDevData*>(pDev->GetExtOutDevData()));
+ if (pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportTaggedPDF())
+ {
+ pPDFExtOutDevData->WrapBeginStructureElement(vcl::PDFWriter::NonStructElement, OUString());
+ }
+
+ pDev->Push();
+
+ pDev->SetFillColor(mColorDark);
+ pDev->SetLineColor();
+
+ pDev->SetTextColor(mColorAnchor);
+ vcl::Font aFont = maLabelFont;
+ aFont.SetFontHeight(aFont.GetFontHeight() * 20);
+ pDev->SetFont(aFont);
+
+ Size aSz = PixelToLogic(GetSizePixel());
+
+ pDev->DrawRect(tools::Rectangle(rPt, aSz));
+
+ if (mxMetadataAuthor->get_visible())
+ {
+ int x, y, width, height;
+ mxMetadataAuthor->get_extents_relative_to(*m_xContainer, x, y, width, height);
+ Point aPos(rPt + PixelToLogic(Point(x, y)));
+ Size aSize(PixelToLogic(Size(width, height)));
+
+ pDev->Push(vcl::PushFlags::CLIPREGION);
+ pDev->IntersectClipRegion(tools::Rectangle(aPos, aSize));
+ pDev->DrawText(aPos, mxMetadataAuthor->get_label());
+ pDev->Pop();
+ }
+
+ if (mxMetadataDate->get_visible())
+ {
+ int x, y, width, height;
+ mxMetadataDate->get_extents_relative_to(*m_xContainer, x, y, width, height);
+ Point aPos(rPt + PixelToLogic(Point(x, y)));
+ Size aSize(PixelToLogic(Size(width, height)));
+
+ pDev->Push(vcl::PushFlags::CLIPREGION);
+ pDev->IntersectClipRegion(tools::Rectangle(aPos, aSize));
+ pDev->DrawText(aPos, mxMetadataDate->get_label());
+ pDev->Pop();
+ }
+
+ if (mxMetadataResolved->get_visible())
+ {
+ int x, y, width, height;
+ mxMetadataResolved->get_extents_relative_to(*m_xContainer, x, y, width, height);
+ Point aPos(rPt + PixelToLogic(Point(x, y)));
+ Size aSize(PixelToLogic(Size(width, height)));
+
+ pDev->Push(vcl::PushFlags::CLIPREGION);
+ pDev->IntersectClipRegion(tools::Rectangle(aPos, aSize));
+ pDev->DrawText(aPos, mxMetadataResolved->get_label());
+ pDev->Pop();
+ }
+
+ mxSidebarTextControl->DrawForPage(pDev, rPt);
+
+ const drawinglayer::geometry::ViewInformation2D aNewViewInfos;
+ std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(
+ drawinglayer::processor2d::createProcessor2DFromOutputDevice(
+ *pDev, aNewViewInfos ));
+
+ if (mpAnchor)
+ pProcessor->process(mpAnchor->getOverlayObjectPrimitive2DSequence());
+ if (mpTextRangeOverlay)
+ pProcessor->process(mpTextRangeOverlay->getOverlayObjectPrimitive2DSequence());
+ pProcessor.reset();
+
+ if (mxVScrollbar->get_vpolicy() != VclPolicyType::NEVER)
+ {
+ // if there is a scrollbar shown, draw "..." to indicate the comment isn't
+ // completely shown
+ int x, y, width, height;
+ mxMenuButton->get_extents_relative_to(*m_xContainer, x, y, width, height);
+ Point aPos(rPt + PixelToLogic(Point(x, y)));
+ pDev->DrawText(aPos, "...");
+ }
+
+ pDev->Pop();
+
+ if (pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportTaggedPDF())
+ {
+ pPDFExtOutDevData->EndStructureElement();
+ }
+}
+
+void SwAnnotationWin::SetPosSizePixelRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight,
+ const tools::Long aPageBorder)
+{
+ mPosSize = tools::Rectangle(Point(nX,nY),Size(nWidth,nHeight));
+ mPageBorder = aPageBorder;
+}
+
+void SwAnnotationWin::SetAnchorRect(const SwRect& aAnchorRect)
+{
+ if (!mAnchorRect.IsEmpty() && mAnchorRect != aAnchorRect)
+ mbAnchorRectChanged = true;
+ mAnchorRect = aAnchorRect;
+}
+
+void SwAnnotationWin::SetSize( const Size& rNewSize )
+{
+ mPosSize.SetSize(rNewSize);
+}
+
+void SwAnnotationWin::SetVirtualPosSize( const Point& aPoint, const Size& aSize)
+{
+ mPosSize = tools::Rectangle(aPoint,aSize);
+}
+
+void SwAnnotationWin::TranslateTopPosition(const tools::Long aAmount)
+{
+ mPosSize.Move(0,aAmount);
+}
+
+void SwAnnotationWin::ShowAnchorOnly(const Point &aPoint)
+{
+ HideNote();
+ SetPosAndSize();
+ if (mpAnchor)
+ {
+ mpAnchor->SetSixthPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y()));
+ mpAnchor->SetSeventhPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y()));
+ mpAnchor->SetAnchorState(AnchorState::All);
+ mpAnchor->setVisible(true);
+ }
+ if (mpShadow)
+ mpShadow->setVisible(false);
+}
+
+void SwAnnotationWin::InitControls()
+{
+ // window controls for author and date
+ mxMetadataAuthor = m_xBuilder->weld_label("author");
+ mxMetadataAuthor->set_accessible_name( SwResId( STR_ACCESS_ANNOTATION_AUTHOR_NAME ) );
+ mxMetadataAuthor->set_direction(AllSettings::GetLayoutRTL());
+
+ maLabelFont = Application::GetSettings().GetStyleSettings().GetLabelFont();
+ maLabelFont.SetFontHeight(8);
+
+ // we should leave this setting alone, but for this we need a better layout algo
+ // with variable meta size height
+ mxMetadataAuthor->set_font(maLabelFont);
+
+ mxMetadataDate = m_xBuilder->weld_label("date");
+ mxMetadataDate->set_accessible_name( SwResId( STR_ACCESS_ANNOTATION_DATE_NAME ) );
+ mxMetadataDate->set_direction(AllSettings::GetLayoutRTL());
+ mxMetadataDate->connect_mouse_move(LINK(this, SwAnnotationWin, MouseMoveHdl));
+
+ // we should leave this setting alone, but for this we need a better layout algo
+ // with variable meta size height
+ mxMetadataDate->set_font(maLabelFont);
+
+ mxMetadataResolved = m_xBuilder->weld_label("resolved");
+ mxMetadataResolved->set_accessible_name( SwResId( STR_ACCESS_ANNOTATION_RESOLVED_NAME ) );
+ mxMetadataResolved->set_direction(AllSettings::GetLayoutRTL());
+ mxMetadataResolved->connect_mouse_move(LINK(this, SwAnnotationWin, MouseMoveHdl));
+
+ // we should leave this setting alone, but for this we need a better layout algo
+ // with variable meta size height
+ mxMetadataResolved->set_font(maLabelFont);
+ mxMetadataResolved->set_label(SwResId(STR_ACCESS_ANNOTATION_RESOLVED_NAME));
+
+ SwDocShell* aShell = mrView.GetDocShell();
+ mpOutliner.reset(new Outliner(&aShell->GetPool(),OutlinerMode::TextObject));
+ mpOutliner->SetStyleSheetPool(static_cast<SwDocStyleSheetPool*>(aShell->GetStyleSheetPool())->GetEEStyleSheetPool());
+ aShell->GetDoc()->SetCalcFieldValueHdl( mpOutliner.get() );
+ mpOutliner->SetUpdateLayout( true );
+
+ mpOutlinerView.reset(new OutlinerView(mpOutliner.get(), nullptr));
+ mpOutliner->InsertView(mpOutlinerView.get());
+
+ //create Scrollbars
+ mxVScrollbar = m_xBuilder->weld_scrolled_window("scrolledwindow", true);
+
+ mxMenuButton = m_xBuilder->weld_menu_button("menubutton");
+ mxMenuButton->set_size_request(METABUTTON_WIDTH, METABUTTON_HEIGHT);
+
+ // actual window which holds the user text
+ mxSidebarTextControl.reset(new SidebarTextControl(*this, mrView, mrMgr));
+ mxSidebarTextControlWin.reset(new weld::CustomWeld(*m_xBuilder, "editview", *mxSidebarTextControl));
+ mxSidebarTextControl->SetPointer(PointerStyle::Text);
+
+ Rescale();
+
+ mpOutlinerView->SetBackgroundColor(COL_TRANSPARENT);
+ mpOutlinerView->SetOutputArea( PixelToLogic( tools::Rectangle(0,0,1,1) ) );
+
+ mxVScrollbar->set_direction(false);
+ mxVScrollbar->connect_vadjustment_changed(LINK(this, SwAnnotationWin, ScrollHdl));
+ mxVScrollbar->connect_mouse_move(LINK(this, SwAnnotationWin, MouseMoveHdl));
+
+ EEControlBits nCntrl = mpOutliner->GetControlWord();
+ // TODO: crash when AUTOCOMPLETE enabled
+ nCntrl |= EEControlBits::MARKFIELDS | EEControlBits::PASTESPECIAL | EEControlBits::AUTOCORRECT | EEControlBits::USECHARATTRIBS; // | EEControlBits::AUTOCOMPLETE;
+ // Our stylesheet pool follows closely the core paragraph styles.
+ // We don't want the rtf import (during paste) to mess with that.
+ nCntrl &= ~EEControlBits::RTFSTYLESHEETS;
+
+ if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
+ {
+ const SwViewOption* pVOpt = pWrtShell->GetViewOptions();
+ if (pVOpt->IsFieldShadings())
+ nCntrl |= EEControlBits::MARKFIELDS;
+ else
+ nCntrl &= ~EEControlBits::MARKFIELDS;
+ if (pVOpt->IsOnlineSpell())
+ nCntrl |= EEControlBits::ONLINESPELLING;
+ else
+ nCntrl &= ~EEControlBits::ONLINESPELLING;
+ }
+ mpOutliner->SetControlWord(nCntrl);
+
+ std::size_t aIndex = SW_MOD()->InsertRedlineAuthor(GetAuthor());
+ SetColor( SwPostItMgr::GetColorDark(aIndex),
+ SwPostItMgr::GetColorLight(aIndex),
+ SwPostItMgr::GetColorAnchor(aIndex));
+
+ CheckMetaText();
+
+ // expand %1 "Author"
+ OUString aText = mxMenuButton->get_item_label("deleteby");
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, GetAuthor());
+ aText = aRewriter.Apply(aText);
+ mxMenuButton->set_item_label("deleteby", aText);
+
+ mxMenuButton->set_accessible_name(SwResId(STR_ACCESS_ANNOTATION_BUTTON_NAME));
+ mxMenuButton->set_accessible_description(SwResId(STR_ACCESS_ANNOTATION_BUTTON_DESC));
+ mxMenuButton->set_tooltip_text(SwResId(STR_ACCESS_ANNOTATION_BUTTON_DESC));
+
+ mxMenuButton->connect_toggled(LINK(this, SwAnnotationWin, ToggleHdl));
+ mxMenuButton->connect_selected(LINK(this, SwAnnotationWin, SelectHdl));
+ mxMenuButton->connect_key_press(LINK(this, SwAnnotationWin, KeyInputHdl));
+ mxMenuButton->connect_mouse_move(LINK(this, SwAnnotationWin, MouseMoveHdl));
+
+ GetOutlinerView()->StartSpeller(mxSidebarTextControl->GetDrawingArea());
+ SetPostItText();
+ mpOutliner->CompleteOnlineSpelling();
+
+ mxSidebarTextControl->Show();
+ mxMetadataAuthor->show();
+ mxMetadataDate->show();
+ mxMetadataResolved->set_visible(IsResolved());
+ mxVScrollbar->set_vpolicy(VclPolicyType::ALWAYS);
+}
+
+void SwAnnotationWin::CheckMetaText()
+{
+ const SvtSysLocale aSysLocale;
+ const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData();
+ OUString sMeta = GetAuthor();
+ if (sMeta.isEmpty())
+ {
+ sMeta = SwResId(STR_NOAUTHOR);
+ }
+ else if (sMeta.getLength() > 23)
+ {
+ sMeta = OUString::Concat(sMeta.subView(0, 20)) + "...";
+ }
+ if ( mxMetadataAuthor->get_label() != sMeta )
+ {
+ mxMetadataAuthor->set_label(sMeta);
+ }
+
+ Date aDate = GetDate();
+ if (aDate.IsValidAndGregorian() )
+ {
+ sMeta = rLocalData.getDate(aDate);
+ }
+ else
+ {
+ sMeta = SwResId(STR_NODATE);
+ }
+ if (GetTime().GetTime()!=0)
+ {
+ sMeta += " " + rLocalData.getTime( GetTime(),false );
+ }
+ if ( mxMetadataDate->get_label() != sMeta )
+ {
+ mxMetadataDate->set_label(sMeta);
+ }
+
+ std::size_t aIndex = SW_MOD()->InsertRedlineAuthor(GetAuthor());
+ SetColor( SwPostItMgr::GetColorDark(aIndex),
+ SwPostItMgr::GetColorLight(aIndex),
+ SwPostItMgr::GetColorAnchor(aIndex));
+}
+
+static Color ColorFromAlphaColor(const sal_uInt8 aTransparency, const Color& aFront, const Color& aBack)
+{
+ return Color(sal_uInt8(aFront.GetRed() * aTransparency / 255.0 + aBack.GetRed() * (1 - aTransparency / 255.0)),
+ sal_uInt8(aFront.GetGreen() * aTransparency / 255.0 + aBack.GetGreen() * (1 - aTransparency / 255.0)),
+ sal_uInt8(aFront.GetBlue() * aTransparency / 255.0 + aBack.GetBlue() * (1 - aTransparency / 255.0)));
+}
+
+void SwAnnotationWin::SetMenuButtonColors()
+{
+ if (!mxMenuButton)
+ return;
+
+ mxMenuButton->set_background(mColorDark);
+
+ SwWrtShell* pWrtShell = mrView.GetWrtShellPtr();
+ if (!pWrtShell)
+ return;
+ const Fraction& rFraction = pWrtShell->GetOut()->GetMapMode().GetScaleY();
+
+ ScopedVclPtrInstance<VirtualDevice> xVirDev;
+ Size aSize(tools::Long(METABUTTON_WIDTH * rFraction),
+ tools::Long(METABUTTON_HEIGHT * rFraction));
+ tools::Rectangle aRect(Point(0, 0), aSize);
+ xVirDev->SetOutputSizePixel(aSize);
+
+ Gradient aGradient(css::awt::GradientStyle_LINEAR,
+ ColorFromAlphaColor(15, mColorAnchor, mColorDark),
+ ColorFromAlphaColor(80, mColorAnchor, mColorDark));
+ xVirDev->DrawGradient(aRect, aGradient);
+
+ //draw rect around button
+ xVirDev->SetFillColor();
+ xVirDev->SetLineColor(ColorFromAlphaColor(90, mColorAnchor, mColorDark));
+ xVirDev->DrawRect(aRect);
+
+ tools::Rectangle aSymbolRect(aRect);
+ // 25% distance to the left and right button border
+ const tools::Long nBorderDistanceLeftAndRight = ((aSymbolRect.GetWidth() * 250) + 500) / 1000;
+ aSymbolRect.AdjustLeft(nBorderDistanceLeftAndRight );
+ aSymbolRect.AdjustRight( -nBorderDistanceLeftAndRight );
+ // 40% distance to the top button border
+ const tools::Long nBorderDistanceTop = ((aSymbolRect.GetHeight() * 400) + 500) / 1000;
+ aSymbolRect.AdjustTop(nBorderDistanceTop );
+ // 15% distance to the bottom button border
+ const tools::Long nBorderDistanceBottom = ((aSymbolRect.GetHeight() * 150) + 500) / 1000;
+ aSymbolRect.AdjustBottom( -nBorderDistanceBottom );
+ DecorationView aDecoView(xVirDev.get());
+ aDecoView.DrawSymbol(aSymbolRect, SymbolType::SPIN_DOWN, GetTextColor(),
+ DrawSymbolFlags::NONE);
+ mxMenuButton->set_image(xVirDev);
+ mxMenuButton->set_size_request(aSize.Width() + 4, aSize.Height() + 4);
+}
+
+void SwAnnotationWin::Rescale()
+{
+ // On Android, this method leads to invoke ImpEditEngine::UpdateViews
+ // which hides the text cursor. Moreover it causes sudden document scroll
+ // when modifying a commented text. Not clear the root cause,
+ // anyway skipping this method fixes the problem, and there should be
+ // no side effect, since the client has disabled annotations rendering.
+ if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations())
+ return;
+
+ MapMode aMode = GetParent()->GetMapMode();
+ aMode.SetOrigin( Point() );
+ SetMapMode( aMode );
+ mxSidebarTextControl->SetMapMode( aMode );
+
+ SwWrtShell* pWrtShell = mrView.GetWrtShellPtr();
+ if (!pWrtShell)
+ return;
+ const Fraction& rFraction = pWrtShell->GetOut()->GetMapMode().GetScaleY();
+
+ vcl::Font aFont = maLabelFont;
+ sal_Int32 nHeight = tools::Long(aFont.GetFontHeight() * rFraction);
+ aFont.SetFontHeight( nHeight );
+
+ if (mxMetadataAuthor)
+ mxMetadataAuthor->set_font(aFont);
+ if (mxMetadataDate)
+ mxMetadataDate->set_font(aFont);
+ if (mxMetadataResolved)
+ mxMetadataResolved->set_font(aFont);
+ SetMenuButtonColors();
+ if (mxVScrollbar)
+ mxVScrollbar->set_scroll_thickness(GetPrefScrollbarWidth());
+}
+
+void SwAnnotationWin::SetPosAndSize()
+{
+ const bool bShowNotes = mrMgr.ShowNotes();
+ if (bShowNotes)
+ {
+ bool bChange = false;
+
+ if (GetSizePixel() != mPosSize.GetSize())
+ {
+ bChange = true;
+ SetSizePixel(mPosSize.GetSize());
+
+ DoResize();
+ }
+
+ if (GetPosPixel().X() != mPosSize.Left() || (std::abs(GetPosPixel().Y() - mPosSize.Top()) > 5) )
+ {
+ bChange = true;
+ SetPosPixel(mPosSize.TopLeft());
+
+ Point aLineStart;
+ Point aLineEnd ;
+ switch ( meSidebarPosition )
+ {
+ case sw::sidebarwindows::SidebarPosition::LEFT:
+ {
+ aLineStart = EditWin().PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) );
+ aLineEnd = EditWin().PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) );
+ }
+ break;
+ case sw::sidebarwindows::SidebarPosition::RIGHT:
+ {
+ aLineStart = EditWin().PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) );
+ aLineEnd = EditWin().PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) );
+ }
+ break;
+ default:
+ OSL_FAIL( "<SwAnnotationWin::SetPosAndSize()> - unexpected position of sidebar" );
+ break;
+ }
+
+ // LOK has map mode disabled, and we still want to perform pixel ->
+ // twips conversion for the size of the line above the note.
+ if (comphelper::LibreOfficeKit::isActive() && !EditWin().IsMapModeEnabled())
+ {
+ EditWin().EnableMapMode();
+ Size aSize(aLineEnd.getX() - aLineStart.getX(), aLineEnd.getY() - aLineStart.getY());
+ aSize = EditWin().PixelToLogic(aSize);
+ aLineEnd = aLineStart;
+ aLineEnd.Move(aSize.getWidth(), aSize.getHeight());
+ EditWin().EnableMapMode(false);
+ }
+
+ if (mpAnchor)
+ {
+ mpAnchor->SetAllPosition( basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom() - 5* 15),
+ basegfx::B2DPoint( mAnchorRect.Left()-5*15 , mAnchorRect.Bottom()+5*15),
+ basegfx::B2DPoint( mAnchorRect.Left()+5*15 , mAnchorRect.Bottom()+5*15),
+ basegfx::B2DPoint( mAnchorRect.Left(), mAnchorRect.Bottom()+2*15),
+ basegfx::B2DPoint( mPageBorder ,mAnchorRect.Bottom()+2*15),
+ basegfx::B2DPoint( aLineStart.X(),aLineStart.Y()),
+ basegfx::B2DPoint( aLineEnd.X(),aLineEnd.Y()));
+ }
+ else
+ {
+ mpAnchor = AnchorOverlayObject::CreateAnchorOverlayObject( mrView,
+ mAnchorRect,
+ mPageBorder,
+ aLineStart,
+ aLineEnd,
+ mColorAnchor );
+ if ( mpAnchor )
+ {
+ mpAnchor->setVisible(true);
+ mpAnchor->SetAnchorState(AnchorState::Tri);
+ if (HasChildPathFocus())
+ {
+ mpAnchor->setLineSolid(true);
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( mpAnchor &&
+ ( mpAnchor->getBasePosition() != basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom()-5*15) ) )
+ {
+ mpAnchor->SetTriPosition( basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom() - 5* 15),
+ basegfx::B2DPoint( mAnchorRect.Left()-5*15 , mAnchorRect.Bottom()+5*15),
+ basegfx::B2DPoint( mAnchorRect.Left()+5*15 , mAnchorRect.Bottom()+5*15),
+ basegfx::B2DPoint( mAnchorRect.Left(), mAnchorRect.Bottom()+2*15),
+ basegfx::B2DPoint( mPageBorder , mAnchorRect.Bottom()+2*15));
+ }
+ }
+
+ if (mpShadow && bChange)
+ {
+ Point aStart = EditWin().PixelToLogic(GetPosPixel()+Point(0,GetSizePixel().Height()));
+ Point aEnd = EditWin().PixelToLogic(GetPosPixel()+Point(GetSizePixel().Width()-1,GetSizePixel().Height()));
+ mpShadow->SetPosition(basegfx::B2DPoint(aStart.X(),aStart.Y()), basegfx::B2DPoint(aEnd.X(),aEnd.Y()));
+ }
+
+ if (IsFollow() && !HasChildPathFocus())
+ {
+ // #i111964#
+ if ( mpAnchor )
+ {
+ mpAnchor->SetAnchorState(AnchorState::End);
+ }
+ }
+ else
+ {
+ // #i111964#
+ if ( mpAnchor )
+ {
+ mpAnchor->SetAnchorState(AnchorState::All);
+ }
+ SwAnnotationWin* pWin = GetTopReplyNote();
+ // #i111964#
+ if ( pWin != this && pWin->Anchor() )
+ {
+ pWin->Anchor()->SetAnchorState(AnchorState::End);
+ }
+ }
+ }
+
+ // text range overlay
+ maAnnotationTextRanges.clear();
+ if ( mrSidebarItem.maLayoutInfo.mnStartNodeIdx != SwNodeOffset(0)
+ && mrSidebarItem.maLayoutInfo.mnStartContent != -1 )
+ {
+ const SwTextAnnotationField* pTextAnnotationField =
+ dynamic_cast< const SwTextAnnotationField* >( mrSidebarItem.GetFormatField().GetTextField() );
+ SwTextNode* pTextNode = pTextAnnotationField ? pTextAnnotationField->GetpTextNode() : nullptr;
+ SwContentNode* pContentNd = nullptr;
+ if (pTextNode)
+ {
+ SwNodes& rNds = pTextNode->GetDoc().GetNodes();
+ pContentNd = rNds[mrSidebarItem.maLayoutInfo.mnStartNodeIdx]->GetContentNode();
+ }
+ if (pContentNd)
+ {
+ SwPosition aStartPos( *pContentNd, mrSidebarItem.maLayoutInfo.mnStartContent );
+ SwShellCursor* pTmpCursor = nullptr;
+ const bool bTableCursorNeeded = pTextNode->FindTableBoxStartNode() != pContentNd->FindTableBoxStartNode();
+ if ( bTableCursorNeeded )
+ {
+ SwShellTableCursor* pTableCursor = new SwShellTableCursor( mrView.GetWrtShell(), aStartPos );
+ pTableCursor->SetMark();
+ pTableCursor->GetMark()->Assign( *pTextNode, pTextAnnotationField->GetStart()+1 );
+ pTableCursor->NewTableSelection();
+ pTmpCursor = pTableCursor;
+ }
+ else
+ {
+ SwShellCursor* pCursor = new SwShellCursor( mrView.GetWrtShell(), aStartPos );
+ pCursor->SetMark();
+ pCursor->GetMark()->Assign(*pTextNode, pTextAnnotationField->GetStart()+1 );
+ pTmpCursor = pCursor;
+ }
+ std::unique_ptr<SwShellCursor> pTmpCursorForAnnotationTextRange( pTmpCursor );
+
+ // For annotation text range rectangles to be calculated correctly,
+ // we need the map mode disabled
+ bool bDisableMapMode = comphelper::LibreOfficeKit::isActive() && EditWin().IsMapModeEnabled();
+ if (bDisableMapMode)
+ EditWin().EnableMapMode(false);
+
+ if (mrSidebarItem.maLayoutInfo.mPositionFromCommentAnchor)
+ pTmpCursorForAnnotationTextRange->FillRects();
+
+ if (bDisableMapMode)
+ EditWin().EnableMapMode();
+
+ SwRects* pRects(pTmpCursorForAnnotationTextRange.get());
+ for(const SwRect & rNextRect : *pRects)
+ {
+ const tools::Rectangle aPntRect(rNextRect.SVRect());
+ maAnnotationTextRanges.emplace_back(
+ aPntRect.Left(), aPntRect.Top(),
+ aPntRect.Right() + 1, aPntRect.Bottom() + 1);
+ }
+ }
+ }
+
+ if (bShowNotes && !maAnnotationTextRanges.empty())
+ {
+ if ( mpTextRangeOverlay != nullptr )
+ {
+ mpTextRangeOverlay->setRanges( std::vector(maAnnotationTextRanges) );
+ if ( mpAnchor != nullptr && mpAnchor->getLineSolid() )
+ {
+ mpTextRangeOverlay->ShowSolidBorder();
+ }
+ else
+ {
+ mpTextRangeOverlay->HideSolidBorder();
+ }
+ }
+ else if (!IsFollow())
+ {
+ // This window is not a reply, then draw its range overlay.
+ mpTextRangeOverlay =
+ sw::overlay::OverlayRanges::CreateOverlayRange(
+ mrView,
+ mColorAnchor,
+ std::vector(maAnnotationTextRanges),
+ mpAnchor && mpAnchor->getLineSolid() );
+ }
+ }
+ else
+ {
+ mpTextRangeOverlay.reset();
+ }
+}
+
+void SwAnnotationWin::DoResize()
+{
+ tools::Long aHeight = GetSizePixel().Height();
+ tools::ULong aWidth = GetSizePixel().Width();
+
+ aHeight -= GetMetaHeight();
+
+ mpOutliner->SetPaperSize( PixelToLogic( Size(aWidth, aHeight) ) ) ;
+ tools::Long aTextHeight = LogicToPixel( mpOutliner->CalcTextSize()).Height();
+
+ mxMetadataAuthor->show();
+ if(IsResolved()) { mxMetadataResolved->show(); }
+ mxMetadataDate->show();
+
+ if (aTextHeight > aHeight)
+ {
+ const int nThickness = mxVScrollbar->get_scroll_thickness();
+ if (nThickness)
+ {
+ // we need vertical scrollbars and have to reduce the width
+ aWidth -= nThickness;
+ mpOutliner->SetPaperSize(PixelToLogic(Size(aWidth, aHeight)));
+ }
+ mxVScrollbar->set_vpolicy(VclPolicyType::ALWAYS);
+ }
+ else
+ {
+ mxVScrollbar->set_vpolicy(VclPolicyType::NEVER);
+ }
+
+ tools::Rectangle aOutputArea = PixelToLogic(tools::Rectangle(0, 0, aWidth, aHeight));
+ if (mxVScrollbar->get_vpolicy() == VclPolicyType::NEVER)
+ {
+ // if we do not have a scrollbar anymore, we want to see the complete text
+ mpOutlinerView->SetVisArea(aOutputArea);
+ }
+ mpOutlinerView->SetOutputArea(aOutputArea);
+ mpOutlinerView->ShowCursor(true, true);
+
+ // Don't leave an empty area at the bottom if we can move the text down.
+ tools::Long nMaxVisAreaTop = mpOutliner->GetTextHeight() - aOutputArea.GetHeight();
+ if (mpOutlinerView->GetVisArea().Top() > nMaxVisAreaTop)
+ {
+ GetOutlinerView()->Scroll(0, mpOutlinerView->GetVisArea().Top() - nMaxVisAreaTop);
+ }
+
+ int nUpper = mpOutliner->GetTextHeight();
+ int nCurrentDocPos = mpOutlinerView->GetVisArea().Top();
+ int nStepIncrement = mpOutliner->GetTextHeight() / 10;
+ int nPageIncrement = PixelToLogic(Size(0,aHeight)).Height() * 8 / 10;
+ int nPageSize = PixelToLogic(Size(0,aHeight)).Height();
+
+ /* limit the page size to below nUpper because gtk's gtk_scrolled_window_start_deceleration has
+ effectively...
+
+ lower = gtk_adjustment_get_lower
+ upper = gtk_adjustment_get_upper - gtk_adjustment_get_page_size
+
+ and requires that upper > lower or the deceleration animation never ends
+ */
+ nPageSize = std::min(nPageSize, nUpper);
+
+ mxVScrollbar->vadjustment_configure(nCurrentDocPos, 0, nUpper,
+ nStepIncrement, nPageIncrement, nPageSize);
+}
+
+void SwAnnotationWin::SetSizePixel( const Size& rNewSize )
+{
+ if (comphelper::LibreOfficeKit::isActive())
+ return;
+
+ InterimItemWindow::SetSizePixel(rNewSize);
+
+ if (mpShadow)
+ {
+ Point aStart = EditWin().PixelToLogic(GetPosPixel()+Point(0,GetSizePixel().Height()));
+ Point aEnd = EditWin().PixelToLogic(GetPosPixel()+Point(GetSizePixel().Width()-1,GetSizePixel().Height()));
+ mpShadow->SetPosition(basegfx::B2DPoint(aStart.X(),aStart.Y()), basegfx::B2DPoint(aEnd.X(),aEnd.Y()));
+ }
+}
+
+void SwAnnotationWin::SetScrollbar()
+{
+ mxVScrollbar->vadjustment_set_value(mpOutlinerView->GetVisArea().Top());
+}
+
+void SwAnnotationWin::ResizeIfNecessary(tools::Long aOldHeight, tools::Long aNewHeight)
+{
+ if (aOldHeight != aNewHeight)
+ {
+ //check for lower border or next note
+ tools::Long aBorder = mrMgr.GetNextBorder();
+ if (aBorder != -1)
+ {
+ if (aNewHeight > GetMinimumSizeWithoutMeta())
+ {
+ tools::Long aNewLowerValue = GetPosPixel().Y() + aNewHeight + GetMetaHeight();
+ if (aNewLowerValue < aBorder)
+ SetSizePixel(Size(GetSizePixel().Width(),aNewHeight+GetMetaHeight()));
+ else
+ SetSizePixel(Size(GetSizePixel().Width(),aBorder - GetPosPixel().Y()));
+ DoResize();
+ Invalidate();
+ }
+ else
+ {
+ if (GetSizePixel().Height() != GetMinimumSizeWithoutMeta() + GetMetaHeight())
+ SetSizePixel(Size(GetSizePixel().Width(),GetMinimumSizeWithoutMeta() + GetMetaHeight()));
+ DoResize();
+ Invalidate();
+ }
+ }
+ else
+ {
+ DoResize();
+ Invalidate();
+ }
+ }
+ else
+ {
+ SetScrollbar();
+ }
+}
+
+void SwAnnotationWin::SetColor(Color aColorDark,Color aColorLight, Color aColorAnchor)
+{
+ mColorDark = aColorDark;
+ mColorLight = aColorLight;
+ mColorAnchor = aColorAnchor;
+
+ if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ return;
+
+ m_xContainer->set_background(mColorDark);
+ SetMenuButtonColors();
+
+ mxMetadataAuthor->set_font_color(aColorAnchor);
+
+ mxMetadataDate->set_font_color(aColorAnchor);
+
+ mxMetadataResolved->set_font_color(aColorAnchor);
+
+ mxVScrollbar->customize_scrollbars(mColorLight,
+ mColorAnchor,
+ mColorDark);
+}
+
+void SwAnnotationWin::SetSidebarPosition(sw::sidebarwindows::SidebarPosition eSidebarPosition)
+{
+ meSidebarPosition = eSidebarPosition;
+}
+
+void SwAnnotationWin::SetReadonly(bool bSet)
+{
+ mbReadonly = bSet;
+ GetOutlinerView()->SetReadOnly(bSet);
+}
+
+void SwAnnotationWin::GetFocus()
+{
+ if (mxSidebarTextControl)
+ mxSidebarTextControl->GrabFocus();
+}
+
+void SwAnnotationWin::LoseFocus()
+{
+}
+
+void SwAnnotationWin::ShowNote()
+{
+ SetPosAndSize();
+ if (!IsVisible())
+ Window::Show();
+ if (mpShadow && !mpShadow->isVisible())
+ mpShadow->setVisible(true);
+ if (mpAnchor && !mpAnchor->isVisible())
+ mpAnchor->setVisible(true);
+ if (mpTextRangeOverlay && !mpTextRangeOverlay->isVisible())
+ mpTextRangeOverlay->setVisible(true);
+
+ collectUIInformation("SHOW",get_id());
+}
+
+void SwAnnotationWin::HideNote()
+{
+ if (IsVisible())
+ Window::Hide();
+ if (mpAnchor)
+ {
+ if (mrMgr.IsShowAnchor())
+ mpAnchor->SetAnchorState(AnchorState::Tri);
+ else
+ mpAnchor->setVisible(false);
+ }
+ if (mpShadow && mpShadow->isVisible())
+ mpShadow->setVisible(false);
+ if (mpTextRangeOverlay && mpTextRangeOverlay->isVisible())
+ mpTextRangeOverlay->setVisible(false);
+ collectUIInformation("HIDE",get_id());
+}
+
+void SwAnnotationWin::ActivatePostIt()
+{
+ mrMgr.AssureStdModeAtShell();
+
+ mpOutliner->ClearModifyFlag();
+ mpOutliner->GetUndoManager().Clear();
+
+ CheckMetaText();
+ SetViewState(ViewState::EDIT);
+
+ // prevent autoscroll to the old cursor location
+ // when cursor out of visible area
+ GetOutlinerView()->ShowCursor(false);
+
+ if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
+ mpOutlinerView->GetEditView().SetInsertMode(pWrtShell->IsInsMode());
+
+ if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ GetOutlinerView()->SetBackgroundColor(mColorDark);
+
+ //tdf#119130 only have the active postit as a dialog control in which pressing
+ //ctrl+tab cycles between text and button so we don't waste time searching
+ //thousands of SwAnnotationWins
+ SetStyle(GetStyle() | WB_DIALOGCONTROL);
+}
+
+void SwAnnotationWin::DeactivatePostIt()
+{
+ //tdf#119130 only have the active postit as a dialog control in which pressing
+ //ctrl+tab cycles between text and button so we don't waste time searching
+ //thousands of SwAnnotationWins
+ SetStyle(GetStyle() & ~WB_DIALOGCONTROL);
+
+ // remove selection, #i87073#
+ if (GetOutlinerView()->GetEditView().HasSelection())
+ {
+ ESelection aSelection = GetOutlinerView()->GetEditView().GetSelection();
+ aSelection.nEndPara = aSelection.nStartPara;
+ aSelection.nEndPos = aSelection.nStartPos;
+ GetOutlinerView()->GetEditView().SetSelection(aSelection);
+ }
+
+ mpOutliner->CompleteOnlineSpelling();
+
+ SetViewState(ViewState::NORMAL);
+ // Make sure this view doesn't emit LOK callbacks during the update, as the
+ // sidebar window's SidebarTextControl doesn't have a valid twip offset
+ // (map mode origin) during that operation.
+ bool bTiledPainting = comphelper::LibreOfficeKit::isTiledPainting();
+ comphelper::LibreOfficeKit::setTiledPainting(true);
+ // write the visible text back into the SwField
+ UpdateData();
+ comphelper::LibreOfficeKit::setTiledPainting(bTiledPainting);
+
+ if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ GetOutlinerView()->SetBackgroundColor(COL_TRANSPARENT);
+
+ if (!mnDeleteEventId && !IsReadOnlyOrProtected() && mpOutliner->GetEditEngine().GetText().isEmpty())
+ {
+ mnDeleteEventId = Application::PostUserEvent( LINK( this, SwAnnotationWin, DeleteHdl), nullptr, true );
+ }
+}
+
+void SwAnnotationWin::ToggleInsMode()
+{
+ if (!mrView.GetWrtShell().IsRedlineOn())
+ {
+ //change outliner
+ mpOutlinerView->GetEditView().SetInsertMode(!mpOutlinerView->GetEditView().IsInsertMode());
+ //change document
+ mrView.GetWrtShell().ToggleInsMode();
+ //update statusbar
+ SfxBindings &rBnd = mrView.GetViewFrame().GetBindings();
+ rBnd.Invalidate(SID_ATTR_INSERT);
+ rBnd.Update(SID_ATTR_INSERT);
+ }
+}
+
+void SwAnnotationWin::ExecuteCommand(sal_uInt16 nSlot)
+{
+ mrMgr.AssureStdModeAtShell();
+
+ switch (nSlot)
+ {
+ case FN_POSTIT:
+ case FN_REPLY:
+ {
+ // if this note is empty, it will be deleted once losing the focus, so no reply, but only a new note
+ // will be created
+ if (!mpOutliner->GetEditEngine().GetText().isEmpty())
+ {
+ OutlinerParaObject aPara(GetOutlinerView()->GetEditView().CreateTextObject());
+ mrMgr.RegisterAnswer(&aPara);
+ }
+ if (mrMgr.HasActiveSidebarWin())
+ mrMgr.SetActiveSidebarWin(nullptr);
+ SwitchToFieldPos();
+ mrView.GetViewFrame().GetDispatcher()->Execute(FN_POSTIT);
+
+ if (nSlot == FN_REPLY)
+ {
+ // Get newly created SwPostItField and set its paraIdParent
+ auto pPostItField = mrMgr.GetLatestPostItField();
+ pPostItField->SetParentId(GetTopReplyNote()->GetParaId());
+ pPostItField->SetParentPostItId(GetTopReplyNote()->GetPostItField()->GetPostItId());
+ pPostItField->SetParentName(GetTopReplyNote()->GetPostItField()->GetName());
+ }
+ break;
+ }
+ case FN_DELETE_COMMENT:
+ //Delete(); // do not kill the parent of our open popup menu
+ mnDeleteEventId = Application::PostUserEvent( LINK( this, SwAnnotationWin, DeleteHdl), nullptr, true );
+ break;
+ case FN_DELETE_COMMENT_THREAD:
+ DeleteThread();
+ break;
+ case FN_RESOLVE_NOTE:
+ ToggleResolved();
+ DoResize();
+ Invalidate();
+ mrMgr.LayoutPostIts();
+ break;
+ case FN_RESOLVE_NOTE_THREAD:
+ GetTopReplyNote()->SetResolved(!IsThreadResolved());
+ mrMgr.UpdateResolvedStatus(GetTopReplyNote());
+ DoResize();
+ Invalidate();
+ mrMgr.LayoutPostIts();
+ break;
+ case FN_FORMAT_ALL_NOTES:
+ case FN_DELETE_ALL_NOTES:
+ case FN_HIDE_ALL_NOTES:
+ // not possible as slot as this would require that "this" is the active postit
+ mrView.GetViewFrame().GetBindings().Execute( nSlot, nullptr, SfxCallMode::ASYNCHRON );
+ break;
+ case FN_DELETE_NOTE_AUTHOR:
+ case FN_HIDE_NOTE_AUTHOR:
+ {
+ // not possible as slot as this would require that "this" is the active postit
+ SfxStringItem aItem( nSlot, GetAuthor() );
+ const SfxPoolItem* aItems[2];
+ aItems[0] = &aItem;
+ aItems[1] = nullptr;
+ mrView.GetViewFrame().GetBindings().Execute( nSlot, aItems, SfxCallMode::ASYNCHRON );
+ }
+ break;
+ default:
+ mrView.GetViewFrame().GetBindings().Execute( nSlot );
+ break;
+ }
+}
+
+SwEditWin& SwAnnotationWin::EditWin()
+{
+ return mrView.GetEditWin();
+}
+
+tools::Long SwAnnotationWin::GetPostItTextHeight()
+{
+ return mpOutliner ? LogicToPixel(mpOutliner->CalcTextSize()).Height() : 0;
+}
+
+void SwAnnotationWin::SwitchToPostIt(sal_uInt16 aDirection)
+{
+ SwAnnotationWin* pPostIt = mrMgr.GetNextPostIt(aDirection, this);
+ if (pPostIt)
+ pPostIt->GrabFocus();
+}
+
+IMPL_LINK(SwAnnotationWin, MouseMoveHdl, const MouseEvent&, rMEvt, bool)
+{
+ if (rMEvt.IsEnterWindow())
+ {
+ mbMouseOver = true;
+ if ( !HasFocus() )
+ {
+ SetViewState(ViewState::VIEW);
+ Invalidate();
+ }
+ }
+ else if (rMEvt.IsLeaveWindow())
+ {
+ mbMouseOver = false;
+ if ( !HasFocus() )
+ {
+ SetViewState(ViewState::NORMAL);
+ Invalidate();
+ }
+ }
+ return false;
+}
+
+bool SwAnnotationWin::SetActiveSidebarWin()
+{
+ if (mrMgr.GetActiveSidebarWin() == this)
+ return false;
+ mrView.GetWrtShell().LockView( true );
+ mrMgr.SetActiveSidebarWin(this);
+ mrView.GetWrtShell().LockView( true );
+
+ return true;
+}
+
+void SwAnnotationWin::UnsetActiveSidebarWin()
+{
+ if (mrMgr.GetActiveSidebarWin() != this)
+ return;
+ mrView.GetWrtShell().LockView( true );
+ mrMgr.SetActiveSidebarWin(nullptr);
+ mrView.GetWrtShell().LockView( false );
+}
+
+void SwAnnotationWin::LockView(bool bLock)
+{
+ mrView.GetWrtShell().LockView( bLock );
+}
+
+IMPL_LINK(SwAnnotationWin, ScrollHdl, weld::ScrolledWindow&, rScrolledWindow, void)
+{
+ tools::Long nDiff = GetOutlinerView()->GetEditView().GetVisArea().Top() - rScrolledWindow.vadjustment_get_value();
+ GetOutlinerView()->Scroll( 0, nDiff );
+}
+
+IMPL_LINK_NOARG(SwAnnotationWin, ModifyHdl, LinkParamNone*, void)
+{
+ mrView.GetDocShell()->SetModified();
+}
+
+IMPL_LINK_NOARG(SwAnnotationWin, DeleteHdl, void*, void)
+{
+ mnDeleteEventId = nullptr;
+ Delete();
+}
+
+void SwAnnotationWin::ResetAttributes()
+{
+ mpOutlinerView->RemoveAttribsKeepLanguages(true);
+ mpOutliner->RemoveFields();
+}
+
+int SwAnnotationWin::GetPrefScrollbarWidth() const
+{
+ if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
+ {
+ const Fraction& f(pWrtShell->GetOut()->GetMapMode().GetScaleY());
+ return tools::Long(Application::GetSettings().GetStyleSettings().GetScrollBarSize() * f);
+ }
+ else
+ return tools::Long(Application::GetSettings().GetStyleSettings().GetScrollBarSize());
+}
+
+sal_Int32 SwAnnotationWin::GetMetaHeight() const
+{
+ const int fields = GetNumFields();
+
+ sal_Int32 nRequiredHeight = 0;
+ weld::Label* aLabels[3] = { mxMetadataAuthor.get(), mxMetadataDate.get(), mxMetadataResolved.get() };
+ for (int i = 0; i < fields; ++i)
+ nRequiredHeight += aLabels[i]->get_preferred_size().Height();
+
+ return nRequiredHeight;
+}
+
+sal_Int32 SwAnnotationWin::GetNumFields() const
+{
+ return IsResolved() ? 3 : 2;
+}
+
+sal_Int32 SwAnnotationWin::GetMinimumSizeWithMeta() const
+{
+ return mrMgr.GetMinimumSizeWithMeta();
+}
+
+sal_Int32 SwAnnotationWin::GetMinimumSizeWithoutMeta() const
+{
+ if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
+ {
+ const Fraction& f(pWrtShell->GetOut()->GetMapMode().GetScaleY());
+ return tools::Long(POSTIT_MINIMUMSIZE_WITHOUT_META * f);
+ }
+ else
+ return tools::Long(POSTIT_MINIMUMSIZE_WITHOUT_META);
+}
+
+void SwAnnotationWin::SetSpellChecking()
+{
+ if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
+ {
+ const SwViewOption* pVOpt = pWrtShell->GetViewOptions();
+ EEControlBits nCntrl = mpOutliner->GetControlWord();
+ mpOutliner->SetControlWord(nCntrl & ~EEControlBits::ONLINESPELLING);
+ if (pVOpt->IsOnlineSpell())
+ mpOutliner->SetControlWord(nCntrl | EEControlBits::ONLINESPELLING);
+
+ mpOutliner->CompleteOnlineSpelling();
+ Invalidate();
+ }
+}
+
+void SwAnnotationWin::SetViewState(ViewState bViewState)
+{
+ switch (bViewState)
+ {
+ case ViewState::EDIT:
+ {
+ if (mpAnchor)
+ {
+ mpAnchor->SetAnchorState(AnchorState::All);
+ SwAnnotationWin* pWin = GetTopReplyNote();
+ // #i111964#
+ if ( pWin != this && pWin->Anchor() )
+ {
+ pWin->Anchor()->SetAnchorState(AnchorState::End);
+ }
+ mpAnchor->setLineSolid(true);
+ if ( mpTextRangeOverlay != nullptr )
+ {
+ mpTextRangeOverlay->ShowSolidBorder();
+ }
+ }
+ if (mpShadow)
+ mpShadow->SetShadowState(SS_EDIT);
+ break;
+ }
+ case ViewState::VIEW:
+ {
+ if (mpAnchor)
+ {
+ mpAnchor->setLineSolid(true);
+ if ( mpTextRangeOverlay != nullptr )
+ {
+ mpTextRangeOverlay->ShowSolidBorder();
+ }
+ }
+ if (mpShadow)
+ mpShadow->SetShadowState(SS_VIEW);
+ break;
+ }
+ case ViewState::NORMAL:
+ {
+ if (mpAnchor)
+ {
+ if (IsFollow())
+ {
+ // if there is no visible parent note, we want to see the complete anchor ??
+ //if (IsAnyStackParentVisible())
+ mpAnchor->SetAnchorState(AnchorState::End);
+ SwAnnotationWin* pTopWinSelf = GetTopReplyNote();
+ SwAnnotationWin* pTopWinActive = mrMgr.HasActiveSidebarWin()
+ ? mrMgr.GetActiveSidebarWin()->GetTopReplyNote()
+ : nullptr;
+ // #i111964#
+ if ( ( pTopWinSelf != this ) &&
+ ( pTopWinSelf != pTopWinActive ) &&
+ pTopWinSelf->Anchor() )
+ {
+ if ( pTopWinSelf != mrMgr.GetActiveSidebarWin() )
+ {
+ pTopWinSelf->Anchor()->setLineSolid(false);
+ if ( pTopWinSelf->TextRange() != nullptr )
+ {
+ pTopWinSelf->TextRange()->HideSolidBorder();
+ }
+ }
+ pTopWinSelf->Anchor()->SetAnchorState(AnchorState::All);
+ }
+ }
+ mpAnchor->setLineSolid(false);
+ if ( mpTextRangeOverlay != nullptr )
+ {
+ mpTextRangeOverlay->HideSolidBorder();
+ }
+ }
+ if ( mpShadow )
+ {
+ mpShadow->SetShadowState(SS_NORMAL);
+ }
+ break;
+ }
+ }
+}
+
+SwAnnotationWin* SwAnnotationWin::GetTopReplyNote()
+{
+ for (SwAnnotationWin* pTopNote = this;;)
+ {
+ if (!pTopNote->IsFollow())
+ return pTopNote;
+ SwAnnotationWin* pPrev = mrMgr.GetNextPostIt(KEY_PAGEUP, pTopNote);
+ if (!pPrev)
+ return pTopNote;
+ pTopNote = pPrev;
+ }
+}
+
+void SwAnnotationWin::SwitchToFieldPos()
+{
+ if ( mrMgr.GetActiveSidebarWin() == this )
+ mrMgr.SetActiveSidebarWin(nullptr);
+ GotoPos();
+ sal_uInt32 aCount = MoveCaret();
+ if (aCount)
+ mrView.GetDocShell()->GetWrtShell()->SwCursorShell::Right(aCount, SwCursorSkipMode::Chars);
+ GrabFocusToDocument();
+ collectUIInformation("LEAVE",get_id());
+}
+
+void SwAnnotationWin::SetChangeTracking( const SwPostItHelper::SwLayoutStatus aLayoutStatus,
+ const Color& aChangeColor )
+{
+ if ( (mLayoutStatus != aLayoutStatus) ||
+ (mChangeColor != aChangeColor) )
+ {
+ mLayoutStatus = aLayoutStatus;
+ mChangeColor = aChangeColor;
+ Invalidate();
+ }
+}
+
+bool SwAnnotationWin::HasScrollbar() const
+{
+ return static_cast<bool>(mxVScrollbar);
+}
+
+bool SwAnnotationWin::IsScrollbarVisible() const
+{
+ return HasScrollbar() && mxVScrollbar->get_vpolicy() == VclPolicyType::ALWAYS;
+}
+
+void SwAnnotationWin::ChangeSidebarItem( SwSidebarItem const & rSidebarItem )
+{
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ const bool bAnchorChanged = mpAnchorFrame != rSidebarItem.maLayoutInfo.mpAnchorFrame;
+ if ( bAnchorChanged )
+ {
+ mrMgr.DisconnectSidebarWinFromFrame( *mpAnchorFrame, *this );
+ }
+#endif
+
+ mrSidebarItem = rSidebarItem;
+ mpAnchorFrame = mrSidebarItem.maLayoutInfo.mpAnchorFrame;
+
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ if (mxSidebarWinAccessible)
+ mxSidebarWinAccessible->ChangeSidebarItem( mrSidebarItem );
+
+ if ( bAnchorChanged )
+ {
+ mrMgr.ConnectSidebarWinToFrame( *(mrSidebarItem.maLayoutInfo.mpAnchorFrame),
+ mrSidebarItem.GetFormatField(),
+ *this );
+ }
+#endif
+}
+
+css::uno::Reference< css::accessibility::XAccessible > SwAnnotationWin::CreateAccessible()
+{
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ // This is rather dodgy code. Normally in CreateAccessible, if we want a custom
+ // object, we return a custom object, but we do no override the default toolkit
+ // window peer.
+ if (!mxSidebarWinAccessible)
+ mxSidebarWinAccessible = new SidebarWinAccessible( *this,
+ mrView.GetWrtShell(),
+ mrSidebarItem );
+#endif
+ return mxSidebarWinAccessible;
+}
+
+} // eof of namespace sw::sidebarwindows
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/DashedLine.cxx b/sw/source/uibase/docvw/DashedLine.cxx
new file mode 100644
index 0000000000..0ede6da3ae
--- /dev/null
+++ b/sw/source/uibase/docvw/DashedLine.cxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <DashedLine.hxx>
+
+#include <basegfx/color/bcolortools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx>
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <drawinglayer/processor2d/processor2dtools.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <memory>
+
+SwDashedLine::SwDashedLine( vcl::Window* pParent, const Color& ( SwViewOption::* pColorFn )() const )
+ : Control( pParent, WB_DIALOGCONTROL | WB_HORZ )
+ , m_pColorFn( pColorFn )
+{
+}
+
+SwDashedLine::~SwDashedLine( )
+{
+}
+
+void SwDashedLine::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
+{
+ const drawinglayer::geometry::ViewInformation2D aNewViewInfos;
+ std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(
+ drawinglayer::processor2d::createProcessor2DFromOutputDevice(rRenderContext, aNewViewInfos));
+
+ // Compute the start and end points
+ const tools::Rectangle aRect(tools::Rectangle(Point(0, 0), rRenderContext.PixelToLogic(GetSizePixel())));
+ double nHalfWidth = double(aRect.Top() + aRect.Bottom()) / 2.0;
+
+ basegfx::B2DPoint aStart(double(aRect.Left()), nHalfWidth);
+ basegfx::B2DPoint aEnd(double(aRect.Right()), nHalfWidth);
+
+ basegfx::B2DPolygon aPolygon;
+ aPolygon.append(aStart);
+ aPolygon.append(aEnd);
+
+ drawinglayer::primitive2d::Primitive2DContainer aSeq(1);
+
+ const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
+
+ std::vector<double> aStrokePattern;
+ basegfx::BColor aColor = (SwViewOption::GetCurrentViewOptions().*m_pColorFn)().getBColor();
+ if (rSettings.GetHighContrastMode())
+ {
+ // Only a solid line in high contrast mode
+ aColor = rSettings.GetDialogTextColor().getBColor();
+ }
+ else
+ {
+ // Get a color for the contrast
+ basegfx::BColor aHslLine = basegfx::utils::rgb2hsl(aColor);
+ double nLuminance = aHslLine.getZ();
+ nLuminance += (1.0 - nLuminance) * 0.75;
+ if (aHslLine.getZ() > 0.7)
+ nLuminance = aHslLine.getZ() * 0.7;
+ aHslLine.setZ(nLuminance);
+ const basegfx::BColor aOtherColor = basegfx::utils::hsl2rgb(aHslLine);
+
+ // Compute the plain line
+ aSeq[0] = new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aPolygon, aOtherColor);
+
+ // Dashed line in twips
+ aStrokePattern.push_back(3);
+ aStrokePattern.push_back(3);
+
+ aSeq.resize(2);
+ }
+
+ // Compute the dashed line primitive
+ aSeq[aSeq.size() - 1] =
+ new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(
+ basegfx::B2DPolyPolygon(aPolygon),
+ drawinglayer::attribute::LineAttribute((SwViewOption::GetCurrentViewOptions().*m_pColorFn)().getBColor()),
+ drawinglayer::attribute::StrokeAttribute(std::move(aStrokePattern)));
+
+ pProcessor->process(aSeq);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/FrameControlsManager.cxx b/sw/source/uibase/docvw/FrameControlsManager.cxx
new file mode 100644
index 0000000000..6fb7aac745
--- /dev/null
+++ b/sw/source/uibase/docvw/FrameControlsManager.cxx
@@ -0,0 +1,296 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <edtwin.hxx>
+#include <cntfrm.hxx>
+#include <FrameControlsManager.hxx>
+#include <HeaderFooterWin.hxx>
+#include <PageBreakWin.hxx>
+#include <UnfloatTableButton.hxx>
+#include <pagefrm.hxx>
+#include <flyfrm.hxx>
+#include <viewopt.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <OutlineContentVisibilityWin.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weldutils.hxx>
+#include <contentcontrolaliasbutton.hxx>
+
+SwFrameControlsManager::SwFrameControlsManager( SwEditWin* pEditWin ) :
+ m_pEditWin( pEditWin )
+{
+}
+
+SwFrameControlsManager::~SwFrameControlsManager()
+{
+}
+
+void SwFrameControlsManager::dispose()
+{
+ m_aControls.clear();
+}
+
+SwFrameControlPtr SwFrameControlsManager::GetControl( FrameControlType eType, const SwFrame* pFrame )
+{
+ SwFrameControlPtrMap& rControls = m_aControls[eType];
+
+ SwFrameControlPtrMap::iterator aIt = rControls.find(pFrame);
+
+ if (aIt != rControls.end())
+ return aIt->second;
+
+ return SwFrameControlPtr();
+}
+
+void SwFrameControlsManager::RemoveControls( const SwFrame* pFrame )
+{
+ for ( auto& rEntry : m_aControls )
+ {
+ SwFrameControlPtrMap& rMap = rEntry.second;
+ rMap.erase(pFrame);
+ }
+}
+
+void SwFrameControlsManager::RemoveControlsByType( FrameControlType eType, const SwFrame* pFrame )
+{
+ SwFrameControlPtrMap& rMap = m_aControls[eType];
+ rMap.erase(pFrame);
+}
+
+void SwFrameControlsManager::HideControls( FrameControlType eType )
+{
+ for ( const auto& rCtrl : m_aControls[eType] )
+ rCtrl.second->ShowAll( false );
+}
+
+void SwFrameControlsManager::SetReadonlyControls( bool bReadonly )
+{
+ for ( auto& rEntry : m_aControls )
+ for ( auto& rCtrl : rEntry.second )
+ rCtrl.second->SetReadonly( bReadonly );
+}
+
+void SwFrameControlsManager::SetHeaderFooterControl( const SwPageFrame* pPageFrame, FrameControlType eType, Point aOffset )
+{
+ assert( eType == FrameControlType::Header || eType == FrameControlType::Footer );
+
+ // Check if we already have the control
+ SwFrameControlPtr pControl;
+ const bool bHeader = ( eType == FrameControlType::Header );
+
+ SwFrameControlPtrMap& rControls = m_aControls[eType];
+
+ SwFrameControlPtrMap::iterator lb = rControls.lower_bound(pPageFrame);
+ if (lb != rControls.end() && !(rControls.key_comp()(pPageFrame, lb->first)))
+ pControl = lb->second;
+ else
+ {
+ SwFrameControlPtr pNewControl =
+ std::make_shared<SwFrameControl>( VclPtr<SwHeaderFooterDashedLine>::Create(
+ m_pEditWin, pPageFrame, bHeader ).get() );
+ const SwViewOption* pViewOpt = m_pEditWin->GetView().GetWrtShell().GetViewOptions();
+ pNewControl->SetReadonly( pViewOpt->IsReadonly() );
+ rControls.insert(lb, make_pair(pPageFrame, pNewControl));
+ pControl.swap( pNewControl );
+ }
+
+ tools::Rectangle aPageRect = m_pEditWin->LogicToPixel( pPageFrame->getFrameArea().SVRect() );
+
+ SwHeaderFooterDashedLine* pWin = dynamic_cast<SwHeaderFooterDashedLine*>(pControl->GetWindow());
+ assert( pWin != nullptr) ;
+ assert( pWin->IsHeader() == bHeader );
+ pWin->SetOffset( aOffset, aPageRect.Left(), aPageRect.Right() );
+
+ if (!pWin->IsVisible())
+ pControl->ShowAll( true );
+}
+
+void SwFrameControlsManager::SetPageBreakControl( const SwPageFrame* pPageFrame )
+{
+ // Check if we already have the control
+ SwFrameControlPtr pControl;
+
+ SwFrameControlPtrMap& rControls = m_aControls[FrameControlType::PageBreak];
+
+ SwFrameControlPtrMap::iterator lb = rControls.lower_bound(pPageFrame);
+ if (lb != rControls.end() && !(rControls.key_comp()(pPageFrame, lb->first)))
+ pControl = lb->second;
+ else
+ {
+ SwFrameControlPtr pNewControl = std::make_shared<SwFrameControl>(
+ VclPtr<SwBreakDashedLine>::Create( m_pEditWin, pPageFrame ).get() );
+ const SwViewOption* pViewOpt = m_pEditWin->GetView().GetWrtShell().GetViewOptions();
+ pNewControl->SetReadonly( pViewOpt->IsReadonly() );
+
+ rControls.insert(lb, make_pair(pPageFrame, pNewControl));
+
+ pControl.swap( pNewControl );
+ }
+
+ SwBreakDashedLine* pWin = static_cast<SwBreakDashedLine*>(pControl->GetWindow());
+ assert (pWin != nullptr);
+ pWin->UpdatePosition();
+ if (!pWin->IsVisible())
+ pControl->ShowAll( true );
+}
+
+void SwFrameControlsManager::SetUnfloatTableButton( const SwFlyFrame* pFlyFrame, bool bShow, Point aTopRightPixel )
+{
+ if(pFlyFrame == nullptr)
+ return;
+
+ // Check if we already have the control
+ SwFrameControlPtr pControl;
+
+ SwFrameControlPtrMap& rControls = m_aControls[FrameControlType::FloatingTable];
+
+ SwFrameControlPtrMap::iterator lb = rControls.lower_bound(pFlyFrame);
+ if (lb != rControls.end() && !(rControls.key_comp()(pFlyFrame, lb->first)))
+ pControl = lb->second;
+ else if (!bShow) // Do not create the control when it's not shown
+ return;
+ else
+ {
+ SwFrameControlPtr pNewControl = std::make_shared<SwFrameControl>(
+ VclPtr<UnfloatTableButton>::Create( m_pEditWin, pFlyFrame ).get() );
+ const SwViewOption* pViewOpt = m_pEditWin->GetView().GetWrtShell().GetViewOptions();
+ pNewControl->SetReadonly( pViewOpt->IsReadonly() );
+
+ rControls.insert(lb, make_pair(pFlyFrame, pNewControl));
+
+ pControl.swap( pNewControl );
+ }
+
+ UnfloatTableButton* pButton = dynamic_cast<UnfloatTableButton*>(pControl->GetWindow());
+ assert(pButton != nullptr);
+ pButton->SetOffset(aTopRightPixel);
+ pControl->ShowAll( bShow );
+}
+
+void SwFrameControlsManager::SetContentControlAliasButton(SwContentControl* pContentControl,
+ Point aTopLeftPixel)
+{
+ SwFrameControlPtr pControl;
+ SwFrameControlPtrMap& rControls = m_aControls[FrameControlType::ContentControl];
+ // We don't really have a key, the SwPaM's mark decides what is the single content control in
+ // this view that can have an alias button.
+ SwFrameControlPtrMap::iterator it = rControls.find(nullptr);
+ if (it != rControls.end())
+ pControl = it->second;
+ else
+ {
+ pControl = std::make_shared<SwFrameControl>(
+ VclPtr<SwContentControlAliasButton>::Create(m_pEditWin, pContentControl).get());
+ const SwViewOption* pViewOpt = m_pEditWin->GetView().GetWrtShell().GetViewOptions();
+ pControl->SetReadonly(pViewOpt->IsReadonly());
+ rControls[nullptr] = pControl;
+ }
+
+ auto pButton = dynamic_cast<SwContentControlAliasButton*>(pControl->GetWindow());
+ assert(pButton);
+ pButton->SetOffset(aTopLeftPixel);
+ pButton->SetContentControl(pContentControl);
+ pControl->ShowAll(true);
+}
+
+SwFrameMenuButtonBase::SwFrameMenuButtonBase(SwEditWin* pEditWin, const SwFrame* pFrame,
+ const OUString& rUIXMLDescription, const OUString& rID)
+ : InterimItemWindow(pEditWin, rUIXMLDescription, rID)
+ , m_pEditWin(pEditWin)
+ , m_pFrame(pFrame)
+{
+}
+
+void SwFrameControlsManager::SetOutlineContentVisibilityButton(const SwContentFrame* pContentFrame)
+{
+ // Check if we already have the control
+ SwFrameControlPtr pControl;
+
+ SwFrameControlPtrMap& rControls = m_aControls[FrameControlType::Outline];
+
+ SwFrameControlPtrMap::iterator lb = rControls.lower_bound(pContentFrame);
+ if (lb != rControls.end() && !(rControls.key_comp()(pContentFrame, lb->first)))
+ {
+ pControl = lb->second;
+ }
+ else
+ {
+ SwFrameControlPtr pNewControl =
+ std::make_shared<SwFrameControl>(VclPtr<SwOutlineContentVisibilityWin>::Create(
+ m_pEditWin, pContentFrame).get());
+ rControls.insert(lb, make_pair(pContentFrame, pNewControl));
+ pControl.swap(pNewControl);
+ }
+
+ SwOutlineContentVisibilityWin* pWin = dynamic_cast<SwOutlineContentVisibilityWin *>(pControl->GetWindow());
+ assert(pWin != nullptr);
+ pWin->Set();
+
+ if (pWin->GetSymbol() == ButtonSymbol::SHOW)
+ pWin->Show(); // show the SHOW button immediately
+ else if (!pWin->IsVisible() && pWin->GetSymbol() == ButtonSymbol::HIDE)
+ pWin->ShowAll(true);
+}
+
+const SwPageFrame* SwFrameMenuButtonBase::GetPageFrame(const SwFrame* pFrame)
+{
+ if (pFrame->IsPageFrame())
+ return static_cast<const SwPageFrame*>(pFrame);
+
+ if (pFrame->IsFlyFrame())
+ return static_cast<const SwFlyFrame*>(pFrame)->GetAnchorFrame()->FindPageFrame();
+
+ return pFrame->FindPageFrame();
+}
+
+const SwPageFrame* SwFrameMenuButtonBase::GetPageFrame() const
+{
+ return SwFrameMenuButtonBase::GetPageFrame(m_pFrame);
+}
+
+void SwFrameMenuButtonBase::dispose()
+{
+ m_pEditWin.clear();
+ m_pFrame = nullptr;
+ m_xVirDev.disposeAndClear();
+ InterimItemWindow::dispose();
+}
+
+void SwFrameMenuButtonBase::SetVirDevFont(OutputDevice& rVirDev)
+{
+ // Get the font and configure it
+ vcl::Font aFont = Application::GetSettings().GetStyleSettings().GetToolFont();
+ weld::SetPointFont(rVirDev, aFont);
+}
+
+void SwFrameMenuButtonBase::SetVirDevFont()
+{
+ SetVirDevFont(*m_xVirDev);
+}
+
+SwFrameControl::SwFrameControl( const VclPtr<vcl::Window> &pWindow )
+{
+ assert(static_cast<bool>(pWindow));
+ mxWindow.reset( pWindow );
+ mpIFace = dynamic_cast<ISwFrameControl *>( pWindow.get() );
+}
+
+SwFrameControl::~SwFrameControl()
+{
+ mpIFace = nullptr;
+ mxWindow.disposeAndClear();
+}
+
+ISwFrameControl::~ISwFrameControl()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/HeaderFooterWin.cxx b/sw/source/uibase/docvw/HeaderFooterWin.cxx
new file mode 100644
index 0000000000..64e34e01f6
--- /dev/null
+++ b/sw/source/uibase/docvw/HeaderFooterWin.cxx
@@ -0,0 +1,594 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <strings.hrc>
+
+#include <doc.hxx>
+#include <drawdoc.hxx>
+#include <cmdid.h>
+#include <DashedLine.hxx>
+#include <docsh.hxx>
+#include <edtwin.hxx>
+#include <fmthdft.hxx>
+#include <HeaderFooterWin.hxx>
+#include <pagedesc.hxx>
+#include <pagefrm.hxx>
+#include <view.hxx>
+#include <viewopt.hxx>
+#include <wrtsh.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+
+#include <basegfx/color/bcolortools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/utils/gradienttools.hxx>
+#include <drawinglayer/attribute/fillgradientattribute.hxx>
+#include <drawinglayer/attribute/fontattribute.hxx>
+#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
+#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
+#include <drawinglayer/primitive2d/textprimitive2d.hxx>
+#include <editeng/boxitem.hxx>
+#include <svx/hdft.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <drawinglayer/processor2d/processor2dtools.hxx>
+#include <vcl/canvastools.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/virdev.hxx>
+#include <memory>
+
+#define TEXT_PADDING 5
+#define BOX_DISTANCE 10
+#define BUTTON_WIDTH 18
+
+using namespace basegfx;
+using namespace basegfx::utils;
+using namespace drawinglayer::attribute;
+
+namespace
+{
+ basegfx::BColor lcl_GetFillColor(const basegfx::BColor& rLineColor)
+ {
+ basegfx::BColor aHslLine = basegfx::utils::rgb2hsl(rLineColor);
+ double nLuminance = aHslLine.getZ() * 2.5;
+ if ( nLuminance == 0 )
+ nLuminance = 0.5;
+ else if ( nLuminance >= 1.0 )
+ nLuminance = aHslLine.getZ() * 0.4;
+ aHslLine.setZ( nLuminance );
+ return basegfx::utils::hsl2rgb( aHslLine );
+ }
+
+ basegfx::BColor lcl_GetLighterGradientColor(const basegfx::BColor& rDarkColor)
+ {
+ basegfx::BColor aHslDark = basegfx::utils::rgb2hsl(rDarkColor);
+ double nLuminance = aHslDark.getZ() * 255 + 20;
+ aHslDark.setZ( nLuminance / 255.0 );
+ return basegfx::utils::hsl2rgb( aHslDark );
+ }
+
+ B2DPolygon lcl_GetPolygon( const ::tools::Rectangle& rRect, bool bOnTop )
+ {
+ const double nRadius = 3;
+ const double nKappa((M_SQRT2 - 1.0) * 4.0 / 3.0);
+
+ B2DPolygon aPolygon;
+ aPolygon.append( B2DPoint( rRect.Left(), rRect.Top() ) );
+
+ {
+ B2DPoint aCorner( rRect.Left(), rRect.Bottom() );
+ B2DPoint aStart( rRect.Left(), rRect.Bottom() - nRadius );
+ B2DPoint aEnd( rRect.Left() + nRadius, rRect.Bottom() );
+ aPolygon.append( aStart );
+ aPolygon.appendBezierSegment(
+ interpolate( aStart, aCorner, nKappa ),
+ interpolate( aEnd, aCorner, nKappa ),
+ aEnd );
+ }
+
+ {
+ B2DPoint aCorner( rRect.Right(), rRect.Bottom() );
+ B2DPoint aStart( rRect.Right() - nRadius, rRect.Bottom() );
+ B2DPoint aEnd( rRect.Right(), rRect.Bottom() - nRadius );
+ aPolygon.append( aStart );
+ aPolygon.appendBezierSegment(
+ interpolate( aStart, aCorner, nKappa ),
+ interpolate( aEnd, aCorner, nKappa ),
+ aEnd );
+ }
+
+ aPolygon.append( B2DPoint( rRect.Right(), rRect.Top() ) );
+
+ if ( !bOnTop )
+ {
+ B2DRectangle aBRect = vcl::unotools::b2DRectangleFromRectangle(rRect);
+ B2DHomMatrix aRotation = createRotateAroundPoint(
+ aBRect.getCenterX(), aBRect.getCenterY(), M_PI );
+ aPolygon.transform( aRotation );
+ }
+
+ return aPolygon;
+ }
+}
+
+void SwFrameButtonPainter::PaintButton(drawinglayer::primitive2d::Primitive2DContainer& rSeq,
+ const tools::Rectangle& rRect, bool bOnTop)
+{
+ rSeq.clear();
+ B2DPolygon aPolygon = lcl_GetPolygon(rRect, bOnTop);
+
+ // Colors
+ basegfx::BColor aLineColor = SwViewOption::GetCurrentViewOptions().GetHeaderFooterMarkColor().getBColor();
+ basegfx::BColor aFillColor = lcl_GetFillColor(aLineColor);
+ basegfx::BColor aLighterColor = lcl_GetLighterGradientColor(aFillColor);
+
+ const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
+ if (rSettings.GetHighContrastMode())
+ {
+ aFillColor = rSettings.GetDialogColor().getBColor();
+ aLineColor = rSettings.GetDialogTextColor().getBColor();
+
+ rSeq.push_back(drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(B2DPolyPolygon(aPolygon), aFillColor)));
+ }
+ else
+ {
+ B2DRectangle aGradientRect = vcl::unotools::b2DRectangleFromRectangle(rRect);
+ double nAngle = M_PI;
+ if (bOnTop)
+ nAngle = 0;
+
+ FillGradientAttribute aFillAttrs(css::awt::GradientStyle_LINEAR, 0.0, 0.0, 0.0, nAngle,
+ basegfx::BColorStops(aLighterColor, aFillColor));
+ rSeq.push_back(drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::FillGradientPrimitive2D(aGradientRect, std::move(aFillAttrs))));
+ }
+
+ // Create the border lines primitive
+ rSeq.push_back(drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(std::move(aPolygon), aLineColor)));
+}
+
+SwHeaderFooterDashedLine::SwHeaderFooterDashedLine(SwEditWin* pEditWin, const SwFrame *pFrame, bool bHeader)
+ : SwDashedLine(pEditWin, &SwViewOption::GetHeaderFooterMarkColor)
+ , m_pEditWin(pEditWin)
+ , m_pFrame(pFrame)
+ , m_bIsHeader(bHeader)
+{
+}
+
+bool SwHeaderFooterDashedLine::IsOnScreen()
+{
+ tools::Rectangle aBounds(GetPosPixel(), GetSizePixel());
+ tools::Rectangle aVisArea = GetEditWin()->LogicToPixel(GetEditWin()->GetView().GetVisArea());
+ return aBounds.Overlaps(aVisArea);
+}
+
+void SwHeaderFooterDashedLine::EnsureWin()
+{
+ if (!m_pWin)
+ {
+ m_pWin = VclPtr<SwHeaderFooterWin>::Create(m_pEditWin, m_pFrame, m_bIsHeader);
+ m_pWin->SetZOrder(this, ZOrderFlags::Before);
+ }
+}
+
+void SwHeaderFooterDashedLine::ShowAll(bool bShow)
+{
+ Show(bShow);
+ if (!m_pWin && IsOnScreen())
+ EnsureWin();
+ if (m_pWin)
+ m_pWin->ShowAll(bShow);
+}
+
+void SwHeaderFooterDashedLine::SetReadonly(bool bReadonly)
+{
+ ShowAll(!bReadonly);
+}
+
+bool SwHeaderFooterDashedLine::Contains(const Point &rDocPt) const
+{
+ if (m_pWin && m_pWin->Contains(rDocPt))
+ return true;
+
+ ::tools::Rectangle aLineRect(GetPosPixel(), GetSizePixel());
+ return aLineRect.Contains(rDocPt);
+}
+
+void SwHeaderFooterDashedLine::SetOffset(Point aOffset, tools::Long nXLineStart, tools::Long nXLineEnd)
+{
+ Point aLinePos(nXLineStart, aOffset.Y());
+ Size aLineSize(nXLineEnd - nXLineStart, 1);
+ SetPosSizePixel(aLinePos, aLineSize);
+
+ bool bOnScreen = IsOnScreen();
+ if (!m_pWin && bOnScreen)
+ {
+ EnsureWin();
+ m_pWin->ShowAll(true);
+ }
+ else if (m_pWin && !bOnScreen)
+ m_pWin.disposeAndClear();
+
+ if (m_pWin)
+ m_pWin->SetOffset(aOffset);
+}
+
+SwHeaderFooterWin::SwHeaderFooterWin(SwEditWin* pEditWin, const SwFrame *pFrame, bool bHeader ) :
+ InterimItemWindow(pEditWin, "modules/swriter/ui/hfmenubutton.ui", "HFMenuButton"),
+ m_xMenuButton(m_xBuilder->weld_menu_button("menubutton")),
+ m_xPushButton(m_xBuilder->weld_button("button")),
+ m_pEditWin(pEditWin),
+ m_pFrame(pFrame),
+ m_bIsHeader( bHeader ),
+ m_bIsAppearing( false ),
+ m_nFadeRate( 100 ),
+ m_aFadeTimer("SwHeaderFooterWin m_aFadeTimer")
+{
+ m_xVirDev = m_xMenuButton->create_virtual_device();
+ SwFrameMenuButtonBase::SetVirDevFont(*m_xVirDev);
+
+ m_xPushButton->connect_clicked(LINK(this, SwHeaderFooterWin, ClickHdl));
+ m_xMenuButton->connect_selected(LINK(this, SwHeaderFooterWin, SelectHdl));
+
+ // set the PopupMenu
+ // Rewrite the menu entries' text
+ if (m_bIsHeader)
+ {
+ m_xMenuButton->set_item_label("edit", SwResId(STR_FORMAT_HEADER));
+ m_xMenuButton->set_item_label("delete", SwResId(STR_DELETE_HEADER));
+ }
+ else
+ {
+ m_xMenuButton->set_item_label("edit", SwResId(STR_FORMAT_FOOTER));
+ m_xMenuButton->set_item_label("delete", SwResId(STR_DELETE_FOOTER));
+ }
+
+ m_aFadeTimer.SetTimeout(50);
+ m_aFadeTimer.SetInvokeHandler(LINK(this, SwHeaderFooterWin, FadeHandler));
+}
+
+SwHeaderFooterWin::~SwHeaderFooterWin( )
+{
+ disposeOnce();
+}
+
+void SwHeaderFooterWin::dispose()
+{
+ m_xPushButton.reset();
+ m_xMenuButton.reset();
+ m_pEditWin.clear();
+ m_xVirDev.disposeAndClear();
+ InterimItemWindow::dispose();
+}
+
+void SwHeaderFooterWin::SetOffset(Point aOffset)
+{
+ // Compute the text to show
+ const SwPageFrame* pPageFrame = SwFrameMenuButtonBase::GetPageFrame(m_pFrame);
+ const SwPageDesc* pDesc = pPageFrame->GetPageDesc();
+ bool bIsFirst = !pDesc->IsFirstShared() && pPageFrame->OnFirstPage();
+ bool bIsLeft = !pDesc->IsHeaderShared() && !pPageFrame->OnRightPage();
+ bool bIsRight = !pDesc->IsHeaderShared() && pPageFrame->OnRightPage();
+ m_sLabel = SwResId(STR_HEADER_TITLE);
+ if (!m_bIsHeader)
+ m_sLabel = bIsFirst ? SwResId(STR_FIRST_FOOTER_TITLE)
+ : bIsLeft ? SwResId(STR_LEFT_FOOTER_TITLE)
+ : bIsRight ? SwResId(STR_RIGHT_FOOTER_TITLE)
+ : SwResId(STR_FOOTER_TITLE );
+ else
+ m_sLabel = bIsFirst ? SwResId(STR_FIRST_HEADER_TITLE)
+ : bIsLeft ? SwResId(STR_LEFT_HEADER_TITLE)
+ : bIsRight ? SwResId(STR_RIGHT_HEADER_TITLE)
+ : SwResId(STR_HEADER_TITLE);
+
+ sal_Int32 nPos = m_sLabel.lastIndexOf("%1");
+ m_sLabel = m_sLabel.replaceAt(nPos, 2, pDesc->GetName());
+ m_xMenuButton->set_accessible_name(m_sLabel);
+
+ // Compute the text size and get the box position & size from it
+ ::tools::Rectangle aTextRect;
+ m_xVirDev->GetTextBoundRect(aTextRect, m_sLabel);
+ ::tools::Rectangle aTextPxRect = m_xVirDev->LogicToPixel(aTextRect);
+ FontMetric aFontMetric = m_xVirDev->GetFontMetric(m_xVirDev->GetFont());
+ Size aBoxSize (aTextPxRect.GetWidth() + BUTTON_WIDTH + TEXT_PADDING * 2,
+ aFontMetric.GetLineHeight() + TEXT_PADDING * 2 );
+
+ tools::Long nYFooterOff = 0;
+ if (!m_bIsHeader)
+ nYFooterOff = aBoxSize.Height();
+
+ Point aBoxPos(aOffset.X() - aBoxSize.Width() - BOX_DISTANCE,
+ aOffset.Y() - nYFooterOff);
+
+ if (AllSettings::GetLayoutRTL())
+ {
+ aBoxPos.setX( aOffset.X() + BOX_DISTANCE );
+ }
+
+ // Set the position & Size of the window
+ SetPosSizePixel(aBoxPos, aBoxSize);
+
+ m_xVirDev->SetOutputSizePixel(aBoxSize);
+ PaintButton();
+}
+
+void SwHeaderFooterWin::ShowAll(bool bShow)
+{
+ bool bIsEmptyHeaderFooter = IsEmptyHeaderFooter();
+ m_xMenuButton->set_visible(!bIsEmptyHeaderFooter);
+ m_xPushButton->set_visible(bIsEmptyHeaderFooter);
+
+ m_bIsAppearing = bShow;
+
+ if (m_aFadeTimer.IsActive())
+ m_aFadeTimer.Stop();
+ m_aFadeTimer.Start();
+}
+
+bool SwHeaderFooterWin::Contains( const Point &rDocPt ) const
+{
+ ::tools::Rectangle aRect(GetPosPixel(), GetSizePixel());
+ return aRect.Contains(rDocPt);
+}
+
+void SwHeaderFooterWin::PaintButton()
+{
+ if (!m_xVirDev)
+ return;
+
+ // Use pixels for the rest of the drawing
+ SetMapMode(MapMode(MapUnit::MapPixel));
+ drawinglayer::primitive2d::Primitive2DContainer aSeq;
+ const ::tools::Rectangle aRect(::tools::Rectangle(Point(0, 0), m_xVirDev->PixelToLogic(GetSizePixel())));
+
+ SwFrameButtonPainter::PaintButton(aSeq, aRect, m_bIsHeader);
+
+ // Create the text primitive
+ basegfx::BColor aLineColor = SwViewOption::GetCurrentViewOptions().GetHeaderFooterMarkColor().getBColor();
+ B2DVector aFontSize;
+ FontAttribute aFontAttr = drawinglayer::primitive2d::getFontAttributeFromVclFont(aFontSize, m_xVirDev->GetFont(), false, false);
+
+ FontMetric aFontMetric = m_xVirDev->GetFontMetric(m_xVirDev->GetFont());
+ double nTextOffsetY = aFontMetric.GetAscent() + TEXT_PADDING;
+ Point aTextPos(TEXT_PADDING, nTextOffsetY);
+
+ basegfx::B2DHomMatrix aTextMatrix(createScaleTranslateB2DHomMatrix(
+ aFontSize.getX(), aFontSize.getY(),
+ double(aTextPos.X()), double(aTextPos.Y())));
+
+ aSeq.push_back(drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
+ aTextMatrix, m_sLabel, 0, m_sLabel.getLength(),
+ std::vector<double>(), {}, std::move(aFontAttr), css::lang::Locale(), aLineColor)));
+
+ // Create the 'plus' or 'arrow' primitive
+ B2DRectangle aSignArea(B2DPoint(aRect.Right() - BUTTON_WIDTH, 0.0),
+ B2DVector(aRect.Right(), aRect.getOpenHeight()));
+
+ B2DPolygon aSign;
+ bool bIsEmptyHeaderFooter = IsEmptyHeaderFooter();
+ if (bIsEmptyHeaderFooter)
+ {
+ // Create the + polygon
+ double nLeft = aSignArea.getMinX() + TEXT_PADDING;
+ double nRight = aSignArea.getMaxX() - TEXT_PADDING;
+ double nHalfW = ( nRight - nLeft ) / 2.0;
+
+ double nTop = aSignArea.getCenterY() - nHalfW;
+ double nBottom = aSignArea.getCenterY() + nHalfW;
+
+ aSign.append(B2DPoint(nLeft, aSignArea.getCenterY() - 1.0));
+ aSign.append(B2DPoint(aSignArea.getCenterX() - 1.0, aSignArea.getCenterY() - 1.0));
+ aSign.append(B2DPoint(aSignArea.getCenterX() - 1.0, nTop));
+ aSign.append(B2DPoint(aSignArea.getCenterX() + 1.0, nTop));
+ aSign.append(B2DPoint(aSignArea.getCenterX() + 1.0, aSignArea.getCenterY() - 1.0));
+ aSign.append(B2DPoint(nRight, aSignArea.getCenterY() - 1.0));
+ aSign.append(B2DPoint(nRight, aSignArea.getCenterY() + 1.0));
+ aSign.append(B2DPoint(aSignArea.getCenterX() + 1.0, aSignArea.getCenterY() + 1.0));
+ aSign.append(B2DPoint(aSignArea.getCenterX() + 1.0, nBottom));
+ aSign.append(B2DPoint(aSignArea.getCenterX() - 1.0, nBottom));
+ aSign.append(B2DPoint(aSignArea.getCenterX() - 1.0, aSignArea.getCenterY() + 1.0));
+ aSign.append(B2DPoint(nLeft, aSignArea.getCenterY() + 1.0));
+ aSign.setClosed(true);
+ }
+ else
+ {
+ // Create the v polygon
+ B2DPoint aLeft(aSignArea.getMinX() + TEXT_PADDING, aSignArea.getCenterY());
+ B2DPoint aRight(aSignArea.getMaxX() - TEXT_PADDING, aSignArea.getCenterY());
+ B2DPoint aBottom((aLeft.getX() + aRight.getX()) / 2.0, aLeft.getY() + 4.0);
+ aSign.append(aLeft);
+ aSign.append(aRight);
+ aSign.append(aBottom);
+ aSign.setClosed(true);
+ }
+
+ BColor aSignColor = COL_BLACK.getBColor();
+ if (Application::GetSettings().GetStyleSettings().GetHighContrastMode())
+ aSignColor = COL_WHITE.getBColor();
+
+ aSeq.push_back( drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
+ B2DPolyPolygon(aSign), aSignColor)) );
+
+ // Create the processor and process the primitives
+ const drawinglayer::geometry::ViewInformation2D aNewViewInfos;
+ std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(
+ drawinglayer::processor2d::createProcessor2DFromOutputDevice(*m_xVirDev, aNewViewInfos));
+
+ // TODO Ghost it all if needed
+ drawinglayer::primitive2d::Primitive2DContainer aGhostedSeq(1);
+ double nFadeRate = double(m_nFadeRate) / 100.0;
+
+ const basegfx::BColorModifierSharedPtr aBColorModifier =
+ std::make_shared<basegfx::BColorModifier_interpolate>(COL_WHITE.getBColor(),
+ 1.0 - nFadeRate);
+
+ aGhostedSeq[0] = drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::ModifiedColorPrimitive2D(std::move(aSeq), aBColorModifier));
+
+ pProcessor->process(aGhostedSeq);
+
+ if (bIsEmptyHeaderFooter)
+ m_xPushButton->set_custom_button(m_xVirDev.get());
+ else
+ m_xMenuButton->set_custom_button(m_xVirDev.get());
+}
+
+bool SwHeaderFooterWin::IsEmptyHeaderFooter( ) const
+{
+ bool bResult = true;
+
+ const SwPageFrame* pPageFrame = SwFrameMenuButtonBase::GetPageFrame(m_pFrame);
+ if (!pPageFrame)
+ {
+ return bResult;
+ }
+
+ // Actually check it
+ const SwPageDesc* pDesc = pPageFrame->GetPageDesc();
+
+ bool const bFirst(pPageFrame->OnFirstPage());
+ const SwFrameFormat *const pFormat = (pPageFrame->OnRightPage())
+ ? pDesc->GetRightFormat(bFirst)
+ : pDesc->GetLeftFormat(bFirst);
+
+ if ( pFormat )
+ {
+ if ( m_bIsHeader )
+ bResult = !pFormat->GetHeader().IsActive();
+ else
+ bResult = !pFormat->GetFooter().IsActive();
+ }
+
+ return bResult;
+}
+
+void SwHeaderFooterWin::ExecuteCommand(std::u16string_view rIdent)
+{
+ SwView& rView = m_pEditWin->GetView();
+ SwWrtShell& rSh = rView.GetWrtShell();
+
+ const SwPageFrame* pPageFrame = SwFrameMenuButtonBase::GetPageFrame(m_pFrame);
+ const OUString& rStyleName = pPageFrame->GetPageDesc()->GetName();
+ if (rIdent == u"edit")
+ {
+ OUString sPageId = m_bIsHeader ? OUString("header") : OUString("footer");
+ rView.GetDocShell()->FormatPage(rView.GetFrameWeld(), rStyleName, sPageId, rSh);
+ }
+ else if (rIdent == u"borderback")
+ {
+ const SwPageDesc* pDesc = pPageFrame->GetPageDesc();
+ const SwFrameFormat& rMaster = pDesc->GetMaster();
+ SwFrameFormat* pHFFormat = const_cast< SwFrameFormat* >( rMaster.GetFooter().GetFooterFormat() );
+ if ( m_bIsHeader )
+ pHFFormat = const_cast< SwFrameFormat* >( rMaster.GetHeader().GetHeaderFormat() );
+ SfxItemSet aSet( pHFFormat->GetAttrSet() );
+
+ // Items to hand over XPropertyList things like XColorList,
+ // XHatchList, XGradientList, and XBitmapList to the Area TabPage:
+ aSet.MergeRange( SID_COLOR_TABLE, SID_PATTERN_LIST );
+ // create needed items for XPropertyList entries from the DrawModel so that
+ // the Area TabPage can access them
+ rSh.GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->PutAreaListItems( aSet );
+
+ aSet.MergeRange(SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER);
+ // Create a box info item... needed by the dialog
+ std::shared_ptr<SvxBoxInfoItem> aBoxInfo(std::make_shared<SvxBoxInfoItem>(SID_ATTR_BORDER_INNER));
+ if (const SvxBoxInfoItem *pBoxInfo = pHFFormat->GetAttrSet().GetItemIfSet(SID_ATTR_BORDER_INNER))
+ aBoxInfo.reset(pBoxInfo->Clone());
+
+ aBoxInfo->SetTable(false);
+ aBoxInfo->SetDist(true);
+ aBoxInfo->SetMinDist(false);
+ aBoxInfo->SetDefDist(MIN_BORDER_DIST);
+ aBoxInfo->SetValid(SvxBoxInfoItemValidFlags::DISABLE);
+ aSet.Put(*aBoxInfo);
+
+ if (svx::ShowBorderBackgroundDlg( GetFrameWeld(), &aSet ) )
+ {
+ pHFFormat->SetFormatAttr( aSet );
+ rView.GetDocShell()->SetModified();
+ }
+ }
+ else if (rIdent == u"delete")
+ {
+ rSh.ChangeHeaderOrFooter( rStyleName, m_bIsHeader, false, true );
+ // warning: "this" may be disposed now
+ rSh.GetWin()->GrabFocusToDocument();
+ }
+ else if (rIdent == u"insert_pagenumber")
+ {
+ SfxViewFrame& rVFrame = rSh.GetView().GetViewFrame();
+ rVFrame.GetBindings().Execute(FN_INSERT_FLD_PGNUMBER);
+ }
+ else if (rIdent == u"insert_pagecount")
+ {
+ SfxViewFrame& rVFrame = rSh.GetView().GetViewFrame();
+ rVFrame.GetBindings().Execute(FN_INSERT_FLD_PGCOUNT);
+ }
+}
+
+IMPL_LINK_NOARG(SwHeaderFooterWin, ClickHdl, weld::Button&, void)
+{
+ SwView& rView = m_pEditWin->GetView();
+ SwWrtShell& rSh = rView.GetWrtShell();
+
+ const SwPageFrame* pPageFrame = SwFrameMenuButtonBase::GetPageFrame(m_pFrame);
+ const OUString& rStyleName = pPageFrame->GetPageDesc()->GetName();
+ {
+ VclPtr<SwHeaderFooterWin> xThis(this);
+ rSh.ChangeHeaderOrFooter( rStyleName, m_bIsHeader, true, false );
+ //tdf#153059 after ChangeHeaderOrFooter is it possible that "this" is disposed
+ if (xThis->isDisposed())
+ return;
+ }
+ m_xPushButton->hide();
+ m_xMenuButton->show();
+ PaintButton();
+}
+
+IMPL_LINK(SwHeaderFooterWin, SelectHdl, const OUString&, rIdent, void)
+{
+ ExecuteCommand(rIdent);
+}
+
+IMPL_LINK_NOARG(SwHeaderFooterWin, FadeHandler, Timer *, void)
+{
+ if (m_bIsAppearing && m_nFadeRate > 0)
+ m_nFadeRate -= 25;
+ else if (!m_bIsAppearing && m_nFadeRate < 100)
+ m_nFadeRate += 25;
+
+ if (m_nFadeRate != 100 && !IsVisible())
+ {
+ Show();
+ }
+ else if (m_nFadeRate == 100 && IsVisible())
+ {
+ Show(false);
+ }
+ else
+ PaintButton();
+
+ if (IsVisible() && m_nFadeRate > 0 && m_nFadeRate < 100)
+ m_aFadeTimer.Start();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx b/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx
new file mode 100644
index 0000000000..9985485502
--- /dev/null
+++ b/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx
@@ -0,0 +1,252 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <edtwin.hxx>
+#include <OutlineContentVisibilityWin.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+
+#include <IDocumentOutlineNodes.hxx>
+#include <txtfrm.hxx>
+#include <ndtxt.hxx>
+#include <vcl/InterimItemWindow.hxx>
+#include <vcl/event.hxx>
+#include <vcl/svapp.hxx>
+#include <strings.hrc>
+
+#include <viewopt.hxx>
+
+#include <FrameControlsManager.hxx>
+
+SwOutlineContentVisibilityWin::SwOutlineContentVisibilityWin(SwEditWin* pEditWin,
+ const SwFrame* pFrame)
+ : InterimItemWindow(pEditWin, "modules/swriter/ui/outlinebutton.ui", "OutlineButton")
+ , m_xShowBtn(m_xBuilder->weld_button("show"))
+ , m_xHideBtn(m_xBuilder->weld_button("hide"))
+ , m_pEditWin(pEditWin)
+ , m_pFrame(pFrame)
+ , m_nDelayAppearing(0)
+ , m_aDelayTimer("SwOutlineContentVisibilityWin m_aDelayTimer")
+ , m_bDestroyed(false)
+ , m_nOutlinePos(SwOutlineNodes::npos)
+{
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ SetPaintTransparent(false);
+ SetBackground(rStyleSettings.GetFaceColor());
+
+ Size aBtnsSize(m_xShowBtn->get_preferred_size());
+ auto nDim = std::max(aBtnsSize.Width(), aBtnsSize.Height());
+ m_xShowBtn->set_size_request(nDim, nDim);
+ m_xHideBtn->set_size_request(nDim, nDim);
+
+ SetSizePixel(get_preferred_size());
+ SetSymbol(ButtonSymbol::NONE);
+
+ m_xShowBtn->connect_mouse_press(LINK(this, SwOutlineContentVisibilityWin, MousePressHdl));
+ m_xHideBtn->connect_mouse_press(LINK(this, SwOutlineContentVisibilityWin, MousePressHdl));
+
+ m_aDelayTimer.SetTimeout(25);
+ m_aDelayTimer.SetInvokeHandler(LINK(this, SwOutlineContentVisibilityWin, DelayAppearHandler));
+}
+
+void SwOutlineContentVisibilityWin::dispose()
+{
+ m_bDestroyed = true;
+ m_aDelayTimer.Stop();
+
+ m_pEditWin.clear();
+ m_pFrame = nullptr;
+
+ m_xHideBtn.reset();
+ m_xShowBtn.reset();
+
+ InterimItemWindow::dispose();
+}
+
+ButtonSymbol SwOutlineContentVisibilityWin::GetSymbol() const
+{
+ if (m_xShowBtn->get_visible())
+ return ButtonSymbol::SHOW;
+ if (m_xHideBtn->get_visible())
+ return ButtonSymbol::HIDE;
+ return ButtonSymbol::NONE;
+}
+
+void SwOutlineContentVisibilityWin::SetSymbol(ButtonSymbol eStyle)
+{
+ if (GetSymbol() == eStyle)
+ return;
+
+ bool bShow = eStyle == ButtonSymbol::SHOW;
+ bool bHide = eStyle == ButtonSymbol::HIDE;
+
+ // disable mouse move for the hidden button so we don't get mouse
+ // leave events we don't care about when we swap buttons
+ m_xShowBtn->connect_mouse_move(Link<const MouseEvent&, bool>());
+ m_xHideBtn->connect_mouse_move(Link<const MouseEvent&, bool>());
+
+ m_xShowBtn->set_visible(bShow);
+ m_xHideBtn->set_visible(bHide);
+
+ weld::Button* pButton = nullptr;
+ if (bShow)
+ pButton = m_xShowBtn.get();
+ else if (bHide)
+ pButton = m_xHideBtn.get();
+ InitControlBase(pButton);
+ if (pButton)
+ pButton->connect_mouse_move(LINK(this, SwOutlineContentVisibilityWin, MouseMoveHdl));
+}
+
+void SwOutlineContentVisibilityWin::Set()
+{
+ const SwTextFrame* pTextFrame = static_cast<const SwTextFrame*>(GetFrame());
+ const SwTextNode* pTextNode = pTextFrame->GetTextNodeFirst();
+ SwWrtShell& rSh = GetEditWin()->GetView().GetWrtShell();
+ const SwOutlineNodes& rOutlineNodes = rSh.GetNodes().GetOutLineNds();
+
+ (void)rOutlineNodes.Seek_Entry(static_cast<SwNode*>(const_cast<SwTextNode*>(pTextNode)),
+ &m_nOutlinePos);
+
+ // set symbol displayed on button
+ bool bVisible = true;
+ const_cast<SwTextNode*>(pTextNode)->GetAttrOutlineContentVisible(bVisible);
+ SetSymbol(bVisible ? ButtonSymbol::HIDE : ButtonSymbol::SHOW);
+
+ // set quick help
+ SwOutlineNodes::size_type nOutlineNodesCount
+ = rSh.getIDocumentOutlineNodesAccess()->getOutlineNodesCount();
+ int nLevel = rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(m_nOutlinePos);
+ OUString sQuickHelp(SwResId(STR_OUTLINE_CONTENT_TOGGLE_VISIBILITY));
+ if (!rSh.GetViewOptions()->IsTreatSubOutlineLevelsAsContent()
+ && m_nOutlinePos + 1 < nOutlineNodesCount
+ && rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(m_nOutlinePos + 1) > nLevel)
+ sQuickHelp += " (" + SwResId(STR_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT) + ")";
+ SetQuickHelpText(sQuickHelp);
+
+ // Set the position of the window
+ SwRect aFrameAreaRect = pTextFrame->getFrameArea();
+ aFrameAreaRect.AddTop(pTextFrame->GetTopMargin());
+ SwSpecialPos aSpecialPos;
+ aSpecialPos.nExtendRange = pTextNode->HasVisibleNumberingOrBullet() ? SwSPExtendRange::BEFORE
+ : SwSPExtendRange::NONE;
+ SwCursorMoveState aMoveState;
+ aMoveState.m_pSpecialPos = &aSpecialPos;
+ SwRect aCharRect;
+ pTextFrame->GetCharRect(aCharRect, SwPosition(*(pTextFrame->GetTextNodeForParaProps())),
+ &aMoveState);
+ Point aPxPt(GetEditWin()->GetOutDev()->LogicToPixel(
+ Point(aCharRect.Left(), aFrameAreaRect.Center().getY())));
+ if (pTextFrame->IsRightToLeft())
+ aPxPt.AdjustX(2);
+ else
+ aPxPt.AdjustX(-(GetSizePixel().getWidth() + 2));
+ aPxPt.AdjustY(-GetSizePixel().getHeight() / 2);
+ SetPosPixel(aPxPt);
+}
+
+void SwOutlineContentVisibilityWin::ShowAll(bool bShow)
+{
+ if (bShow)
+ {
+ m_nDelayAppearing = 0;
+ if (!m_bDestroyed && m_aDelayTimer.IsActive())
+ m_aDelayTimer.Stop();
+ if (!m_bDestroyed)
+ m_aDelayTimer.Start();
+ }
+ else
+ Hide();
+}
+
+bool SwOutlineContentVisibilityWin::Contains(const Point& rDocPt) const
+{
+ ::tools::Rectangle aRect(GetPosPixel(), GetSizePixel());
+ if (aRect.Contains(rDocPt))
+ return true;
+ return false;
+}
+
+IMPL_LINK(SwOutlineContentVisibilityWin, MouseMoveHdl, const MouseEvent&, rMEvt, bool)
+{
+ if (rMEvt.IsLeaveWindow())
+ {
+ if (GetSymbol() == ButtonSymbol::HIDE)
+ {
+ // MouseMove event may not be seen by the edit window for example when move is to
+ // a show button or when move is outside of the edit window.
+ // Only hide when mouse leave results in leaving the frame.
+ tools::Rectangle aFrameAreaPxRect
+ = GetEditWin()->LogicToPixel(GetFrame()->getFrameArea().SVRect());
+ auto nY = GetPosPixel().getY() + rMEvt.GetPosPixel().getY();
+ if (nY <= 0 || nY <= aFrameAreaPxRect.Top() || nY >= aFrameAreaPxRect.Bottom()
+ || nY >= GetEditWin()->GetSizePixel().Height())
+ {
+ GetEditWin()->SetSavedOutlineFrame(nullptr);
+ GetEditWin()->GetFrameControlsManager().RemoveControlsByType(
+ FrameControlType::Outline, GetFrame());
+ // warning: "this" is disposed now
+ }
+ }
+ }
+ else if (rMEvt.IsEnterWindow())
+ {
+ // Leave window event might not have resulted in removing hide button from saved frame
+ // and the edit win might not receive mouse event between leaving saved frame button and
+ // entering this button.
+ if (GetFrame() != GetEditWin()->GetSavedOutlineFrame())
+ {
+ SwFrameControlPtr pFrameControl = GetEditWin()->GetFrameControlsManager().GetControl(
+ FrameControlType::Outline, GetEditWin()->GetSavedOutlineFrame());
+ if (pFrameControl)
+ {
+ SwOutlineContentVisibilityWin* pControl
+ = dynamic_cast<SwOutlineContentVisibilityWin*>(pFrameControl->GetIFacePtr());
+ if (pControl && pControl->GetSymbol() == ButtonSymbol::HIDE)
+ {
+ GetEditWin()->GetFrameControlsManager().RemoveControlsByType(
+ FrameControlType::Outline, GetEditWin()->GetSavedOutlineFrame());
+ // The outline content visibility window frame control (hide button)
+ // for saved outline frame is now disposed.
+ }
+ }
+ GetEditWin()->SetSavedOutlineFrame(
+ static_cast<SwTextFrame*>(const_cast<SwFrame*>(GetFrame())));
+ }
+ if (!m_bDestroyed && m_aDelayTimer.IsActive())
+ m_aDelayTimer.Stop();
+ // bring button to top
+ SetZOrder(this, ZOrderFlags::First);
+ }
+ return false;
+}
+
+// Toggle the outline content visibility on mouse press
+IMPL_LINK(SwOutlineContentVisibilityWin, MousePressHdl, const MouseEvent&, rMEvt, bool)
+{
+ Hide();
+ GetEditWin()->ToggleOutlineContentVisibility(m_nOutlinePos, rMEvt.IsRight());
+ return false;
+}
+
+IMPL_LINK_NOARG(SwOutlineContentVisibilityWin, DelayAppearHandler, Timer*, void)
+{
+ const int TICKS_BEFORE_WE_APPEAR = 3;
+ if (m_nDelayAppearing < TICKS_BEFORE_WE_APPEAR)
+ {
+ ++m_nDelayAppearing;
+ m_aDelayTimer.Start();
+ return;
+ }
+ if (GetEditWin()->GetSavedOutlineFrame() == GetFrame())
+ Show();
+ m_aDelayTimer.Stop();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/OverlayRanges.cxx b/sw/source/uibase/docvw/OverlayRanges.cxx
new file mode 100644
index 0000000000..2b30f9543e
--- /dev/null
+++ b/sw/source/uibase/docvw/OverlayRanges.cxx
@@ -0,0 +1,176 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "OverlayRanges.hxx"
+#include <view.hxx>
+#include <svx/sdrpaintwindow.hxx>
+#include <svx/svdview.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
+#include <svtools/optionsdrawinglayer.hxx>
+
+namespace
+{
+ // combine ranges geometrically to a single, ORed polygon
+ basegfx::B2DPolyPolygon impCombineRangesToPolyPolygon(const std::vector< basegfx::B2DRange >& rRanges)
+ {
+ const sal_uInt32 nCount(rRanges.size());
+ basegfx::B2DPolyPolygon aRetval;
+
+ for(sal_uInt32 a(0); a < nCount; a++)
+ {
+ const basegfx::B2DPolygon aDiscretePolygon(basegfx::utils::createPolygonFromRect(rRanges[a]));
+
+ if(0 == a)
+ {
+ aRetval.append(aDiscretePolygon);
+ }
+ else
+ {
+ aRetval = basegfx::utils::solvePolygonOperationOr(aRetval, basegfx::B2DPolyPolygon(aDiscretePolygon));
+ }
+ }
+
+ return aRetval;
+ }
+}
+
+namespace sw::overlay
+{
+ drawinglayer::primitive2d::Primitive2DContainer OverlayRanges::createOverlayObjectPrimitive2DSequence()
+ {
+ const sal_uInt32 nCount(getRanges().size());
+ drawinglayer::primitive2d::Primitive2DContainer aRetval;
+ aRetval.resize(nCount);
+ for ( sal_uInt32 a = 0; a < nCount; ++a )
+ {
+ const basegfx::BColor aRGBColor(getBaseColor().getBColor());
+ const basegfx::B2DPolygon aPolygon(basegfx::utils::createPolygonFromRect(maRanges[a]));
+ aRetval[a] = drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
+ basegfx::B2DPolyPolygon(aPolygon),
+ aRGBColor));
+ }
+ // embed all rectangles in transparent paint
+ const sal_uInt16 nTransparence( SvtOptionsDrawinglayer::GetTransparentSelectionPercent() );
+ const double fTransparence( nTransparence / 100.0 );
+ const drawinglayer::primitive2d::Primitive2DReference aUnifiedTransparence(
+ new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
+ std::move(aRetval),
+ fTransparence));
+
+ if ( mbShowSolidBorder )
+ {
+ const basegfx::BColor aRGBColor(getBaseColor().getBColor());
+ basegfx::B2DPolyPolygon aPolyPolygon(impCombineRangesToPolyPolygon(getRanges()));
+ const drawinglayer::primitive2d::Primitive2DReference aOutline(
+ new drawinglayer::primitive2d::PolyPolygonHairlinePrimitive2D(
+ std::move(aPolyPolygon),
+ aRGBColor));
+
+ aRetval = drawinglayer::primitive2d::Primitive2DContainer { aUnifiedTransparence, aOutline };
+ }
+ else
+ {
+ aRetval = drawinglayer::primitive2d::Primitive2DContainer { aUnifiedTransparence };
+ }
+
+ return aRetval;
+ }
+
+ /*static*/ std::unique_ptr<OverlayRanges> OverlayRanges::CreateOverlayRange(
+ SwView const & rDocView,
+ const Color& rColor,
+ std::vector< basegfx::B2DRange >&& rRanges,
+ const bool bShowSolidBorder )
+ {
+ std::unique_ptr<OverlayRanges> pOverlayRanges;
+
+ SdrView* pView = rDocView.GetDrawView();
+ if ( pView != nullptr )
+ {
+ SdrPaintWindow* pCandidate = pView->GetPaintWindow(0);
+ const rtl::Reference<sdr::overlay::OverlayManager>& xTargetOverlay = pCandidate->GetOverlayManager();
+
+ if ( xTargetOverlay.is() )
+ {
+ pOverlayRanges.reset(new sw::overlay::OverlayRanges( rColor, std::move(rRanges), bShowSolidBorder ));
+ xTargetOverlay->add( *pOverlayRanges );
+ }
+ }
+
+ return pOverlayRanges;
+ }
+
+ OverlayRanges::OverlayRanges(
+ const Color& rColor,
+ std::vector< basegfx::B2DRange >&& rRanges,
+ const bool bShowSolidBorder )
+ : sdr::overlay::OverlayObject( rColor )
+ , maRanges( std::move(rRanges) )
+ , mbShowSolidBorder( bShowSolidBorder )
+ {
+ // no AA for highlight overlays
+ allowAntiAliase(false);
+ }
+
+ OverlayRanges::~OverlayRanges()
+ {
+ if( getOverlayManager() )
+ {
+ getOverlayManager()->remove(*this);
+ }
+ }
+
+ void OverlayRanges::setRanges(std::vector< basegfx::B2DRange >&& rNew)
+ {
+ if(rNew != maRanges)
+ {
+ maRanges = std::move(rNew);
+ objectChange();
+ }
+ }
+
+ void OverlayRanges::ShowSolidBorder()
+ {
+ if ( !mbShowSolidBorder )
+ {
+ mbShowSolidBorder = true;
+ objectChange();
+ }
+ }
+
+ void OverlayRanges::HideSolidBorder()
+ {
+ if ( mbShowSolidBorder )
+ {
+ mbShowSolidBorder = false;
+ objectChange();
+ }
+ }
+
+} // end of namespace sw::overlay
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/OverlayRanges.hxx b/sw/source/uibase/docvw/OverlayRanges.hxx
new file mode 100644
index 0000000000..d698e2cde3
--- /dev/null
+++ b/sw/source/uibase/docvw/OverlayRanges.hxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <svx/sdr/overlay/overlayobject.hxx>
+#include <basegfx/range/b2drange.hxx>
+
+#include <memory>
+#include <vector>
+
+class SwView;
+
+namespace sw::overlay
+ {
+ class OverlayRanges final : public sdr::overlay::OverlayObject
+ {
+ public:
+ static std::unique_ptr<OverlayRanges> CreateOverlayRange(
+ SwView const & rDocView,
+ const Color& rColor,
+ std::vector< basegfx::B2DRange >&& rRanges,
+ const bool bShowSolidBorder );
+
+ virtual ~OverlayRanges() override;
+
+ // data read access
+ const std::vector< basegfx::B2DRange >& getRanges() const
+ {
+ return maRanges;
+ }
+
+ // data write access
+ void setRanges(std::vector< basegfx::B2DRange >&& rNew);
+
+ void ShowSolidBorder();
+ void HideSolidBorder();
+
+ private:
+ OverlayRanges(
+ const Color& rColor,
+ std::vector< basegfx::B2DRange >&& rRanges,
+ const bool bShowSolidBorder );
+
+ // geometry creation for OverlayObject
+ virtual drawinglayer::primitive2d::Primitive2DContainer createOverlayObjectPrimitive2DSequence() override;
+
+ // geometry of overlay
+ std::vector< basegfx::B2DRange > maRanges;
+ bool mbShowSolidBorder;
+ };
+} // end of namespace sw::overlay
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/PageBreakWin.cxx b/sw/source/uibase/docvw/PageBreakWin.cxx
new file mode 100644
index 0000000000..561dd56a25
--- /dev/null
+++ b/sw/source/uibase/docvw/PageBreakWin.cxx
@@ -0,0 +1,506 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <bitmaps.hlst>
+
+#include <cmdid.h>
+#include <cntfrm.hxx>
+#include <txtfrm.hxx>
+#include <notxtfrm.hxx>
+#include <ndtxt.hxx>
+#include <DashedLine.hxx>
+#include <doc.hxx>
+#include <edtwin.hxx>
+#include <fmtpdsc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IDocumentContentOperations.hxx>
+#include <PageBreakWin.hxx>
+#include <pagefrm.hxx>
+#include <PostItMgr.hxx>
+#include <FrameControlsManager.hxx>
+#include <strings.hrc>
+#include <tabfrm.hxx>
+#include <uiitems.hxx>
+#include <uiobject.hxx>
+#include <view.hxx>
+#include <viewopt.hxx>
+#include <wrtsh.hxx>
+
+#include <basegfx/color/bcolortools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <drawinglayer/primitive2d/discretebitmapprimitive2d.hxx>
+#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <drawinglayer/processor2d/processor2dtools.hxx>
+#include <editeng/formatbreakitem.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/stritem.hxx>
+#include <vcl/canvastools.hxx>
+#include <vcl/event.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <memory>
+
+#define BUTTON_WIDTH 30
+#define BUTTON_HEIGHT 19
+#define ARROW_WIDTH 9
+
+using namespace basegfx;
+using namespace basegfx::utils;
+
+SwBreakDashedLine::SwBreakDashedLine(SwEditWin* pEditWin, const SwFrame *pFrame)
+ : SwDashedLine(pEditWin, &SwViewOption::GetPageBreakColor)
+ , m_pEditWin(pEditWin)
+ , m_pFrame(pFrame)
+{
+ set_id("PageBreak"); // for uitest
+}
+
+SwPageBreakWin& SwBreakDashedLine::GetOrCreateWin()
+{
+ if (!m_pWin)
+ {
+ m_pWin = VclPtr<SwPageBreakWin>::Create(this, m_pEditWin, m_pFrame);
+ m_pWin->SetPosSizePixel(m_aBtnRect.TopLeft(), m_aBtnRect.GetSize());
+ m_pWin->SetZOrder(this, ZOrderFlags::Before);
+ }
+ return *m_pWin;
+}
+
+void SwBreakDashedLine::DestroyWin()
+{
+ m_pWin.disposeAndClear();
+}
+
+void SwBreakDashedLine::MouseMove( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeaveWindow() )
+ {
+ // don't fade if we just move to the 'button'
+ Point aEventPos( GetPosPixel() + rMEvt.GetPosPixel() );
+ if (m_pWin && (!Contains(aEventPos) || !m_pWin->IsVisible()))
+ m_pWin->Fade(false);
+ }
+ else if (!m_pWin || !m_pWin->IsVisible())
+ {
+ GetOrCreateWin().Fade(true);
+ }
+
+ if (!rMEvt.IsSynthetic() && (!m_pWin || !m_pWin->IsVisible()))
+ {
+ UpdatePosition(rMEvt.GetPosPixel());
+ }
+}
+
+void SwBreakDashedLine::ShowAll(bool bShow)
+{
+ Show(bShow);
+}
+
+void SwBreakDashedLine::SetReadonly(bool bReadonly)
+{
+ ShowAll(!bReadonly);
+}
+
+bool SwBreakDashedLine::Contains(const Point &rDocPt) const
+{
+ if (m_aBtnRect.Contains(rDocPt))
+ return true;
+
+ ::tools::Rectangle aLineRect(GetPosPixel(), GetSizePixel());
+ return aLineRect.Contains(rDocPt);
+}
+
+SwPageBreakWin::SwPageBreakWin(SwBreakDashedLine* pLine, SwEditWin* pEditWin, const SwFrame *pFrame) :
+ InterimItemWindow(pEditWin, "modules/swriter/ui/pbmenubutton.ui", "PBMenuButton"),
+ m_xMenuButton(m_xBuilder->weld_menu_button("menubutton")),
+ m_pLine(pLine),
+ m_pEditWin(pEditWin),
+ m_pFrame(pFrame),
+ m_bIsAppearing( false ),
+ m_nFadeRate( 100 ),
+ m_nDelayAppearing( 0 ),
+ m_aFadeTimer("SwPageBreakWin m_aFadeTimer"),
+ m_bDestroyed( false )
+{
+ m_xMenuButton->connect_toggled(LINK(this, SwPageBreakWin, ToggleHdl));
+ m_xMenuButton->connect_selected(LINK(this, SwPageBreakWin, SelectHdl));
+ m_xMenuButton->set_accessible_name(SwResId(STR_PAGE_BREAK_BUTTON));
+
+ m_xVirDev = m_xMenuButton->create_virtual_device();
+ SwFrameMenuButtonBase::SetVirDevFont(*m_xVirDev);
+
+ // Use pixels for the rest of the drawing
+ m_xVirDev->SetMapMode( MapMode ( MapUnit::MapPixel ) );
+
+ m_aFadeTimer.SetTimeout( 50 );
+ m_aFadeTimer.SetInvokeHandler( LINK( this, SwPageBreakWin, FadeHandler ) );
+}
+
+SwPageBreakWin::~SwPageBreakWin( )
+{
+ disposeOnce();
+}
+
+void SwPageBreakWin::dispose()
+{
+ m_bDestroyed = true;
+ m_aFadeTimer.Stop();
+ m_xVirDev.disposeAndClear();
+
+ m_pLine.clear();
+ m_pEditWin.clear();
+
+ m_xMenuButton.reset();
+ InterimItemWindow::dispose();
+}
+
+void SwPageBreakWin::PaintButton()
+{
+ if (!m_xVirDev)
+ return;
+
+ const ::tools::Rectangle aRect(::tools::Rectangle(Point(0, 0), m_xVirDev->PixelToLogic(GetSizePixel())));
+
+ // Properly paint the control
+ BColor aColor = SwViewOption::GetCurrentViewOptions().GetPageBreakColor().getBColor();
+
+ BColor aHslLine = rgb2hsl(aColor);
+ double nLuminance = aHslLine.getZ();
+ nLuminance += (1.0 - nLuminance) * 0.75;
+ if ( aHslLine.getZ() > 0.7 )
+ nLuminance = aHslLine.getZ() * 0.7;
+ aHslLine.setZ(nLuminance);
+ BColor aOtherColor = hsl2rgb(aHslLine);
+
+ const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
+ if (rSettings.GetHighContrastMode())
+ {
+ aColor = rSettings.GetDialogTextColor().getBColor();
+ aOtherColor = rSettings.GetDialogColor().getBColor();
+ }
+
+ bool bRtl = AllSettings::GetLayoutRTL();
+
+ drawinglayer::primitive2d::Primitive2DContainer aSeq(3);
+ B2DRectangle aBRect = vcl::unotools::b2DRectangleFromRectangle(aRect);
+ B2DPolygon aPolygon = createPolygonFromRect(aBRect, 3.0 / BUTTON_WIDTH, 3.0 / BUTTON_HEIGHT);
+
+ // Create the polygon primitives
+ aSeq[0].set(new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
+ B2DPolyPolygon(aPolygon), aOtherColor));
+ aSeq[1].set(new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
+ std::move(aPolygon), aColor));
+
+ // Create the primitive for the image
+ BitmapEx aBmpEx(RID_BMP_PAGE_BREAK);
+ double nImgOfstX = 3.0;
+ if (bRtl)
+ nImgOfstX = aRect.Right() - aBmpEx.GetSizePixel().Width() - 3.0;
+ aSeq[2].set(new drawinglayer::primitive2d::DiscreteBitmapPrimitive2D(
+ aBmpEx, B2DPoint(nImgOfstX, 1.0)));
+
+ double nTop = double(aRect.getOpenHeight()) / 2.0;
+ double nBottom = nTop + 4.0;
+ double nLeft = aRect.getOpenWidth() - ARROW_WIDTH - 6.0;
+ if (bRtl)
+ nLeft = ARROW_WIDTH - 2.0;
+ double nRight = nLeft + 8.0;
+
+ B2DPolygon aTriangle;
+ aTriangle.append(B2DPoint(nLeft, nTop));
+ aTriangle.append(B2DPoint(nRight, nTop));
+ aTriangle.append(B2DPoint((nLeft + nRight) / 2.0, nBottom));
+ aTriangle.setClosed(true);
+
+ BColor aTriangleColor = COL_BLACK.getBColor();
+ if (Application::GetSettings().GetStyleSettings().GetHighContrastMode())
+ aTriangleColor = COL_WHITE.getBColor();
+
+ aSeq.emplace_back();
+ aSeq.back().set( new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
+ B2DPolyPolygon(aTriangle), aTriangleColor));
+
+ drawinglayer::primitive2d::Primitive2DContainer aGhostedSeq(1);
+ double nFadeRate = double(m_nFadeRate) / 100.0;
+ const basegfx::BColorModifierSharedPtr aBColorModifier =
+ std::make_shared<basegfx::BColorModifier_interpolate>(COL_WHITE.getBColor(),
+ 1.0 - nFadeRate);
+ aGhostedSeq[0].set( new drawinglayer::primitive2d::ModifiedColorPrimitive2D(
+ std::move(aSeq), aBColorModifier));
+
+ // Create the processor and process the primitives
+ const drawinglayer::geometry::ViewInformation2D aNewViewInfos;
+ std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(
+ drawinglayer::processor2d::createProcessor2DFromOutputDevice(*m_xVirDev, aNewViewInfos));
+
+ pProcessor->process(aGhostedSeq);
+
+ m_xMenuButton->set_custom_button(m_xVirDev.get());
+}
+
+static SvxBreak lcl_GetBreakItem(const SwContentFrame* pCnt)
+{
+ SvxBreak eBreak = SvxBreak::NONE;
+ if ( pCnt )
+ {
+ if ( pCnt->IsInTab() )
+ eBreak = pCnt->FindTabFrame()->GetBreakItem().GetBreak();
+ else
+ eBreak = pCnt->GetBreakItem().GetBreak();
+ }
+ return eBreak;
+}
+
+IMPL_LINK(SwPageBreakWin, SelectHdl, const OUString&, rIdent, void)
+{
+ SwFrameControlPtr pFrameControl = m_pEditWin->GetFrameControlsManager().GetControl(FrameControlType::PageBreak, m_pFrame);
+
+ m_pLine->execute(rIdent);
+
+ // Only fade if there is more than this temporary shared pointer:
+ // The main reference has been deleted due to a page break removal
+ if (pFrameControl.use_count() > 1)
+ Fade( false );
+}
+
+void SwBreakDashedLine::execute(std::u16string_view rIdent)
+{
+ const SwPageFrame* pPageFrame = SwFrameMenuButtonBase::GetPageFrame(m_pFrame);
+ // Is there a PageBefore break on this page?
+ SwContentFrame *pCnt = const_cast<SwContentFrame*>(pPageFrame->FindFirstBodyContent());
+ SvxBreak eBreak = lcl_GetBreakItem( pCnt );
+
+ // Also check the previous page - to see if there is a PageAfter break
+ SwContentFrame *pPrevCnt = nullptr;
+ SvxBreak ePrevBreak = SvxBreak::NONE;
+ const SwPageFrame* pPrevPage = static_cast<const SwPageFrame*>(pPageFrame->GetPrev());
+ if ( pPrevPage )
+ {
+ pPrevCnt = const_cast<SwContentFrame*>(pPrevPage->FindLastBodyContent());
+ ePrevBreak = lcl_GetBreakItem( pPrevCnt );
+ }
+
+ if (pCnt && rIdent == u"edit")
+ {
+ SwWrtShell& rSh = m_pEditWin->GetView().GetWrtShell();
+ bool bOldLock = rSh.IsViewLocked();
+ rSh.LockView( true );
+
+ // Order of edit detection: first RES_BREAK PageAfter, then RES_BREAK PageBefore/RES_PAGEDESC
+ if ( ePrevBreak == SvxBreak::PageAfter )
+ pCnt = pPrevCnt;
+
+ SwContentNode& rNd = pCnt->IsTextFrame()
+ ? *static_cast<SwTextFrame*>(pCnt)->GetTextNodeFirst()
+ : *static_cast<SwNoTextFrame*>(pCnt)->GetNode();
+
+ if ( pCnt->IsInTab() )
+ {
+ rSh.Push( );
+ rSh.ClearMark();
+
+ rSh.SetSelection( SwPaM(rNd) );
+
+ SfxStringItem aItem(m_pEditWin->GetView().GetPool().GetWhich(FN_FORMAT_TABLE_DLG), "textflow");
+ m_pEditWin->GetView().GetViewFrame().GetDispatcher()->ExecuteList(
+ FN_FORMAT_TABLE_DLG,
+ SfxCallMode::SYNCHRON | SfxCallMode::RECORD,
+ { &aItem });
+
+ rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+ }
+ else
+ {
+ SwPaM aPaM( rNd );
+ SwPaMItem aPaMItem( m_pEditWin->GetView().GetPool( ).GetWhich( FN_PARAM_PAM ), &aPaM );
+ SfxStringItem aItem( SID_PARA_DLG, "textflow" );
+ m_pEditWin->GetView().GetViewFrame().GetDispatcher()->ExecuteList(
+ SID_PARA_DLG,
+ SfxCallMode::SYNCHRON | SfxCallMode::RECORD,
+ { &aItem, &aPaMItem });
+ }
+ rSh.LockView( bOldLock );
+ m_pEditWin->GrabFocus( );
+ }
+ else if (pCnt && rIdent == u"delete")
+ {
+ SwContentNode& rNd = pCnt->IsTextFrame()
+ ? *static_cast<SwTextFrame*>(pCnt)->GetTextNodeFirst()
+ : *static_cast<SwNoTextFrame*>(pCnt)->GetNode();
+
+ rNd.GetDoc().GetIDocumentUndoRedo( ).StartUndo( SwUndoId::UI_DELETE_PAGE_BREAK, nullptr );
+
+ SfxItemSetFixed<RES_PAGEDESC, RES_BREAK> aSet(
+ m_pEditWin->GetView().GetWrtShell().GetAttrPool());
+
+ aSet.Put( SwFormatPageDesc( nullptr ) );
+ // This break could be from the current paragraph, if it has a PageBefore break.
+ if ( eBreak == SvxBreak::PageBefore )
+ aSet.Put( SvxFormatBreakItem( SvxBreak::NONE, RES_BREAK ) );
+
+ rNd.GetDoc().getIDocumentContentOperations().InsertItemSet(
+ SwPaM(rNd), aSet, SetAttrMode::DEFAULT, pPageFrame->getRootFrame());
+
+ // This break could be from the previous paragraph, if it has a PageAfter break.
+ if ( ePrevBreak == SvxBreak::PageAfter )
+ {
+ SwContentNode& rPrevNd = pPrevCnt->IsTextFrame()
+ ? *static_cast<SwTextFrame*>(pPrevCnt)->GetTextNodeFirst()
+ : *static_cast<SwNoTextFrame*>(pPrevCnt)->GetNode();
+ aSet.ClearItem();
+ aSet.Put( SvxFormatBreakItem( SvxBreak::NONE, RES_BREAK ) );
+ rPrevNd.GetDoc().getIDocumentContentOperations().InsertItemSet(
+ SwPaM(rPrevNd), aSet, SetAttrMode::DEFAULT, pPrevCnt->getRootFrame());
+ }
+
+ rNd.GetDoc().GetIDocumentUndoRedo( ).EndUndo( SwUndoId::UI_DELETE_PAGE_BREAK, nullptr );
+ }
+}
+
+void SwBreakDashedLine::UpdatePosition(const std::optional<Point>& xEvtPt)
+{
+ if ( xEvtPt )
+ {
+ if ( xEvtPt == m_xMousePt )
+ return;
+ m_xMousePt = xEvtPt;
+ }
+
+ const SwPageFrame* pPageFrame = SwFrameMenuButtonBase::GetPageFrame(m_pFrame);
+ const SwFrame* pPrevPage = pPageFrame;
+ do
+ {
+ pPrevPage = pPrevPage->GetPrev();
+ }
+ while ( pPrevPage && ( ( pPrevPage->getFrameArea().Top( ) == pPageFrame->getFrameArea().Top( ) )
+ || static_cast< const SwPageFrame* >( pPrevPage )->IsEmptyPage( ) ) );
+
+ ::tools::Rectangle aBoundRect = GetEditWin()->LogicToPixel( pPageFrame->GetBoundRect(GetEditWin()->GetOutDev()).SVRect() );
+ ::tools::Rectangle aFrameRect = GetEditWin()->LogicToPixel( pPageFrame->getFrameArea().SVRect() );
+
+ tools::Long nYLineOffset = ( aBoundRect.Top() + aFrameRect.Top() ) / 2;
+ if ( pPrevPage )
+ {
+ ::tools::Rectangle aPrevFrameRect = GetEditWin()->LogicToPixel( pPrevPage->getFrameArea().SVRect() );
+ nYLineOffset = ( aPrevFrameRect.Bottom() + aFrameRect.Top() ) / 2;
+ }
+
+ // Get the page + sidebar coords
+ tools::Long nPgLeft = aFrameRect.Left();
+ tools::Long nPgRight = aFrameRect.Right();
+
+ tools::ULong nSidebarWidth = 0;
+ const SwPostItMgr* pPostItMngr = GetEditWin()->GetView().GetWrtShell().GetPostItMgr();
+ if ( pPostItMngr && pPostItMngr->HasNotes() && pPostItMngr->ShowNotes() )
+ nSidebarWidth = pPostItMngr->GetSidebarBorderWidth( true ) + pPostItMngr->GetSidebarWidth( true );
+
+ if ( pPageFrame->SidebarPosition( ) == sw::sidebarwindows::SidebarPosition::LEFT )
+ nPgLeft -= nSidebarWidth;
+ else if ( pPageFrame->SidebarPosition( ) == sw::sidebarwindows::SidebarPosition::RIGHT )
+ nPgRight += nSidebarWidth;
+
+ Size aBtnSize( BUTTON_WIDTH + ARROW_WIDTH, BUTTON_HEIGHT );
+
+ // Place the button on the left or right?
+ ::tools::Rectangle aVisArea = GetEditWin()->LogicToPixel( GetEditWin()->GetView().GetVisArea() );
+
+ tools::Long nLineLeft = std::max( nPgLeft, aVisArea.Left() );
+ tools::Long nLineRight = std::min( nPgRight, aVisArea.Right() );
+ tools::Long nBtnLeft = nLineLeft;
+
+ if ( m_xMousePt )
+ {
+ nBtnLeft = nLineLeft + m_xMousePt->X() - aBtnSize.getWidth() / 2;
+
+ if ( nBtnLeft < nLineLeft )
+ nBtnLeft = nLineLeft;
+ else if ( ( nBtnLeft + aBtnSize.getWidth() ) > nLineRight )
+ nBtnLeft = nLineRight - aBtnSize.getWidth();
+ }
+
+ // Set the button position
+ m_aBtnRect = ::tools::Rectangle(Point(nBtnLeft, nYLineOffset - BUTTON_HEIGHT / 2), aBtnSize);
+ if (m_pWin)
+ m_pWin->SetRectanglePixel(m_aBtnRect);
+
+ // Set the line position
+ Point aLinePos( nLineLeft, nYLineOffset - 5 );
+ Size aLineSize( nLineRight - nLineLeft, 10 );
+ SetPosSizePixel(aLinePos, aLineSize);
+}
+
+void SwPageBreakWin::SetRectanglePixel(const ::tools::Rectangle& rRect)
+{
+ SetPosSizePixel(rRect.TopLeft(), rRect.GetSize());
+ m_xVirDev->SetOutputSizePixel(rRect.GetSize());
+}
+
+void SwPageBreakWin::Fade( bool bFadeIn )
+{
+ m_bIsAppearing = bFadeIn;
+ if ( bFadeIn )
+ m_nDelayAppearing = 0;
+
+ if ( !m_bDestroyed && m_aFadeTimer.IsActive( ) )
+ m_aFadeTimer.Stop();
+ if ( !m_bDestroyed )
+ m_aFadeTimer.Start( );
+}
+
+IMPL_LINK(SwPageBreakWin, ToggleHdl, weld::Toggleable&, rMenuButton, void)
+{
+ // hide on dropdown, draw fully unfaded if dropdown before fully faded in
+ Fade(rMenuButton.get_active());
+}
+
+IMPL_LINK_NOARG(SwPageBreakWin, FadeHandler, Timer *, void)
+{
+ const int TICKS_BEFORE_WE_APPEAR = 10;
+ if ( m_bIsAppearing && m_nDelayAppearing < TICKS_BEFORE_WE_APPEAR )
+ {
+ ++m_nDelayAppearing;
+ m_aFadeTimer.Start();
+ return;
+ }
+
+ if ( m_bIsAppearing && m_nFadeRate > 0 )
+ m_nFadeRate -= 25;
+ else if ( !m_bIsAppearing && m_nFadeRate < 100 )
+ m_nFadeRate += 25;
+
+ if ( m_nFadeRate != 100 && !IsVisible() )
+ Show();
+ else if ( m_nFadeRate == 100 && IsVisible( ) )
+ {
+ Hide();
+ m_pLine->DestroyWin();
+ return;
+ }
+ else
+ {
+ m_pLine->UpdatePosition();
+ PaintButton();
+ }
+
+ if (IsVisible( ) && m_nFadeRate > 0 && m_nFadeRate < 100)
+ m_aFadeTimer.Start();
+}
+
+FactoryFunction SwBreakDashedLine::GetUITestFactory() const
+{
+ return PageBreakUIObject::create;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/PostItMgr.cxx b/sw/source/uibase/docvw/PostItMgr.cxx
new file mode 100644
index 0000000000..12c5e4f52d
--- /dev/null
+++ b/sw/source/uibase/docvw/PostItMgr.cxx
@@ -0,0 +1,2541 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_wasm_strip.h>
+
+#include <boost/property_tree/json_parser.hpp>
+
+#include <PostItMgr.hxx>
+#include <postithelper.hxx>
+
+#include <AnnotationWin.hxx>
+#include "frmsidebarwincontainer.hxx"
+#include <accmap.hxx>
+
+#include <SidebarWindowsConsts.hxx>
+#include "AnchorOverlayObject.hxx"
+#include "ShadowOverlayObject.hxx"
+
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/settings.hxx>
+
+#include <chrdlgmodes.hxx>
+#include <viewopt.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <wrtsh.hxx>
+#include <doc.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentFieldsAccess.hxx>
+#include <docstyle.hxx>
+#include <fldbas.hxx>
+#include <fmtfld.hxx>
+#include <docufld.hxx>
+#include <edtwin.hxx>
+#include <txtfld.hxx>
+#include <txtannotationfld.hxx>
+#include <rootfrm.hxx>
+#include <SwRewriter.hxx>
+#include <tools/color.hxx>
+#include <unotools/datetime.hxx>
+
+#include <swmodule.hxx>
+#include <strings.hrc>
+#include <cmdid.h>
+
+#include <sfx2/request.hxx>
+#include <sfx2/event.hxx>
+#include <svl/srchitem.hxx>
+
+#include <svl/languageoptions.hxx>
+#include <svl/hint.hxx>
+
+#include <svx/svdview.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/outlobj.hxx>
+
+#include <comphelper/lok.hxx>
+#include <comphelper/string.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+#include <annotsh.hxx>
+#include <swabstdlg.hxx>
+#include <memory>
+
+// distance between Anchor Y and initial note position
+#define POSTIT_INITIAL_ANCHOR_DISTANCE 20
+//distance between two postits
+#define POSTIT_SPACE_BETWEEN 8
+#define POSTIT_MINIMUMSIZE_WITH_META 60
+#define POSTIT_SCROLL_SIDEBAR_HEIGHT 20
+
+// if we layout more often we stop, this should never happen
+#define MAX_LOOP_COUNT 50
+
+using namespace sw::sidebarwindows;
+using namespace sw::annotation;
+
+namespace {
+
+ enum class CommentNotificationType { Add, Remove, Modify, Resolve };
+
+ bool comp_pos(const std::unique_ptr<SwSidebarItem>& a, const std::unique_ptr<SwSidebarItem>& b)
+ {
+ // sort by anchor position
+ SwPosition aPosAnchorA = a->GetAnchorPosition();
+ SwPosition aPosAnchorB = b->GetAnchorPosition();
+
+ bool aAnchorAInFooter = false;
+ bool aAnchorBInFooter = false;
+
+ // is the anchor placed in Footnote or the Footer?
+ if( aPosAnchorA.GetNode().FindFootnoteStartNode() || aPosAnchorA.GetNode().FindFooterStartNode() )
+ aAnchorAInFooter = true;
+ if( aPosAnchorB.GetNode().FindFootnoteStartNode() || aPosAnchorB.GetNode().FindFooterStartNode() )
+ aAnchorBInFooter = true;
+
+ // fdo#34800
+ // if AnchorA is in footnote, and AnchorB isn't
+ // we do not want to change over the position
+ if( aAnchorAInFooter && !aAnchorBInFooter )
+ return false;
+ // if aAnchorA is not placed in a footnote, and aAnchorB is
+ // force a change over
+ else if( !aAnchorAInFooter && aAnchorBInFooter )
+ return true;
+ // If neither or both are in the footer, compare the positions.
+ // Since footnotes are in Inserts section of nodes array and footers
+ // in Autotext section, all footnotes precede any footers so no need
+ // to check that.
+ else
+ return aPosAnchorA < aPosAnchorB;
+ }
+
+ /// Emits LOK notification about one addition/removal/change of a comment
+ void lcl_CommentNotification(const SwView* pView, const CommentNotificationType nType, const SwSidebarItem* pItem, const sal_uInt32 nPostItId)
+ {
+ if (!comphelper::LibreOfficeKit::isActive())
+ return;
+
+ boost::property_tree::ptree aAnnotation;
+ aAnnotation.put("action", (nType == CommentNotificationType::Add ? "Add" :
+ (nType == CommentNotificationType::Remove ? "Remove" :
+ (nType == CommentNotificationType::Modify ? "Modify" :
+ (nType == CommentNotificationType::Resolve ? "Resolve" : "???")))));
+ aAnnotation.put("id", nPostItId);
+ if (nType != CommentNotificationType::Remove && pItem != nullptr)
+ {
+ sw::annotation::SwAnnotationWin* pWin = pItem->mpPostIt.get();
+
+ const SwPostItField* pField = pWin->GetPostItField();
+ const SwRect& aRect = pWin->GetAnchorRect();
+ tools::Rectangle aSVRect(aRect.Pos().getX(),
+ aRect.Pos().getY(),
+ aRect.Pos().getX() + aRect.SSize().Width(),
+ aRect.Pos().getY() + aRect.SSize().Height());
+
+ if (!pItem->maLayoutInfo.mPositionFromCommentAnchor)
+ {
+ // Comments on frames: anchor position is the corner position, not the whole frame.
+ aSVRect.SetSize(Size(0, 0));
+ }
+
+ std::vector<OString> aRects;
+ for (const basegfx::B2DRange& aRange : pWin->GetAnnotationTextRanges())
+ {
+ const SwRect rect(aRange.getMinX(), aRange.getMinY(), aRange.getWidth(), aRange.getHeight());
+ aRects.push_back(rect.SVRect().toString());
+ }
+ const OString sRects = comphelper::string::join("; ", aRects);
+
+ aAnnotation.put("id", pField->GetPostItId());
+ aAnnotation.put("parentId", pField->GetParentPostItId());
+ aAnnotation.put("author", pField->GetPar1().toUtf8().getStr());
+ aAnnotation.put("text", pField->GetPar2().toUtf8().getStr());
+ aAnnotation.put("resolved", pField->GetResolved() ? "true" : "false");
+ aAnnotation.put("dateTime", utl::toISO8601(pField->GetDateTime().GetUNODateTime()));
+ aAnnotation.put("anchorPos", aSVRect.toString());
+ aAnnotation.put("textRange", sRects.getStr());
+ }
+
+ boost::property_tree::ptree aTree;
+ aTree.add_child("comment", aAnnotation);
+ std::stringstream aStream;
+ boost::property_tree::write_json(aStream, aTree);
+ std::string aPayload = aStream.str();
+
+ if (pView)
+ {
+ pView->libreOfficeKitViewCallback(LOK_CALLBACK_COMMENT, OString(aPayload));
+ }
+ }
+
+} // anonymous namespace
+
+SwPostItMgr::SwPostItMgr(SwView* pView)
+ : mpView(pView)
+ , mpWrtShell(mpView->GetDocShell()->GetWrtShell())
+ , mpEditWin(&mpView->GetEditWin())
+ , mnEventId(nullptr)
+ , mbWaitingForCalcRects(false)
+ , mpActivePostIt(nullptr)
+ , mbLayout(false)
+ , mbLayoutHeight(0)
+ , mbLayouting(false)
+ , mbReadOnly(mpView->GetDocShell()->IsReadOnly())
+ , mbDeleteNote(true)
+ , mbIsShowAnchor( false )
+{
+ if(!mpView->GetDrawView() )
+ mpView->GetWrtShell().MakeDrawView();
+
+ SwNoteProps aProps;
+ mbIsShowAnchor = aProps.IsShowAnchor();
+
+ //make sure we get the colour yellow always, even if not the first one of comments or redlining
+ SW_MOD()->GetRedlineAuthor();
+
+ // collect all PostIts and redline comments that exist after loading the document
+ // don't check for existence for any of them, don't focus them
+ AddPostIts(false,false);
+ /* this code can be used once we want redline comments in the Sidebar
+ AddRedlineComments(false,false);
+ */
+ // we want to receive stuff like SfxHintId::DocChanged
+ StartListening(*mpView->GetDocShell());
+ // listen to stylesheet pool to update on stylesheet rename,
+ // as EditTextObject references styles by name.
+ StartListening(*static_cast<SwDocStyleSheetPool*>(mpView->GetDocShell()->GetStyleSheetPool())->GetEEStyleSheetPool());
+ if (!mvPostItFields.empty())
+ {
+ mbWaitingForCalcRects = true;
+ mnEventId = Application::PostUserEvent( LINK( this, SwPostItMgr, CalcHdl) );
+ }
+}
+
+SwPostItMgr::~SwPostItMgr()
+{
+ if ( mnEventId )
+ Application::RemoveUserEvent( mnEventId );
+ // forget about all our Sidebar windows
+ RemoveSidebarWin();
+ EndListeningAll();
+
+ mPages.clear();
+}
+
+bool SwPostItMgr::CheckForRemovedPostIts()
+{
+ IDocumentRedlineAccess const& rIDRA(mpWrtShell->getIDocumentRedlineAccess());
+ bool bRemoved = false;
+ auto it = mvPostItFields.begin();
+ while(it != mvPostItFields.end())
+ {
+ if (!(*it)->UseElement(*mpWrtShell->GetLayout(), rIDRA))
+ {
+ EndListening(const_cast<SfxBroadcaster&>(*(*it)->GetBroadcaster()));
+
+ if((*it)->mpPostIt && (*it)->mpPostIt->GetPostItField())
+ lcl_CommentNotification(mpView, CommentNotificationType::Remove, nullptr, (*it)->mpPostIt->GetPostItField()->GetPostItId());
+
+ std::unique_ptr<SwSidebarItem> p = std::move(*it);
+ it = mvPostItFields.erase(it);
+ if (GetActiveSidebarWin() == p->mpPostIt)
+ SetActiveSidebarWin(nullptr);
+ p->mpPostIt.disposeAndClear();
+
+ if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations())
+ {
+ const SwPostItField* pPostItField = static_cast<const SwPostItField*>(p->GetFormatField().GetField());
+ lcl_CommentNotification(mpView, CommentNotificationType::Remove, nullptr, pPostItField->GetPostItId());
+ }
+
+ bRemoved = true;
+ }
+ else
+ ++it;
+ }
+
+ if ( !bRemoved )
+ return false;
+
+ // make sure that no deleted items remain in page lists
+ // todo: only remove deleted ones?!
+ if ( mvPostItFields.empty() )
+ {
+ PreparePageContainer();
+ PrepareView();
+ }
+ else
+ {
+ // if postits are there make sure that page lists are not empty
+ // otherwise sudden paints can cause pain (in BorderOverPageBorder)
+ CalcRects();
+ }
+
+ return true;
+}
+
+SwSidebarItem* SwPostItMgr::InsertItem(SfxBroadcaster* pItem, bool bCheckExistence, bool bFocus)
+{
+ if (bCheckExistence)
+ {
+ for (auto const& postItField : mvPostItFields)
+ {
+ if ( postItField->GetBroadcaster() == pItem )
+ return nullptr;
+ }
+ }
+ mbLayout = bFocus;
+
+ SwSidebarItem* pAnnotationItem = nullptr;
+ if (auto pSwFormatField = dynamic_cast< SwFormatField *>( pItem ))
+ {
+ mvPostItFields.push_back(std::make_unique<SwAnnotationItem>(*pSwFormatField, bFocus));
+ pAnnotationItem = mvPostItFields.back().get();
+ }
+ assert(dynamic_cast< const SwFormatField *>( pItem ) && "Mgr::InsertItem: seems like new stuff was added");
+ StartListening(*pItem);
+ return pAnnotationItem;
+}
+
+void SwPostItMgr::RemoveItem( SfxBroadcaster* pBroadcast )
+{
+ EndListening(*pBroadcast);
+ auto i = std::find_if(mvPostItFields.begin(), mvPostItFields.end(),
+ [&pBroadcast](const std::unique_ptr<SwSidebarItem>& pField) { return pField->GetBroadcaster() == pBroadcast; });
+ if (i != mvPostItFields.end())
+ {
+ std::unique_ptr<SwSidebarItem> p = std::move(*i);
+ // tdf#120487 remove from list before dispose, so comment window
+ // won't be recreated due to the entry still in the list if focus
+ // transferring from the pPostIt triggers relayout of postits
+ // tdf#133348 remove from list before calling SetActiveSidebarWin
+ // so GetNextPostIt won't deal with mvPostItFields containing empty unique_ptr
+ mvPostItFields.erase(i);
+ if (GetActiveSidebarWin() == p->mpPostIt)
+ SetActiveSidebarWin(nullptr);
+ p->mpPostIt.disposeAndClear();
+ }
+ mbLayout = true;
+ PrepareView();
+}
+
+void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ if (rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint)
+ {
+ const SfxEventHint& rSfxEventHint = static_cast<const SfxEventHint&>(rHint);
+ if (rSfxEventHint.GetEventId() == SfxEventHintId::SwEventLayoutFinished)
+ {
+ if ( !mbWaitingForCalcRects && !mvPostItFields.empty())
+ {
+ mbWaitingForCalcRects = true;
+ mnEventId = Application::PostUserEvent( LINK( this, SwPostItMgr, CalcHdl) );
+ }
+ }
+ }
+ else if ( const SwFormatFieldHint * pFormatHint = dynamic_cast<const SwFormatFieldHint*>(&rHint) )
+ {
+ SwFormatField* pField = const_cast <SwFormatField*>( pFormatHint->GetField() );
+ switch ( pFormatHint->Which() )
+ {
+ case SwFormatFieldHintWhich::INSERTED :
+ {
+ if (!pField)
+ {
+ AddPostIts();
+ break;
+ }
+ // get field to be inserted from hint
+ if ( pField->IsFieldInDoc() )
+ {
+ bool bEmpty = !HasNotes();
+ SwSidebarItem* pItem = InsertItem( pField, true, false );
+
+ if (bEmpty && !mvPostItFields.empty())
+ PrepareView(true);
+
+ // True until the layout of this post it finishes
+ if (pItem)
+ pItem->mbPendingLayout = true;
+ }
+ else
+ {
+ OSL_FAIL("Inserted field not in document!" );
+ }
+ break;
+ }
+ case SwFormatFieldHintWhich::REMOVED:
+ {
+ if (mbDeleteNote)
+ {
+ if (!pField)
+ {
+ const bool bWasRemoved = CheckForRemovedPostIts();
+ // tdf#143643 ensure relayout on undo of insert comment
+ if (bWasRemoved)
+ mbLayout = true;
+ break;
+ }
+ RemoveItem(pField);
+
+ // If LOK has disabled tiled annotations, emit annotation callbacks
+ if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations())
+ {
+ SwPostItField* pPostItField = static_cast<SwPostItField*>(pField->GetField());
+ lcl_CommentNotification(mpView, CommentNotificationType::Remove, nullptr, pPostItField->GetPostItId());
+ }
+ }
+ break;
+ }
+ case SwFormatFieldHintWhich::FOCUS:
+ {
+ if (pFormatHint->GetView()== mpView)
+ Focus(rBC);
+ break;
+ }
+ case SwFormatFieldHintWhich::CHANGED:
+ case SwFormatFieldHintWhich::RESOLVED:
+ {
+ SwFormatField* pFormatField = dynamic_cast<SwFormatField*>(&rBC);
+ for (auto const& postItField : mvPostItFields)
+ {
+ if ( pFormatField == postItField->GetBroadcaster() )
+ {
+ if (postItField->mpPostIt)
+ {
+ postItField->mpPostIt->SetPostItText();
+ mbLayout = true;
+ }
+
+ // If LOK has disabled tiled annotations, emit annotation callbacks
+ if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations())
+ {
+ if(SwFormatFieldHintWhich::CHANGED == pFormatHint->Which())
+ lcl_CommentNotification(mpView, CommentNotificationType::Modify, postItField.get(), 0);
+ else
+ lcl_CommentNotification(mpView, CommentNotificationType::Resolve, postItField.get(), 0);
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ else if ( const SfxStyleSheetModifiedHint * pStyleHint = dynamic_cast<const SfxStyleSheetModifiedHint*>(&rHint) )
+ {
+ for (const auto& postItField : mvPostItFields)
+ {
+ auto pField = static_cast<SwPostItField*>(postItField->GetFormatField().GetField());
+ pField->ChangeStyleSheetName(pStyleHint->GetOldName(), pStyleHint->GetStyleSheet());
+ }
+ }
+ else
+ {
+ SfxHintId nId = rHint.GetId();
+ switch ( nId )
+ {
+ case SfxHintId::ModeChanged:
+ {
+ if ( mbReadOnly != mpView->GetDocShell()->IsReadOnly() )
+ {
+ mbReadOnly = !mbReadOnly;
+ SetReadOnlyState();
+ mbLayout = true;
+ }
+ break;
+ }
+ case SfxHintId::DocChanged:
+ {
+ if ( mpView->GetDocShell() == &rBC )
+ {
+ if ( !mbWaitingForCalcRects && !mvPostItFields.empty())
+ {
+ mbWaitingForCalcRects = true;
+ mnEventId = Application::PostUserEvent( LINK( this, SwPostItMgr, CalcHdl) );
+ }
+ }
+ break;
+ }
+ case SfxHintId::LanguageChanged:
+ {
+ SetSpellChecking();
+ break;
+ }
+ case SfxHintId::SwSplitNodeOperation:
+ {
+ // if we are in a SplitNode/Cut operation, do not delete note and then add again, as this will flicker
+ mbDeleteNote = !mbDeleteNote;
+ break;
+ }
+ case SfxHintId::Dying:
+ {
+ if ( mpView->GetDocShell() != &rBC )
+ {
+ // field to be removed is the broadcaster
+ OSL_FAIL("Notification for removed SwFormatField was not sent!");
+ RemoveItem(&rBC);
+ }
+ break;
+ }
+ default: break;
+ }
+ }
+}
+
+void SwPostItMgr::Focus(const SfxBroadcaster& rBC)
+{
+ if (!mpWrtShell->GetViewOptions()->IsPostIts())
+ {
+ SfxRequest aRequest(mpView->GetViewFrame(), SID_TOGGLE_NOTES);
+ mpView->ExecViewOptions(aRequest);
+ }
+
+ for (auto const& postItField : mvPostItFields)
+ {
+ // field to get the focus is the broadcaster
+ if ( &rBC == postItField->GetBroadcaster() )
+ {
+ if (postItField->mpPostIt)
+ {
+ if (postItField->mpPostIt->IsResolved() &&
+ !mpWrtShell->GetViewOptions()->IsResolvedPostIts())
+ {
+ SfxRequest aRequest(mpView->GetViewFrame(), SID_TOGGLE_RESOLVED_NOTES);
+ mpView->ExecViewOptions(aRequest);
+ }
+ postItField->mpPostIt->GrabFocus();
+ MakeVisible(postItField->mpPostIt);
+ }
+ else
+ {
+ // when the layout algorithm starts, this postit is created and receives focus
+ postItField->mbFocus = true;
+ }
+ }
+ }
+}
+
+bool SwPostItMgr::CalcRects()
+{
+ if ( mnEventId )
+ {
+ // if CalcRects() was forced and an event is still pending: remove it
+ // it is superfluous and also may cause reentrance problems if triggered while layouting
+ Application::RemoveUserEvent( mnEventId );
+ mnEventId = nullptr;
+ }
+
+ bool bChange = false;
+ bool bRepair = false;
+ PreparePageContainer();
+ if ( !mvPostItFields.empty() )
+ {
+ IDocumentRedlineAccess const& rIDRA(mpWrtShell->getIDocumentRedlineAccess());
+ for (auto const& pItem : mvPostItFields)
+ {
+ if (!pItem->UseElement(*mpWrtShell->GetLayout(), rIDRA))
+ {
+ OSL_FAIL("PostIt is not in doc or other wrong use");
+ bRepair = true;
+ continue;
+ }
+ const SwRect aOldAnchorRect( pItem->maLayoutInfo.mPosition );
+ const SwPostItHelper::SwLayoutStatus eOldLayoutStatus = pItem->mLayoutStatus;
+ const SwNodeOffset nOldStartNodeIdx( pItem->maLayoutInfo.mnStartNodeIdx );
+ const sal_Int32 nOldStartContent( pItem->maLayoutInfo.mnStartContent );
+ {
+ // update layout information
+ const SwTextAnnotationField* pTextAnnotationField =
+ dynamic_cast< const SwTextAnnotationField* >( pItem->GetFormatField().GetTextField() );
+ const ::sw::mark::IMark* pAnnotationMark =
+ pTextAnnotationField != nullptr ? pTextAnnotationField->GetAnnotationMark() : nullptr;
+ if ( pAnnotationMark != nullptr )
+ {
+ pItem->mLayoutStatus =
+ SwPostItHelper::getLayoutInfos(
+ pItem->maLayoutInfo,
+ pItem->GetAnchorPosition(),
+ pAnnotationMark );
+ }
+ else
+ {
+ pItem->mLayoutStatus =
+ SwPostItHelper::getLayoutInfos( pItem->maLayoutInfo, pItem->GetAnchorPosition() );
+ }
+ }
+ bChange = bChange
+ || pItem->maLayoutInfo.mPosition != aOldAnchorRect
+ || pItem->mLayoutStatus != eOldLayoutStatus
+ || pItem->maLayoutInfo.mnStartNodeIdx != nOldStartNodeIdx
+ || pItem->maLayoutInfo.mnStartContent != nOldStartContent;
+ }
+
+ // show notes in right order in navigator
+ //prevent Anchors during layout to overlap, e.g. when moving a frame
+ if (mvPostItFields.size()>1 )
+ std::stable_sort(mvPostItFields.begin(), mvPostItFields.end(), comp_pos);
+
+ // sort the items into the right page vector, so layout can be done by page
+ for (auto const& pItem : mvPostItFields)
+ {
+ if( SwPostItHelper::INVISIBLE == pItem->mLayoutStatus )
+ {
+ if (pItem->mpPostIt)
+ pItem->mpPostIt->HideNote();
+ continue;
+ }
+
+ if( SwPostItHelper::HIDDEN == pItem->mLayoutStatus )
+ {
+ if (!mpWrtShell->GetViewOptions()->IsShowHiddenChar())
+ {
+ if (pItem->mpPostIt)
+ pItem->mpPostIt->HideNote();
+ continue;
+ }
+ }
+
+ const tools::ULong aPageNum = pItem->maLayoutInfo.mnPageNumber;
+ if (aPageNum > mPages.size())
+ {
+ const tools::ULong nNumberOfPages = mPages.size();
+ mPages.reserve(aPageNum);
+ for (tools::ULong j=0; j<aPageNum - nNumberOfPages; ++j)
+ mPages.emplace_back( new SwPostItPageItem());
+ }
+ mPages[aPageNum-1]->mvSidebarItems.push_back(pItem.get());
+ mPages[aPageNum-1]->mPageRect = pItem->maLayoutInfo.mPageFrame;
+ mPages[aPageNum-1]->eSidebarPosition = pItem->maLayoutInfo.meSidebarPosition;
+ }
+
+ if (!bChange && mpWrtShell->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE))
+ {
+ tools::Long nLayoutHeight = SwPostItHelper::getLayoutHeight( mpWrtShell->GetLayout() );
+ if( nLayoutHeight > mbLayoutHeight )
+ {
+ if (mPages[0]->bScrollbar || HasScrollbars())
+ bChange = true;
+ }
+ else if( nLayoutHeight < mbLayoutHeight )
+ {
+ if (mPages[0]->bScrollbar || !BorderOverPageBorder(1))
+ bChange = true;
+ }
+ }
+ }
+
+ if ( bRepair )
+ CheckForRemovedPostIts();
+
+ mbLayoutHeight = SwPostItHelper::getLayoutHeight( mpWrtShell->GetLayout() );
+ mbWaitingForCalcRects = false;
+ return bChange;
+}
+
+bool SwPostItMgr::HasScrollbars() const
+{
+ for (auto const& postItField : mvPostItFields)
+ {
+ if (postItField->mbShow && postItField->mpPostIt && postItField->mpPostIt->HasScrollbar())
+ return true;
+ }
+ return false;
+}
+
+void SwPostItMgr::PreparePageContainer()
+{
+ // we do not just delete the SwPostItPageItem, so offset/scrollbar is not lost
+ tools::Long lPageSize = mpWrtShell->GetNumPages();
+ tools::Long lContainerSize = mPages.size();
+
+ if (lContainerSize < lPageSize)
+ {
+ mPages.reserve(lPageSize);
+ for (tools::Long i=0; i<lPageSize - lContainerSize;i++)
+ mPages.emplace_back( new SwPostItPageItem());
+ }
+ else if (lContainerSize > lPageSize)
+ {
+ for (int i=mPages.size()-1; i >= lPageSize;--i)
+ {
+ mPages.pop_back();
+ }
+ }
+ // only clear the list, DO NOT delete the objects itself
+ for (auto const& page : mPages)
+ {
+ page->mvSidebarItems.clear();
+ if (mvPostItFields.empty())
+ page->bScrollbar = false;
+ }
+}
+
+void SwPostItMgr::LayoutPostIts()
+{
+ const bool bLoKitActive = comphelper::LibreOfficeKit::isActive();
+ const bool bTiledAnnotations = comphelper::LibreOfficeKit::isTiledAnnotations();
+ const bool bShowNotes = ShowNotes();
+
+ const bool bEnableMapMode = bLoKitActive && !mpEditWin->IsMapModeEnabled();
+ if (bEnableMapMode)
+ mpEditWin->EnableMapMode();
+
+ if ( !mvPostItFields.empty() && !mbWaitingForCalcRects )
+ {
+ mbLayouting = true;
+
+ //loop over all pages and do the layout
+ // - create SwPostIt if necessary
+ // - place SwPostIts on their initial position
+ // - calculate necessary height for all PostIts together
+ bool bUpdate = false;
+ for (std::unique_ptr<SwPostItPageItem>& pPage : mPages)
+ {
+ // only layout if there are notes on this page
+ if (!pPage->mvSidebarItems.empty())
+ {
+ std::vector<SwAnnotationWin*> aVisiblePostItList;
+ tools::ULong lNeededHeight = 0;
+
+ for (auto const& pItem : pPage->mvSidebarItems)
+ {
+ VclPtr<SwAnnotationWin> pPostIt = pItem->mpPostIt;
+
+ if (pItem->mbShow)
+ {
+ if (!pPostIt)
+ {
+ pPostIt = pItem->GetSidebarWindow( mpView->GetEditWin(),
+ *this );
+ pPostIt->InitControls();
+ pPostIt->SetReadonly(mbReadOnly);
+ pItem->mpPostIt = pPostIt;
+ if (mpAnswer)
+ {
+ if (pPostIt->GetPostItField()->GetParentPostItId() != 0) //do we really have another note in front of this one
+ pPostIt->InitAnswer(*mpAnswer);
+ mpAnswer.reset();
+ }
+ }
+
+ pPostIt->SetChangeTracking(
+ pItem->mLayoutStatus,
+ GetColorAnchor(pItem->maLayoutInfo.mRedlineAuthor));
+ pPostIt->SetSidebarPosition(pPage->eSidebarPosition);
+
+ if (pPostIt->GetPostItField()->GetParentPostItId() != 0)
+ pPostIt->SetFollow(true);
+
+ tools::Long aPostItHeight = 0;
+ if (bShowNotes)
+ {
+ tools::Long mlPageBorder = 0;
+ tools::Long mlPageEnd = 0;
+
+ if (pPage->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT )
+ {
+ // x value for notes positioning
+ mlPageBorder = mpEditWin->LogicToPixel( Point( pPage->mPageRect.Left(), 0)).X() - GetSidebarWidth(true);// - GetSidebarBorderWidth(true);
+ //bending point
+ mlPageEnd =
+ mpWrtShell->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE)
+ ? pItem->maLayoutInfo.mPagePrtArea.Left()
+ : pPage->mPageRect.Left() + 350;
+ }
+ else if (pPage->eSidebarPosition == sw::sidebarwindows::SidebarPosition::RIGHT )
+ {
+ // x value for notes positioning
+ mlPageBorder = mpEditWin->LogicToPixel( Point(pPage->mPageRect.Right(), 0)).X() + GetSidebarBorderWidth(true);
+ //bending point
+ mlPageEnd =
+ mpWrtShell->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE)
+ ? pItem->maLayoutInfo.mPagePrtArea.Right() :
+ pPage->mPageRect.Right() - 350;
+ }
+
+ tools::Long Y = mpEditWin->LogicToPixel( Point(0,pItem->maLayoutInfo.mPosition.Bottom())).Y();
+
+ aPostItHeight = ( pPostIt->GetPostItTextHeight() < pPostIt->GetMinimumSizeWithoutMeta()
+ ? pPostIt->GetMinimumSizeWithoutMeta()
+ : pPostIt->GetPostItTextHeight() )
+ + pPostIt->GetMetaHeight();
+ pPostIt->SetPosSizePixelRect( mlPageBorder ,
+ Y - GetInitialAnchorDistance(),
+ GetSidebarWidth(true),
+ aPostItHeight,
+ mlPageEnd );
+ }
+
+ pPostIt->SetAnchorRect(pItem->maLayoutInfo.mPosition);
+
+ pPostIt->ChangeSidebarItem( *pItem );
+
+ if (pItem->mbFocus)
+ {
+ mbLayout = true;
+ pPostIt->GrabFocus();
+ pItem->mbFocus = false;
+ }
+ // only the visible postits are used for the final layout
+ aVisiblePostItList.push_back(pPostIt);
+ if (bShowNotes)
+ lNeededHeight += pPostIt->IsFollow() ? aPostItHeight : aPostItHeight+GetSpaceBetween();
+ }
+ else // we don't want to see it
+ {
+ if (pPostIt)
+ pPostIt->HideNote();
+ }
+ }
+
+ if (!aVisiblePostItList.empty() && ShowNotes())
+ {
+ bool bOldScrollbar = pPage->bScrollbar;
+ pPage->bScrollbar = LayoutByPage(aVisiblePostItList, pPage->mPageRect.SVRect(), lNeededHeight);
+ if (!pPage->bScrollbar)
+ {
+ pPage->lOffset = 0;
+ }
+ else if (sal_Int32 nScrollSize = GetScrollSize())
+ {
+ //when we changed our zoom level, the offset value can be too big, so lets check for the largest possible zoom value
+ tools::Long aAvailableHeight = mpEditWin->LogicToPixel(Size(0,pPage->mPageRect.Height())).Height() - 2 * GetSidebarScrollerHeight();
+ tools::Long lOffset = -1 * nScrollSize * (aVisiblePostItList.size() - aAvailableHeight / nScrollSize);
+ if (pPage->lOffset < lOffset)
+ pPage->lOffset = lOffset;
+ }
+ bUpdate = (bOldScrollbar != pPage->bScrollbar) || bUpdate;
+ const tools::Long aSidebarheight = pPage->bScrollbar ? mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height() : 0;
+ /*
+ TODO
+ - enlarge all notes till GetNextBorder(), as we resized to average value before
+ */
+ //lets hide the ones which overlap the page
+ for (auto const& visiblePostIt : aVisiblePostItList)
+ {
+ if (pPage->lOffset != 0)
+ visiblePostIt->TranslateTopPosition(pPage->lOffset);
+
+ bool bBottom = mpEditWin->PixelToLogic(Point(0,visiblePostIt->VirtualPos().Y()+visiblePostIt->VirtualSize().Height())).Y() <= (pPage->mPageRect.Bottom()-aSidebarheight);
+ bool bTop = mpEditWin->PixelToLogic(Point(0,visiblePostIt->VirtualPos().Y())).Y() >= (pPage->mPageRect.Top()+aSidebarheight);
+ if ( bBottom && bTop )
+ {
+ // When tiled rendering, make sure that only the
+ // view that has the comment focus emits callbacks,
+ // so the editing view jumps to the comment, but
+ // not the others.
+ bool bTiledPainting = comphelper::LibreOfficeKit::isTiledPainting();
+ if (!bTiledPainting)
+ // No focus -> disable callbacks.
+ comphelper::LibreOfficeKit::setTiledPainting(!visiblePostIt->HasChildPathFocus());
+ visiblePostIt->ShowNote();
+ if (!bTiledPainting)
+ comphelper::LibreOfficeKit::setTiledPainting(bTiledPainting);
+ }
+ else
+ {
+ if (mpEditWin->PixelToLogic(Point(0,visiblePostIt->VirtualPos().Y())).Y() < (pPage->mPageRect.Top()+aSidebarheight))
+ {
+ if ( pPage->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT )
+ visiblePostIt->ShowAnchorOnly(Point( pPage->mPageRect.Left(),
+ pPage->mPageRect.Top()));
+ else if ( pPage->eSidebarPosition == sw::sidebarwindows::SidebarPosition::RIGHT )
+ visiblePostIt->ShowAnchorOnly(Point( pPage->mPageRect.Right(),
+ pPage->mPageRect.Top()));
+ }
+ else
+ {
+ if ( pPage->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT )
+ visiblePostIt->ShowAnchorOnly(Point(pPage->mPageRect.Left(),
+ pPage->mPageRect.Bottom()));
+ else if ( pPage->eSidebarPosition == sw::sidebarwindows::SidebarPosition::RIGHT )
+ visiblePostIt->ShowAnchorOnly(Point(pPage->mPageRect.Right(),
+ pPage->mPageRect.Bottom()));
+ }
+ OSL_ENSURE(pPage->bScrollbar,"SwPostItMgr::LayoutByPage(): note overlaps, but bScrollbar is not true");
+ }
+ }
+ }
+ else
+ {
+ for (auto const& visiblePostIt : aVisiblePostItList)
+ {
+ visiblePostIt->SetPosAndSize();
+ }
+
+ bool bOldScrollbar = pPage->bScrollbar;
+ pPage->bScrollbar = false;
+ bUpdate = (bOldScrollbar != pPage->bScrollbar) || bUpdate;
+ }
+
+ for (auto const& visiblePostIt : aVisiblePostItList)
+ {
+ if (bLoKitActive && !bTiledAnnotations)
+ {
+ if (visiblePostIt->GetSidebarItem().mbPendingLayout)
+ lcl_CommentNotification(mpView, CommentNotificationType::Add, &visiblePostIt->GetSidebarItem(), 0);
+ else if (visiblePostIt->IsAnchorRectChanged())
+ {
+ lcl_CommentNotification(mpView, CommentNotificationType::Modify, &visiblePostIt->GetSidebarItem(), 0);
+ visiblePostIt->ResetAnchorRectChanged();
+ }
+ }
+
+ // Layout for this post it finished now
+ visiblePostIt->GetSidebarItem().mbPendingLayout = false;
+ }
+ }
+ else
+ {
+ if (pPage->bScrollbar)
+ bUpdate = true;
+ pPage->bScrollbar = false;
+ }
+ }
+
+ if (!bShowNotes)
+ { // we do not want to see the notes anymore -> Options-Writer-View-Notes
+ IDocumentRedlineAccess const& rIDRA(mpWrtShell->getIDocumentRedlineAccess());
+ bool bRepair = false;
+ for (auto const& postItField : mvPostItFields)
+ {
+ if (!postItField->UseElement(*mpWrtShell->GetLayout(), rIDRA))
+ {
+ OSL_FAIL("PostIt is not in doc!");
+ bRepair = true;
+ continue;
+ }
+
+ if (postItField->mpPostIt)
+ {
+ postItField->mpPostIt->HideNote();
+ if (postItField->mpPostIt->HasChildPathFocus())
+ {
+ SetActiveSidebarWin(nullptr);
+ postItField->mpPostIt->GrabFocusToDocument();
+ }
+ }
+ }
+
+ if ( bRepair )
+ CheckForRemovedPostIts();
+ }
+
+ // notes scrollbar is otherwise not drawn correctly for some cases
+ // scrollbar area is enough
+ if (bUpdate)
+ mpEditWin->Invalidate(); /*This is a super expensive relayout and render of the entire page*/
+
+ mbLayouting = false;
+ }
+
+ if (bEnableMapMode)
+ mpEditWin->EnableMapMode(false);
+}
+
+bool SwPostItMgr::BorderOverPageBorder(tools::ULong aPage) const
+{
+ if ( mPages[aPage-1]->mvSidebarItems.empty() )
+ {
+ OSL_FAIL("Notes SidePane painted but no rects and page lists calculated!");
+ return false;
+ }
+
+ auto aItem = mPages[aPage-1]->mvSidebarItems.end();
+ --aItem;
+ OSL_ENSURE ((*aItem)->mpPostIt,"BorderOverPageBorder: NULL postIt, should never happen");
+ if ((*aItem)->mpPostIt)
+ {
+ const tools::Long aSidebarheight = mPages[aPage-1]->bScrollbar ? mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height() : 0;
+ const tools::Long aEndValue = mpEditWin->PixelToLogic(Point(0,(*aItem)->mpPostIt->GetPosPixel().Y()+(*aItem)->mpPostIt->GetSizePixel().Height())).Y();
+ return aEndValue <= mPages[aPage-1]->mPageRect.Bottom()-aSidebarheight;
+ }
+ else
+ return false;
+}
+
+void SwPostItMgr::DrawNotesForPage(OutputDevice *pOutDev, sal_uInt32 nPage)
+{
+ assert(nPage < mPages.size());
+ if (nPage >= mPages.size())
+ return;
+ for (auto const& pItem : mPages[nPage]->mvSidebarItems)
+ {
+ SwAnnotationWin* pPostIt = pItem->mpPostIt;
+ if (!pPostIt)
+ continue;
+ Point aPoint(mpEditWin->PixelToLogic(pPostIt->GetPosPixel()));
+ pPostIt->DrawForPage(pOutDev, aPoint);
+ }
+}
+
+void SwPostItMgr::PaintTile(OutputDevice& rRenderContext)
+{
+ for (const std::unique_ptr<SwSidebarItem>& pItem : mvPostItFields)
+ {
+ SwAnnotationWin* pPostIt = pItem->mpPostIt;
+ if (!pPostIt)
+ continue;
+
+ bool bEnableMapMode = !mpEditWin->IsMapModeEnabled();
+ mpEditWin->EnableMapMode();
+ rRenderContext.Push(vcl::PushFlags::MAPMODE);
+ Point aOffset(mpEditWin->PixelToLogic(pPostIt->GetPosPixel()));
+ MapMode aMapMode(rRenderContext.GetMapMode());
+ aMapMode.SetOrigin(aMapMode.GetOrigin() + aOffset);
+ rRenderContext.SetMapMode(aMapMode);
+ Size aSize(rRenderContext.PixelToLogic(pPostIt->GetSizePixel()));
+ tools::Rectangle aRectangle(Point(0, 0), aSize);
+
+ pPostIt->PaintTile(rRenderContext, aRectangle);
+
+ rRenderContext.Pop();
+ if (bEnableMapMode)
+ mpEditWin->EnableMapMode(false);
+ }
+}
+
+void SwPostItMgr::Scroll(const tools::Long lScroll,const tools::ULong aPage)
+{
+ OSL_ENSURE((lScroll % GetScrollSize() )==0,"SwPostItMgr::Scroll: scrolling by wrong value");
+ // do not scroll more than necessary up or down
+ if ( ((mPages[aPage-1]->lOffset == 0) && (lScroll>0)) || ( BorderOverPageBorder(aPage) && (lScroll<0)) )
+ return;
+
+ const bool bOldUp = ArrowEnabled(KEY_PAGEUP,aPage);
+ const bool bOldDown = ArrowEnabled(KEY_PAGEDOWN,aPage);
+ const tools::Long aSidebarheight = mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height();
+ for (auto const& item : mPages[aPage-1]->mvSidebarItems)
+ {
+ SwAnnotationWin* pPostIt = item->mpPostIt;
+ // if this is an answer, we should take the normal position and not the real, slightly moved position
+ pPostIt->SetVirtualPosSize(pPostIt->GetPosPixel(),pPostIt->GetSizePixel());
+ pPostIt->TranslateTopPosition(lScroll);
+
+ if (item->mbShow)
+ {
+ bool bBottom = mpEditWin->PixelToLogic(Point(0,pPostIt->VirtualPos().Y()+pPostIt->VirtualSize().Height())).Y() <= (mPages[aPage-1]->mPageRect.Bottom()-aSidebarheight);
+ bool bTop = mpEditWin->PixelToLogic(Point(0,pPostIt->VirtualPos().Y())).Y() >= (mPages[aPage-1]->mPageRect.Top()+aSidebarheight);
+ if ( bBottom && bTop)
+ {
+ pPostIt->ShowNote();
+ }
+ else
+ {
+ if ( mpEditWin->PixelToLogic(Point(0,pPostIt->VirtualPos().Y())).Y() < (mPages[aPage-1]->mPageRect.Top()+aSidebarheight))
+ {
+ if (mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT)
+ pPostIt->ShowAnchorOnly(Point(mPages[aPage-1]->mPageRect.Left(),mPages[aPage-1]->mPageRect.Top()));
+ else if (mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::RIGHT)
+ pPostIt->ShowAnchorOnly(Point(mPages[aPage-1]->mPageRect.Right(),mPages[aPage-1]->mPageRect.Top()));
+ }
+ else
+ {
+ if (mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT)
+ pPostIt->ShowAnchorOnly(Point(mPages[aPage-1]->mPageRect.Left(),mPages[aPage-1]->mPageRect.Bottom()));
+ else if (mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::RIGHT)
+ pPostIt->ShowAnchorOnly(Point(mPages[aPage-1]->mPageRect.Right(),mPages[aPage-1]->mPageRect.Bottom()));
+ }
+ }
+ }
+ }
+ mPages[aPage-1]->lOffset += lScroll;
+ if ( (bOldUp != ArrowEnabled(KEY_PAGEUP,aPage)) ||(bOldDown != ArrowEnabled(KEY_PAGEDOWN,aPage)) )
+ {
+ mpEditWin->Invalidate(GetBottomScrollRect(aPage));
+ mpEditWin->Invalidate(GetTopScrollRect(aPage));
+ }
+}
+
+void SwPostItMgr::AutoScroll(const SwAnnotationWin* pPostIt,const tools::ULong aPage )
+{
+ // otherwise all notes are visible
+ if (!mPages[aPage-1]->bScrollbar)
+ return;
+
+ const tools::Long aSidebarheight = mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height();
+ const bool bBottom = mpEditWin->PixelToLogic(Point(0,pPostIt->GetPosPixel().Y()+pPostIt->GetSizePixel().Height())).Y() <= (mPages[aPage-1]->mPageRect.Bottom()-aSidebarheight);
+ const bool bTop = mpEditWin->PixelToLogic(Point(0,pPostIt->GetPosPixel().Y())).Y() >= (mPages[aPage-1]->mPageRect.Top()+aSidebarheight);
+ if ( !(bBottom && bTop))
+ {
+ const tools::Long aDiff = bBottom ? mpEditWin->LogicToPixel(Point(0,mPages[aPage-1]->mPageRect.Top() + aSidebarheight)).Y() - pPostIt->GetPosPixel().Y() :
+ mpEditWin->LogicToPixel(Point(0,mPages[aPage-1]->mPageRect.Bottom() - aSidebarheight)).Y() - (pPostIt->GetPosPixel().Y()+pPostIt->GetSizePixel().Height());
+ // this just adds the missing value to get the next a* GetScrollSize() after aDiff
+ // e.g aDiff= 61 POSTIT_SCROLL=50 --> lScroll = 100
+ const auto nScrollSize = GetScrollSize();
+ assert(nScrollSize);
+ const tools::Long lScroll = bBottom ? (aDiff + ( nScrollSize - (aDiff % nScrollSize))) : (aDiff - (nScrollSize + (aDiff % nScrollSize)));
+ Scroll(lScroll, aPage);
+ }
+}
+
+void SwPostItMgr::MakeVisible(const SwAnnotationWin* pPostIt )
+{
+ tools::Long aPage = -1;
+ // we don't know the page yet, lets find it ourselves
+ std::vector<SwPostItPageItem*>::size_type n=0;
+ for (auto const& page : mPages)
+ {
+ for (auto const& item : page->mvSidebarItems)
+ {
+ if (item->mpPostIt==pPostIt)
+ {
+ aPage = n+1;
+ break;
+ }
+ }
+ ++n;
+ }
+ if (aPage!=-1)
+ AutoScroll(pPostIt,aPage);
+ tools::Rectangle aNoteRect (Point(pPostIt->GetPosPixel().X(),pPostIt->GetPosPixel().Y()-5),pPostIt->GetSizePixel());
+ if (!aNoteRect.IsEmpty())
+ mpWrtShell->MakeVisible(SwRect(mpEditWin->PixelToLogic(aNoteRect)));
+}
+
+bool SwPostItMgr::ArrowEnabled(sal_uInt16 aDirection,tools::ULong aPage) const
+{
+ switch (aDirection)
+ {
+ case KEY_PAGEUP:
+ {
+ return (mPages[aPage-1]->lOffset != 0);
+ }
+ case KEY_PAGEDOWN:
+ {
+ return (!BorderOverPageBorder(aPage));
+ }
+ default: return false;
+ }
+}
+
+Color SwPostItMgr::GetArrowColor(sal_uInt16 aDirection,tools::ULong aPage) const
+{
+ if (ArrowEnabled(aDirection,aPage))
+ {
+ if (Application::GetSettings().GetStyleSettings().GetHighContrastMode())
+ return COL_WHITE;
+ else
+ return COL_NOTES_SIDEPANE_ARROW_ENABLED;
+ }
+ else
+ {
+ return COL_NOTES_SIDEPANE_ARROW_DISABLED;
+ }
+}
+
+bool SwPostItMgr::LayoutByPage(std::vector<SwAnnotationWin*> &aVisiblePostItList, const tools::Rectangle& rBorder, tools::Long lNeededHeight)
+{
+ /*** General layout idea:***/
+ // - if we have space left, we always move the current one up,
+ // otherwise the next one down
+ // - first all notes are resized
+ // - then the real layout starts
+
+ //rBorder is the page rect
+ const tools::Rectangle aBorder = mpEditWin->LogicToPixel(rBorder);
+ tools::Long lTopBorder = aBorder.Top() + 5;
+ tools::Long lBottomBorder = aBorder.Bottom() - 5;
+ const tools::Long lVisibleHeight = lBottomBorder - lTopBorder; //aBorder.GetHeight() ;
+ const size_t nPostItListSize = aVisiblePostItList.size();
+ tools::Long lTranslatePos = 0;
+ bool bScrollbars = false;
+
+ // do all necessary resizings
+ if (nPostItListSize > 0 && lVisibleHeight < lNeededHeight)
+ {
+ // ok, now we have to really resize and adding scrollbars
+ const tools::Long lAverageHeight = (lVisibleHeight - nPostItListSize*GetSpaceBetween()) / nPostItListSize;
+ if (lAverageHeight<GetMinimumSizeWithMeta())
+ {
+ bScrollbars = true;
+ lTopBorder += GetSidebarScrollerHeight() + 10;
+ lBottomBorder -= (GetSidebarScrollerHeight() + 10);
+ for (auto const& visiblePostIt : aVisiblePostItList)
+ visiblePostIt->SetSize(Size(visiblePostIt->VirtualSize().getWidth(),visiblePostIt->GetMinimumSizeWithMeta()));
+ }
+ else
+ {
+ for (auto const& visiblePostIt : aVisiblePostItList)
+ {
+ if ( visiblePostIt->VirtualSize().getHeight() > lAverageHeight)
+ visiblePostIt->SetSize(Size(visiblePostIt->VirtualSize().getWidth(),lAverageHeight));
+ }
+ }
+ }
+
+ //start the real layout so nothing overlaps anymore
+ if (aVisiblePostItList.size()>1)
+ {
+ int loop = 0;
+ bool bDone = false;
+ // if no window is moved anymore we are finished
+ while (!bDone)
+ {
+ loop++;
+ bDone = true;
+ tools::Long lSpaceUsed = lTopBorder + GetSpaceBetween();
+ for(auto i = aVisiblePostItList.begin(); i != aVisiblePostItList.end() ; ++i)
+ {
+ auto aNextPostIt = i;
+ ++aNextPostIt;
+
+ if (aNextPostIt != aVisiblePostItList.end())
+ {
+ lTranslatePos = ( (*i)->VirtualPos().Y() + (*i)->VirtualSize().Height()) - (*aNextPostIt)->VirtualPos().Y();
+ if (lTranslatePos > 0) // note windows overlaps the next one
+ {
+ // we are not done yet, loop at least once more
+ bDone = false;
+ // if there is space left, move the current note up
+ // it could also happen that there is no space left for the first note due to a scrollbar
+ // then we also jump into, so we move the current one up and the next one down
+ if ( (lSpaceUsed <= (*i)->VirtualPos().Y()) || (i==aVisiblePostItList.begin()))
+ {
+ // we have space left, so let's move the current one up
+ if ( ((*i)->VirtualPos().Y()- lTranslatePos - GetSpaceBetween()) > lTopBorder)
+ {
+ if ((*aNextPostIt)->IsFollow())
+ (*i)->TranslateTopPosition(-1*(lTranslatePos+ANCHORLINE_WIDTH));
+ else
+ (*i)->TranslateTopPosition(-1*(lTranslatePos+GetSpaceBetween()));
+ }
+ else
+ {
+ tools::Long lMoveUp = (*i)->VirtualPos().Y() - lTopBorder;
+ (*i)->TranslateTopPosition(-1* lMoveUp);
+ if ((*aNextPostIt)->IsFollow())
+ (*aNextPostIt)->TranslateTopPosition( (lTranslatePos+ANCHORLINE_WIDTH) - lMoveUp);
+ else
+ (*aNextPostIt)->TranslateTopPosition( (lTranslatePos+GetSpaceBetween()) - lMoveUp);
+ }
+ }
+ else
+ {
+ // no space left, left move the next one down
+ if ((*aNextPostIt)->IsFollow())
+ (*aNextPostIt)->TranslateTopPosition(lTranslatePos+ANCHORLINE_WIDTH);
+ else
+ (*aNextPostIt)->TranslateTopPosition(lTranslatePos+GetSpaceBetween());
+ }
+ }
+ else
+ {
+ // the first one could overlap the topborder instead of a second note
+ if (i==aVisiblePostItList.begin())
+ {
+ tools::Long lMoveDown = lTopBorder - (*i)->VirtualPos().Y();
+ if (lMoveDown>0)
+ {
+ bDone = false;
+ (*i)->TranslateTopPosition( lMoveDown);
+ }
+ }
+ }
+ if ( (*aNextPostIt)->IsFollow() )
+ lSpaceUsed += (*i)->VirtualSize().Height() + ANCHORLINE_WIDTH;
+ else
+ lSpaceUsed += (*i)->VirtualSize().Height() + GetSpaceBetween();
+ }
+ else
+ {
+ //(*i) is the last visible item
+ auto aPrevPostIt = i;
+ --aPrevPostIt;
+ lTranslatePos = ( (*aPrevPostIt)->VirtualPos().Y() + (*aPrevPostIt)->VirtualSize().Height() ) - (*i)->VirtualPos().Y();
+ if (lTranslatePos > 0)
+ {
+ bDone = false;
+ if ( ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height()+lTranslatePos) < lBottomBorder)
+ {
+ if ( (*i)->IsFollow() )
+ (*i)->TranslateTopPosition(lTranslatePos+ANCHORLINE_WIDTH);
+ else
+ (*i)->TranslateTopPosition(lTranslatePos+GetSpaceBetween());
+ }
+ else
+ {
+ (*i)->TranslateTopPosition(lBottomBorder - ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height()) );
+ }
+ }
+ else
+ {
+ // note does not overlap, but we might be over the lower border
+ // only do this if there are no scrollbars, otherwise notes are supposed to overlap the border
+ if (!bScrollbars && ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height() > lBottomBorder) )
+ {
+ bDone = false;
+ (*i)->TranslateTopPosition(lBottomBorder - ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height()));
+ }
+ }
+ }
+ }
+ // security check so we don't loop forever
+ if (loop>MAX_LOOP_COUNT)
+ {
+ OSL_FAIL("PostItMgr::Layout(): We are looping forever");
+ break;
+ }
+ }
+ }
+ else
+ {
+ // only one left, make sure it is not hidden at the top or bottom
+ auto i = aVisiblePostItList.begin();
+ lTranslatePos = lTopBorder - (*i)->VirtualPos().Y();
+ if (lTranslatePos>0)
+ {
+ (*i)->TranslateTopPosition(lTranslatePos+GetSpaceBetween());
+ }
+ lTranslatePos = lBottomBorder - ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height());
+ if (lTranslatePos<0)
+ {
+ (*i)->TranslateTopPosition(lTranslatePos);
+ }
+ }
+ return bScrollbars;
+ }
+
+void SwPostItMgr::AddPostIts(const bool bCheckExistence, const bool bFocus)
+{
+ const bool bEmpty = mvPostItFields.empty();
+ IDocumentRedlineAccess const& rIDRA(mpWrtShell->getIDocumentRedlineAccess());
+ SwFieldType* pType = mpView->GetDocShell()->GetDoc()->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Postit, OUString(),false);
+ std::vector<SwFormatField*> vFormatFields;
+ pType->CollectPostIts(vFormatFields, rIDRA, mpWrtShell->GetLayout()->IsHideRedlines());
+
+ for (std::vector<SwFormatField*>::iterator i = vFormatFields.begin(); i != vFormatFields.end(); i++)
+ {
+ SwPostItField *pChildPostIt = static_cast<SwPostItField*>((*i)->GetField());
+
+ if (pChildPostIt->GetParentId() != 0 || !pChildPostIt->GetParentName().isEmpty())
+ {
+ for (std::vector<SwFormatField*>::iterator j = vFormatFields.begin(); j != vFormatFields.end(); j++)
+ {
+ SwPostItField *pParentPostIt = static_cast<SwPostItField*>((*j)->GetField());
+ if (pChildPostIt->GetParentId() != 0 && pParentPostIt->GetParaId() == pChildPostIt->GetParentId())
+ {
+ pChildPostIt->SetParentPostItId(pParentPostIt->GetPostItId());
+ pChildPostIt->SetParentName(pParentPostIt->GetName());
+ }
+ else if (!pParentPostIt->GetName().isEmpty() && pParentPostIt->GetName() == pChildPostIt->GetParentName())
+ {
+ pChildPostIt->SetParentPostItId(pParentPostIt->GetPostItId());
+ pChildPostIt->SetParentName(pParentPostIt->GetName());
+ }
+ }
+ }
+ }
+
+ for(auto pFormatField : vFormatFields)
+ InsertItem(pFormatField, bCheckExistence, bFocus);
+ // if we just added the first one we have to update the view for centering
+ if (bEmpty && !mvPostItFields.empty())
+ PrepareView(true);
+}
+
+void SwPostItMgr::RemoveSidebarWin()
+{
+ for (auto& postItField : mvPostItFields)
+ {
+ EndListening( *const_cast<SfxBroadcaster*>(postItField->GetBroadcaster()) );
+ postItField->mpPostIt.disposeAndClear();
+ postItField.reset();
+ }
+ mvPostItFields.clear();
+
+ // all postits removed, no items should be left in pages
+ PreparePageContainer();
+}
+
+namespace {
+
+class FilterFunctor
+{
+public:
+ virtual bool operator()(const SwFormatField* pField) const = 0;
+ virtual ~FilterFunctor() {}
+};
+
+class IsPostitField : public FilterFunctor
+{
+public:
+ bool operator()(const SwFormatField* pField) const override
+ {
+ return pField->GetField()->GetTyp()->Which() == SwFieldIds::Postit;
+ }
+};
+
+class IsPostitFieldWithAuthorOf : public FilterFunctor
+{
+ OUString m_sAuthor;
+public:
+ explicit IsPostitFieldWithAuthorOf(OUString aAuthor)
+ : m_sAuthor(std::move(aAuthor))
+ {
+ }
+ bool operator()(const SwFormatField* pField) const override
+ {
+ if (pField->GetField()->GetTyp()->Which() != SwFieldIds::Postit)
+ return false;
+ return static_cast<const SwPostItField*>(pField->GetField())->GetPar1() == m_sAuthor;
+ }
+};
+
+class IsPostitFieldWithPostitId : public FilterFunctor
+{
+ sal_uInt32 m_nPostItId;
+public:
+ explicit IsPostitFieldWithPostitId(sal_uInt32 nPostItId)
+ : m_nPostItId(nPostItId)
+ {}
+
+ bool operator()(const SwFormatField* pField) const override
+ {
+ if (pField->GetField()->GetTyp()->Which() != SwFieldIds::Postit)
+ return false;
+ return static_cast<const SwPostItField*>(pField->GetField())->GetPostItId() == m_nPostItId;
+ }
+};
+
+class IsFieldNotDeleted : public FilterFunctor
+{
+private:
+ IDocumentRedlineAccess const& m_rIDRA;
+ FilterFunctor const& m_rNext;
+
+public:
+ IsFieldNotDeleted(IDocumentRedlineAccess const& rIDRA,
+ const FilterFunctor & rNext)
+ : m_rIDRA(rIDRA)
+ , m_rNext(rNext)
+ {
+ }
+ bool operator()(const SwFormatField* pField) const override
+ {
+ if (!m_rNext(pField))
+ return false;
+ if (!pField->GetTextField())
+ return false;
+ return !sw::IsFieldDeletedInModel(m_rIDRA, *pField->GetTextField());
+ }
+};
+
+//Manages the passed in vector by automatically removing entries if they are deleted
+//and automatically adding entries if they appear in the document and match the
+//functor.
+//
+//This will completely refill in the case of a "anonymous" NULL pField stating
+//rather unhelpfully that "something changed" so you may process the same
+//Fields more than once.
+class FieldDocWatchingStack : public SfxListener
+{
+ std::vector<std::unique_ptr<SwSidebarItem>>& m_aSidebarItems;
+ std::vector<const SwFormatField*> m_aFormatFields;
+ SwDocShell& m_rDocShell;
+ FilterFunctor& m_rFilter;
+
+ virtual void Notify(SfxBroadcaster&, const SfxHint& rHint) override
+ {
+ const SwFormatFieldHint* pHint = dynamic_cast<const SwFormatFieldHint*>(&rHint);
+ if (!pHint)
+ return;
+
+ bool bAllInvalidated = false;
+ if (pHint->Which() == SwFormatFieldHintWhich::REMOVED)
+ {
+ const SwFormatField* pField = pHint->GetField();
+ bAllInvalidated = pField == nullptr;
+ if (!bAllInvalidated && m_rFilter(pField))
+ {
+ EndListening(const_cast<SwFormatField&>(*pField));
+ std::erase(m_aFormatFields, pField);
+ }
+ }
+ else if (pHint->Which() == SwFormatFieldHintWhich::INSERTED)
+ {
+ const SwFormatField* pField = pHint->GetField();
+ bAllInvalidated = pField == nullptr;
+ if (!bAllInvalidated && m_rFilter(pField))
+ {
+ StartListening(const_cast<SwFormatField&>(*pField));
+ m_aFormatFields.push_back(pField);
+ }
+ }
+
+ if (bAllInvalidated)
+ FillVector();
+
+ return;
+ }
+
+public:
+ FieldDocWatchingStack(std::vector<std::unique_ptr<SwSidebarItem>>& in, SwDocShell &rDocShell, FilterFunctor& rFilter)
+ : m_aSidebarItems(in)
+ , m_rDocShell(rDocShell)
+ , m_rFilter(rFilter)
+ {
+ FillVector();
+ StartListening(m_rDocShell);
+ }
+ void FillVector()
+ {
+ EndListeningToAllFields();
+ m_aFormatFields.clear();
+ m_aFormatFields.reserve(m_aSidebarItems.size());
+ for (auto const& p : m_aSidebarItems)
+ {
+ const SwFormatField& rField = p->GetFormatField();
+ if (!m_rFilter(&rField))
+ continue;
+ StartListening(const_cast<SwFormatField&>(rField));
+ m_aFormatFields.push_back(&rField);
+ }
+ }
+ void EndListeningToAllFields()
+ {
+ for (auto const& pField : m_aFormatFields)
+ {
+ EndListening(const_cast<SwFormatField&>(*pField));
+ }
+ }
+ virtual ~FieldDocWatchingStack() override
+ {
+ EndListeningToAllFields();
+ EndListening(m_rDocShell);
+ }
+ const SwFormatField* pop()
+ {
+ if (m_aFormatFields.empty())
+ return nullptr;
+ const SwFormatField* p = m_aFormatFields.back();
+ EndListening(const_cast<SwFormatField&>(*p));
+ m_aFormatFields.pop_back();
+ return p;
+ }
+};
+
+}
+
+// copy to new vector, otherwise RemoveItem would operate and delete stuff on mvPostItFields as well
+// RemoveItem will clean up the core field and visible postit if necessary
+// we cannot just delete everything as before, as postits could move into change tracking
+void SwPostItMgr::Delete(const OUString& rAuthor)
+{
+ mpWrtShell->StartAllAction();
+ if (HasActiveSidebarWin() && (GetActiveSidebarWin()->GetAuthor() == rAuthor))
+ {
+ SetActiveSidebarWin(nullptr);
+ }
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, SwResId(STR_DELETE_AUTHOR_NOTES) + rAuthor);
+ mpWrtShell->StartUndo( SwUndoId::DELETE, &aRewriter );
+
+ IsPostitFieldWithAuthorOf aFilter(rAuthor);
+ IDocumentRedlineAccess const& rIDRA(mpWrtShell->getIDocumentRedlineAccess());
+ IsFieldNotDeleted aFilter2(rIDRA, aFilter);
+ FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(), aFilter2);
+ while (const SwFormatField* pField = aStack.pop())
+ {
+ if (mpWrtShell->GotoField(*pField))
+ mpWrtShell->DelRight();
+ }
+ mpWrtShell->EndUndo();
+ PrepareView();
+ mpWrtShell->EndAllAction();
+ mbLayout = true;
+ CalcRects();
+ LayoutPostIts();
+}
+
+void SwPostItMgr::Delete(sal_uInt32 nPostItId)
+{
+ mpWrtShell->StartAllAction();
+ if (HasActiveSidebarWin() &&
+ mpActivePostIt->GetPostItField()->GetPostItId() == nPostItId)
+ {
+ SetActiveSidebarWin(nullptr);
+ }
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, SwResId(STR_CONTENT_TYPE_SINGLE_POSTIT));
+ mpWrtShell->StartUndo( SwUndoId::DELETE, &aRewriter );
+
+ IsPostitFieldWithPostitId aFilter(nPostItId);
+ IDocumentRedlineAccess const& rIDRA(mpWrtShell->getIDocumentRedlineAccess());
+ IsFieldNotDeleted aFilter2(rIDRA, aFilter);
+ FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(), aFilter2);
+ const SwFormatField* pField = aStack.pop();
+ if (pField && mpWrtShell->GotoField(*pField))
+ mpWrtShell->DelRight();
+ mpWrtShell->EndUndo();
+ PrepareView();
+ mpWrtShell->EndAllAction();
+ mbLayout = true;
+ CalcRects();
+ LayoutPostIts();
+}
+
+void SwPostItMgr::DeleteCommentThread(sal_uInt32 nPostItId)
+{
+ mpWrtShell->StartAllAction();
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, SwResId(STR_CONTENT_TYPE_SINGLE_POSTIT));
+
+ // We have no undo ID at the moment.
+
+ IsPostitFieldWithPostitId aFilter(nPostItId);
+ FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(), aFilter);
+ const SwFormatField* pField = aStack.pop();
+ // pField now contains our AnnotationWin object
+ if (pField) {
+ SwAnnotationWin* pWin = GetSidebarWin(pField);
+ pWin->DeleteThread();
+ }
+ PrepareView();
+ mpWrtShell->EndAllAction();
+ mbLayout = true;
+ CalcRects();
+ LayoutPostIts();
+}
+
+void SwPostItMgr::ToggleResolved(sal_uInt32 nPostItId)
+{
+ mpWrtShell->StartAllAction();
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, SwResId(STR_CONTENT_TYPE_SINGLE_POSTIT));
+
+ // We have no undo ID at the moment.
+
+ IsPostitFieldWithPostitId aFilter(nPostItId);
+ FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(), aFilter);
+ const SwFormatField* pField = aStack.pop();
+ // pField now contains our AnnotationWin object
+ if (pField) {
+ SwAnnotationWin* pWin = GetSidebarWin(pField);
+ pWin->ToggleResolved();
+ }
+
+ PrepareView();
+ mpWrtShell->EndAllAction();
+ mbLayout = true;
+ CalcRects();
+ LayoutPostIts();
+}
+
+void SwPostItMgr::ToggleResolvedForThread(sal_uInt32 nPostItId)
+{
+ mpWrtShell->StartAllAction();
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, SwResId(STR_CONTENT_TYPE_SINGLE_POSTIT));
+
+ // We have no undo ID at the moment.
+
+ IsPostitFieldWithPostitId aFilter(nPostItId);
+ FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(), aFilter);
+ const SwFormatField* pField = aStack.pop();
+ // pField now contains our AnnotationWin object
+ if (pField) {
+ SwAnnotationWin* pWin = GetSidebarWin(pField);
+ pWin->ToggleResolvedForThread();
+ }
+
+ PrepareView();
+ mpWrtShell->EndAllAction();
+ mbLayout = true;
+ CalcRects();
+ LayoutPostIts();
+}
+
+
+void SwPostItMgr::Delete()
+{
+ mpWrtShell->StartAllAction();
+ SetActiveSidebarWin(nullptr);
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, SwResId(STR_DELETE_ALL_NOTES) );
+ mpWrtShell->StartUndo( SwUndoId::DELETE, &aRewriter );
+
+ IsPostitField aFilter;
+ IDocumentRedlineAccess const& rIDRA(mpWrtShell->getIDocumentRedlineAccess());
+ IsFieldNotDeleted aFilter2(rIDRA, aFilter);
+ FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(),
+ aFilter2);
+ while (const SwFormatField* pField = aStack.pop())
+ {
+ if (mpWrtShell->GotoField(*pField))
+ mpWrtShell->DelRight();
+ }
+
+ mpWrtShell->EndUndo();
+ PrepareView();
+ mpWrtShell->EndAllAction();
+ mbLayout = true;
+ CalcRects();
+ LayoutPostIts();
+}
+
+void SwPostItMgr::ExecuteFormatAllDialog(SwView& rView)
+{
+ if (mvPostItFields.empty())
+ return;
+ sw::annotation::SwAnnotationWin *pOrigActiveWin = GetActiveSidebarWin();
+ sw::annotation::SwAnnotationWin *pWin = pOrigActiveWin;
+ if (!pWin)
+ {
+ for (auto const& postItField : mvPostItFields)
+ {
+ pWin = postItField->mpPostIt;
+ if (pWin)
+ break;
+ }
+ }
+ if (!pWin)
+ return;
+ SetActiveSidebarWin(pWin);
+ OutlinerView* pOLV = pWin->GetOutlinerView();
+ SfxItemSet aEditAttr(pOLV->GetAttribs());
+ SfxItemPool* pPool(SwAnnotationShell::GetAnnotationPool(rView));
+ SfxItemSetFixed<XATTR_FILLSTYLE, XATTR_FILLCOLOR, EE_ITEMS_START, EE_ITEMS_END> aDlgAttr(*pPool);
+ aDlgAttr.Put(aEditAttr);
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateSwCharDlg(rView.GetFrameWeld(), rView, aDlgAttr, SwCharDlgMode::Ann));
+ sal_uInt16 nRet = pDlg->Execute();
+ if (RET_OK == nRet)
+ {
+ aDlgAttr.Put(*pDlg->GetOutputItemSet());
+ FormatAll(aDlgAttr);
+ }
+ pDlg.disposeAndClear();
+ SetActiveSidebarWin(pOrigActiveWin);
+}
+
+void SwPostItMgr::FormatAll(const SfxItemSet &rNewAttr)
+{
+ mpWrtShell->StartAllAction();
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, SwResId(STR_FORMAT_ALL_NOTES) );
+ mpWrtShell->StartUndo( SwUndoId::INSATTR, &aRewriter );
+
+ for (auto const& postItField : mvPostItFields)
+ {
+ if (!postItField->mpPostIt)
+ continue;
+ OutlinerView* pOLV = postItField->mpPostIt->GetOutlinerView();
+ //save old selection
+ ESelection aOrigSel(pOLV->GetSelection());
+ //select all
+ Outliner *pOutliner = pOLV->GetOutliner();
+ if (pOutliner)
+ {
+ sal_Int32 nParaCount = pOutliner->GetParagraphCount();
+ if (nParaCount > 0)
+ pOLV->SelectRange(0, nParaCount);
+ }
+ //set new char properties
+ pOLV->SetAttribs(rNewAttr);
+ //restore old selection
+ pOLV->SetSelection(aOrigSel);
+ // tdf#91596 store updated formatting in SwField
+ postItField->mpPostIt->UpdateData();
+ }
+
+ mpWrtShell->EndUndo();
+ PrepareView();
+ mpWrtShell->EndAllAction();
+ mbLayout = true;
+ CalcRects();
+ LayoutPostIts();
+}
+
+void SwPostItMgr::Hide( std::u16string_view rAuthor )
+{
+ for (auto const& postItField : mvPostItFields)
+ {
+ if ( postItField->mpPostIt && (postItField->mpPostIt->GetAuthor() == rAuthor) )
+ {
+ postItField->mbShow = false;
+ postItField->mpPostIt->HideNote();
+ }
+ }
+
+ LayoutPostIts();
+}
+
+void SwPostItMgr::Hide()
+{
+ for (auto const& postItField : mvPostItFields)
+ {
+ postItField->mbShow = false;
+ if (postItField->mpPostIt)
+ postItField->mpPostIt->HideNote();
+ }
+}
+
+void SwPostItMgr::Show()
+{
+ for (auto const& postItField : mvPostItFields)
+ {
+ postItField->mbShow = true;
+ }
+ LayoutPostIts();
+}
+
+SwAnnotationWin* SwPostItMgr::GetSidebarWin( const SfxBroadcaster* pBroadcaster) const
+{
+ for (auto const& postItField : mvPostItFields)
+ {
+ if ( postItField->GetBroadcaster() == pBroadcaster)
+ return postItField->mpPostIt;
+ }
+ return nullptr;
+}
+
+sw::annotation::SwAnnotationWin* SwPostItMgr::GetAnnotationWin(const SwPostItField* pField) const
+{
+ for (auto const& postItField : mvPostItFields)
+ {
+ if ( postItField->GetFormatField().GetField() == pField )
+ return postItField->mpPostIt.get();
+ }
+ return nullptr;
+}
+
+sw::annotation::SwAnnotationWin* SwPostItMgr::GetAnnotationWin(const sal_uInt32 nPostItId) const
+{
+ for (auto const& postItField : mvPostItFields)
+ {
+ if ( static_cast<const SwPostItField*>(postItField->GetFormatField().GetField())->GetPostItId() == nPostItId )
+ return postItField->mpPostIt.get();
+ }
+ return nullptr;
+}
+
+SwPostItField* SwPostItMgr::GetLatestPostItField()
+{
+ return static_cast<SwPostItField*>(mvPostItFields.back()->GetFormatField().GetField());
+}
+
+SwAnnotationWin* SwPostItMgr::GetNextPostIt( sal_uInt16 aDirection,
+ SwAnnotationWin* aPostIt )
+{
+ if (mvPostItFields.size()>1)
+ {
+ auto i = std::find_if(mvPostItFields.begin(), mvPostItFields.end(),
+ [&aPostIt](const std::unique_ptr<SwSidebarItem>& pField) { return pField->mpPostIt == aPostIt; });
+ if (i == mvPostItFields.end())
+ return nullptr;
+
+ auto iNextPostIt = i;
+ if (aDirection == KEY_PAGEUP)
+ {
+ if ( iNextPostIt == mvPostItFields.begin() )
+ {
+ return nullptr;
+ }
+ --iNextPostIt;
+ }
+ else
+ {
+ ++iNextPostIt;
+ if ( iNextPostIt == mvPostItFields.end() )
+ {
+ return nullptr;
+ }
+ }
+ // lets quit, we are back at the beginning
+ if ( (*iNextPostIt)->mpPostIt == aPostIt)
+ return nullptr;
+ return (*iNextPostIt)->mpPostIt;
+ }
+ else
+ return nullptr;
+}
+
+tools::Long SwPostItMgr::GetNextBorder()
+{
+ for (auto const& pPage : mPages)
+ {
+ for(auto b = pPage->mvSidebarItems.begin(); b!= pPage->mvSidebarItems.end(); ++b)
+ {
+ if ((*b)->mpPostIt == mpActivePostIt)
+ {
+ auto aNext = b;
+ ++aNext;
+ bool bFollow = (aNext != pPage->mvSidebarItems.end()) && (*aNext)->mpPostIt->IsFollow();
+ if ( pPage->bScrollbar || bFollow )
+ {
+ return -1;
+ }
+ else
+ {
+ //if this is the last item, return the bottom border otherwise the next item
+ if (aNext == pPage->mvSidebarItems.end())
+ return mpEditWin->LogicToPixel(Point(0,pPage->mPageRect.Bottom())).Y() - GetSpaceBetween();
+ else
+ return (*aNext)->mpPostIt->GetPosPixel().Y() - GetSpaceBetween();
+ }
+ }
+ }
+ }
+
+ OSL_FAIL("SwPostItMgr::GetNextBorder(): We have to find a next border here");
+ return -1;
+}
+
+void SwPostItMgr::SetShadowState(const SwPostItField* pField,bool bCursor)
+{
+ if (pField)
+ {
+ if (pField !=mShadowState.mpShadowField)
+ {
+ if (mShadowState.mpShadowField)
+ {
+ // reset old one if still alive
+ // TODO: does not work properly if mouse and cursor was set
+ sw::annotation::SwAnnotationWin* pOldPostIt =
+ GetAnnotationWin(mShadowState.mpShadowField);
+ if (pOldPostIt && pOldPostIt->Shadow() && (pOldPostIt->Shadow()->GetShadowState() != SS_EDIT))
+ pOldPostIt->SetViewState(ViewState::NORMAL);
+ }
+ //set new one, if it is not currently edited
+ sw::annotation::SwAnnotationWin* pNewPostIt = GetAnnotationWin(pField);
+ if (pNewPostIt && pNewPostIt->Shadow() && (pNewPostIt->Shadow()->GetShadowState() != SS_EDIT))
+ {
+ pNewPostIt->SetViewState(ViewState::VIEW);
+ //remember our new field
+ mShadowState.mpShadowField = pField;
+ mShadowState.bCursor = false;
+ mShadowState.bMouse = false;
+ }
+ }
+ if (bCursor)
+ mShadowState.bCursor = true;
+ else
+ mShadowState.bMouse = true;
+ }
+ else
+ {
+ if (mShadowState.mpShadowField)
+ {
+ if (bCursor)
+ mShadowState.bCursor = false;
+ else
+ mShadowState.bMouse = false;
+ if (!mShadowState.bCursor && !mShadowState.bMouse)
+ {
+ // reset old one if still alive
+ sw::annotation::SwAnnotationWin* pOldPostIt = GetAnnotationWin(mShadowState.mpShadowField);
+ if (pOldPostIt && pOldPostIt->Shadow() && (pOldPostIt->Shadow()->GetShadowState() != SS_EDIT))
+ {
+ pOldPostIt->SetViewState(ViewState::NORMAL);
+ mShadowState.mpShadowField = nullptr;
+ }
+ }
+ }
+ }
+}
+
+void SwPostItMgr::PrepareView(bool bIgnoreCount)
+{
+ if (!HasNotes() || bIgnoreCount)
+ {
+ mpWrtShell->StartAllAction();
+ SwRootFrame* pLayout = mpWrtShell->GetLayout();
+ if ( pLayout )
+ SwPostItHelper::setSidebarChanged( pLayout,
+ mpWrtShell->getIDocumentSettingAccess().get( DocumentSettingId::BROWSE_MODE ) );
+ mpWrtShell->EndAllAction();
+ }
+}
+
+bool SwPostItMgr::ShowScrollbar(const tools::ULong aPage) const
+{
+ if (mPages.size() > aPage-1)
+ return (mPages[aPage-1]->bScrollbar && !mbWaitingForCalcRects);
+ else
+ return false;
+}
+
+bool SwPostItMgr::IsHit(const Point &aPointPixel)
+{
+ if (HasNotes() && ShowNotes())
+ {
+ const Point aPoint = mpEditWin->PixelToLogic(aPointPixel);
+ const SwRootFrame* pLayout = mpWrtShell->GetLayout();
+ SwRect aPageFrame;
+ const tools::ULong nPageNum = SwPostItHelper::getPageInfo( aPageFrame, pLayout, aPoint );
+ if( nPageNum )
+ {
+ tools::Rectangle aRect;
+ OSL_ENSURE(mPages.size()>nPageNum-1,"SwPostitMgr:: page container size wrong");
+ aRect = mPages[nPageNum-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT
+ ? tools::Rectangle(Point(aPageFrame.Left()-GetSidebarWidth()-GetSidebarBorderWidth(),aPageFrame.Top()),Size(GetSidebarWidth(),aPageFrame.Height()))
+ : tools::Rectangle( Point(aPageFrame.Right()+GetSidebarBorderWidth(),aPageFrame.Top()) , Size(GetSidebarWidth(),aPageFrame.Height()));
+ if (aRect.Contains(aPoint))
+ {
+ // we hit the note's sidebar
+ // lets now test for the arrow area
+ if (mPages[nPageNum-1]->bScrollbar)
+ return ScrollbarHit(nPageNum,aPoint);
+ else
+ return false;
+ }
+ }
+ }
+ return false;
+}
+
+vcl::Window* SwPostItMgr::IsHitSidebarWindow(const Point& rPointLogic)
+{
+ vcl::Window* pRet = nullptr;
+
+ if (HasNotes() && ShowNotes())
+ {
+ bool bEnableMapMode = !mpEditWin->IsMapModeEnabled();
+ if (bEnableMapMode)
+ mpEditWin->EnableMapMode();
+
+ for (const std::unique_ptr<SwSidebarItem>& pItem : mvPostItFields)
+ {
+ SwAnnotationWin* pPostIt = pItem->mpPostIt;
+ if (!pPostIt)
+ continue;
+
+ if (pPostIt->IsHitWindow(rPointLogic))
+ {
+ pRet = pPostIt;
+ break;
+ }
+ }
+
+ if (bEnableMapMode)
+ mpEditWin->EnableMapMode(false);
+ }
+
+ return pRet;
+}
+
+tools::Rectangle SwPostItMgr::GetBottomScrollRect(const tools::ULong aPage) const
+{
+ SwRect aPageRect = mPages[aPage-1]->mPageRect;
+ Point aPointBottom = mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT
+ ? Point(aPageRect.Left() - GetSidebarWidth() - GetSidebarBorderWidth() + mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- mpEditWin->PixelToLogic(Size(0,2+GetSidebarScrollerHeight())).Height())
+ : Point(aPageRect.Right() + GetSidebarBorderWidth() + mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- mpEditWin->PixelToLogic(Size(0,2+GetSidebarScrollerHeight())).Height());
+ Size aSize(GetSidebarWidth() - mpEditWin->PixelToLogic(Size(4,0)).Width(), mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height()) ;
+ return tools::Rectangle(aPointBottom,aSize);
+}
+
+tools::Rectangle SwPostItMgr::GetTopScrollRect(const tools::ULong aPage) const
+{
+ SwRect aPageRect = mPages[aPage-1]->mPageRect;
+ Point aPointTop = mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT
+ ? Point(aPageRect.Left() - GetSidebarWidth() -GetSidebarBorderWidth()+ mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + mpEditWin->PixelToLogic(Size(0,2)).Height())
+ : Point(aPageRect.Right() + GetSidebarBorderWidth() + mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + mpEditWin->PixelToLogic(Size(0,2)).Height());
+ Size aSize(GetSidebarWidth() - mpEditWin->PixelToLogic(Size(4,0)).Width(), mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height()) ;
+ return tools::Rectangle(aPointTop,aSize);
+}
+
+//IMPORTANT: if you change the rects here, also change SwPageFrame::PaintNotesSidebar()
+bool SwPostItMgr::ScrollbarHit(const tools::ULong aPage,const Point &aPoint)
+{
+ SwRect aPageRect = mPages[aPage-1]->mPageRect;
+ Point aPointBottom = mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT
+ ? Point(aPageRect.Left() - GetSidebarWidth()-GetSidebarBorderWidth() + mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- mpEditWin->PixelToLogic(Size(0,2+GetSidebarScrollerHeight())).Height())
+ : Point(aPageRect.Right() + GetSidebarBorderWidth()+ mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- mpEditWin->PixelToLogic(Size(0,2+GetSidebarScrollerHeight())).Height());
+
+ Point aPointTop = mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT
+ ? Point(aPageRect.Left() - GetSidebarWidth()-GetSidebarBorderWidth()+ mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + mpEditWin->PixelToLogic(Size(0,2)).Height())
+ : Point(aPageRect.Right()+GetSidebarBorderWidth()+ mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + mpEditWin->PixelToLogic(Size(0,2)).Height());
+
+ tools::Rectangle aRectBottom(GetBottomScrollRect(aPage));
+ tools::Rectangle aRectTop(GetTopScrollRect(aPage));
+
+ if (aRectBottom.Contains(aPoint))
+ {
+ if (aPoint.X() < tools::Long((aPointBottom.X() + GetSidebarWidth()/3)))
+ Scroll( GetScrollSize(),aPage);
+ else
+ Scroll( -1*GetScrollSize(), aPage);
+ return true;
+ }
+ else if (aRectTop.Contains(aPoint))
+ {
+ if (aPoint.X() < tools::Long((aPointTop.X() + GetSidebarWidth()/3*2)))
+ Scroll(GetScrollSize(), aPage);
+ else
+ Scroll(-1*GetScrollSize(), aPage);
+ return true;
+ }
+ return false;
+}
+
+void SwPostItMgr::CorrectPositions()
+{
+ if ( mbWaitingForCalcRects || mbLayouting || mvPostItFields.empty() )
+ return;
+
+ // find first valid note
+ SwAnnotationWin *pFirstPostIt = nullptr;
+ for (auto const& postItField : mvPostItFields)
+ {
+ pFirstPostIt = postItField->mpPostIt;
+ if (pFirstPostIt)
+ break;
+ }
+
+ //if we have not found a valid note, forget about it and leave
+ if (!pFirstPostIt)
+ return;
+
+ // yeah, I know, if this is a left page it could be wrong, but finding the page and the note is probably not even faster than just doing it
+ // check, if anchor overlay object exists.
+ const tools::Long aAnchorX = pFirstPostIt->Anchor()
+ ? mpEditWin->LogicToPixel( Point(static_cast<tools::Long>(pFirstPostIt->Anchor()->GetSixthPosition().getX()),0)).X()
+ : 0;
+ const tools::Long aAnchorY = pFirstPostIt->Anchor()
+ ? mpEditWin->LogicToPixel( Point(0,static_cast<tools::Long>(pFirstPostIt->Anchor()->GetSixthPosition().getY()))).Y() + 1
+ : 0;
+ if (Point(aAnchorX,aAnchorY) == pFirstPostIt->GetPosPixel())
+ return;
+
+ tools::Long aAnchorPosX = 0;
+ tools::Long aAnchorPosY = 0;
+ for (const std::unique_ptr<SwPostItPageItem>& pPage : mPages)
+ {
+ for (auto const& item : pPage->mvSidebarItems)
+ {
+ // check, if anchor overlay object exists.
+ if ( item->mbShow && item->mpPostIt && item->mpPostIt->Anchor() )
+ {
+ aAnchorPosX = pPage->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT
+ ? mpEditWin->LogicToPixel( Point(static_cast<tools::Long>(item->mpPostIt->Anchor()->GetSeventhPosition().getX()),0)).X()
+ : mpEditWin->LogicToPixel( Point(static_cast<tools::Long>(item->mpPostIt->Anchor()->GetSixthPosition().getX()),0)).X();
+ aAnchorPosY = mpEditWin->LogicToPixel( Point(0,static_cast<tools::Long>(item->mpPostIt->Anchor()->GetSixthPosition().getY()))).Y() + 1;
+ item->mpPostIt->SetPosPixel(Point(aAnchorPosX,aAnchorPosY));
+ }
+ }
+ }
+}
+
+bool SwPostItMgr::ShowNotes() const
+{
+ // we only want to see notes if Options - Writer - View - Notes is ticked
+ return mpWrtShell->GetViewOptions()->IsPostIts();
+}
+
+bool SwPostItMgr::HasNotes() const
+{
+ return !mvPostItFields.empty();
+}
+
+tools::ULong SwPostItMgr::GetSidebarWidth(bool bPx) const
+{
+ bool bEnableMapMode = !mpWrtShell->GetOut()->IsMapModeEnabled();
+ sal_uInt16 nZoom = mpWrtShell->GetViewOptions()->GetZoom();
+ if (comphelper::LibreOfficeKit::isActive() && !bEnableMapMode)
+ {
+ // The output device is the tile and contains the real wanted scale factor.
+ double fScaleX = double(mpWrtShell->GetOut()->GetMapMode().GetScaleX());
+ nZoom = fScaleX * 100;
+ }
+ tools::ULong aWidth = static_cast<tools::ULong>(nZoom * 1.8);
+
+ if (bPx)
+ return aWidth;
+ else
+ {
+ if (bEnableMapMode)
+ // The output device is the window.
+ mpWrtShell->GetOut()->EnableMapMode();
+ tools::Long nRet = mpWrtShell->GetOut()->PixelToLogic(Size(aWidth, 0)).Width();
+ if (bEnableMapMode)
+ mpWrtShell->GetOut()->EnableMapMode(false);
+ return nRet;
+ }
+}
+
+tools::ULong SwPostItMgr::GetSidebarBorderWidth(bool bPx) const
+{
+ if (bPx)
+ return 2;
+ else
+ return mpWrtShell->GetOut()->PixelToLogic(Size(2,0)).Width();
+}
+
+Color SwPostItMgr::GetColorDark(std::size_t aAuthorIndex)
+{
+ if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
+ {
+ static const Color aArrayNormal[] = {
+ COL_AUTHOR1_NORMAL, COL_AUTHOR2_NORMAL, COL_AUTHOR3_NORMAL,
+ COL_AUTHOR4_NORMAL, COL_AUTHOR5_NORMAL, COL_AUTHOR6_NORMAL,
+ COL_AUTHOR7_NORMAL, COL_AUTHOR8_NORMAL, COL_AUTHOR9_NORMAL };
+
+ return aArrayNormal[ aAuthorIndex % SAL_N_ELEMENTS( aArrayNormal )];
+ }
+ else
+ return COL_WHITE;
+}
+
+Color SwPostItMgr::GetColorLight(std::size_t aAuthorIndex)
+{
+ if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
+ {
+ static const Color aArrayLight[] = {
+ COL_AUTHOR1_LIGHT, COL_AUTHOR2_LIGHT, COL_AUTHOR3_LIGHT,
+ COL_AUTHOR4_LIGHT, COL_AUTHOR5_LIGHT, COL_AUTHOR6_LIGHT,
+ COL_AUTHOR7_LIGHT, COL_AUTHOR8_LIGHT, COL_AUTHOR9_LIGHT };
+
+ return aArrayLight[ aAuthorIndex % SAL_N_ELEMENTS( aArrayLight )];
+ }
+ else
+ return COL_WHITE;
+}
+
+Color SwPostItMgr::GetColorAnchor(std::size_t aAuthorIndex)
+{
+ if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
+ {
+ static const Color aArrayAnchor[] = {
+ COL_AUTHOR1_DARK, COL_AUTHOR2_DARK, COL_AUTHOR3_DARK,
+ COL_AUTHOR4_DARK, COL_AUTHOR5_DARK, COL_AUTHOR6_DARK,
+ COL_AUTHOR7_DARK, COL_AUTHOR8_DARK, COL_AUTHOR9_DARK };
+
+ return aArrayAnchor[ aAuthorIndex % SAL_N_ELEMENTS( aArrayAnchor )];
+ }
+ else
+ return COL_WHITE;
+}
+
+void SwPostItMgr::SetActiveSidebarWin( SwAnnotationWin* p)
+{
+ if ( p == mpActivePostIt )
+ return;
+
+ // we need the temp variable so we can set mpActivePostIt before we call DeactivatePostIt
+ // therefore we get a new layout in DOCCHANGED when switching from postit to document,
+ // otherwise, GetActivePostIt() would still hold our old postit
+ SwAnnotationWin* pActive = mpActivePostIt;
+ mpActivePostIt = p;
+ if (pActive)
+ {
+ pActive->DeactivatePostIt();
+ mShadowState.mpShadowField = nullptr;
+ }
+ if (mpActivePostIt)
+ {
+ mpActivePostIt->GotoPos();
+ mpView->AttrChangedNotify(nullptr);
+ mpActivePostIt->ActivatePostIt();
+ }
+}
+
+IMPL_LINK_NOARG( SwPostItMgr, CalcHdl, void*, void )
+{
+ mnEventId = nullptr;
+ if ( mbLayouting )
+ {
+ OSL_FAIL("Reentrance problem in Layout Manager!");
+ mbWaitingForCalcRects = false;
+ return;
+ }
+
+ // do not change order, even if it would seem so in the first place, we need the calcrects always
+ if (CalcRects() || mbLayout)
+ {
+ mbLayout = false;
+ LayoutPostIts();
+ }
+}
+
+void SwPostItMgr::Rescale()
+{
+ for (auto const& postItField : mvPostItFields)
+ if ( postItField->mpPostIt )
+ postItField->mpPostIt->Rescale();
+}
+
+sal_Int32 SwPostItMgr::GetInitialAnchorDistance() const
+{
+ const Fraction& f( mpEditWin->GetMapMode().GetScaleY() );
+ return sal_Int32(POSTIT_INITIAL_ANCHOR_DISTANCE * f);
+}
+
+sal_Int32 SwPostItMgr::GetSpaceBetween() const
+{
+ const Fraction& f( mpEditWin->GetMapMode().GetScaleY() );
+ return sal_Int32(POSTIT_SPACE_BETWEEN * f);
+}
+
+sal_Int32 SwPostItMgr::GetScrollSize() const
+{
+ const Fraction& f( mpEditWin->GetMapMode().GetScaleY() );
+ return sal_Int32((POSTIT_SPACE_BETWEEN + POSTIT_MINIMUMSIZE_WITH_META) * f);
+}
+
+sal_Int32 SwPostItMgr::GetMinimumSizeWithMeta() const
+{
+ const Fraction& f( mpEditWin->GetMapMode().GetScaleY() );
+ return sal_Int32(POSTIT_MINIMUMSIZE_WITH_META * f);
+}
+
+sal_Int32 SwPostItMgr::GetSidebarScrollerHeight() const
+{
+ const Fraction& f( mpEditWin->GetMapMode().GetScaleY() );
+ return sal_Int32(POSTIT_SCROLL_SIDEBAR_HEIGHT * f);
+}
+
+void SwPostItMgr::SetSpellChecking()
+{
+ for (auto const& postItField : mvPostItFields)
+ if ( postItField->mpPostIt )
+ postItField->mpPostIt->SetSpellChecking();
+}
+
+void SwPostItMgr::SetReadOnlyState()
+{
+ for (auto const& postItField : mvPostItFields)
+ if ( postItField->mpPostIt )
+ postItField->mpPostIt->SetReadonly( mbReadOnly );
+}
+
+void SwPostItMgr::CheckMetaText()
+{
+ for (auto const& postItField : mvPostItFields)
+ if ( postItField->mpPostIt )
+ postItField->mpPostIt->CheckMetaText();
+
+}
+
+sal_uInt16 SwPostItMgr::Replace(SvxSearchItem const * pItem)
+{
+ SwAnnotationWin* pWin = GetActiveSidebarWin();
+ sal_uInt16 aResult = pWin->GetOutlinerView()->StartSearchAndReplace( *pItem );
+ if (!aResult)
+ SetActiveSidebarWin(nullptr);
+ return aResult;
+}
+
+sal_uInt16 SwPostItMgr::FinishSearchReplace(const i18nutil::SearchOptions2& rSearchOptions, bool bSrchForward)
+{
+ SwAnnotationWin* pWin = GetActiveSidebarWin();
+ SvxSearchItem aItem(SID_SEARCH_ITEM );
+ aItem.SetSearchOptions(rSearchOptions);
+ aItem.SetBackward(!bSrchForward);
+ sal_uInt16 aResult = pWin->GetOutlinerView()->StartSearchAndReplace( aItem );
+ if (!aResult)
+ SetActiveSidebarWin(nullptr);
+ return aResult;
+}
+
+sal_uInt16 SwPostItMgr::SearchReplace(const SwFormatField &pField, const i18nutil::SearchOptions2& rSearchOptions, bool bSrchForward)
+{
+ sal_uInt16 aResult = 0;
+ SwAnnotationWin* pWin = GetSidebarWin(&pField);
+ if (pWin)
+ {
+ ESelection aOldSelection = pWin->GetOutlinerView()->GetSelection();
+ if (bSrchForward)
+ pWin->GetOutlinerView()->SetSelection(ESelection(0,0,0,0));
+ else
+ pWin->GetOutlinerView()->SetSelection(
+ ESelection(EE_PARA_MAX_COUNT,EE_TEXTPOS_MAX_COUNT,EE_PARA_MAX_COUNT,EE_TEXTPOS_MAX_COUNT));
+ SvxSearchItem aItem(SID_SEARCH_ITEM );
+ aItem.SetSearchOptions(rSearchOptions);
+ aItem.SetBackward(!bSrchForward);
+ aResult = pWin->GetOutlinerView()->StartSearchAndReplace( aItem );
+ if (!aResult)
+ pWin->GetOutlinerView()->SetSelection(aOldSelection);
+ else
+ {
+ SetActiveSidebarWin(pWin);
+ MakeVisible(pWin);
+ }
+ }
+ return aResult;
+}
+
+void SwPostItMgr::AssureStdModeAtShell()
+{
+ mpWrtShell->AssureStdMode();
+}
+
+bool SwPostItMgr::HasActiveSidebarWin() const
+{
+ return mpActivePostIt != nullptr;
+}
+
+bool SwPostItMgr::HasActiveAnnotationWin() const
+{
+ return HasActiveSidebarWin() &&
+ mpActivePostIt != nullptr;
+}
+
+void SwPostItMgr::GrabFocusOnActiveSidebarWin()
+{
+ if ( HasActiveSidebarWin() )
+ {
+ mpActivePostIt->GrabFocus();
+ }
+}
+
+void SwPostItMgr::UpdateDataOnActiveSidebarWin()
+{
+ if ( HasActiveSidebarWin() )
+ {
+ mpActivePostIt->UpdateData();
+ }
+}
+
+void SwPostItMgr::DeleteActiveSidebarWin()
+{
+ if ( HasActiveSidebarWin() )
+ {
+ mpActivePostIt->Delete();
+ }
+}
+
+void SwPostItMgr::HideActiveSidebarWin()
+{
+ if ( HasActiveSidebarWin() )
+ {
+ mpActivePostIt->Hide();
+ }
+}
+
+void SwPostItMgr::ToggleInsModeOnActiveSidebarWin()
+{
+ if ( HasActiveSidebarWin() )
+ {
+ mpActivePostIt->ToggleInsMode();
+ }
+}
+
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+void SwPostItMgr::ConnectSidebarWinToFrame( const SwFrame& rFrame,
+ const SwFormatField& rFormatField,
+ SwAnnotationWin& rSidebarWin )
+{
+ if ( mpFrameSidebarWinContainer == nullptr )
+ {
+ mpFrameSidebarWinContainer.reset(new SwFrameSidebarWinContainer());
+ }
+
+ const bool bInserted = mpFrameSidebarWinContainer->insert( rFrame, rFormatField, rSidebarWin );
+ if ( bInserted &&
+ mpWrtShell->GetAccessibleMap() )
+ {
+ mpWrtShell->GetAccessibleMap()->InvalidatePosOrSize( nullptr, nullptr, &rSidebarWin, SwRect() );
+ }
+}
+
+void SwPostItMgr::DisconnectSidebarWinFromFrame( const SwFrame& rFrame,
+ SwAnnotationWin& rSidebarWin )
+{
+ if ( mpFrameSidebarWinContainer != nullptr )
+ {
+ const bool bRemoved = mpFrameSidebarWinContainer->remove( rFrame, rSidebarWin );
+ if ( bRemoved &&
+ mpWrtShell->GetAccessibleMap() )
+ {
+ mpWrtShell->GetAccessibleMap()->A11yDispose( nullptr, nullptr, &rSidebarWin );
+ }
+ }
+}
+#endif // ENABLE_WASM_STRIP_ACCESSIBILITY
+
+bool SwPostItMgr::HasFrameConnectedSidebarWins( const SwFrame& rFrame )
+{
+ bool bRet( false );
+
+ if ( mpFrameSidebarWinContainer != nullptr )
+ {
+ bRet = !mpFrameSidebarWinContainer->empty( rFrame );
+ }
+
+ return bRet;
+}
+
+vcl::Window* SwPostItMgr::GetSidebarWinForFrameByIndex( const SwFrame& rFrame,
+ const sal_Int32 nIndex )
+{
+ vcl::Window* pSidebarWin( nullptr );
+
+ if ( mpFrameSidebarWinContainer != nullptr )
+ {
+ pSidebarWin = mpFrameSidebarWinContainer->get( rFrame, nIndex );
+ }
+
+ return pSidebarWin;
+}
+
+void SwPostItMgr::GetAllSidebarWinForFrame( const SwFrame& rFrame,
+ std::vector< vcl::Window* >* pChildren )
+{
+ if ( mpFrameSidebarWinContainer != nullptr )
+ {
+ mpFrameSidebarWinContainer->getAll( rFrame, pChildren );
+ }
+}
+
+void SwPostItMgr::ShowHideResolvedNotes(bool visible) {
+ for (auto const& pPage : mPages)
+ {
+ for(auto b = pPage->mvSidebarItems.begin(); b!= pPage->mvSidebarItems.end(); ++b)
+ {
+ if ((*b)->mpPostIt->IsResolved())
+ {
+ (*b)->mpPostIt->SetResolved(true);
+ (*b)->mpPostIt->GetSidebarItem().mbShow = visible;
+ }
+ }
+ }
+ LayoutPostIts();
+}
+
+void SwPostItMgr::UpdateResolvedStatus(const sw::annotation::SwAnnotationWin* topNote) {
+ // Given the topmost note as an argument, scans over all notes and sets the
+ // 'resolved' state of each descendant of the top notes to the resolved state
+ // of the top note.
+ bool resolved = topNote->IsResolved();
+ for (auto const& pPage : mPages)
+ {
+ for(auto b = pPage->mvSidebarItems.begin(); b!= pPage->mvSidebarItems.end(); ++b)
+ {
+ if((*b)->mpPostIt->GetTopReplyNote() == topNote) {
+ (*b)->mpPostIt->SetResolved(resolved);
+ }
+ }
+ }
+}
+
+void SwNoteProps::ImplCommit() {}
+void SwNoteProps::Notify( const css::uno::Sequence< OUString >& ) {}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/ShadowOverlayObject.cxx b/sw/source/uibase/docvw/ShadowOverlayObject.cxx
new file mode 100644
index 0000000000..0d0450876d
--- /dev/null
+++ b/sw/source/uibase/docvw/ShadowOverlayObject.cxx
@@ -0,0 +1,241 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ShadowOverlayObject.hxx"
+
+#include <view.hxx>
+#include <svx/sdrpaintwindow.hxx>
+#include <svx/svdview.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+
+#include <sw_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/primitivetools2d.hxx>
+#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
+#include <basegfx/utils/gradienttools.hxx>
+
+namespace sw::sidebarwindows {
+
+// helper SwPostItShadowPrimitive
+
+namespace {
+
+// Used to allow view-dependent primitive definition. For that purpose, the
+// initially created primitive (this one) always has to be view-independent,
+// but the decomposition is made view-dependent. Very simple primitive which
+// just remembers the discrete data and applies it at decomposition time.
+class ShadowPrimitive : public drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D
+{
+private:
+ basegfx::B2DPoint maBasePosition;
+ basegfx::B2DPoint maSecondPosition;
+ ShadowState maShadowState;
+
+protected:
+ virtual void create2DDecomposition(
+ drawinglayer::primitive2d::Primitive2DContainer& rContainer,
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation) const override;
+
+public:
+ ShadowPrimitive(
+ const basegfx::B2DPoint& rBasePosition,
+ const basegfx::B2DPoint& rSecondPosition,
+ ShadowState aShadowState)
+ : maBasePosition(rBasePosition),
+ maSecondPosition(rSecondPosition),
+ maShadowState(aShadowState)
+ {}
+
+ // data access
+ const basegfx::B2DPoint& getSecondPosition() const { return maSecondPosition; }
+
+ virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const override;
+
+ virtual sal_uInt32 getPrimitive2DID() const override;
+};
+
+}
+
+void ShadowPrimitive::create2DDecomposition(
+ drawinglayer::primitive2d::Primitive2DContainer& rContainer,
+ const drawinglayer::geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+ // get logic sizes in object coordinate system
+ basegfx::B2DRange aRange(maBasePosition);
+
+ switch(maShadowState)
+ {
+ case SS_NORMAL:
+ {
+ aRange.expand(basegfx::B2DTuple(getSecondPosition().getX(), getSecondPosition().getY() + (2.0 * getDiscreteUnit())));
+
+ ::drawinglayer::attribute::FillGradientAttribute aFillGradientAttribute(
+ css::awt::GradientStyle_LINEAR,
+ 0.0,
+ 0.5,
+ 0.5,
+ M_PI,
+ basegfx::BColorStops(
+ basegfx::BColor(230.0/255.0,230.0/255.0,230.0/255.0),
+ basegfx::BColor(180.0/255.0,180.0/255.0,180.0/255.0)));
+
+ rContainer.push_back(
+ new drawinglayer::primitive2d::FillGradientPrimitive2D(
+ aRange,
+ std::move(aFillGradientAttribute)));
+ break;
+ }
+ case SS_VIEW:
+ {
+ aRange.expand(basegfx::B2DTuple(getSecondPosition().getX(), getSecondPosition().getY() + (4.0 * getDiscreteUnit())));
+ drawinglayer::attribute::FillGradientAttribute aFillGradientAttribute(
+ css::awt::GradientStyle_LINEAR,
+ 0.0,
+ 0.5,
+ 0.5,
+ M_PI,
+ basegfx::BColorStops(
+ basegfx::BColor(230.0/255.0,230.0/255.0,230.0/255.0),
+ basegfx::BColor(180.0/255.0,180.0/255.0,180.0/255.0)));
+
+ rContainer.push_back(
+ new drawinglayer::primitive2d::FillGradientPrimitive2D(
+ aRange,
+ std::move(aFillGradientAttribute)));
+ break;
+ }
+ case SS_EDIT:
+ {
+ aRange.expand(basegfx::B2DTuple(getSecondPosition().getX(), getSecondPosition().getY() + (4.0 * getDiscreteUnit())));
+ drawinglayer::attribute::FillGradientAttribute aFillGradientAttribute(
+ css::awt::GradientStyle_LINEAR,
+ 0.0,
+ 0.5,
+ 0.5,
+ M_PI,
+ basegfx::BColorStops(
+ basegfx::BColor(230.0/255.0,230.0/255.0,230.0/255.0),
+ basegfx::BColor(83.0/255.0,83.0/255.0,83.0/255.0)));
+
+ rContainer.push_back(
+ new drawinglayer::primitive2d::FillGradientPrimitive2D(
+ aRange,
+ std::move(aFillGradientAttribute)));
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
+bool ShadowPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const
+{
+ if(drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
+ {
+ const ShadowPrimitive& rCompare = static_cast< const ShadowPrimitive& >(rPrimitive);
+
+ return (maBasePosition == rCompare.maBasePosition
+ && getSecondPosition() == rCompare.getSecondPosition()
+ && maShadowState == rCompare.maShadowState);
+ }
+
+ return false;
+}
+
+sal_uInt32 ShadowPrimitive::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_SWSIDEBARSHADOWPRIMITIVE;
+}
+
+/* static */ std::unique_ptr<ShadowOverlayObject> ShadowOverlayObject::CreateShadowOverlayObject( SwView const & rDocView )
+{
+ std::unique_ptr<ShadowOverlayObject> pShadowOverlayObject;
+
+ if ( rDocView.GetDrawView() )
+ {
+ SdrPaintWindow* pPaintWindow = rDocView.GetDrawView()->GetPaintWindow(0);
+ if( pPaintWindow )
+ {
+ const rtl::Reference< sdr::overlay::OverlayManager >& xOverlayManager = pPaintWindow->GetOverlayManager();
+
+ if ( xOverlayManager.is() )
+ {
+ pShadowOverlayObject.reset( new ShadowOverlayObject( basegfx::B2DPoint(0,0),
+ basegfx::B2DPoint(0,0),
+ Color(0,0,0) ) );
+ xOverlayManager->add(*pShadowOverlayObject);
+ }
+ }
+ }
+
+ return pShadowOverlayObject;
+}
+
+ShadowOverlayObject::ShadowOverlayObject( const basegfx::B2DPoint& rBasePos,
+ const basegfx::B2DPoint& rSecondPosition,
+ Color aBaseColor )
+ : OverlayObjectWithBasePosition(rBasePos, aBaseColor)
+ , maSecondPosition(rSecondPosition)
+ , mShadowState(SS_NORMAL)
+{
+}
+
+ShadowOverlayObject::~ShadowOverlayObject()
+{
+ if ( getOverlayManager() )
+ {
+ getOverlayManager()->remove(*this);
+ }
+}
+
+drawinglayer::primitive2d::Primitive2DContainer ShadowOverlayObject::createOverlayObjectPrimitive2DSequence()
+{
+ const drawinglayer::primitive2d::Primitive2DReference aReference(
+ new ShadowPrimitive( getBasePosition(),
+ maSecondPosition,
+ GetShadowState() ) );
+ return drawinglayer::primitive2d::Primitive2DContainer { aReference };
+}
+
+void ShadowOverlayObject::SetShadowState(ShadowState aState)
+{
+ if (mShadowState != aState)
+ {
+ mShadowState = aState;
+
+ objectChange();
+ }
+}
+
+void ShadowOverlayObject::SetPosition( const basegfx::B2DPoint& rPoint1,
+ const basegfx::B2DPoint& rPoint2)
+{
+ if(!rPoint1.equal(getBasePosition()) || !rPoint2.equal(maSecondPosition))
+ {
+ maBasePosition = rPoint1;
+ maSecondPosition = rPoint2;
+
+ objectChange();
+ }
+}
+
+} // end of namespace sw::sidebarwindows
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/ShadowOverlayObject.hxx b/sw/source/uibase/docvw/ShadowOverlayObject.hxx
new file mode 100644
index 0000000000..cd612f7ce5
--- /dev/null
+++ b/sw/source/uibase/docvw/ShadowOverlayObject.hxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include <svx/sdr/overlay/overlayobject.hxx>
+
+class SwView;
+
+namespace sw::sidebarwindows {
+
+enum ShadowState
+{
+ SS_NORMAL,
+ SS_VIEW,
+ SS_EDIT
+};
+
+class ShadowOverlayObject: public sdr::overlay::OverlayObjectWithBasePosition
+{
+protected:
+ // geometry creation for OverlayObject
+ virtual drawinglayer::primitive2d::Primitive2DContainer createOverlayObjectPrimitive2DSequence() override;
+
+private:
+ basegfx::B2DPoint maSecondPosition;
+ ShadowState mShadowState;
+
+ ShadowOverlayObject( const basegfx::B2DPoint& rBasePos,
+ const basegfx::B2DPoint& rSecondPosition,
+ Color aBaseColor );
+
+public:
+ virtual ~ShadowOverlayObject() override;
+
+ void SetShadowState(ShadowState aState);
+ ShadowState GetShadowState() const {return mShadowState;}
+
+ void SetPosition( const basegfx::B2DPoint& rPoint1,
+ const basegfx::B2DPoint& rPoint2 );
+
+ static std::unique_ptr<ShadowOverlayObject> CreateShadowOverlayObject( SwView const & rDocView );
+};
+
+} // end of namespace sw::sidebarwindows
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/SidebarTxtControl.cxx b/sw/source/uibase/docvw/SidebarTxtControl.cxx
new file mode 100644
index 0000000000..281544a7af
--- /dev/null
+++ b/sw/source/uibase/docvw/SidebarTxtControl.cxx
@@ -0,0 +1,473 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_wasm_strip.h>
+
+#include "SidebarTxtControl.hxx"
+
+#include <docsh.hxx>
+#include <doc.hxx>
+
+#include <PostItMgr.hxx>
+
+#include <cmdid.h>
+#include <strings.hrc>
+
+#include <unotools/securityoptions.hxx>
+#include <officecfg/Office/Common.hxx>
+
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/sfxhelp.hxx>
+
+#include <vcl/commandevent.hxx>
+#include <vcl/event.hxx>
+#include <vcl/ptrstyle.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/gradient.hxx>
+#include <vcl/settings.hxx>
+
+#include <editeng/outliner.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/flditem.hxx>
+
+#include <uitool.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <AnnotationWin.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <redline.hxx>
+#include <memory>
+
+namespace sw::sidebarwindows {
+
+SidebarTextControl::SidebarTextControl(sw::annotation::SwAnnotationWin& rSidebarWin,
+ SwView& rDocView,
+ SwPostItMgr& rPostItMgr)
+ : mrSidebarWin(rSidebarWin)
+ , mrDocView(rDocView)
+ , mrPostItMgr(rPostItMgr)
+ , mbMouseDownGainingFocus(false)
+{
+}
+
+EditView* SidebarTextControl::GetEditView() const
+{
+ OutlinerView* pOutlinerView = mrSidebarWin.GetOutlinerView();
+ if (!pOutlinerView)
+ return nullptr;
+ return &pOutlinerView->GetEditView();
+}
+
+EditEngine* SidebarTextControl::GetEditEngine() const
+{
+ OutlinerView* pOutlinerView = mrSidebarWin.GetOutlinerView();
+ if (!pOutlinerView)
+ return nullptr;
+ return pOutlinerView->GetEditView().GetEditEngine();
+}
+
+void SidebarTextControl::SetDrawingArea(weld::DrawingArea* pDrawingArea)
+{
+ Size aSize(0, 0);
+ pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
+
+ SetOutputSizePixel(aSize);
+
+ weld::CustomWidgetController::SetDrawingArea(pDrawingArea);
+
+ EnableRTL(false);
+
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ Color aBgColor = rStyleSettings.GetWindowColor();
+
+ OutputDevice& rDevice = pDrawingArea->get_ref_device();
+
+ rDevice.SetMapMode(MapMode(MapUnit::MapTwip));
+ rDevice.SetBackground(aBgColor);
+
+ Size aOutputSize(rDevice.PixelToLogic(aSize));
+
+ EditView* pEditView = GetEditView();
+ pEditView->setEditViewCallbacks(this);
+
+ EditEngine* pEditEngine = GetEditEngine();
+ // For tdf#143443 note we want an 'infinite' height initially (which is the
+ // editengines default). For tdf#144686 it is helpful if the initial width
+ // is the "SidebarWidth" so the calculated text height is always meaningful
+ // for layout in the sidebar.
+ Size aPaperSize(mrPostItMgr.GetSidebarWidth(), pEditEngine->GetPaperSize().Height());
+ pEditEngine->SetPaperSize(aPaperSize);
+ pEditEngine->SetRefDevice(mrDocView.GetWrtShell().getIDocumentDeviceAccess().getReferenceDevice(false));
+
+ pEditView->SetOutputArea(tools::Rectangle(Point(0, 0), aOutputSize));
+ pEditView->SetBackgroundColor(aBgColor);
+
+ pDrawingArea->set_cursor(PointerStyle::Text);
+
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ InitAccessible();
+#endif
+}
+
+void SidebarTextControl::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark)
+{
+ Point aMousePos = EditViewOutputDevice().PixelToLogic(rPosition);
+ m_xEditView->SetCursorLogicPosition(aMousePos, bPoint, bClearMark);
+}
+
+void SidebarTextControl::GetFocus()
+{
+ WeldEditView::GetFocus();
+ if ( !mrSidebarWin.IsMouseOver() )
+ Invalidate();
+ mrSidebarWin.SetActiveSidebarWin();
+}
+
+void SidebarTextControl::LoseFocus()
+{
+ // write the visible text back into the SwField
+ mrSidebarWin.UpdateData();
+
+ WeldEditView::LoseFocus();
+ if ( !mrSidebarWin.IsMouseOver() )
+ {
+ Invalidate();
+ }
+ // set false for autoscroll to typing location
+ mrSidebarWin.LockView(false);
+}
+
+OUString SidebarTextControl::RequestHelp(tools::Rectangle& rHelpRect)
+{
+ if (EditView* pEditView = GetEditView())
+ {
+ Point aPos = rHelpRect.TopLeft();
+
+ const OutputDevice& rOutDev = pEditView->GetOutputDevice();
+ Point aLogicClick = rOutDev.PixelToLogic(aPos);
+ const SvxFieldItem* pItem = pEditView->GetField(aLogicClick);
+ if (pItem)
+ {
+ const SvxFieldData* pField = pItem->GetField();
+ const SvxURLField* pURL = dynamic_cast<const SvxURLField*>( pField );
+ if (pURL)
+ {
+ rHelpRect = tools::Rectangle(aPos, Size(50, 10));
+ return SfxHelp::GetURLHelpText(pURL->GetURL());
+ }
+ }
+ }
+
+ TranslateId pResId;
+ switch( mrSidebarWin.GetLayoutStatus() )
+ {
+ case SwPostItHelper::INSERTED: pResId = STR_REDLINE_INSERT; break;
+ case SwPostItHelper::DELETED: pResId = STR_REDLINE_DELETE; break;
+ default: break;
+ }
+
+ SwContentAtPos aContentAtPos( IsAttrAtPos::Redline );
+ if ( pResId &&
+ mrDocView.GetWrtShell().GetContentAtPos( mrSidebarWin.GetAnchorPos(), aContentAtPos ) )
+ {
+ OUString sText = SwResId(pResId) + ": " +
+ aContentAtPos.aFnd.pRedl->GetAuthorString() + " - " +
+ GetAppLangDateTimeString( aContentAtPos.aFnd.pRedl->GetTimeStamp() );
+ return sText;
+ }
+
+ return OUString();
+}
+
+void SidebarTextControl::EditViewScrollStateChange()
+{
+ mrSidebarWin.SetScrollbar();
+}
+
+void SidebarTextControl::DrawForPage(OutputDevice* pDev, const Point& rPt)
+{
+ //Take the control's height, but overwrite the scrollbar area if there was one
+ OutputDevice& rDevice = GetDrawingArea()->get_ref_device();
+ Size aSize(rDevice.PixelToLogic(GetOutputSizePixel()));
+
+ if (OutlinerView* pOutlinerView = mrSidebarWin.GetOutlinerView())
+ {
+ pOutlinerView->GetOutliner()->Draw(*pDev, tools::Rectangle(rPt, aSize));
+ }
+
+ if ( mrSidebarWin.GetLayoutStatus()!=SwPostItHelper::DELETED )
+ return;
+
+ pDev->Push(vcl::PushFlags::LINECOLOR);
+
+ pDev->SetLineColor(mrSidebarWin.GetChangeColor());
+ Point aBottomRight(rPt);
+ aBottomRight.Move(aSize);
+ pDev->DrawLine(rPt, aBottomRight);
+
+ Point aTopRight(rPt);
+ aTopRight.Move(Size(aSize.Width(), 0));
+
+ Point aBottomLeft(rPt);
+ aBottomLeft.Move(Size(0, aSize.Height()));
+
+ pDev->DrawLine(aTopRight, aBottomLeft);
+
+ pDev->Pop();
+}
+
+void SidebarTextControl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ Size aSize = GetOutputSizePixel();
+ Point aPos;
+
+ if (!rRenderContext.GetSettings().GetStyleSettings().GetHighContrastMode())
+ {
+ if (mrSidebarWin.IsMouseOverSidebarWin() || HasFocus())
+ {
+ rRenderContext.DrawGradient(tools::Rectangle(aPos, rRenderContext.PixelToLogic(aSize)),
+ Gradient(css::awt::GradientStyle_LINEAR, mrSidebarWin.ColorDark(), mrSidebarWin.ColorDark()));
+ }
+ else
+ {
+ rRenderContext.DrawGradient(tools::Rectangle(aPos, rRenderContext.PixelToLogic(aSize)),
+ Gradient(css::awt::GradientStyle_LINEAR, mrSidebarWin.ColorLight(), mrSidebarWin.ColorDark()));
+ }
+ }
+
+ DoPaint(rRenderContext, rRect);
+
+ if (mrSidebarWin.GetLayoutStatus() != SwPostItHelper::DELETED)
+ return;
+
+ const AntialiasingFlags nFormerAntialiasing( rRenderContext.GetAntialiasing() );
+ const bool bIsAntiAliasing = officecfg::Office::Common::Drawinglayer::AntiAliasing::get();
+ if ( bIsAntiAliasing )
+ rRenderContext.SetAntialiasing(AntialiasingFlags::Enable);
+ rRenderContext.SetLineColor(mrSidebarWin.GetChangeColor());
+ rRenderContext.DrawLine(rRenderContext.PixelToLogic(aPos),
+ rRenderContext.PixelToLogic(aPos + Point(aSize.Width(),
+ aSize.Height() * 0.95)));
+ rRenderContext.DrawLine(rRenderContext.PixelToLogic(aPos + Point(aSize.Width(),
+ 0)),
+ rRenderContext.PixelToLogic(aPos + Point(0,
+ aSize.Height() * 0.95)));
+ if ( bIsAntiAliasing )
+ rRenderContext.SetAntialiasing(nFormerAntialiasing);
+}
+
+void SidebarTextControl::MakeVisible()
+{
+ //let's make sure we see our note
+ mrPostItMgr.MakeVisible(&mrSidebarWin);
+}
+
+bool SidebarTextControl::KeyInput( const KeyEvent& rKeyEvt )
+{
+ const vcl::KeyCode& rKeyCode = rKeyEvt.GetKeyCode();
+ const sal_uInt16 nKey = rKeyCode.GetCode();
+ if (nKey == KEY_F12 && getenv("SW_DEBUG"))
+ {
+ if (rKeyEvt.GetKeyCode().IsShift())
+ {
+ mrDocView.GetDocShell()->GetDoc()->dumpAsXml();
+ return true;
+ }
+ }
+
+ bool bDone = false;
+
+ if ( ( rKeyCode.IsMod1() && rKeyCode.IsMod2() ) &&
+ ( (nKey == KEY_PAGEUP) || (nKey == KEY_PAGEDOWN) ) )
+ {
+ mrSidebarWin.SwitchToPostIt(nKey);
+ bDone = true;
+ }
+ else if ( nKey == KEY_ESCAPE ||
+ ( rKeyCode.IsMod1() &&
+ ( nKey == KEY_PAGEUP ||
+ nKey == KEY_PAGEDOWN ) ) )
+ {
+ mrSidebarWin.SwitchToFieldPos();
+ bDone = true;
+ }
+ else if ( rKeyCode.GetFullCode() == KEY_INSERT )
+ {
+ mrSidebarWin.ToggleInsMode();
+ bDone = true;
+ }
+ else
+ {
+ MakeVisible();
+
+ tools::Long aOldHeight = mrSidebarWin.GetPostItTextHeight();
+
+ /// HACK: need to switch off processing of Undo/Redo in Outliner
+ if ( !( (nKey == KEY_Z || nKey == KEY_Y) && rKeyCode.IsMod1()) )
+ {
+ bool bIsProtected = mrSidebarWin.IsReadOnlyOrProtected();
+ if ( !bIsProtected || !EditEngine::DoesKeyChangeText(rKeyEvt) )
+ {
+ EditView* pEditView = GetEditView();
+ bDone = pEditView && pEditView->PostKeyEvent(rKeyEvt);
+ }
+ else
+ mrDocView.GetWrtShell().InfoReadOnlyDialog(false);
+ }
+ if (bDone)
+ mrSidebarWin.ResizeIfNecessary( aOldHeight, mrSidebarWin.GetPostItTextHeight() );
+ else
+ {
+ // write back data first when showing navigator
+ if ( nKey==KEY_F5 )
+ mrSidebarWin.UpdateData();
+ bDone = mrDocView.KeyInput(rKeyEvt);
+ }
+ }
+
+ mrDocView.GetViewFrame().GetBindings().InvalidateAll(false);
+
+ return bDone;
+}
+
+bool SidebarTextControl::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ if (EditView* pEditView = GetEditView())
+ {
+ bool bExecuteMod = SvtSecurityOptions::IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink);
+
+ if ( !bExecuteMod || (rMEvt.GetModifier() == KEY_MOD1))
+ {
+ const OutputDevice& rOutDev = pEditView->GetOutputDevice();
+ Point aLogicClick = rOutDev.PixelToLogic(rMEvt.GetPosPixel());
+ if (const SvxFieldItem* pItem = pEditView->GetField(aLogicClick))
+ {
+ const SvxFieldData* pField = pItem->GetField();
+ const SvxURLField* pURL = dynamic_cast<const SvxURLField*>( pField );
+ if ( pURL )
+ {
+ pEditView->MouseButtonDown( rMEvt );
+ SwWrtShell &rSh = mrDocView.GetWrtShell();
+ const OUString& sURL( pURL->GetURL() );
+ const OUString& sTarget( pURL->GetTargetFrame() );
+ ::LoadURL(rSh, sURL, LoadUrlFlags::NONE, sTarget);
+ return true;
+ }
+ }
+ }
+ }
+
+ mbMouseDownGainingFocus = !HasFocus();
+ GrabFocus();
+
+ bool bRet = WeldEditView::MouseButtonDown(rMEvt);
+
+ mrDocView.GetViewFrame().GetBindings().InvalidateAll(false);
+
+ return bRet;
+}
+
+bool SidebarTextControl::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ bool bRet = WeldEditView::MouseButtonUp(rMEvt);
+
+ if (mbMouseDownGainingFocus)
+ {
+ MakeVisible();
+ mbMouseDownGainingFocus = false;
+ }
+
+ return bRet;
+}
+
+bool SidebarTextControl::MouseMove(const MouseEvent& rMEvt)
+{
+ if (rMEvt.IsEnterWindow())
+ GetDrawingArea()->set_cursor(PointerStyle::Text);
+ return WeldEditView::MouseMove(rMEvt);
+}
+
+IMPL_LINK( SidebarTextControl, OnlineSpellCallback, SpellCallbackInfo&, rInfo, void )
+{
+ if ( rInfo.nCommand == SpellCallbackCommand::STARTSPELLDLG )
+ {
+ mrDocView.GetViewFrame().GetDispatcher()->Execute( FN_SPELL_GRAMMAR_DIALOG, SfxCallMode::ASYNCHRON);
+ }
+}
+
+bool SidebarTextControl::Command( const CommandEvent& rCEvt )
+{
+ EditView* pEditView = GetEditView();
+
+ if ( rCEvt.GetCommand() == CommandEventId::ContextMenu )
+ {
+ if (IsMouseCaptured())
+ ReleaseMouse();
+ if ( !mrSidebarWin.IsReadOnlyOrProtected() &&
+ pEditView &&
+ pEditView->IsWrongSpelledWordAtPos( rCEvt.GetMousePosPixel(), true ))
+ {
+ Link<SpellCallbackInfo&,void> aLink = LINK(this, SidebarTextControl, OnlineSpellCallback);
+ pEditView->ExecuteSpellPopup(rCEvt.GetMousePosPixel(), aLink);
+ }
+ else
+ {
+ Point aPos;
+ if (rCEvt.IsMouseEvent())
+ aPos = rCEvt.GetMousePosPixel();
+ else
+ {
+ const Size aSize = GetOutputSizePixel();
+ aPos = Point( aSize.getWidth()/2, aSize.getHeight()/2 );
+ }
+ SfxDispatcher::ExecutePopup(&mrSidebarWin, &aPos);
+ }
+ return true;
+ }
+ else if (rCEvt.GetCommand() == CommandEventId::Wheel)
+ {
+ // if no scrollbar, or extra keys held scroll the document and consume
+ // this event, otherwise don't consume and let the event get to the
+ // surrounding scrolled window
+ if (!mrSidebarWin.IsScrollbarVisible())
+ {
+ mrDocView.HandleWheelCommands(rCEvt);
+ return true;
+ }
+ else
+ {
+ const CommandWheelData* pData = rCEvt.GetWheelData();
+ if (pData->IsShift() || pData->IsMod1() || pData->IsMod2())
+ {
+ mrDocView.HandleWheelCommands(rCEvt);
+ return true;
+ }
+ }
+ }
+
+ return WeldEditView::Command(rCEvt);
+}
+
+} // end of namespace sw::sidebarwindows
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/SidebarTxtControl.hxx b/sw/source/uibase/docvw/SidebarTxtControl.hxx
new file mode 100644
index 0000000000..891d320038
--- /dev/null
+++ b/sw/source/uibase/docvw/SidebarTxtControl.hxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <svx/weldeditview.hxx>
+
+class OutlinerView;
+class SwView;
+class SwPostItMgr;
+struct SpellCallbackInfo;
+namespace sw::annotation { class SwAnnotationWin; }
+
+namespace sw::sidebarwindows {
+
+class SidebarTextControl : public WeldEditView
+{
+ private:
+ sw::annotation::SwAnnotationWin& mrSidebarWin;
+ SwView& mrDocView;
+ SwPostItMgr& mrPostItMgr;
+ bool mbMouseDownGainingFocus;
+
+ void MakeVisible();
+
+ protected:
+ virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
+
+ virtual bool Command(const CommandEvent& rCEvt) override;
+ virtual void GetFocus() override;
+ virtual void LoseFocus() override;
+
+ virtual OUString RequestHelp(tools::Rectangle& rRect) override;
+
+ public:
+ SidebarTextControl(sw::annotation::SwAnnotationWin& rSidebarWin,
+ SwView& rDocView,
+ SwPostItMgr& rPostItMgr);
+
+ virtual EditView* GetEditView() const override;
+
+ virtual EditEngine* GetEditEngine() const override;
+
+ virtual void EditViewScrollStateChange() override;
+
+ void SetDrawingArea(weld::DrawingArea* pDrawingArea) override;
+
+ void SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark);
+
+ virtual bool KeyInput(const KeyEvent& rKeyEvt) override;
+ virtual bool MouseButtonDown(const MouseEvent& rMEvt) override;
+ virtual bool MouseButtonUp(const MouseEvent& rMEvt) override;
+ virtual bool MouseMove(const MouseEvent& rMEvt) override;
+
+ void SetMapMode(const MapMode& rNewMapMode)
+ {
+ OutputDevice& rDevice = GetDrawingArea()->get_ref_device();
+ rDevice.SetMapMode(rNewMapMode);
+ }
+
+ DECL_LINK( OnlineSpellCallback, SpellCallbackInfo&, void );
+
+ void DrawForPage(OutputDevice* pDev, const Point& rPos);
+};
+
+} // end of namespace sw::sidebarwindows
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/SidebarWinAcc.cxx b/sw/source/uibase/docvw/SidebarWinAcc.cxx
new file mode 100644
index 0000000000..f489bc140b
--- /dev/null
+++ b/sw/source/uibase/docvw/SidebarWinAcc.cxx
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "SidebarWinAcc.hxx"
+#include <AnnotationWin.hxx>
+
+#include <viewsh.hxx>
+#include <accmap.hxx>
+#include <toolkit/awt/vclxaccessiblecomponent.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <mutex>
+
+namespace sw::sidebarwindows {
+
+namespace {
+
+// declaration and implementation of accessible context for <SidebarWinAccessible> instance
+class SidebarWinAccessibleContext : public VCLXAccessibleComponent
+{
+ public:
+ explicit SidebarWinAccessibleContext( sw::annotation::SwAnnotationWin& rSidebarWin,
+ SwViewShell& rViewShell,
+ const SwFrame* pAnchorFrame )
+ : VCLXAccessibleComponent( dynamic_cast<VCLXWindow*>(rSidebarWin.CreateAccessible().get()) )
+ , mrViewShell( rViewShell )
+ , mpAnchorFrame( pAnchorFrame )
+ {
+ rSidebarWin.SetAccessibleRole( css::accessibility::AccessibleRole::COMMENT );
+ }
+
+ void ChangeAnchor( const SwFrame* pAnchorFrame )
+ {
+ std::scoped_lock aGuard(maMutex);
+
+ mpAnchorFrame = pAnchorFrame;
+ }
+
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
+ getAccessibleParent() override
+ {
+ std::scoped_lock aGuard(maMutex);
+
+ css::uno::Reference< css::accessibility::XAccessible > xAccParent;
+
+ if ( mpAnchorFrame &&
+ mrViewShell.GetAccessibleMap() )
+ {
+ xAccParent = mrViewShell.GetAccessibleMap()->GetContext( mpAnchorFrame, false );
+ }
+
+ return xAccParent;
+ }
+
+ virtual sal_Int64 SAL_CALL getAccessibleIndexInParent() override
+ {
+ std::scoped_lock aGuard(maMutex);
+
+ sal_Int64 nIndex( -1 );
+
+ if ( mpAnchorFrame && GetWindow() &&
+ mrViewShell.GetAccessibleMap() )
+ {
+ nIndex = mrViewShell.GetAccessibleMap()->GetChildIndex( *mpAnchorFrame,
+ *GetWindow() );
+ }
+
+ return nIndex;
+ }
+
+ private:
+ SwViewShell& mrViewShell;
+ const SwFrame* mpAnchorFrame;
+
+ std::mutex maMutex;
+};
+
+}
+
+// implementation of accessible for <SwAnnotationWin> instance
+SidebarWinAccessible::SidebarWinAccessible( sw::annotation::SwAnnotationWin& rSidebarWin,
+ SwViewShell& rViewShell,
+ const SwSidebarItem& rSidebarItem )
+ : mrSidebarWin( rSidebarWin )
+ , mrViewShell( rViewShell )
+ , mpAnchorFrame( rSidebarItem.maLayoutInfo.mpAnchorFrame )
+ , m_bAccContextCreated( false )
+{
+ SetWindow( &mrSidebarWin );
+}
+
+SidebarWinAccessible::~SidebarWinAccessible()
+{
+}
+
+void SidebarWinAccessible::ChangeSidebarItem( const SwSidebarItem& rSidebarItem )
+{
+ if ( !m_bAccContextCreated )
+ return;
+
+ css::uno::Reference< css::accessibility::XAccessibleContext > xAcc
+ = getAccessibleContext();
+ if ( xAcc.is() )
+ {
+ SidebarWinAccessibleContext* pAccContext =
+ dynamic_cast<SidebarWinAccessibleContext*>(xAcc.get());
+ if ( pAccContext )
+ {
+ pAccContext->ChangeAnchor( rSidebarItem.maLayoutInfo.mpAnchorFrame );
+ }
+ }
+}
+
+css::uno::Reference< css::accessibility::XAccessibleContext > SidebarWinAccessible::CreateAccessibleContext()
+{
+ rtl::Reference<SidebarWinAccessibleContext> pAccContext =
+ new SidebarWinAccessibleContext( mrSidebarWin,
+ mrViewShell,
+ mpAnchorFrame );
+ m_bAccContextCreated = true;
+ return pAccContext;
+}
+
+} // end of namespace sw::sidebarwindows
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/SidebarWinAcc.hxx b/sw/source/uibase/docvw/SidebarWinAcc.hxx
new file mode 100644
index 0000000000..5453a42c9a
--- /dev/null
+++ b/sw/source/uibase/docvw/SidebarWinAcc.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <toolkit/awt/vclxwindow.hxx>
+
+class SwViewShell;
+class SwSidebarItem;
+class SwFrame;
+namespace sw::annotation { class SwAnnotationWin; }
+
+namespace sw::sidebarwindows {
+
+class SidebarWinAccessible : public VCLXWindow
+{
+ public:
+ explicit SidebarWinAccessible( sw::annotation::SwAnnotationWin& rSidebarWin,
+ SwViewShell& rViewShell,
+ const SwSidebarItem& rSidebarItem );
+ virtual ~SidebarWinAccessible() override;
+
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext >
+ CreateAccessibleContext() override;
+
+ void ChangeSidebarItem( const SwSidebarItem& rSidebarItem );
+
+ private:
+ sw::annotation::SwAnnotationWin& mrSidebarWin;
+ SwViewShell& mrViewShell;
+ const SwFrame* mpAnchorFrame;
+ bool m_bAccContextCreated;
+};
+
+} // end of namespace sw::sidebarwindows
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/UnfloatTableButton.cxx b/sw/source/uibase/docvw/UnfloatTableButton.cxx
new file mode 100644
index 0000000000..4e8449383e
--- /dev/null
+++ b/sw/source/uibase/docvw/UnfloatTableButton.cxx
@@ -0,0 +1,245 @@
+/* -*- 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 <UnfloatTableButton.hxx>
+#include <HeaderFooterWin.hxx>
+
+#include <edtwin.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <strings.hrc>
+#include <fmtpdsc.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/settings.hxx>
+#include <viewopt.hxx>
+#include <frame.hxx>
+#include <flyfrm.hxx>
+#include <tabfrm.hxx>
+#include <txtfrm.hxx>
+#include <pagefrm.hxx>
+#include <ndindex.hxx>
+#include <ndtxt.hxx>
+#include <swtable.hxx>
+#include <unoprnms.hxx>
+#include <unotbl.hxx>
+#include <IDocumentState.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IDocumentLayoutAccess.hxx>
+#include <drawinglayer/primitive2d/textprimitive2d.hxx>
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <drawinglayer/attribute/fontattribute.hxx>
+#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <drawinglayer/processor2d/processor2dtools.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <svl/grabbagitem.hxx>
+#include <doc.hxx>
+
+#define TEXT_PADDING 3
+#define BOX_DISTANCE 3
+#define BUTTON_WIDTH 12
+
+UnfloatTableButton::UnfloatTableButton(SwEditWin* pEditWin, const SwFrame* pFrame)
+ : SwFrameMenuButtonBase(pEditWin, pFrame, "modules/swriter/ui/unfloatbutton.ui",
+ "UnfloatButton")
+ , m_xPushButton(m_xBuilder->weld_button("button"))
+ , m_sLabel(SwResId(STR_UNFLOAT_TABLE))
+{
+ m_xPushButton->set_accessible_name(m_sLabel);
+ m_xVirDev = m_xPushButton->create_virtual_device();
+ m_xPushButton->connect_clicked(LINK(this, UnfloatTableButton, ClickHdl));
+ SetVirDevFont();
+}
+
+weld::Button* UnfloatTableButton::GetButton() { return m_xPushButton.get(); }
+
+UnfloatTableButton::~UnfloatTableButton() { disposeOnce(); }
+
+void UnfloatTableButton::dispose()
+{
+ m_xPushButton.reset();
+ m_xVirDev.disposeAndClear();
+ SwFrameMenuButtonBase::dispose();
+}
+
+void UnfloatTableButton::SetOffset(Point aTopRightPixel)
+{
+ // Compute the text size and get the box position & size from it
+ tools::Rectangle aTextRect;
+ m_xVirDev->GetTextBoundRect(aTextRect, m_sLabel);
+ tools::Rectangle aTextPxRect = m_xVirDev->LogicToPixel(aTextRect);
+ FontMetric aFontMetric = m_xVirDev->GetFontMetric(m_xVirDev->GetFont());
+ Size aBoxSize(aTextPxRect.GetWidth() + BUTTON_WIDTH + TEXT_PADDING * 2,
+ aFontMetric.GetLineHeight() + TEXT_PADDING * 2);
+
+ Point aBoxPos(aTopRightPixel.X() - aBoxSize.Width() - BOX_DISTANCE, aTopRightPixel.Y());
+
+ if (AllSettings::GetLayoutRTL())
+ {
+ aBoxPos.setX(aTopRightPixel.X() + BOX_DISTANCE);
+ }
+
+ // Set the position & Size of the window
+ SetPosSizePixel(aBoxPos, aBoxSize);
+ m_xVirDev->SetOutputSizePixel(aBoxSize);
+
+ PaintButton();
+}
+
+IMPL_LINK_NOARG(UnfloatTableButton, ClickHdl, weld::Button&, void)
+{
+ assert(GetFrame()->IsFlyFrame());
+ // const_cast is needed because of bad design of ISwFrameControl and derived classes
+ SwFlyFrame* pFlyFrame = const_cast<SwFlyFrame*>(static_cast<const SwFlyFrame*>(GetFrame()));
+
+ // Find the table inside the text frame
+ SwTabFrame* pTableFrame = nullptr;
+ SwFrame* pLower = pFlyFrame->GetLower();
+ while (pLower)
+ {
+ if (pLower->IsTabFrame())
+ {
+ pTableFrame = static_cast<SwTabFrame*>(pLower);
+ break;
+ }
+ pLower = pLower->GetNext();
+ }
+
+ if (pTableFrame == nullptr)
+ return;
+
+ // Insert the table at the position of the text node which has the frame anchored to
+ SwFrame* pAnchoreFrame = pFlyFrame->AnchorFrame();
+ if (pAnchoreFrame == nullptr || !pAnchoreFrame->IsTextFrame())
+ return;
+
+ SwTextFrame* pTextFrame = static_cast<SwTextFrame*>(pAnchoreFrame);
+ if (pTextFrame->GetTextNodeFirst() == nullptr)
+ return;
+
+ SwTableNode* pTableNode = pTableFrame->GetTable()->GetTableNode();
+ if (pTableNode == nullptr)
+ return;
+
+ SwDoc& rDoc = pTextFrame->GetDoc();
+
+ // tdf#129176: clear "TablePosition" grab bag, since we explicitly change the position here
+ // See DomainMapperTableHandler::endTableGetTableStyle, where the grab bag is filled, and
+ // DocxAttributeOutput::TableDefinition that uses it on export
+ SwFrameFormat* pTableFormat = pTableFrame->GetTable()->GetFrameFormat();
+ assert(pTableFormat);
+ if (const SfxGrabBagItem* pGrabBagItem = pTableFormat->GetAttrSet().GetItem(RES_FRMATR_GRABBAG))
+ {
+ SfxGrabBagItem aGrabBagItem(*pGrabBagItem); // Editable copy
+ if (aGrabBagItem.GetGrabBag().erase("TablePosition"))
+ {
+ css::uno::Any aVal;
+ aGrabBagItem.QueryValue(aVal);
+ const rtl::Reference<SwXTextTable> xTable
+ = SwXTextTable::CreateXTextTable(pTableFormat);
+ xTable->setPropertyValue(UNO_NAME_TABLE_INTEROP_GRAB_BAG, aVal);
+ }
+ }
+
+ // When we move the table before the first text node, we need to clear RES_PAGEDESC attribute
+ // of the text node otherwise LO will create a page break after the table
+ if (pTextFrame->GetTextNodeFirst())
+ {
+ const SwPageDesc* pPageDesc
+ = pTextFrame->GetPageDescItem().GetPageDesc(); // First text node of the page has this
+ if (pPageDesc)
+ {
+ // First set the existing page desc for the table node
+ SfxItemSetFixed<RES_PAGEDESC, RES_PAGEDESC> aSet(
+ GetEditWin()->GetView().GetWrtShell().GetAttrPool());
+ aSet.Put(SwFormatPageDesc(pPageDesc));
+ SwPaM aPaMTable(*pTableNode);
+ rDoc.getIDocumentContentOperations().InsertItemSet(
+ aPaMTable, aSet, SetAttrMode::DEFAULT, GetPageFrame()->getRootFrame());
+
+ // Then remove pagedesc from the attributes of the text node
+ aSet.Put(SwFormatPageDesc(nullptr));
+ SwPaM aPaMTextNode(*pTextFrame->GetTextNodeFirst());
+ rDoc.getIDocumentContentOperations().InsertItemSet(
+ aPaMTextNode, aSet, SetAttrMode::DEFAULT, GetPageFrame()->getRootFrame());
+ }
+ }
+
+ SwWrtShell& rWrtShell = GetEditWin()->GetView().GetWrtShell();
+ rWrtShell.UnfloatFlyFrame();
+
+ rDoc.getIDocumentState().SetModified();
+
+ // Undoing MoveNodeRange() is not working correctly in case of tables, it crashes sometimes
+ // So don't allow to undo after unfloating (similar to MakeFlyAndMove() method)
+ if (rDoc.GetIDocumentUndoRedo().DoesUndo())
+ {
+ rDoc.GetIDocumentUndoRedo().DelAllUndoObj();
+ }
+}
+
+void UnfloatTableButton::PaintButton()
+{
+ if (!m_xVirDev)
+ return;
+
+ m_xVirDev->SetMapMode(MapMode(MapUnit::MapPixel));
+ drawinglayer::primitive2d::Primitive2DContainer aSeq;
+ const ::tools::Rectangle aRect(
+ ::tools::Rectangle(Point(0, 0), m_xVirDev->PixelToLogic(GetSizePixel())));
+
+ // Create button
+ SwFrameButtonPainter::PaintButton(aSeq, aRect, true);
+
+ // Create the text primitive
+ basegfx::BColor aLineColor
+ = SwViewOption::GetCurrentViewOptions().GetHeaderFooterMarkColor().getBColor();
+ basegfx::B2DVector aFontSize;
+ drawinglayer::attribute::FontAttribute aFontAttr
+ = drawinglayer::primitive2d::getFontAttributeFromVclFont(aFontSize, m_xVirDev->GetFont(),
+ false, false);
+
+ FontMetric aFontMetric = m_xVirDev->GetFontMetric(m_xVirDev->GetFont());
+ double nTextOffsetY = aFontMetric.GetAscent() + TEXT_PADDING;
+ double nTextOffsetX = std::abs(aRect.GetWidth() - m_xVirDev->GetTextWidth(m_sLabel)) / 2.0;
+ Point aTextPos(nTextOffsetX, nTextOffsetY);
+
+ basegfx::B2DHomMatrix aTextMatrix(basegfx::utils::createScaleTranslateB2DHomMatrix(
+ aFontSize.getX(), aFontSize.getY(), static_cast<double>(aTextPos.X()),
+ static_cast<double>(aTextPos.Y())));
+
+ aSeq.push_back(drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
+ aTextMatrix, m_sLabel, 0, m_sLabel.getLength(), std::vector<double>(), {},
+ std::move(aFontAttr), css::lang::Locale(), aLineColor)));
+
+ // Create the processor and process the primitives
+ const drawinglayer::geometry::ViewInformation2D aNewViewInfos;
+ std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(
+ drawinglayer::processor2d::createProcessor2DFromOutputDevice(*m_xVirDev, aNewViewInfos));
+
+ pProcessor->process(aSeq);
+
+ m_xPushButton->set_custom_button(m_xVirDev.get());
+}
+
+void UnfloatTableButton::ShowAll(bool bShow) { Show(bShow); }
+
+bool UnfloatTableButton::Contains(const Point& rDocPt) const
+{
+ ::tools::Rectangle aRect(GetPosPixel(), GetSizePixel());
+ if (aRect.Contains(rDocPt))
+ return true;
+
+ return false;
+}
+
+void UnfloatTableButton::SetReadonly(bool bReadonly) { ShowAll(!bReadonly); }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/source/uibase/docvw/contentcontrolaliasbutton.cxx b/sw/source/uibase/docvw/contentcontrolaliasbutton.cxx
new file mode 100644
index 0000000000..0d11b5c606
--- /dev/null
+++ b/sw/source/uibase/docvw/contentcontrolaliasbutton.cxx
@@ -0,0 +1,151 @@
+/* -*- 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 <contentcontrolaliasbutton.hxx>
+
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <drawinglayer/attribute/fontattribute.hxx>
+#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
+#include <drawinglayer/primitive2d/textprimitive2d.hxx>
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <drawinglayer/processor2d/processor2dtools.hxx>
+#include <vcl/metric.hxx>
+
+#include <HeaderFooterWin.hxx>
+#include <edtwin.hxx>
+#include <formatcontentcontrol.hxx>
+#include <swabstdlg.hxx>
+#include <view.hxx>
+#include <viewopt.hxx>
+#include <wrtsh.hxx>
+
+#define TEXT_PADDING 3
+#define BOX_DISTANCE 3
+#define BUTTON_WIDTH 12
+
+SwContentControlAliasButton::SwContentControlAliasButton(SwEditWin* pEditWin,
+ SwContentControl* pContentControl)
+ : SwFrameMenuButtonBase(pEditWin, nullptr, "modules/swriter/ui/contentcontrolaliasbutton.ui",
+ "ContentControlAliasButton")
+ , m_xPushButton(m_xBuilder->weld_button("button"))
+ , m_sLabel(pContentControl->GetAlias())
+{
+ m_xPushButton->set_accessible_name(m_sLabel);
+ m_xPushButton->connect_clicked(LINK(this, SwContentControlAliasButton, ClickHdl));
+ m_xVirDev = m_xPushButton->create_virtual_device();
+ SetVirDevFont();
+}
+
+SwContentControlAliasButton::~SwContentControlAliasButton() { disposeOnce(); }
+
+void SwContentControlAliasButton::dispose()
+{
+ m_xPushButton.reset();
+ m_xVirDev.disposeAndClear();
+ SwFrameMenuButtonBase::dispose();
+}
+
+void SwContentControlAliasButton::SetOffset(Point aTopLeftPixel)
+{
+ // Compute the text size and get the box position & size from it.
+ tools::Rectangle aTextRect;
+ m_xVirDev->GetTextBoundRect(aTextRect, m_sLabel);
+ tools::Rectangle aTextPxRect = m_xVirDev->LogicToPixel(aTextRect);
+ FontMetric aFontMetric = m_xVirDev->GetFontMetric(m_xVirDev->GetFont());
+ Size aBoxSize(aTextPxRect.GetWidth() + BUTTON_WIDTH + TEXT_PADDING * 2,
+ aFontMetric.GetLineHeight() + TEXT_PADDING * 2);
+ Point aBoxPos(aTopLeftPixel.X() + BOX_DISTANCE, aTopLeftPixel.Y() - aBoxSize.Height());
+
+ // Set the position & size of the window.
+ SetPosSizePixel(aBoxPos, aBoxSize);
+ m_xVirDev->SetOutputSizePixel(aBoxSize);
+
+ PaintButton();
+}
+
+IMPL_LINK_NOARG(SwContentControlAliasButton, ClickHdl, weld::Button&, void)
+{
+ if (m_bReadOnly)
+ {
+ return;
+ }
+
+ SwView& rView = GetEditWin()->GetView();
+ SwWrtShell& rWrtSh = rView.GetWrtShell();
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(
+ pFact->CreateSwContentControlDlg(GetEditWin()->GetFrameWeld(), rWrtSh));
+ VclAbstractDialog::AsyncContext aContext;
+ aContext.maEndDialogFn = [](sal_Int32) {};
+ pDlg->StartExecuteAsync(aContext);
+}
+
+void SwContentControlAliasButton::PaintButton()
+{
+ if (!m_xVirDev)
+ {
+ return;
+ }
+
+ m_xVirDev->SetMapMode(MapMode(MapUnit::MapPixel));
+ drawinglayer::primitive2d::Primitive2DContainer aSeq;
+ tools::Rectangle aRect(Point(0, 0), m_xVirDev->PixelToLogic(GetSizePixel()));
+
+ // Create button
+ SwFrameButtonPainter::PaintButton(aSeq, aRect, /*bOnTop=*/false);
+
+ // Create the text primitive
+ const SwViewOption* pVOpt = GetEditWin()->GetView().GetWrtShell().GetViewOptions();
+ basegfx::BColor aLineColor = pVOpt->GetHeaderFooterMarkColor().getBColor();
+ basegfx::B2DVector aFontSize;
+ drawinglayer::attribute::FontAttribute aFontAttr
+ = drawinglayer::primitive2d::getFontAttributeFromVclFont(aFontSize, m_xVirDev->GetFont(),
+ false, false);
+
+ FontMetric aFontMetric = m_xVirDev->GetFontMetric(m_xVirDev->GetFont());
+ double nTextOffsetY = aFontMetric.GetAscent() + TEXT_PADDING;
+ double nTextOffsetX = std::abs(aRect.GetWidth() - m_xVirDev->GetTextWidth(m_sLabel)) / 2.0;
+ Point aTextPos(nTextOffsetX, nTextOffsetY);
+
+ basegfx::B2DHomMatrix aTextMatrix = basegfx::utils::createScaleTranslateB2DHomMatrix(
+ aFontSize.getX(), aFontSize.getY(), static_cast<double>(aTextPos.X()),
+ static_cast<double>(aTextPos.Y()));
+
+ aSeq.push_back(drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
+ aTextMatrix, m_sLabel, 0, m_sLabel.getLength(), std::vector<double>(), {},
+ std::move(aFontAttr), css::lang::Locale(), aLineColor)));
+
+ // Create the processor and process the primitives
+ drawinglayer::geometry::ViewInformation2D aViewInfo;
+ std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor
+ = drawinglayer::processor2d::createProcessor2DFromOutputDevice(*m_xVirDev, aViewInfo);
+
+ pProcessor->process(aSeq);
+
+ m_xPushButton->set_custom_button(m_xVirDev.get());
+}
+
+void SwContentControlAliasButton::ShowAll(bool bShow) { Show(bShow); }
+
+bool SwContentControlAliasButton::Contains(const Point& rDocPt) const
+{
+ tools::Rectangle aRect(GetPosPixel(), GetSizePixel());
+ return aRect.Contains(rDocPt);
+}
+
+void SwContentControlAliasButton::SetReadonly(bool bReadonly) { m_bReadOnly = bReadonly; }
+
+void SwContentControlAliasButton::SetContentControl(SwContentControl* pContentControl)
+{
+ m_sLabel = pContentControl->GetAlias();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/edtdd.cxx b/sw/source/uibase/docvw/edtdd.cxx
new file mode 100644
index 0000000000..287d2969f6
--- /dev/null
+++ b/sw/source/uibase/docvw/edtdd.cxx
@@ -0,0 +1,501 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svdview.hxx>
+#include <editeng/outliner.hxx>
+#include <svx/svdobj.hxx>
+#include <sot/exchange.hxx>
+#include <sot/formats.hxx>
+#include <sfx2/bindings.hxx>
+#include <vcl/commandevent.hxx>
+#include <osl/diagnose.h>
+
+#include <sfx2/viewfrm.hxx>
+#include <fmturl.hxx>
+#include <frmfmt.hxx>
+#include <wrtsh.hxx>
+#include <edtdd.hxx>
+#include <edtwin.hxx>
+#include <view.hxx>
+#include <viewopt.hxx>
+#include <swdtflvr.hxx>
+#include <swmodule.hxx>
+#include <docsh.hxx>
+#include <wdocsh.hxx>
+
+using namespace ::com::sun::star;
+
+// no include "dbgoutsw.hxx" here!!!!!!
+
+bool g_bExecuteDrag = false;
+
+void SwEditWin::StartDDTimer()
+{
+ m_aTimer.SetInvokeHandler(LINK(this, SwEditWin, DDHandler));
+ m_aTimer.SetTimeout(480);
+ m_aTimer.Start();
+ g_bDDTimerStarted = true;
+}
+
+void SwEditWin::StopDDTimer(SwWrtShell *pSh, const Point &rPt)
+{
+ m_aTimer.Stop();
+ g_bDDTimerStarted = false;
+ if(!pSh->IsSelFrameMode())
+ pSh->CallSetCursor(&rPt, false);
+ m_aTimer.SetInvokeHandler(LINK(this,SwEditWin, TimerHandler));
+}
+
+void SwEditWin::StartDrag( sal_Int8 /*nAction*/, const Point& rPosPixel )
+{
+ if (m_rView.GetObjectShell()->isContentExtractionLocked())
+ return;
+
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ if( rSh.GetDrawView() )
+ {
+ CommandEvent aDragEvent( rPosPixel, CommandEventId::StartDrag, true );
+ if( rSh.GetDrawView()->Command( aDragEvent, this ) )
+ {
+ m_rView.GetViewFrame().GetBindings().InvalidateAll(false);
+ return; // Event evaluated by SdrView
+ }
+ }
+
+ if ( m_pApplyTempl || rSh.IsDrawCreate() || IsDrawAction())
+ return;
+
+ bool bStart = false, bDelSelect = false;
+ SdrObject *pObj = nullptr;
+ Point aDocPos( PixelToLogic( rPosPixel ) );
+ const bool bInSelect = rSh.IsInSelect();
+ if (!bInSelect && rSh.TestCurrPam(aDocPos, true))
+ //We are not selecting and aren't at a selection
+ bStart = true;
+ else if ( !g_bFrameDrag && rSh.IsSelFrameMode() &&
+ rSh.IsInsideSelectedObj( aDocPos ) &&
+ nullptr == m_pAnchorMarker)
+ {
+ //We are not dragging internally and are not at an
+ //object (frame, draw object)
+
+ // #i106131# *and* AnchorDrag is *not* active: When active,
+ // entering global drag mode will destroy the AnchorHdl but
+ // keep the now invalid ptr in place, next access will crash.
+ // It is indeed wrong to enter drag mode when AnchorDrag is
+ // already active
+ bStart = true;
+ }
+ else if( !g_bFrameDrag && m_rView.GetDocShell()->IsReadOnly() &&
+ OBJCNT_NONE != rSh.GetObjCntType( aDocPos, pObj ))
+ {
+ rSh.LockPaint(LockPaintReason::StartDrag);
+ if( rSh.SelectObj( aDocPos, 0, pObj ))
+ bStart = bDelSelect = true;
+ else
+ rSh.UnlockPaint();
+ }
+ else if (!bInSelect)// tdf#116384 only drag hyperlink if user's not currently setting the selection
+ {
+ SwContentAtPos aSwContentAtPos( IsAttrAtPos::InetAttr );
+ bStart = rSh.GetContentAtPos( aDocPos,
+ aSwContentAtPos );
+ }
+
+ if ( !bStart || m_bIsInDrag )
+ return;
+
+ // If the add selection mode has been pushed in the MouseButtonDown handler it needs to be
+ // popped or it will remain active and noticeable in the statusbar selection control until the
+ // next MouseButtonUp event after the DnD, since a MouseButtonUp event is not received by the
+ // edit window when DnD is done.
+ if (g_bModePushed)
+ {
+ rSh.PopMode();
+ g_bModePushed = false;
+ }
+
+ m_bMBPressed = false;
+ ReleaseMouse();
+ g_bFrameDrag = false;
+ g_bExecuteDrag = true;
+ SwEditWin::s_nDDStartPosY = aDocPos.Y();
+ SwEditWin::s_nDDStartPosX = aDocPos.X();
+ m_aMovePos = aDocPos;
+ StartExecuteDrag();
+ if( bDelSelect )
+ {
+ rSh.UnSelectFrame();
+ rSh.UnlockPaint();
+ }
+}
+
+void SwEditWin::StartExecuteDrag()
+{
+ if( !g_bExecuteDrag || m_bIsInDrag )
+ return;
+
+ m_bIsInDrag = true;
+
+ rtl::Reference<SwTransferable> pTransfer = new SwTransferable( m_rView.GetWrtShell() );
+
+ pTransfer->StartDrag( this, m_aMovePos );
+}
+
+void SwEditWin::DragFinished()
+{
+ DropCleanup();
+ m_aTimer.SetInvokeHandler( LINK(this,SwEditWin, TimerHandler) );
+ m_bIsInDrag = false;
+}
+
+void SwEditWin::DropCleanup()
+{
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+
+ // reset statuses
+ g_bNoInterrupt = false;
+ if ( m_bOldIdleSet )
+ {
+ rSh.GetViewOptions()->SetIdle( m_bOldIdle );
+ m_bOldIdleSet = false;
+ }
+ if ( m_pUserMarker )
+ CleanupDropUserMarker();
+ else
+ rSh.UnSetVisibleCursor();
+
+}
+
+void SwEditWin::CleanupDropUserMarker()
+{
+ if ( m_pUserMarker )
+ {
+ m_pUserMarker.reset();
+ m_pUserMarkerObj = nullptr;
+ }
+}
+
+//exhibition hack (MA,MBA)
+void SwView::SelectShellForDrop()
+{
+ if ( !GetCurShell() )
+ SelectShell();
+}
+
+sal_Int8 SwEditWin::ExecuteDrop( const ExecuteDropEvent& rEvt )
+{
+ GetView().SelectShellForDrop();
+ DropCleanup();
+ sal_Int8 nRet = DND_ACTION_NONE;
+
+ //A Drop to an open OutlinerView doesn't concern us (also see QueryDrop)
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ const Point aDocPt( PixelToLogic( rEvt.maPosPixel ));
+ SdrObject *pObj = nullptr;
+ OutlinerView* pOLV;
+ rSh.GetObjCntType( aDocPt, pObj );
+
+ if( pObj && nullptr != ( pOLV = rSh.GetDrawView()->GetTextEditOutlinerView() ))
+ {
+ tools::Rectangle aRect( pOLV->GetOutputArea() );
+ aRect.Union( pObj->GetLogicRect() );
+ const Point aPos = pOLV->GetWindow()->PixelToLogic(rEvt.maPosPixel);
+ if ( aRect.Contains(aPos) )
+ {
+ rSh.StartAllAction();
+ rSh.EndAllAction();
+ return nRet;
+ }
+ }
+
+ // There's a special treatment for file lists with a single
+ // element, that depends on the actual content of the
+ // Transferable to be accessible. Since the transferable
+ // may only be accessed after the drop has been accepted
+ // (according to KA due to Java D&D), we'll have to
+ // reevaluate the drop action once more _with_ the
+ // Transferable.
+ sal_uInt8 nEventAction;
+ sal_Int8 nUserOpt = rEvt.mbDefault ? EXCHG_IN_ACTION_DEFAULT
+ : rEvt.mnAction;
+ SotExchangeActionFlags nActionFlags;
+ m_nDropAction = SotExchange::GetExchangeAction(
+ GetDataFlavorExVector(),
+ m_nDropDestination,
+ rEvt.mnAction,
+ nUserOpt, m_nDropFormat, nEventAction, SotClipboardFormatId::NONE,
+ &rEvt.maDropEvent.Transferable,
+ &nActionFlags );
+
+ TransferableDataHelper aData( rEvt.maDropEvent.Transferable );
+ nRet = rEvt.mnAction;
+ if( !SwTransferable::PasteData( aData, rSh, m_nDropAction, nActionFlags, m_nDropFormat,
+ m_nDropDestination, false, rEvt.mbDefault, &aDocPt, nRet))
+ nRet = DND_ACTION_NONE;
+ else if ( SW_MOD()->m_pDragDrop )
+ //Don't clean up anymore at internal D&D!
+ SW_MOD()->m_pDragDrop->SetCleanUp( false );
+
+ return nRet;
+}
+
+SotExchangeDest SwEditWin::GetDropDestination( const Point& rPixPnt, SdrObject ** ppObj )
+{
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ const Point aDocPt( PixelToLogic( rPixPnt ) );
+ if (rSh.IsOverReadOnlyPos(aDocPt) || rSh.DocPtInsideInputField(aDocPt))
+ return SotExchangeDest::NONE;
+
+ SdrObject *pObj = nullptr;
+ const ObjCntType eType = rSh.GetObjCntType( aDocPt, pObj );
+
+ //Drop to OutlinerView (TextEdit in Drawing) should decide it on its own!
+ if( pObj )
+ {
+ OutlinerView* pOLV = rSh.GetDrawView()->GetTextEditOutlinerView();
+ if ( pOLV )
+ {
+ tools::Rectangle aRect( pOLV->GetOutputArea() );
+ aRect.Union( pObj->GetLogicRect() );
+ const Point aPos = pOLV->GetWindow()->PixelToLogic( rPixPnt );
+ if( aRect.Contains( aPos ) )
+ return SotExchangeDest::NONE;
+ }
+ }
+
+ //What do we want to drop on now?
+ SotExchangeDest nDropDestination = SotExchangeDest::NONE;
+
+ //Did anything else arrive from the DrawingEngine?
+ if( OBJCNT_NONE != eType )
+ {
+ switch ( eType )
+ {
+ case OBJCNT_GRF:
+ {
+ bool bLink,
+ bIMap = nullptr != rSh.GetFormatFromObj( aDocPt )->GetURL().GetMap();
+ OUString aDummy;
+ rSh.GetGrfAtPos( aDocPt, aDummy, bLink );
+ if ( bLink && bIMap )
+ nDropDestination = SotExchangeDest::DOC_LNKD_GRAPH_W_IMAP;
+ else if ( bLink )
+ nDropDestination = SotExchangeDest::DOC_LNKD_GRAPHOBJ;
+ else if ( bIMap )
+ nDropDestination = SotExchangeDest::DOC_GRAPH_W_IMAP;
+ else
+ nDropDestination = SotExchangeDest::DOC_GRAPHOBJ;
+ }
+ break;
+ case OBJCNT_FLY:
+ if( dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) != nullptr )
+ nDropDestination = SotExchangeDest::DOC_TEXTFRAME_WEB;
+ else
+ nDropDestination = SotExchangeDest::DOC_TEXTFRAME;
+ break;
+ case OBJCNT_OLE: nDropDestination = SotExchangeDest::DOC_OLEOBJ; break;
+ case OBJCNT_CONTROL: /* no Action avail */
+ case OBJCNT_SIMPLE: nDropDestination = SotExchangeDest::DOC_DRAWOBJ; break;
+ case OBJCNT_URLBUTTON: nDropDestination = SotExchangeDest::DOC_URLBUTTON; break;
+ case OBJCNT_GROUPOBJ: nDropDestination = SotExchangeDest::DOC_GROUPOBJ; break;
+
+ default: OSL_ENSURE( false, "new ObjectType?" );
+ }
+ }
+ if ( nDropDestination == SotExchangeDest::NONE )
+ {
+ if( dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) != nullptr )
+ nDropDestination = SotExchangeDest::SWDOC_FREE_AREA_WEB;
+ else
+ nDropDestination = SotExchangeDest::SWDOC_FREE_AREA;
+ }
+ if( ppObj )
+ *ppObj = pObj;
+ return nDropDestination;
+}
+
+sal_Int8 SwEditWin::AcceptDrop( const AcceptDropEvent& rEvt )
+{
+ if( rEvt.mbLeaving )
+ {
+ DropCleanup();
+ return rEvt.mnAction;
+ }
+
+ if( m_rView.GetDocShell()->IsReadOnly() )
+ return DND_ACTION_NONE;
+
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+
+ Point aPixPt( rEvt.maPosPixel );
+
+ // If the cursor is near the inner boundary
+ // we attempt to scroll towards the desired direction.
+ tools::Rectangle aWin(Point(), GetOutputSizePixel());
+ const int nMargin = 10;
+ aWin.AdjustLeft(nMargin );
+ aWin.AdjustTop(nMargin );
+ aWin.AdjustRight( -nMargin );
+ aWin.AdjustBottom( -nMargin );
+ if(!aWin.Contains(aPixPt)) {
+ static sal_uInt64 last_tick = 0;
+ sal_uInt64 current_tick = tools::Time::GetSystemTicks();
+ if((current_tick-last_tick) > 500) {
+ last_tick = current_tick;
+ if(!m_bOldIdleSet) {
+ m_bOldIdle = rSh.GetViewOptions()->IsIdle();
+ rSh.GetViewOptions()->SetIdle(false);
+ m_bOldIdleSet = true;
+ }
+ CleanupDropUserMarker();
+ if(aPixPt.X() > aWin.Right()) aPixPt.AdjustX(nMargin );
+ if(aPixPt.X() < aWin.Left()) aPixPt.AdjustX( -nMargin );
+ if(aPixPt.Y() > aWin.Bottom()) aPixPt.AdjustY(nMargin );
+ if(aPixPt.Y() < aWin.Top()) aPixPt.AdjustY( -nMargin );
+ Point aDocPt(PixelToLogic(aPixPt));
+ SwRect rect(aDocPt,Size(1,1));
+ rSh.MakeVisible(rect);
+ }
+ }
+
+ if(m_bOldIdleSet) {
+ rSh.GetViewOptions()->SetIdle( m_bOldIdle );
+ m_bOldIdleSet = false;
+ }
+
+ SdrObject *pObj = nullptr;
+ m_nDropDestination = GetDropDestination( aPixPt, &pObj );
+ if( m_nDropDestination == SotExchangeDest::NONE )
+ return DND_ACTION_NONE;
+
+ sal_uInt8 nEventAction;
+ sal_Int8 nUserOpt = rEvt.mbDefault ? EXCHG_IN_ACTION_DEFAULT
+ : rEvt.mnAction;
+
+ m_nDropAction = SotExchange::GetExchangeAction(
+ GetDataFlavorExVector(),
+ m_nDropDestination,
+ rEvt.mnAction,
+ nUserOpt, m_nDropFormat, nEventAction );
+
+ if( EXCHG_INOUT_ACTION_NONE != m_nDropAction )
+ {
+ const Point aDocPt( PixelToLogic( aPixPt ) );
+
+ //With the default action we still want to have a say.
+ SwModule *pMod = SW_MOD();
+ if( pMod->m_pDragDrop )
+ {
+ bool bCleanup = false;
+ //Drawing objects in Headers/Footers are not allowed
+
+ SwWrtShell *pSrcSh = pMod->m_pDragDrop->GetShell();
+ if( (pSrcSh->GetSelFrameType() == FrameTypeFlags::DRAWOBJ) &&
+ pSrcSh->IsSelContainsControl() &&
+ (rSh.GetFrameType( &aDocPt, false ) & (FrameTypeFlags::HEADER|FrameTypeFlags::FOOTER)) )
+ {
+ bCleanup = true;
+ }
+ // don't more position protected objects!
+ else if( DND_ACTION_MOVE == rEvt.mnAction &&
+ pSrcSh->IsSelObjProtected( FlyProtectFlags::Pos ) != FlyProtectFlags::NONE )
+ {
+ bCleanup = true;
+ }
+ else if( rEvt.mbDefault )
+ {
+ // internal Drag&Drop: within same Doc a Move
+ // otherwise a Copy - Task 54974
+ nEventAction = pSrcSh->GetDoc() == rSh.GetDoc()
+ ? DND_ACTION_MOVE
+ : DND_ACTION_COPY;
+ }
+ if ( bCleanup )
+ {
+ CleanupDropUserMarker();
+ rSh.UnSetVisibleCursor();
+ return DND_ACTION_NONE;
+ }
+ }
+ else
+ {
+ //D&D from outside of SW should be a Copy per default.
+ if( EXCHG_IN_ACTION_DEFAULT == nEventAction &&
+ DND_ACTION_MOVE == rEvt.mnAction )
+ nEventAction = DND_ACTION_COPY;
+
+ if( (SotClipboardFormatId::SBA_FIELDDATAEXCHANGE == m_nDropFormat &&
+ EXCHG_IN_ACTION_LINK == m_nDropAction) ||
+ SotClipboardFormatId::SBA_CTRLDATAEXCHANGE == m_nDropFormat )
+ {
+ SdrMarkView* pMView = rSh.GetDrawView();
+ if( pMView && !pMView->IsDesignMode() )
+ return DND_ACTION_NONE;
+ }
+ }
+
+ if ( EXCHG_IN_ACTION_DEFAULT != nEventAction )
+ nUserOpt = static_cast<sal_Int8>(nEventAction);
+
+ // show DropCursor or UserMarker ?
+ if( SotExchangeDest::SWDOC_FREE_AREA_WEB == m_nDropDestination ||
+ SotExchangeDest::SWDOC_FREE_AREA == m_nDropDestination )
+ {
+ CleanupDropUserMarker();
+ SwContentAtPos aCont( IsAttrAtPos::ContentCheck );
+ if(rSh.GetContentAtPos(aDocPt, aCont))
+ rSh.SwCursorShell::SetVisibleCursor( aDocPt );
+ }
+ else
+ {
+ rSh.UnSetVisibleCursor();
+
+ if ( m_pUserMarkerObj != pObj )
+ {
+ CleanupDropUserMarker();
+ m_pUserMarkerObj = pObj;
+
+ if(m_pUserMarkerObj)
+ {
+ m_pUserMarker.reset(new SdrDropMarkerOverlay( *rSh.GetDrawView(), *m_pUserMarkerObj ));
+ }
+ }
+ }
+ return nUserOpt;
+ }
+
+ CleanupDropUserMarker();
+ rSh.UnSetVisibleCursor();
+ return DND_ACTION_NONE;
+}
+
+IMPL_LINK_NOARG(SwEditWin, DDHandler, Timer *, void)
+{
+ g_bDDTimerStarted = false;
+ m_aTimer.Stop();
+ m_aTimer.SetTimeout(240);
+ m_bMBPressed = false;
+ ReleaseMouse();
+ g_bFrameDrag = false;
+ g_bExecuteDrag = true;
+ StartExecuteDrag();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx
new file mode 100644
index 0000000000..322928eb4e
--- /dev/null
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -0,0 +1,6897 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_wasm_strip.h>
+
+#include <swtypes.hxx>
+#include <hintids.hxx>
+
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/awt/PopupMenuDirection.hpp>
+#include <com/sun/star/awt/XPopupMenu.hpp>
+#include <com/sun/star/i18n/XBreakIterator.hpp>
+#include <com/sun/star/i18n/ScriptType.hpp>
+#include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
+#include <com/sun/star/i18n/UnicodeScript.hpp>
+#include <com/sun/star/i18n/XExtendedInputSequenceChecker.hpp>
+#include <com/sun/star/ui/ContextMenuExecuteEvent.hpp>
+
+#include <comphelper/scopeguard.hxx>
+#include <comphelper/string.hxx>
+
+#include <vcl/dialoghelper.hxx>
+#include <vcl/inputctx.hxx>
+#include <vcl/help.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/ptrstyle.hxx>
+#include <svl/macitem.hxx>
+#include <unotools/securityoptions.hxx>
+#include <basic/sbxvar.hxx>
+#include <svl/ctloptions.hxx>
+#include <basic/sbx.hxx>
+#include <svl/eitem.hxx>
+#include <svl/stritem.hxx>
+#include <sfx2/ipclient.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <svl/ptitem.hxx>
+#include <editeng/sizeitem.hxx>
+#include <editeng/langitem.hxx>
+#include <svx/statusitem.hxx>
+#include <svx/svdview.hxx>
+#include <svx/svdhdl.hxx>
+#include <svx/svdoutl.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/svxacorr.hxx>
+#include <editeng/flditem.hxx>
+#include <editeng/colritem.hxx>
+#include <unotools/charclass.hxx>
+#include <unotools/datetime.hxx>
+
+#include <comphelper/lok.hxx>
+#include <sfx2/lokhelper.hxx>
+
+#include <editeng/acorrcfg.hxx>
+#include <bookmark.hxx>
+#include <SwSmartTagMgr.hxx>
+#include <edtdd.hxx>
+#include <edtwin.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <textboxhelper.hxx>
+#include <dcontact.hxx>
+#include <fldbas.hxx>
+#include <swmodule.hxx>
+#include <docsh.hxx>
+#include <viewopt.hxx>
+#include <drawbase.hxx>
+#include <dselect.hxx>
+#include <textsh.hxx>
+#include <shdwcrsr.hxx>
+#include <txatbase.hxx>
+#include <fmtanchr.hxx>
+#include <fmtornt.hxx>
+#include <fmthdft.hxx>
+#include <frmfmt.hxx>
+#include <modcfg.hxx>
+#include <fmtcol.hxx>
+#include <wview.hxx>
+#include <gloslst.hxx>
+#include <inputwin.hxx>
+#include <gloshdl.hxx>
+#include <swundo.hxx>
+#include <drwtxtsh.hxx>
+#include <fchrfmt.hxx>
+#include "romenu.hxx"
+#include <initui.hxx>
+#include <frmatr.hxx>
+#include <extinput.hxx>
+#include <acmplwrd.hxx>
+#include <swcalwrp.hxx>
+#include <swdtflvr.hxx>
+#include <breakit.hxx>
+#include <checkit.hxx>
+#include <pagefrm.hxx>
+
+#include <helpids.h>
+#include <cmdid.h>
+#include <uitool.hxx>
+#include <fmtfollowtextflow.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <charfmt.hxx>
+#include <numrule.hxx>
+#include <pagedesc.hxx>
+#include <svtools/ruler.hxx>
+#include <formatclipboard.hxx>
+#include <vcl/svapp.hxx>
+#include <wordcountdialog.hxx>
+#include <fmtfld.hxx>
+
+#include <IMark.hxx>
+#include <doc.hxx>
+#include <xmloff/odffields.hxx>
+
+#include <PostItMgr.hxx>
+#include <FrameControlsManager.hxx>
+#include <AnnotationWin.hxx>
+
+#include <algorithm>
+#include <vector>
+
+#include <rootfrm.hxx>
+
+#include <unotools/syslocaleoptions.hxx>
+#include <i18nlangtag/mslangid.hxx>
+#include <salhelper/singletonref.hxx>
+#include <sfx2/event.hxx>
+#include <memory>
+
+#include "../../core/crsr/callnk.hxx"
+#include <IDocumentOutlineNodes.hxx>
+#include <ndtxt.hxx>
+#include <cntfrm.hxx>
+#include <txtfrm.hxx>
+#include <strings.hrc>
+#include <textcontentcontrol.hxx>
+#include <contentcontrolbutton.hxx>
+
+using namespace sw::mark;
+using namespace ::com::sun::star;
+
+/**
+ * Globals
+ */
+static bool g_bInputLanguageSwitched = false;
+
+// Usually in MouseButtonUp a selection is revoked when the selection is
+// not currently being pulled open. Unfortunately in MouseButtonDown there
+// is being selected at double/triple click. That selection is completely
+// finished in the Handler and thus can't be distinguished in the Up.
+// To resolve this g_bHoldSelection is set in Down and evaluated in Up.
+static bool g_bHoldSelection = false;
+
+bool g_bFrameDrag = false;
+static bool g_bValidCursorPos = false;
+bool g_bModePushed = false;
+bool g_bDDTimerStarted = false;
+bool g_bDDINetAttr = false;
+static SdrHdlKind g_eSdrMoveHdl = SdrHdlKind::User;
+
+QuickHelpData* SwEditWin::s_pQuickHlpData = nullptr;
+
+tools::Long SwEditWin::s_nDDStartPosY = 0;
+tools::Long SwEditWin::s_nDDStartPosX = 0;
+
+static SfxShell* lcl_GetTextShellFromDispatcher( SwView const & rView );
+
+/// Check if the selected shape has a TextBox: if so, go into that instead.
+static bool lcl_goIntoTextBox(SwEditWin& rEditWin, SwWrtShell& rSh)
+{
+ SdrMark* pMark = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0);
+ if (!pMark)
+ return false;
+
+ SdrObject* pSdrObject = pMark->GetMarkedSdrObj();
+ SwFrameFormat* pObjectFormat = ::FindFrameFormat(pSdrObject);
+ if (SwFrameFormat* pTextBoxFormat = SwTextBoxHelper::getOtherTextBoxFormat(pObjectFormat, RES_DRAWFRMFMT))
+ {
+ SdrObject* pTextBox = pTextBoxFormat->FindRealSdrObject();
+ SdrView* pSdrView = rSh.GetDrawView();
+ // Unmark the shape.
+ pSdrView->UnmarkAllObj();
+ // Mark the textbox.
+ rSh.SelectObj(Point(), SW_ALLOW_TEXTBOX, pTextBox);
+ // Clear the DrawFuncPtr.
+ rEditWin.StopInsFrame();
+ return true;
+ }
+ return false;
+}
+
+class SwAnchorMarker
+{
+ SdrHdl* m_pHdl;
+ Point m_aHdlPos;
+ Point m_aLastPos;
+ bool m_bTopRightHandle;
+public:
+ explicit SwAnchorMarker( SdrHdl* pH )
+ : m_pHdl( pH )
+ , m_aHdlPos( pH->GetPos() )
+ , m_aLastPos( pH->GetPos() )
+ , m_bTopRightHandle( pH->GetKind() == SdrHdlKind::Anchor_TR )
+ {}
+ const Point& GetLastPos() const { return m_aLastPos; }
+ void SetLastPos( const Point& rNew ) { m_aLastPos = rNew; }
+ void SetPos( const Point& rNew ) { m_pHdl->SetPos( rNew ); }
+ const Point& GetHdlPos() const { return m_aHdlPos; }
+ SdrHdl* GetHdl() const { return m_pHdl; }
+ void ChgHdl( SdrHdl* pNew )
+ {
+ m_pHdl = pNew;
+ if ( m_pHdl )
+ {
+ m_bTopRightHandle = (m_pHdl->GetKind() == SdrHdlKind::Anchor_TR);
+ }
+ }
+ Point GetPosForHitTest( const OutputDevice& rOut )
+ {
+ Point aHitTestPos( m_pHdl->GetPos() );
+ aHitTestPos = rOut.LogicToPixel( aHitTestPos );
+ if ( m_bTopRightHandle )
+ {
+ aHitTestPos += Point( -1, 1 );
+ }
+ else
+ {
+ aHitTestPos += Point( 1, 1 );
+ }
+ aHitTestPos = rOut.PixelToLogic( aHitTestPos );
+
+ return aHitTestPos;
+ }
+};
+
+/// Assists with auto-completion of AutoComplete words and AutoText names.
+struct QuickHelpData
+{
+ /// Strings that at least partially match an input word, and match length.
+ std::vector<std::pair<OUString, sal_uInt16>> m_aHelpStrings;
+ /// Index of the current help string.
+ sal_uInt16 nCurArrPos;
+ static constexpr sal_uInt16 nNoPos = std::numeric_limits<sal_uInt16>::max();
+
+ /// Help data stores AutoText names rather than AutoComplete words.
+ bool m_bIsAutoText;
+ /// Display help string as a tip rather than inline.
+ bool m_bIsTip;
+ /// Tip ID when a help string is displayed as a tip.
+ void* nTipId;
+ /// Append a space character to the displayed help string (if appropriate).
+ bool m_bAppendSpace;
+
+ /// Help string is currently displayed.
+ bool m_bIsDisplayed;
+
+ QuickHelpData() { ClearContent(); }
+
+ void Move( QuickHelpData& rCpy );
+ void ClearContent();
+ void Start(SwWrtShell& rSh, bool bRestart);
+ void Stop( SwWrtShell& rSh );
+
+ bool HasContent() const { return !m_aHelpStrings.empty() && nCurArrPos != nNoPos; }
+ const OUString& CurStr() const { return m_aHelpStrings[nCurArrPos].first; }
+ sal_uInt16 CurLen() const { return m_aHelpStrings[nCurArrPos].second; }
+
+ /// Next help string.
+ void Next( bool bEndLess )
+ {
+ if( ++nCurArrPos >= m_aHelpStrings.size() )
+ nCurArrPos = (bEndLess && !m_bIsAutoText ) ? 0 : nCurArrPos-1;
+ }
+ /// Previous help string.
+ void Previous( bool bEndLess )
+ {
+ if( 0 == nCurArrPos-- )
+ nCurArrPos = (bEndLess && !m_bIsAutoText ) ? m_aHelpStrings.size()-1 : 0;
+ }
+
+ // Fills internal structures with hopefully helpful information.
+ void FillStrArr( SwWrtShell const & rSh, const OUString& rWord );
+ void SortAndFilter(const OUString &rOrigWord);
+};
+
+/**
+ * Avoid minimal movement shiver
+ */
+#define HIT_PIX 2 /* hit tolerance in pixel */
+#define MIN_MOVE 4
+
+static bool IsMinMove(const Point &rStartPos, const Point &rLPt)
+{
+ return std::abs(rStartPos.X() - rLPt.X()) > MIN_MOVE ||
+ std::abs(rStartPos.Y() - rLPt.Y()) > MIN_MOVE;
+}
+
+/**
+ * For MouseButtonDown - determine whether a DrawObject
+ * a NO SwgFrame was hit! Shift/Ctrl should only result
+ * in selecting, with DrawObjects; at SwgFlys to trigger
+ * hyperlinks if applicable (Download/NewWindow!)
+ */
+static bool IsDrawObjSelectable( const SwWrtShell& rSh, const Point& rPt )
+{
+ bool bRet = true;
+ SdrObject* pObj;
+ switch( rSh.GetObjCntType( rPt, pObj ))
+ {
+ case OBJCNT_NONE:
+ case OBJCNT_FLY:
+ case OBJCNT_GRF:
+ case OBJCNT_OLE:
+ bRet = false;
+ break;
+ default:; //prevent warning
+ }
+ return bRet;
+}
+
+/*
+ * Switch pointer
+ */
+void SwEditWin::UpdatePointer(const Point &rLPt, sal_uInt16 nModifier )
+{
+ SetQuickHelpText(OUString());
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ if( m_pApplyTempl )
+ {
+ PointerStyle eStyle = PointerStyle::Fill;
+ if ( rSh.IsOverReadOnlyPos( rLPt ) )
+ {
+ m_pUserMarker.reset();
+
+ eStyle = PointerStyle::NotAllowed;
+ }
+ else
+ {
+ SwRect aRect;
+ SwRect* pRect = &aRect;
+ const SwFrameFormat* pFormat = nullptr;
+
+ bool bFrameIsValidTarget = false;
+ if( m_pApplyTempl->m_pFormatClipboard )
+ bFrameIsValidTarget = m_pApplyTempl->m_pFormatClipboard->HasContentForThisType( SelectionType::Frame );
+ else if( !m_pApplyTempl->nColor )
+ bFrameIsValidTarget = ( m_pApplyTempl->eType == SfxStyleFamily::Frame );
+
+ if( bFrameIsValidTarget &&
+ nullptr !=(pFormat = rSh.GetFormatFromObj( rLPt, &pRect )) &&
+ dynamic_cast<const SwFlyFrameFormat*>( pFormat) )
+ {
+ //turn on highlight for frame
+ tools::Rectangle aTmp( pRect->SVRect() );
+
+ if ( !m_pUserMarker )
+ {
+ m_pUserMarker.reset(new SdrDropMarkerOverlay( *rSh.GetDrawView(), aTmp ));
+ }
+ }
+ else
+ {
+ m_pUserMarker.reset();
+ }
+
+ rSh.SwCursorShell::SetVisibleCursor( rLPt );
+ }
+ SetPointer( eStyle );
+ return;
+ }
+
+ if( !rSh.VisArea().Width() )
+ return;
+
+ CurrShell aCurr(&rSh);
+
+ if ( IsChainMode() )
+ {
+ SwRect aRect;
+ SwChainRet nChainable = rSh.Chainable( aRect, *rSh.GetFlyFrameFormat(), rLPt );
+ PointerStyle eStyle = nChainable != SwChainRet::OK
+ ? PointerStyle::ChainNotAllowed : PointerStyle::Chain;
+ if ( nChainable == SwChainRet::OK )
+ {
+ tools::Rectangle aTmp( aRect.SVRect() );
+
+ if ( !m_pUserMarker )
+ {
+ m_pUserMarker.reset(new SdrDropMarkerOverlay( *rSh.GetDrawView(), aTmp ));
+ }
+ }
+ else
+ {
+ m_pUserMarker.reset();
+ }
+
+ SetPointer( eStyle );
+ return;
+ }
+
+ bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
+ if ( !bExecHyperlinks )
+ {
+ const bool bSecureOption = SvtSecurityOptions::IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink );
+ if ( ( bSecureOption && nModifier == KEY_MOD1 ) ||
+ ( !bSecureOption && nModifier != KEY_MOD1 ) )
+ bExecHyperlinks = true;
+ }
+
+ const bool bExecSmarttags = nModifier == KEY_MOD1;
+
+ SdrView *pSdrView = rSh.GetDrawView();
+ bool bPrefSdrPointer = false;
+ bool bHitHandle = false;
+ bool bCntAtPos = false;
+ bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
+ rSh.IsCursorReadonly();
+ m_aActHitType = SdrHitKind::NONE;
+ PointerStyle eStyle = PointerStyle::Text;
+ if ( !pSdrView )
+ bCntAtPos = true;
+ else if ( (bHitHandle = (pSdrView->PickHandle(rLPt) != nullptr)) )
+ {
+ m_aActHitType = SdrHitKind::Object;
+ bPrefSdrPointer = true;
+ }
+ else
+ {
+ const bool bNotInSelObj = !rSh.IsInsideSelectedObj( rLPt );
+ if ( m_rView.GetDrawFuncPtr() && !m_bInsDraw && bNotInSelObj )
+ {
+ m_aActHitType = SdrHitKind::Object;
+ if (IsObjectSelect())
+ eStyle = PointerStyle::Arrow;
+ else
+ bPrefSdrPointer = true;
+ }
+ else
+ {
+ SdrPageView* pPV = nullptr;
+ pSdrView->SetHitTolerancePixel( HIT_PIX );
+ SdrObject* pObj = (bNotInSelObj && bExecHyperlinks) ?
+ pSdrView->PickObj(rLPt, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::PICKMACRO) :
+ nullptr;
+ if (pObj)
+ {
+ SdrObjMacroHitRec aTmp;
+ aTmp.aPos = rLPt;
+ aTmp.pPageView = pPV;
+ SetPointer( pObj->GetMacroPointer( aTmp ) );
+ return;
+ }
+ else
+ {
+ // dvo: IsObjSelectable() eventually calls SdrView::PickObj, so
+ // apparently this is used to determine whether this is a
+ // drawling layer object or not.
+ if ( rSh.IsObjSelectable( rLPt ) )
+ {
+ if (pSdrView->IsTextEdit())
+ {
+ m_aActHitType = SdrHitKind::NONE;
+ bPrefSdrPointer = true;
+ }
+ else
+ {
+ SdrViewEvent aVEvt;
+ SdrHitKind eHit = pSdrView->PickAnything(rLPt, aVEvt);
+
+ if (eHit == SdrHitKind::UrlField && bExecHyperlinks)
+ {
+ m_aActHitType = SdrHitKind::Object;
+ bPrefSdrPointer = true;
+ }
+ else
+ {
+ // if we're over a selected object, we show an
+ // ARROW by default. We only show a MOVE if 1) the
+ // object is selected, and 2) it may be moved
+ // (i.e., position is not protected).
+ bool bMovable =
+ (!bNotInSelObj) &&
+ (rSh.IsObjSelected() || rSh.IsFrameSelected()) &&
+ (rSh.IsSelObjProtected(FlyProtectFlags::Pos) == FlyProtectFlags::NONE);
+
+ SdrObject* pSelectableObj = rSh.GetObjAt(rLPt);
+ // Don't update pointer if this is a background image only.
+ if (pSelectableObj->GetLayer() != rSh.GetDoc()->getIDocumentDrawModelAccess().GetHellId())
+ eStyle = bMovable ? PointerStyle::Move : PointerStyle::Arrow;
+ m_aActHitType = SdrHitKind::Object;
+ }
+ }
+ }
+ else
+ {
+ if ( rSh.IsFrameSelected() && !bNotInSelObj )
+ {
+ // dvo: this branch appears to be dead and should be
+ // removed in a future version. Reason: The condition
+ // !bNotInSelObj means that this branch will only be
+ // executed in the cursor points inside a selected
+ // object. However, if this is the case, the previous
+ // if( rSh.IsObjSelectable(rLPt) ) must always be true:
+ // rLPt is inside a selected object, then obviously
+ // rLPt is over a selectable object.
+ if (rSh.IsSelObjProtected(FlyProtectFlags::Size) != FlyProtectFlags::NONE)
+ eStyle = PointerStyle::NotAllowed;
+ else
+ eStyle = PointerStyle::Move;
+ m_aActHitType = SdrHitKind::Object;
+ }
+ else
+ {
+ if ( m_rView.GetDrawFuncPtr() )
+ bPrefSdrPointer = true;
+ else
+ bCntAtPos = true;
+ }
+ }
+ }
+ }
+ }
+ if ( bPrefSdrPointer )
+ {
+ if (bIsDocReadOnly || (rSh.IsObjSelected() && rSh.IsSelObjProtected(FlyProtectFlags::Content) != FlyProtectFlags::NONE))
+ SetPointer( PointerStyle::NotAllowed );
+ else
+ {
+ if (m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->IsInsertForm() && !bHitHandle)
+ SetPointer( PointerStyle::DrawRect );
+ else
+ SetPointer( pSdrView->GetPreferredPointer( rLPt, rSh.GetOut() ) );
+ }
+ }
+ else
+ {
+ if( !rSh.IsPageAtPos( rLPt ) || m_pAnchorMarker )
+ eStyle = PointerStyle::Arrow;
+ else
+ {
+ // Even if we already have something, prefer URLs if possible.
+ SwContentAtPos aUrlPos(IsAttrAtPos::InetAttr);
+ if (bCntAtPos || rSh.GetContentAtPos(rLPt, aUrlPos))
+ {
+ SwContentAtPos aSwContentAtPos(
+ IsAttrAtPos::Field |
+ IsAttrAtPos::ClickField |
+ IsAttrAtPos::InetAttr |
+ IsAttrAtPos::Ftn |
+ IsAttrAtPos::SmartTag);
+ if( rSh.GetContentAtPos( rLPt, aSwContentAtPos) )
+ {
+ // Is edit inline input field
+ if (IsAttrAtPos::Field == aSwContentAtPos.eContentAtPos
+ && aSwContentAtPos.pFndTextAttr != nullptr
+ && aSwContentAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD)
+ {
+ const SwField *pCursorField = rSh.CursorInsideInputField() ? rSh.GetCurField( true ) : nullptr;
+ if (!(pCursorField && pCursorField == aSwContentAtPos.pFndTextAttr->GetFormatField().GetField()))
+ eStyle = PointerStyle::RefHand;
+ }
+ else
+ {
+ const bool bClickToFollow = IsAttrAtPos::InetAttr == aSwContentAtPos.eContentAtPos ||
+ IsAttrAtPos::SmartTag == aSwContentAtPos.eContentAtPos;
+ if( !bClickToFollow ||
+ (IsAttrAtPos::InetAttr == aSwContentAtPos.eContentAtPos && bExecHyperlinks) ||
+ (IsAttrAtPos::SmartTag == aSwContentAtPos.eContentAtPos && bExecSmarttags) )
+ eStyle = PointerStyle::RefHand;
+ }
+ }
+ else if (GetView().GetWrtShell().GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ {
+ aSwContentAtPos.eContentAtPos = IsAttrAtPos::Outline;
+ if (rSh.GetContentAtPos(rLPt, aSwContentAtPos))
+ {
+ if (IsAttrAtPos::Outline == aSwContentAtPos.eContentAtPos)
+ {
+ if (nModifier == KEY_MOD1)
+ {
+ eStyle = PointerStyle::RefHand;
+ // set quick help
+ if(aSwContentAtPos.aFnd.pNode && aSwContentAtPos.aFnd.pNode->IsTextNode())
+ {
+ const SwNodes& rNds = GetView().GetWrtShell().GetDoc()->GetNodes();
+ SwOutlineNodes::size_type nPos;
+ rNds.GetOutLineNds().Seek_Entry(aSwContentAtPos.aFnd.pNode->GetTextNode(), &nPos);
+ SwOutlineNodes::size_type nOutlineNodesCount
+ = rSh.getIDocumentOutlineNodesAccess()->getOutlineNodesCount();
+ int nLevel = rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos);
+ OUString sQuickHelp(SwResId(STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY));
+ if (!rSh.GetViewOptions()->IsTreatSubOutlineLevelsAsContent()
+ && nPos + 1 < nOutlineNodesCount
+ && rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos + 1) > nLevel)
+ sQuickHelp += " (" + SwResId(STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT) + ")";
+ SetQuickHelpText(sQuickHelp);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // which kind of text pointer have we to show - horz / vert - ?
+ if( PointerStyle::Text == eStyle && rSh.IsInVerticalText( &rLPt ))
+ eStyle = PointerStyle::TextVertical;
+ else if (rSh.GetViewOptions()->CanHideWhitespace() &&
+ rSh.GetLayout()->IsBetweenPages(rLPt))
+ {
+ if (rSh.GetViewOptions()->IsHideWhitespaceMode())
+ eStyle = PointerStyle::ShowWhitespace;
+ else
+ eStyle = PointerStyle::HideWhitespace;
+ }
+
+ if( m_pShadCursor )
+ {
+ if( text::HoriOrientation::LEFT == m_eOrient ) // Arrow to the right
+ eStyle = PointerStyle::AutoScrollE;
+ else // Arrow to the left
+ eStyle = PointerStyle::AutoScrollW;
+ }
+
+ SetPointer( eStyle );
+ }
+}
+
+/**
+ * Increase timer for selection
+ */
+IMPL_LINK_NOARG(SwEditWin, TimerHandler, Timer *, void)
+{
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ Point aModPt( m_aMovePos );
+ const SwRect aOldVis( rSh.VisArea() );
+ bool bDone = false;
+
+ if ( !rSh.VisArea().Contains( aModPt ) )
+ {
+ if ( m_bInsDraw )
+ {
+ const int nMaxScroll = 40;
+ m_rView.Scroll( tools::Rectangle(aModPt,Size(1,1)), nMaxScroll, nMaxScroll);
+ bDone = true;
+ }
+ else if ( g_bFrameDrag )
+ {
+ rSh.Drag(&aModPt, false);
+ bDone = true;
+ }
+ if ( !bDone )
+ aModPt = rSh.GetContentPos( aModPt,aModPt.Y() > rSh.VisArea().Bottom() );
+ }
+ if ( !bDone && !(g_bFrameDrag || m_bInsDraw) )
+ {
+ if ( m_xRowColumnSelectionStart )
+ {
+ Point aPos( aModPt );
+ rSh.SelectTableRowCol( *m_xRowColumnSelectionStart, &aPos, m_bIsRowDrag );
+ }
+ else
+ rSh.CallSetCursor( &aModPt, false );
+
+ // It can be that a "jump" over a table cannot be accomplished like
+ // that. So we jump over the table by Up/Down here.
+ const SwRect& rVisArea = rSh.VisArea();
+ if( aOldVis == rVisArea && !rSh.IsStartOfDoc() && !rSh.IsEndOfDoc() )
+ {
+ // take the center point of VisArea to
+ // decide in which direction the user want.
+ if( aModPt.Y() < ( rVisArea.Top() + rVisArea.Height() / 2 ) )
+ rSh.Up( true );
+ else
+ rSh.Down( true );
+ }
+ }
+
+ m_aMovePos += rSh.VisArea().Pos() - aOldVis.Pos();
+ JustifyAreaTimer();
+}
+
+void SwEditWin::JustifyAreaTimer()
+{
+ const tools::Rectangle &rVisArea = GetView().GetVisArea();
+#ifdef UNX
+ const tools::Long coMinLen = 100;
+#else
+ const tools::Long coMinLen = 50;
+#endif
+ tools::Long const nTimeout = 800,
+ nDiff = std::max(
+ std::max( m_aMovePos.Y() - rVisArea.Bottom(), rVisArea.Top() - m_aMovePos.Y() ),
+ std::max( m_aMovePos.X() - rVisArea.Right(), rVisArea.Left() - m_aMovePos.X()));
+ m_aTimer.SetTimeout( std::max( coMinLen, nTimeout - nDiff*2L) );
+}
+
+void SwEditWin::LeaveArea(const Point &rPos)
+{
+ m_aMovePos = rPos;
+ JustifyAreaTimer();
+ if( !m_aTimer.IsActive() )
+ m_aTimer.Start();
+ m_pShadCursor.reset();
+}
+
+inline void SwEditWin::EnterArea()
+{
+ m_aTimer.Stop();
+}
+
+/**
+ * Insert mode for frames
+ */
+void SwEditWin::InsFrame(sal_uInt16 nCols)
+{
+ StdDrawMode(SdrObjKind::NewFrame, false);
+ m_bInsFrame = true;
+ m_nInsFrameColCount = nCols;
+}
+
+void SwEditWin::StdDrawMode( SdrObjKind eSdrObjectKind, bool bObjSelect )
+{
+ SetSdrDrawMode( eSdrObjectKind );
+
+ if (bObjSelect)
+ m_rView.SetDrawFuncPtr(std::make_unique<DrawSelection>( &m_rView.GetWrtShell(), this, &m_rView ));
+ else
+ m_rView.SetDrawFuncPtr(std::make_unique<SwDrawBase>( &m_rView.GetWrtShell(), this, &m_rView ));
+
+ m_rView.SetSelDrawSlot();
+ SetSdrDrawMode( eSdrObjectKind );
+ if (bObjSelect)
+ m_rView.GetDrawFuncPtr()->Activate( SID_OBJECT_SELECT );
+ else
+ m_rView.GetDrawFuncPtr()->Activate( sal::static_int_cast< sal_uInt16 >(eSdrObjectKind) );
+ m_bInsFrame = false;
+ m_nInsFrameColCount = 1;
+}
+
+void SwEditWin::StopInsFrame()
+{
+ if (m_rView.GetDrawFuncPtr())
+ {
+ m_rView.GetDrawFuncPtr()->Deactivate();
+ m_rView.SetDrawFuncPtr(nullptr);
+ }
+ m_rView.LeaveDrawCreate(); // leave construction mode
+ m_bInsFrame = false;
+ m_nInsFrameColCount = 1;
+}
+
+bool SwEditWin::IsInputSequenceCheckingRequired( const OUString &rText, const SwPaM& rCursor )
+{
+ if ( !SvtCTLOptions::IsCTLFontEnabled() ||
+ !SvtCTLOptions::IsCTLSequenceChecking() )
+ return false;
+
+ if ( 0 == rCursor.Start()->GetContentIndex() ) /* first char needs not to be checked */
+ return false;
+
+ SwBreakIt *pBreakIter = SwBreakIt::Get();
+ uno::Reference < i18n::XBreakIterator > xBI = pBreakIter->GetBreakIter();
+ assert(xBI.is());
+ tools::Long nCTLScriptPos = -1;
+
+ if (xBI->getScriptType( rText, 0 ) == i18n::ScriptType::COMPLEX)
+ nCTLScriptPos = 0;
+ else
+ nCTLScriptPos = xBI->nextScript( rText, 0, i18n::ScriptType::COMPLEX );
+
+ return (0 <= nCTLScriptPos && nCTLScriptPos <= rText.getLength());
+}
+
+//return INVALID_HINT if language should not be explicitly overridden, the correct
+//HintId to use for the eBufferLanguage otherwise
+static sal_uInt16 lcl_isNonDefaultLanguage(LanguageType eBufferLanguage, SwView const & rView,
+ const OUString &rInBuffer)
+{
+ sal_uInt16 nWhich = INVALID_HINT;
+
+ //If the option to IgnoreLanguageChange is set, short-circuit this method
+ //which results in the document/paragraph language remaining the same
+ //despite a change to the keyboard/input language
+ SvtSysLocaleOptions aSysLocaleOptions;
+ if(aSysLocaleOptions.IsIgnoreLanguageChange())
+ {
+ return INVALID_HINT;
+ }
+
+ bool bLang = true;
+ if(eBufferLanguage != LANGUAGE_DONTKNOW)
+ {
+ switch( SvtLanguageOptions::GetI18NScriptTypeOfLanguage( eBufferLanguage ))
+ {
+ case i18n::ScriptType::ASIAN: nWhich = RES_CHRATR_CJK_LANGUAGE; break;
+ case i18n::ScriptType::COMPLEX: nWhich = RES_CHRATR_CTL_LANGUAGE; break;
+ case i18n::ScriptType::LATIN: nWhich = RES_CHRATR_LANGUAGE; break;
+ default: bLang = false;
+ }
+ if(bLang)
+ {
+ SfxItemSet aLangSet(rView.GetPool(), nWhich, nWhich);
+ SwWrtShell& rSh = rView.GetWrtShell();
+ rSh.GetCurAttr(aLangSet);
+ if(SfxItemState::DEFAULT <= aLangSet.GetItemState(nWhich))
+ {
+ LanguageType eLang = static_cast<const SvxLanguageItem&>(aLangSet.Get(nWhich)).GetLanguage();
+ if ( eLang == eBufferLanguage )
+ {
+ // current language attribute equal to language reported from system
+ bLang = false;
+ }
+ else if ( !g_bInputLanguageSwitched && RES_CHRATR_LANGUAGE == nWhich )
+ {
+ // special case: switching between two "LATIN" languages
+ // In case the current keyboard setting might be suitable
+ // for both languages we can't safely assume that the user
+ // wants to use the language reported from the system,
+ // except if we knew that it was explicitly switched (thus
+ // the check for "bInputLangeSwitched").
+
+ // The language reported by the system could be just the
+ // system default language that the user is not even aware
+ // of, because no language selection tool is installed at
+ // all. In this case the OOo language should get preference
+ // as it might have been selected by the user explicitly.
+
+ // Usually this case happens if the OOo language is
+ // different to the system language but the system keyboard
+ // is still suitable for the OOo language (e.g. writing
+ // English texts with a German keyboard).
+
+ // For non-latin keyboards overwriting the attribute is
+ // still valid. We do this for cyrillic and greek ATM. In
+ // future versions of OOo this should be replaced by a
+ // configuration switch that allows to give the preference
+ // to the OOo setting or the system setting explicitly
+ // and/or a better handling of the script type.
+ i18n::UnicodeScript eType = !rInBuffer.isEmpty() ?
+ GetAppCharClass().getScript( rInBuffer, 0 ) :
+ i18n::UnicodeScript_kScriptCount;
+
+ bool bSystemIsNonLatin = false;
+ switch ( eType )
+ {
+ case i18n::UnicodeScript_kGreek:
+ case i18n::UnicodeScript_kCyrillic:
+ // in case other UnicodeScripts require special
+ // keyboards they can be added here
+ bSystemIsNonLatin = true;
+ break;
+ default:
+ break;
+ }
+
+ bool bOOoLangIsNonLatin = MsLangId::isNonLatinWestern( eLang);
+
+ bLang = (bSystemIsNonLatin != bOOoLangIsNonLatin);
+ }
+ }
+ }
+ }
+ return bLang ? nWhich : INVALID_HINT;
+}
+
+/**
+ * Character buffer is inserted into the document
+ */
+void SwEditWin::FlushInBuffer()
+{
+ if ( m_aKeyInputFlushTimer.IsActive())
+ m_aKeyInputFlushTimer.Stop();
+
+ if ( m_aInBuffer.isEmpty() )
+ return;
+
+ SwWrtShell& rSh = m_rView.GetWrtShell();
+
+ // generate new sequence input checker if not already done
+ if ( !pCheckIt )
+ pCheckIt = new SwCheckIt;
+
+ uno::Reference < i18n::XExtendedInputSequenceChecker > xISC = pCheckIt->xCheck;
+ if ( xISC.is() && IsInputSequenceCheckingRequired( m_aInBuffer, *rSh.GetCursor() ) )
+ {
+
+ // apply (Thai) input sequence checking/correction
+
+ rSh.Push(); // push current cursor to stack
+
+ // get text from the beginning (i.e left side) of current selection
+ // to the start of the paragraph
+ rSh.NormalizePam(); // make point be the first (left) one
+ if (!rSh.GetCursor()->HasMark())
+ rSh.GetCursor()->SetMark();
+ rSh.GetCursor()->GetMark()->SetContent(0);
+
+ const OUString aOldText( rSh.GetCursor()->GetText() );
+ const sal_Int32 nOldLen = aOldText.getLength();
+
+ sal_Int32 nExpandSelection = 0;
+ if (nOldLen > 0)
+ {
+ sal_Int32 nTmpPos = nOldLen;
+ sal_Int16 nCheckMode = SvtCTLOptions::IsCTLSequenceCheckingRestricted() ?
+ i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC;
+
+ OUString aNewText( aOldText );
+ if (SvtCTLOptions::IsCTLSequenceCheckingTypeAndReplace())
+ {
+ for( sal_Int32 k = 0; k < m_aInBuffer.getLength(); ++k)
+ {
+ const sal_Unicode cChar = m_aInBuffer[k];
+ const sal_Int32 nPrevPos =xISC->correctInputSequence( aNewText, nTmpPos - 1, cChar, nCheckMode );
+
+ // valid sequence or sequence could be corrected:
+ if (nPrevPos != aNewText.getLength())
+ nTmpPos = nPrevPos + 1;
+ }
+
+ // find position of first character that has changed
+ sal_Int32 nNewLen = aNewText.getLength();
+ const sal_Unicode *pOldText = aOldText.getStr();
+ const sal_Unicode *pNewText = aNewText.getStr();
+ sal_Int32 nChgPos = 0;
+ while ( nChgPos < nOldLen && nChgPos < nNewLen &&
+ pOldText[nChgPos] == pNewText[nChgPos] )
+ ++nChgPos;
+
+ const sal_Int32 nChgLen = nNewLen - nChgPos;
+ if (nChgLen)
+ {
+ m_aInBuffer = aNewText.copy( nChgPos, nChgLen );
+ nExpandSelection = nOldLen - nChgPos;
+ }
+ else
+ m_aInBuffer.clear();
+ }
+ else
+ {
+ for( sal_Int32 k = 0; k < m_aInBuffer.getLength(); ++k )
+ {
+ const sal_Unicode cChar = m_aInBuffer[k];
+ if (xISC->checkInputSequence( aNewText, nTmpPos - 1, cChar, nCheckMode ))
+ {
+ // character can be inserted:
+ aNewText += OUStringChar( cChar );
+ ++nTmpPos;
+ }
+ }
+ m_aInBuffer = aNewText.copy( aOldText.getLength() ); // copy new text to be inserted to buffer
+ }
+ }
+
+ // at this point now we will insert the buffer text 'normally' some lines below...
+
+ rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+
+ if (m_aInBuffer.isEmpty())
+ return;
+
+ // if text prior to the original selection needs to be changed
+ // as well, we now expand the selection accordingly.
+ SwPaM &rCursor = *rSh.GetCursor();
+ const sal_Int32 nCursorStartPos = rCursor.Start()->GetContentIndex();
+ OSL_ENSURE( nCursorStartPos >= nExpandSelection, "cannot expand selection as specified!!" );
+ if (nExpandSelection && nCursorStartPos >= nExpandSelection)
+ {
+ if (!rCursor.HasMark())
+ rCursor.SetMark();
+ rCursor.Start()->AdjustContent( -nExpandSelection );
+ }
+ }
+
+ uno::Reference< frame::XDispatchRecorder > xRecorder =
+ m_rView.GetViewFrame().GetBindings().GetRecorder();
+ if ( xRecorder.is() )
+ {
+ // determine shell
+ SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView );
+ // generate request and record
+ if (pSfxShell)
+ {
+ SfxRequest aReq(m_rView.GetViewFrame(), FN_INSERT_STRING);
+ aReq.AppendItem( SfxStringItem( FN_INSERT_STRING, m_aInBuffer ) );
+ aReq.Done();
+ }
+ }
+
+ sal_uInt16 nWhich = lcl_isNonDefaultLanguage(m_eBufferLanguage, m_rView, m_aInBuffer);
+ if (nWhich != INVALID_HINT )
+ {
+ SvxLanguageItem aLangItem( m_eBufferLanguage, nWhich );
+ rSh.SetAttrItem( aLangItem );
+ }
+
+ rSh.Insert( m_aInBuffer );
+ m_eBufferLanguage = LANGUAGE_DONTKNOW;
+ m_aInBuffer.clear();
+}
+
+#define MOVE_LEFT_SMALL 0
+#define MOVE_UP_SMALL 1
+#define MOVE_RIGHT_BIG 2
+#define MOVE_DOWN_BIG 3
+#define MOVE_LEFT_BIG 4
+#define MOVE_UP_BIG 5
+#define MOVE_RIGHT_SMALL 6
+#define MOVE_DOWN_SMALL 7
+
+// #i121236# Support for shift key in writer
+#define MOVE_LEFT_HUGE 8
+#define MOVE_UP_HUGE 9
+#define MOVE_RIGHT_HUGE 10
+#define MOVE_DOWN_HUGE 11
+
+void SwEditWin::ChangeFly( sal_uInt8 nDir, bool bWeb )
+{
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ SwRect aTmp = rSh.GetFlyRect();
+ if( !aTmp.HasArea() ||
+ rSh.IsSelObjProtected( FlyProtectFlags::Pos ) != FlyProtectFlags::NONE )
+ return;
+
+ SfxItemSetFixed<
+ RES_FRM_SIZE, RES_FRM_SIZE,
+ RES_PROTECT, RES_PROTECT,
+ RES_VERT_ORIENT, RES_ANCHOR,
+ RES_COL, RES_COL,
+ RES_FOLLOW_TEXT_FLOW, RES_FOLLOW_TEXT_FLOW>
+ aSet( rSh.GetAttrPool() );
+ rSh.GetFlyFrameAttr( aSet );
+ RndStdIds eAnchorId = aSet.Get(RES_ANCHOR).GetAnchorId();
+ Size aSnap;
+ bool bHuge(MOVE_LEFT_HUGE == nDir ||
+ MOVE_UP_HUGE == nDir ||
+ MOVE_RIGHT_HUGE == nDir ||
+ MOVE_DOWN_HUGE == nDir);
+
+ if(MOVE_LEFT_SMALL == nDir ||
+ MOVE_UP_SMALL == nDir ||
+ MOVE_RIGHT_SMALL == nDir ||
+ MOVE_DOWN_SMALL == nDir )
+ {
+ aSnap = PixelToLogic(Size(1,1));
+ }
+ else
+ {
+ aSnap = rSh.GetViewOptions()->GetSnapSize();
+ short nDiv = rSh.GetViewOptions()->GetDivisionX();
+ if ( nDiv > 0 )
+ aSnap.setWidth( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Width()) / nDiv ) );
+ nDiv = rSh.GetViewOptions()->GetDivisionY();
+ if ( nDiv > 0 )
+ aSnap.setHeight( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Height()) / nDiv ) );
+ }
+
+ if(bHuge)
+ {
+ // #i121236# 567twips == 1cm, but just take three times the normal snap
+ aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3);
+ }
+
+ SwRect aBoundRect;
+ Point aRefPoint;
+ // adjustment for allowing vertical position
+ // aligned to page for fly frame anchored to paragraph or to character.
+ {
+ const SwFormatVertOrient& aVert( aSet.Get(RES_VERT_ORIENT) );
+ const bool bFollowTextFlow =
+ aSet.Get(RES_FOLLOW_TEXT_FLOW).GetValue();
+ const SwFormatAnchor& rFormatAnchor = aSet.Get(RES_ANCHOR);
+ rSh.CalcBoundRect( aBoundRect, eAnchorId,
+ text::RelOrientation::FRAME, aVert.GetRelationOrient(),
+ &rFormatAnchor, bFollowTextFlow,
+ false, &aRefPoint );
+ }
+ tools::Long nLeft = std::min( aTmp.Left() - aBoundRect.Left(), aSnap.Width() );
+ tools::Long nRight = std::min( aBoundRect.Right() - aTmp.Right(), aSnap.Width() );
+ tools::Long nUp = std::min( aTmp.Top() - aBoundRect.Top(), aSnap.Height() );
+ tools::Long nDown = std::min( aBoundRect.Bottom() - aTmp.Bottom(), aSnap.Height() );
+
+ switch ( nDir )
+ {
+ case MOVE_LEFT_BIG:
+ case MOVE_LEFT_HUGE:
+ case MOVE_LEFT_SMALL: aTmp.Left( aTmp.Left() - nLeft );
+ break;
+
+ case MOVE_UP_BIG:
+ case MOVE_UP_HUGE:
+ case MOVE_UP_SMALL: aTmp.Top( aTmp.Top() - nUp );
+ break;
+
+ case MOVE_RIGHT_SMALL:
+ if( aTmp.Width() < aSnap.Width() + MINFLY )
+ break;
+ nRight = aSnap.Width();
+ [[fallthrough]];
+ case MOVE_RIGHT_HUGE:
+ case MOVE_RIGHT_BIG: aTmp.Left( aTmp.Left() + nRight );
+ break;
+
+ case MOVE_DOWN_SMALL:
+ if( aTmp.Height() < aSnap.Height() + MINFLY )
+ break;
+ nDown = aSnap.Height();
+ [[fallthrough]];
+ case MOVE_DOWN_HUGE:
+ case MOVE_DOWN_BIG: aTmp.Top( aTmp.Top() + nDown );
+ break;
+
+ default: OSL_ENSURE(true, "ChangeFly: Unknown direction." );
+ }
+ bool bSet = false;
+ if ((RndStdIds::FLY_AS_CHAR == eAnchorId) && ( nDir % 2 ))
+ {
+ tools::Long aDiff = aTmp.Top() - aRefPoint.Y();
+ if( aDiff > 0 )
+ aDiff = 0;
+ else if ( aDiff < -aTmp.Height() )
+ aDiff = -aTmp.Height();
+ SwFormatVertOrient aVert( aSet.Get(RES_VERT_ORIENT) );
+ sal_Int16 eNew;
+ if( bWeb )
+ {
+ eNew = aVert.GetVertOrient();
+ bool bDown = 0 != ( nDir & 0x02 );
+ switch( eNew )
+ {
+ case text::VertOrientation::CHAR_TOP:
+ if( bDown ) eNew = text::VertOrientation::CENTER;
+ break;
+ case text::VertOrientation::CENTER:
+ eNew = bDown ? text::VertOrientation::TOP : text::VertOrientation::CHAR_TOP;
+ break;
+ case text::VertOrientation::TOP:
+ if( !bDown ) eNew = text::VertOrientation::CENTER;
+ break;
+ case text::VertOrientation::LINE_TOP:
+ if( bDown ) eNew = text::VertOrientation::LINE_CENTER;
+ break;
+ case text::VertOrientation::LINE_CENTER:
+ eNew = bDown ? text::VertOrientation::LINE_BOTTOM : text::VertOrientation::LINE_TOP;
+ break;
+ case text::VertOrientation::LINE_BOTTOM:
+ if( !bDown ) eNew = text::VertOrientation::LINE_CENTER;
+ break;
+ default:; //prevent warning
+ }
+ }
+ else
+ {
+ aVert.SetPos( aDiff );
+ eNew = text::VertOrientation::NONE;
+ }
+ aVert.SetVertOrient( eNew );
+ aSet.Put( aVert );
+ bSet = true;
+ }
+ if (bWeb && (RndStdIds::FLY_AT_PARA == eAnchorId)
+ && ( nDir==MOVE_LEFT_SMALL || nDir==MOVE_RIGHT_BIG ))
+ {
+ SwFormatHoriOrient aHori( aSet.Get(RES_HORI_ORIENT) );
+ sal_Int16 eNew;
+ eNew = aHori.GetHoriOrient();
+ switch( eNew )
+ {
+ case text::HoriOrientation::RIGHT:
+ if( nDir==MOVE_LEFT_SMALL )
+ eNew = text::HoriOrientation::LEFT;
+ break;
+ case text::HoriOrientation::LEFT:
+ if( nDir==MOVE_RIGHT_BIG )
+ eNew = text::HoriOrientation::RIGHT;
+ break;
+ default:; //prevent warning
+ }
+ if( eNew != aHori.GetHoriOrient() )
+ {
+ aHori.SetHoriOrient( eNew );
+ aSet.Put( aHori );
+ bSet = true;
+ }
+ }
+ rSh.StartAllAction();
+ if( bSet )
+ rSh.SetFlyFrameAttr( aSet );
+ bool bSetPos = (RndStdIds::FLY_AS_CHAR != eAnchorId);
+ if(bSetPos && bWeb)
+ {
+ bSetPos = RndStdIds::FLY_AT_PAGE == eAnchorId;
+ }
+ if( bSetPos )
+ rSh.SetFlyPos( aTmp.Pos() );
+ rSh.EndAllAction();
+
+}
+
+void SwEditWin::ChangeDrawing( sal_uInt8 nDir )
+{
+ // start undo action in order to get only one
+ // undo action for this change.
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ rSh.StartUndo();
+
+ tools::Long nX = 0;
+ tools::Long nY = 0;
+ const bool bOnePixel(
+ MOVE_LEFT_SMALL == nDir ||
+ MOVE_UP_SMALL == nDir ||
+ MOVE_RIGHT_SMALL == nDir ||
+ MOVE_DOWN_SMALL == nDir);
+ const bool bHuge(
+ MOVE_LEFT_HUGE == nDir ||
+ MOVE_UP_HUGE == nDir ||
+ MOVE_RIGHT_HUGE == nDir ||
+ MOVE_DOWN_HUGE == nDir);
+ SwMove nAnchorDir = SwMove::UP;
+ switch(nDir)
+ {
+ case MOVE_LEFT_SMALL:
+ case MOVE_LEFT_HUGE:
+ case MOVE_LEFT_BIG:
+ nX = -1;
+ nAnchorDir = SwMove::LEFT;
+ break;
+ case MOVE_UP_SMALL:
+ case MOVE_UP_HUGE:
+ case MOVE_UP_BIG:
+ nY = -1;
+ break;
+ case MOVE_RIGHT_SMALL:
+ case MOVE_RIGHT_HUGE:
+ case MOVE_RIGHT_BIG:
+ nX = +1;
+ nAnchorDir = SwMove::RIGHT;
+ break;
+ case MOVE_DOWN_SMALL:
+ case MOVE_DOWN_HUGE:
+ case MOVE_DOWN_BIG:
+ nY = +1;
+ nAnchorDir = SwMove::DOWN;
+ break;
+ }
+
+ if(0 != nX || 0 != nY)
+ {
+ FlyProtectFlags nProtect = rSh.IsSelObjProtected( FlyProtectFlags::Pos|FlyProtectFlags::Size );
+ Size aSnap( rSh.GetViewOptions()->GetSnapSize() );
+ short nDiv = rSh.GetViewOptions()->GetDivisionX();
+ if ( nDiv > 0 )
+ aSnap.setWidth( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Width()) / nDiv ) );
+ nDiv = rSh.GetViewOptions()->GetDivisionY();
+ if ( nDiv > 0 )
+ aSnap.setHeight( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Height()) / nDiv ) );
+
+ if(bOnePixel)
+ {
+ aSnap = PixelToLogic(Size(1,1));
+ }
+ else if(bHuge)
+ {
+ // #i121236# 567twips == 1cm, but just take three times the normal snap
+ aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3);
+ }
+
+ nX *= aSnap.Width();
+ nY *= aSnap.Height();
+
+ SdrView *pSdrView = rSh.GetDrawView();
+ const SdrHdlList& rHdlList = pSdrView->GetHdlList();
+ SdrHdl* pHdl = rHdlList.GetFocusHdl();
+ rSh.StartAllAction();
+ if(nullptr == pHdl)
+ {
+ // now move the selected draw objects
+ // if the object's position is not protected
+ if(!(nProtect&FlyProtectFlags::Pos))
+ {
+ // Check if object is anchored as character and move direction
+ bool bDummy1, bDummy2;
+ const bool bVertAnchor = rSh.IsFrameVertical( true, bDummy1, bDummy2 );
+ bool bHoriMove = !bVertAnchor == !( nDir % 2 );
+ bool bMoveAllowed =
+ !bHoriMove || (rSh.GetAnchorId() != RndStdIds::FLY_AS_CHAR);
+ if ( bMoveAllowed )
+ {
+ pSdrView->MoveAllMarked(Size(nX, nY));
+ rSh.SetModified();
+ }
+ }
+ }
+ else
+ {
+ // move handle with index nHandleIndex
+ if (nX || nY)
+ {
+ if( SdrHdlKind::Anchor == pHdl->GetKind() ||
+ SdrHdlKind::Anchor_TR == pHdl->GetKind() )
+ {
+ // anchor move cannot be allowed when position is protected
+ if(!(nProtect&FlyProtectFlags::Pos))
+ rSh.MoveAnchor( nAnchorDir );
+ }
+ //now resize if size is protected
+ else if(!(nProtect&FlyProtectFlags::Size))
+ {
+ // now move the Handle (nX, nY)
+ Point aStartPoint(pHdl->GetPos());
+ Point aEndPoint(pHdl->GetPos() + Point(nX, nY));
+ const SdrDragStat& rDragStat = pSdrView->GetDragStat();
+
+ // start dragging
+ pSdrView->BegDragObj(aStartPoint, nullptr, pHdl, 0);
+
+ if(pSdrView->IsDragObj())
+ {
+ bool bWasNoSnap = rDragStat.IsNoSnap();
+ bool bWasSnapEnabled = pSdrView->IsSnapEnabled();
+
+ // switch snapping off
+ if(!bWasNoSnap)
+ const_cast<SdrDragStat&>(rDragStat).SetNoSnap();
+ if(bWasSnapEnabled)
+ pSdrView->SetSnapEnabled(false);
+
+ pSdrView->MovAction(aEndPoint);
+ pSdrView->EndDragObj();
+ rSh.SetModified();
+
+ // restore snap
+ if(!bWasNoSnap)
+ const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap);
+ if(bWasSnapEnabled)
+ pSdrView->SetSnapEnabled(bWasSnapEnabled);
+ }
+ }
+ }
+ }
+ rSh.EndAllAction();
+ }
+
+ rSh.EndUndo();
+}
+
+/**
+ * KeyEvents
+ */
+void SwEditWin::KeyInput(const KeyEvent &rKEvt)
+{
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+
+ if (comphelper::LibreOfficeKit::isActive() && m_rView.GetPostItMgr())
+ {
+ if (vcl::Window* pWindow = m_rView.GetPostItMgr()->GetActiveSidebarWin())
+ {
+ pWindow->KeyInput(rKEvt);
+ return;
+ }
+ }
+
+ sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();
+
+ if (nKey == KEY_ESCAPE)
+ {
+ if (m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard)
+ {
+ m_pApplyTempl->m_pFormatClipboard->Erase();
+ SetApplyTemplate(SwApplyTemplate());
+ m_rView.GetViewFrame().GetBindings().Invalidate(SID_FORMATPAINTBRUSH);
+ }
+ else if (rSh.IsHeaderFooterEdit())
+ {
+ bool bHeader = bool(FrameTypeFlags::HEADER & rSh.GetFrameType(nullptr, false));
+ if (bHeader)
+ rSh.SttPg();
+ else
+ rSh.EndPg();
+ rSh.ToggleHeaderFooterEdit();
+ }
+ }
+
+ SfxObjectShell *pObjSh = m_rView.GetViewFrame().GetObjectShell();
+ if ( m_bLockInput || (pObjSh && pObjSh->GetProgress()) )
+ // When the progress bar is active or a progress is
+ // running on a document, no order is being taken
+ return;
+
+ m_pShadCursor.reset();
+ // Do not reset the timer here, otherwise when flooded with events it would never time out
+ // if every key event stopped and started it again.
+ comphelper::ScopeGuard keyInputFlushTimerStop([this]() { m_aKeyInputFlushTimer.Stop(); });
+
+ bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
+ rSh.IsCursorReadonly();
+
+ //if the language changes the buffer must be flushed
+ LanguageType eNewLanguage = GetInputLanguage();
+ if(!bIsDocReadOnly && m_eBufferLanguage != eNewLanguage && !m_aInBuffer.isEmpty())
+ {
+ FlushInBuffer();
+ }
+ m_eBufferLanguage = eNewLanguage;
+
+ QuickHelpData aTmpQHD;
+ if( s_pQuickHlpData->m_bIsDisplayed )
+ {
+ aTmpQHD.Move( *s_pQuickHlpData );
+ s_pQuickHlpData->Stop( rSh );
+ }
+
+ // OS:the DrawView also needs a readonly-Flag as well
+ if ( !bIsDocReadOnly && rSh.GetDrawView() && rSh.GetDrawView()->KeyInput( rKEvt, this ) )
+ {
+ rSh.GetView().GetViewFrame().GetBindings().InvalidateAll( false );
+ rSh.SetModified();
+ return; // Event evaluated by SdrView
+ }
+
+ if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
+ {
+ StopInsFrame();
+ rSh.Edit();
+ }
+
+ bool bFlushBuffer = false;
+ bool bNormalChar = false;
+ bool bAppendSpace = s_pQuickHlpData->m_bAppendSpace;
+ s_pQuickHlpData->m_bAppendSpace = false;
+
+ if (nKey == KEY_F12 && getenv("SW_DEBUG"))
+ {
+ if( rKEvt.GetKeyCode().IsShift())
+ {
+ GetView().GetDocShell()->GetDoc()->dumpAsXml();
+ }
+ else
+ {
+ SwRootFrame* pLayout = GetView().GetDocShell()->GetWrtShell()->GetLayout();
+ pLayout->dumpAsXml( );
+ }
+ return;
+ }
+
+ KeyEvent aKeyEvent( rKEvt );
+ // look for vertical mappings
+ if( !bIsDocReadOnly && !rSh.IsSelFrameMode() && !rSh.IsObjSelected() )
+ {
+ if( KEY_UP == nKey || KEY_DOWN == nKey ||
+ KEY_LEFT == nKey || KEY_RIGHT == nKey )
+ {
+ // In general, we want to map the direction keys if we are inside
+ // some vertical formatted text.
+ // 1. Exception: For a table cursor in a horizontal table, the
+ // directions should never be mapped.
+ // 2. Exception: For a table cursor in a vertical table, the
+ // directions should always be mapped.
+ const bool bVertText = rSh.IsInVerticalText();
+ const bool bTableCursor = rSh.GetTableCursor();
+ const bool bVertTable = rSh.IsTableVertical();
+ if( ( bVertText && ( !bTableCursor || bVertTable ) ) ||
+ ( bTableCursor && bVertTable ) )
+ {
+ SvxFrameDirection eDirection = rSh.GetTextDirection();
+ if (eDirection == SvxFrameDirection::Vertical_LR_BT)
+ {
+ // Map from physical to logical, so rotate clockwise.
+ if (KEY_UP == nKey)
+ nKey = KEY_RIGHT;
+ else if (KEY_DOWN == nKey)
+ nKey = KEY_LEFT;
+ else if (KEY_LEFT == nKey)
+ nKey = KEY_UP;
+ else /* KEY_RIGHT == nKey */
+ nKey = KEY_DOWN;
+ }
+ else
+ {
+ // Attempt to integrate cursor travelling for mongolian layout does not work.
+ // Thus, back to previous mapping of cursor keys to direction keys.
+ if( KEY_UP == nKey ) nKey = KEY_LEFT;
+ else if( KEY_DOWN == nKey ) nKey = KEY_RIGHT;
+ else if( KEY_LEFT == nKey ) nKey = KEY_DOWN;
+ else /* KEY_RIGHT == nKey */ nKey = KEY_UP;
+ }
+ }
+
+ if ( rSh.IsInRightToLeftText() )
+ {
+ if( KEY_LEFT == nKey ) nKey = KEY_RIGHT;
+ else if( KEY_RIGHT == nKey ) nKey = KEY_LEFT;
+ }
+
+ aKeyEvent = KeyEvent( rKEvt.GetCharCode(),
+ vcl::KeyCode( nKey, rKEvt.GetKeyCode().GetModifier() ),
+ rKEvt.GetRepeat() );
+ }
+ }
+
+ const vcl::KeyCode& rKeyCode = aKeyEvent.GetKeyCode();
+ sal_Unicode aCh = aKeyEvent.GetCharCode();
+
+ // enable switching to notes anchor with Ctrl - Alt - Page Up/Down
+ // pressing this inside a note will switch to next/previous note
+ if ((rKeyCode.IsMod1() && rKeyCode.IsMod2()) && ((rKeyCode.GetCode() == KEY_PAGEUP) || (rKeyCode.GetCode() == KEY_PAGEDOWN)))
+ {
+ const bool bNext = rKeyCode.GetCode()==KEY_PAGEDOWN;
+ const SwFieldType* pFieldType = rSh.GetFieldType( 0, SwFieldIds::Postit );
+ rSh.MoveFieldType( pFieldType, bNext );
+ return;
+ }
+
+ if (SwTextContentControl* pTextContentControl = rSh.CursorInsideContentControl())
+ {
+ // Check if this combination of rKeyCode and pTextContentControl should open a popup.
+ const SwFormatContentControl& rFormatContentControl = pTextContentControl->GetContentControl();
+ std::shared_ptr<SwContentControl> pContentControl = rFormatContentControl.GetContentControl();
+ if (pContentControl->ShouldOpenPopup(rKeyCode))
+ {
+ SwShellCursor* pCursor = rSh.GetCursor_();
+ if (pCursor)
+ {
+ VclPtr<SwContentControlButton> pContentControlButton = pCursor->GetContentControlButton();
+ if (pContentControlButton)
+ {
+ pContentControlButton->StartPopup();
+ return;
+ }
+ }
+ }
+ }
+
+ const SwFrameFormat* pFlyFormat = rSh.GetFlyFrameFormat();
+
+ if (pFlyFormat)
+ {
+ // See if the fly frame's anchor is in a content control. If so,
+ // try to interact with it.
+ const SwFormatAnchor& rFormatAnchor = pFlyFormat->GetAnchor();
+ SwNode* pAnchorNode = rFormatAnchor.GetAnchorNode();
+ if (pAnchorNode)
+ {
+ SwTextNode* pTextNode = pAnchorNode->GetTextNode();
+ if (pTextNode)
+ {
+ sal_Int32 nContentIdx = rFormatAnchor.GetAnchorContentOffset();
+ SwTextAttr* pAttr = pTextNode->GetTextAttrAt(
+ nContentIdx, RES_TXTATR_CONTENTCONTROL, ::sw::GetTextAttrMode::Parent);
+ if (pAttr)
+ {
+ SwTextContentControl* pTextContentControl
+ = static_txtattr_cast<SwTextContentControl*>(pAttr);
+ const SwFormatContentControl& rFormatContentControl
+ = pTextContentControl->GetContentControl();
+ std::shared_ptr<SwContentControl> pContentControl
+ = rFormatContentControl.GetContentControl();
+ if (pContentControl->IsInteractingCharacter(aCh))
+ {
+ rSh.GotoContentControl(rFormatContentControl);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ if( pFlyFormat )
+ {
+ SvMacroItemId nEvent;
+
+ if( 32 <= aCh &&
+ 0 == (( KEY_MOD1 | KEY_MOD2 ) & rKeyCode.GetModifier() ))
+ nEvent = SvMacroItemId::SwFrmKeyInputAlpha;
+ else
+ nEvent = SvMacroItemId::SwFrmKeyInputNoAlpha;
+
+ const SvxMacro* pMacro = pFlyFormat->GetMacro().GetMacroTable().Get( nEvent );
+ if( pMacro )
+ {
+ SbxArrayRef xArgs = new SbxArray;
+ SbxVariableRef xVar = new SbxVariable;
+ xVar->PutString( pFlyFormat->GetName() );
+ xArgs->Put(xVar.get(), 1);
+
+ xVar = new SbxVariable;
+ if( SvMacroItemId::SwFrmKeyInputAlpha == nEvent )
+ xVar->PutChar( aCh );
+ else
+ xVar->PutUShort( rKeyCode.GetModifier() | rKeyCode.GetCode() );
+ xArgs->Put(xVar.get(), 2);
+
+ OUString sRet;
+ rSh.ExecMacro( *pMacro, &sRet, xArgs.get() );
+ if( !sRet.isEmpty() && sRet.toInt32()!=0 )
+ return ;
+ }
+ }
+ SelectionType nLclSelectionType;
+ //A is converted to 1
+ if( rKeyCode.GetFullCode() == (KEY_A | KEY_MOD1 |KEY_SHIFT)
+ && rSh.HasDrawView() &&
+ (bool(nLclSelectionType = rSh.GetSelectionType()) &&
+ ((nLclSelectionType & (SelectionType::Frame|SelectionType::Graphic)) ||
+ ((nLclSelectionType & (SelectionType::DrawObject|SelectionType::DbForm)) &&
+ rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1))))
+ {
+ SdrHdlList& rHdlList = const_cast<SdrHdlList&>(rSh.GetDrawView()->GetHdlList());
+ SdrHdl* pAnchor = rHdlList.GetHdl(SdrHdlKind::Anchor);
+ if ( ! pAnchor )
+ pAnchor = rHdlList.GetHdl(SdrHdlKind::Anchor_TR);
+ if(pAnchor)
+ rHdlList.SetFocusHdl(pAnchor);
+ return;
+ }
+
+ SvxAutoCorrCfg* pACfg = nullptr;
+ SvxAutoCorrect* pACorr = nullptr;
+
+ uno::Reference< frame::XDispatchRecorder > xRecorder =
+ m_rView.GetViewFrame().GetBindings().GetRecorder();
+ if ( !xRecorder.is() )
+ {
+ pACfg = &SvxAutoCorrCfg::Get();
+ pACorr = pACfg->GetAutoCorrect();
+ }
+
+ SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig();
+
+ OUString sFormulaEntry;
+
+ enum class SwKeyState { CheckKey, InsChar, InsTab,
+ NoNum, NumOff, NumOrNoNum, NumDown, NumUp,
+ NumIndentInc, NumIndentDec,
+
+ OutlineLvOff,
+ NextCell, PrevCell, OutlineUp, OutlineDown,
+ GlossaryExpand, NextPrevGlossary,
+ AutoFormatByInput,
+ NextObject, PrevObject,
+ KeyToView,
+ LaunchOLEObject, GoIntoFly, GoIntoDrawing,
+ EnterDrawHandleMode,
+ CheckDocReadOnlyKeys,
+ CheckAutoCorrect, EditFormula,
+ ColLeftBig, ColRightBig,
+ ColLeftSmall, ColRightSmall,
+ ColBottomBig,
+ ColBottomSmall,
+ CellLeftBig, CellRightBig,
+ CellLeftSmall, CellRightSmall,
+ CellTopBig, CellBottomBig,
+ CellTopSmall, CellBottomSmall,
+
+ Fly_Change, Draw_Change,
+ SpecialInsert,
+ EnterCharCell,
+ GotoNextFieldMark,
+ GotoPrevFieldMark,
+ End };
+
+ SwKeyState eKeyState = bIsDocReadOnly ? SwKeyState::CheckDocReadOnlyKeys : SwKeyState::CheckKey;
+ SwKeyState eNextKeyState = SwKeyState::End;
+ sal_uInt8 nDir = 0;
+
+ if (m_nKS_NUMDOWN_Count > 0)
+ m_nKS_NUMDOWN_Count--;
+
+ if (m_nKS_NUMINDENTINC_Count > 0)
+ m_nKS_NUMINDENTINC_Count--;
+
+ while( SwKeyState::End != eKeyState )
+ {
+ SwKeyState eFlyState = SwKeyState::KeyToView;
+
+ switch( eKeyState )
+ {
+ case SwKeyState::CheckKey:
+ eKeyState = SwKeyState::KeyToView; // default forward to View
+
+ if (!comphelper::LibreOfficeKit::isActive() &&
+ !rKeyCode.IsMod2() && '=' == aCh &&
+ !rSh.IsTableMode() && rSh.GetTableFormat() &&
+ rSh.IsSttPara() &&
+ !rSh.HasReadonlySel())
+ {
+ // at the beginning of the table's cell a '=' ->
+ // call EditRow (F2-functionality)
+ // [Avoid this for LibreOfficeKit, as the separate input window
+ // steals the focus & things go wrong - the user never gets
+ // the focus back.]
+ rSh.Push();
+ if( !rSh.MoveSection( GoCurrSection, fnSectionStart) &&
+ !rSh.IsTableBoxTextFormat() )
+ {
+ // is at the beginning of the box
+ eKeyState = SwKeyState::EditFormula;
+ if( rSh.HasMark() )
+ rSh.SwapPam();
+ else
+ rSh.SttSelect();
+ rSh.MoveSection( GoCurrSection, fnSectionEnd );
+ rSh.Pop();
+ rSh.EndSelect();
+ sFormulaEntry = "=";
+ }
+ else
+ rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+ }
+ else
+ {
+ if( pACorr && aTmpQHD.HasContent() && !rSh.HasSelection() &&
+ !rSh.HasReadonlySel() && !aTmpQHD.m_bIsAutoText &&
+ pACorr->GetSwFlags().nAutoCmpltExpandKey ==
+ (rKeyCode.GetModifier() | rKeyCode.GetCode()) )
+ {
+ eKeyState = SwKeyState::GlossaryExpand;
+ break;
+ }
+
+ switch( rKeyCode.GetModifier() | rKeyCode.GetCode() )
+ {
+ case KEY_RIGHT | KEY_MOD2:
+ eKeyState = SwKeyState::ColRightBig;
+ eFlyState = SwKeyState::Fly_Change;
+ nDir = MOVE_RIGHT_SMALL;
+ goto KEYINPUT_CHECKTABLE;
+
+ case KEY_LEFT | KEY_MOD2:
+ eKeyState = SwKeyState::ColRightSmall;
+ eFlyState = SwKeyState::Fly_Change;
+ nDir = MOVE_LEFT_SMALL;
+ goto KEYINPUT_CHECKTABLE;
+
+ case KEY_RIGHT | KEY_MOD2 | KEY_SHIFT:
+ eKeyState = SwKeyState::ColLeftSmall;
+ goto KEYINPUT_CHECKTABLE;
+
+ case KEY_LEFT | KEY_MOD2 | KEY_SHIFT:
+ eKeyState = SwKeyState::ColLeftBig;
+ goto KEYINPUT_CHECKTABLE;
+
+ case KEY_RIGHT | KEY_MOD2 | KEY_MOD1:
+ eKeyState = SwKeyState::CellRightBig;
+ goto KEYINPUT_CHECKTABLE;
+
+ case KEY_LEFT | KEY_MOD2 | KEY_MOD1:
+ eKeyState = SwKeyState::CellRightSmall;
+ goto KEYINPUT_CHECKTABLE;
+
+ case KEY_RIGHT | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
+ eKeyState = SwKeyState::CellLeftSmall;
+ goto KEYINPUT_CHECKTABLE;
+
+ case KEY_LEFT | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
+ eKeyState = SwKeyState::CellLeftBig;
+ goto KEYINPUT_CHECKTABLE;
+
+ case KEY_UP | KEY_MOD2:
+ eKeyState = SwKeyState::ColBottomSmall;
+ eFlyState = SwKeyState::Fly_Change;
+ nDir = MOVE_UP_SMALL;
+ goto KEYINPUT_CHECKTABLE;
+
+ case KEY_DOWN | KEY_MOD2:
+ eKeyState = SwKeyState::ColBottomBig;
+ eFlyState = SwKeyState::Fly_Change;
+ nDir = MOVE_DOWN_SMALL;
+ goto KEYINPUT_CHECKTABLE;
+
+ case KEY_UP | KEY_MOD2 | KEY_MOD1:
+ eKeyState = SwKeyState::CellBottomSmall;
+ goto KEYINPUT_CHECKTABLE;
+
+ case KEY_DOWN | KEY_MOD2 | KEY_MOD1:
+ eKeyState = SwKeyState::CellBottomBig;
+ goto KEYINPUT_CHECKTABLE;
+
+ case KEY_UP | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
+ eKeyState = SwKeyState::CellTopBig;
+ goto KEYINPUT_CHECKTABLE;
+
+ case KEY_DOWN | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
+ eKeyState = SwKeyState::CellTopSmall;
+ goto KEYINPUT_CHECKTABLE;
+
+KEYINPUT_CHECKTABLE:
+ // Resolve bugs 49091, 53190, 93402 and
+ // https://bz.apache.org/ooo/show_bug.cgi?id=113502
+ // but provide an option for restoring interactive
+ // table sizing functionality when needed.
+ if (
+ ! (Window::GetIndicatorState() & KeyIndicatorState::CAPSLOCK)
+ && m_rView.KeyInput( aKeyEvent ) // Keystroke is customized
+ )
+ {
+ bFlushBuffer = true;
+ bNormalChar = false;
+ eKeyState = SwKeyState::End;
+ break ;
+ }
+
+ if( rSh.IsTableMode() || !rSh.GetTableFormat() )
+ {
+ if(!pFlyFormat && SwKeyState::KeyToView != eFlyState &&
+ (rSh.GetSelectionType() & (SelectionType::DrawObject|SelectionType::DbForm)) &&
+ rSh.GetDrawView()->AreObjectsMarked())
+ eKeyState = SwKeyState::Draw_Change;
+
+ if( pFlyFormat )
+ eKeyState = eFlyState;
+ else if( SwKeyState::Draw_Change != eKeyState)
+ eKeyState = SwKeyState::EnterCharCell;
+ }
+ break;
+
+ // huge object move
+ case KEY_RIGHT | KEY_SHIFT:
+ case KEY_LEFT | KEY_SHIFT:
+ case KEY_UP | KEY_SHIFT:
+ case KEY_DOWN | KEY_SHIFT:
+ {
+ const SelectionType nSelectionType = rSh.GetSelectionType();
+ if ( ( pFlyFormat
+ && ( nSelectionType & (SelectionType::Frame|SelectionType::Ole|SelectionType::Graphic) ) )
+ || ( ( nSelectionType & (SelectionType::DrawObject|SelectionType::DbForm) )
+ && rSh.GetDrawView()->AreObjectsMarked() ) )
+ {
+ eKeyState = pFlyFormat ? SwKeyState::Fly_Change : SwKeyState::Draw_Change;
+ if (nSelectionType & SelectionType::DrawObject)
+ {
+ // tdf#137964: always move the DrawObject if one is selected
+ eKeyState = SwKeyState::Draw_Change;
+ }
+ switch ( rKeyCode.GetCode() )
+ {
+ case KEY_RIGHT: nDir = MOVE_RIGHT_HUGE; break;
+ case KEY_LEFT: nDir = MOVE_LEFT_HUGE; break;
+ case KEY_UP: nDir = MOVE_UP_HUGE; break;
+ case KEY_DOWN: nDir = MOVE_DOWN_HUGE; break;
+ }
+ }
+ break;
+ }
+
+ case KEY_LEFT:
+ case KEY_LEFT | KEY_MOD1:
+ {
+ bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
+ if(!bMod1)
+ {
+ eFlyState = SwKeyState::Fly_Change;
+ nDir = MOVE_LEFT_BIG;
+ }
+ goto KEYINPUT_CHECKTABLE_INSDEL;
+ }
+ case KEY_RIGHT | KEY_MOD1:
+ {
+ goto KEYINPUT_CHECKTABLE_INSDEL;
+ }
+ case KEY_UP:
+ case KEY_UP | KEY_MOD1:
+ {
+ bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
+ if(!bMod1)
+ {
+ eFlyState = SwKeyState::Fly_Change;
+ nDir = MOVE_UP_BIG;
+ }
+ goto KEYINPUT_CHECKTABLE_INSDEL;
+ }
+ case KEY_DOWN:
+ case KEY_DOWN | KEY_MOD1:
+ {
+ bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
+ if(!bMod1)
+ {
+ ::sw::mark::IFieldmark* pMark = rSh.GetCurrentFieldmark();
+ if (auto pDropDown = dynamic_cast<FieldmarkWithDropDownButton*>(pMark))
+ {
+ pDropDown->LaunchPopup();
+ eKeyState = SwKeyState::End;
+ break;
+ }
+ eFlyState = SwKeyState::Fly_Change;
+ nDir = MOVE_DOWN_BIG;
+ }
+ goto KEYINPUT_CHECKTABLE_INSDEL;
+ }
+
+KEYINPUT_CHECKTABLE_INSDEL:
+ if( rSh.IsTableMode() || !rSh.GetTableFormat() )
+ {
+ const SelectionType nSelectionType = rSh.GetSelectionType();
+
+ eKeyState = SwKeyState::KeyToView;
+ if(SwKeyState::KeyToView != eFlyState)
+ {
+ if((nSelectionType & (SelectionType::DrawObject|SelectionType::DbForm)) &&
+ rSh.GetDrawView()->AreObjectsMarked())
+ eKeyState = SwKeyState::Draw_Change;
+ else if(nSelectionType & (SelectionType::Frame|SelectionType::Ole|SelectionType::Graphic))
+ eKeyState = SwKeyState::Fly_Change;
+ }
+ }
+ break;
+
+
+ case KEY_DELETE:
+ if ( !rSh.HasReadonlySel() || rSh.CursorInsideInputField())
+ {
+ if (rSh.IsInFrontOfLabel() && rSh.NumOrNoNum())
+ eKeyState = SwKeyState::NumOrNoNum;
+ }
+ else if (!rSh.IsCursorInParagraphMetadataField())
+ {
+ rSh.InfoReadOnlyDialog(false);
+ eKeyState = SwKeyState::End;
+ }
+ break;
+
+ case KEY_RETURN:
+ {
+ if ( !rSh.HasReadonlySel()
+ && !rSh.CursorInsideInputField()
+ && !rSh.CursorInsideContentControl() )
+ {
+ const SelectionType nSelectionType = rSh.GetSelectionType();
+ if(nSelectionType & SelectionType::Ole)
+ eKeyState = SwKeyState::LaunchOLEObject;
+ else if(nSelectionType & SelectionType::Frame)
+ eKeyState = SwKeyState::GoIntoFly;
+ else if((nSelectionType & SelectionType::DrawObject) &&
+ !(nSelectionType & SelectionType::DrawObjectEditMode) &&
+ rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1)
+ {
+ eKeyState = SwKeyState::GoIntoDrawing;
+ if (lcl_goIntoTextBox(*this, rSh))
+ eKeyState = SwKeyState::GoIntoFly;
+ }
+ else if( aTmpQHD.HasContent() && !rSh.HasSelection() &&
+ aTmpQHD.m_bIsAutoText )
+ eKeyState = SwKeyState::GlossaryExpand;
+
+ //RETURN and empty paragraph in numbering -> end numbering
+ else if( m_aInBuffer.isEmpty() &&
+ rSh.GetNumRuleAtCurrCursorPos() &&
+ !rSh.GetNumRuleAtCurrCursorPos()->IsOutlineRule() &&
+ !rSh.HasSelection() &&
+ rSh.IsSttPara() && rSh.IsEndPara() )
+ {
+ eKeyState = SwKeyState::NumOff;
+ eNextKeyState = SwKeyState::OutlineLvOff;
+ }
+ //RETURN for new paragraph with AutoFormatting
+ else if( pACfg && pACfg->IsAutoFormatByInput() &&
+ !(nSelectionType & (SelectionType::Graphic |
+ SelectionType::Ole | SelectionType::Frame |
+ SelectionType::TableCell | SelectionType::DrawObject |
+ SelectionType::DrawObjectEditMode)) )
+ {
+ eKeyState = SwKeyState::AutoFormatByInput;
+ }
+ else
+ {
+ eNextKeyState = eKeyState;
+ eKeyState = SwKeyState::CheckAutoCorrect;
+ }
+ }
+ }
+ break;
+ case KEY_RETURN | KEY_MOD2:
+ {
+ if ( !rSh.HasReadonlySel()
+ && !rSh.IsSttPara()
+ && rSh.GetNumRuleAtCurrCursorPos()
+ && !rSh.CursorInsideInputField() )
+ {
+ eKeyState = SwKeyState::NoNum;
+ }
+ else if( rSh.CanSpecialInsert() )
+ eKeyState = SwKeyState::SpecialInsert;
+ }
+ break;
+ case KEY_BACKSPACE:
+ case KEY_BACKSPACE | KEY_SHIFT:
+ if ( !rSh.HasReadonlySel() || rSh.CursorInsideInputField())
+ {
+ bool bDone = false;
+ // try to add comment for code snip:
+ // Remove the paragraph indent, if the cursor is at the
+ // beginning of a paragraph, there is no selection
+ // and no numbering rule found at the current paragraph
+ // Also try to remove indent, if current paragraph
+ // has numbering rule, but isn't counted and only
+ // key <backspace> is hit.
+ const bool bOnlyBackspaceKey( KEY_BACKSPACE == rKeyCode.GetFullCode() );
+ if ( rSh.IsSttPara()
+ && !rSh.HasSelection()
+ && ( rSh.GetNumRuleAtCurrCursorPos() == nullptr
+ || ( rSh.IsNoNum() && bOnlyBackspaceKey ) ) )
+ {
+ bDone = rSh.TryRemoveIndent();
+ }
+
+ if (bDone)
+ eKeyState = SwKeyState::End;
+ else
+ {
+ if ( rSh.IsSttPara() && !rSh.IsNoNum() )
+ {
+ if (m_nKS_NUMDOWN_Count > 0 &&
+ 0 < rSh.GetNumLevel())
+ {
+ eKeyState = SwKeyState::NumUp;
+ m_nKS_NUMDOWN_Count = 2;
+ bDone = true;
+ }
+ else if (m_nKS_NUMINDENTINC_Count > 0)
+ {
+ eKeyState = SwKeyState::NumIndentDec;
+ m_nKS_NUMINDENTINC_Count = 2;
+ bDone = true;
+ }
+ }
+
+ // If the cursor is in an empty paragraph, which has
+ // a numbering, but not the outline numbering, and
+ // there is no selection, the numbering has to be
+ // deleted on key <Backspace>.
+ // Otherwise method <SwEditShell::NumOrNoNum(..)>
+ // should only change the <IsCounted()> state of
+ // the current paragraph depending of the key.
+ // On <backspace> it is set to <false>,
+ // on <shift-backspace> it is set to <true>.
+ // Thus, assure that method <SwEditShell::NumOrNum(..)>
+ // is only called for the intended purpose.
+ if ( !bDone && rSh.IsSttPara() )
+ {
+ bool bCallNumOrNoNum( false );
+ if ( bOnlyBackspaceKey && !rSh.IsNoNum() )
+ {
+ bCallNumOrNoNum = true;
+ }
+ else if ( !bOnlyBackspaceKey && rSh.IsNoNum() )
+ {
+ bCallNumOrNoNum = true;
+ }
+ else if ( bOnlyBackspaceKey
+ && rSh.IsSttPara()
+ && rSh.IsEndPara()
+ && !rSh.HasSelection() )
+ {
+ const SwNumRule* pCurrNumRule( rSh.GetNumRuleAtCurrCursorPos() );
+ if ( pCurrNumRule != nullptr
+ && pCurrNumRule != rSh.GetOutlineNumRule() )
+ {
+ bCallNumOrNoNum = true;
+ }
+ }
+ if ( bCallNumOrNoNum
+ && rSh.NumOrNoNum( !bOnlyBackspaceKey ) )
+ {
+ eKeyState = SwKeyState::NumOrNoNum;
+ }
+ }
+ }
+ }
+ else if (!rSh.IsCursorInParagraphMetadataField())
+ {
+ rSh.InfoReadOnlyDialog(false);
+ eKeyState = SwKeyState::End;
+ }
+ break;
+
+ case KEY_RIGHT:
+ {
+ eFlyState = SwKeyState::Fly_Change;
+ nDir = MOVE_RIGHT_BIG;
+ goto KEYINPUT_CHECKTABLE_INSDEL;
+ }
+ case KEY_TAB:
+ {
+ // Rich text contentControls accept tabs and fieldmarks and other rich text,
+ // so first act on cases that are not a content control
+ SwTextContentControl* pTextContentControl = rSh.CursorInsideContentControl();
+ if ((rSh.IsFormProtected() && !pTextContentControl) ||
+ rSh.GetCurrentFieldmark() || rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT)
+ {
+ eKeyState = SwKeyState::GotoNextFieldMark;
+ }
+ else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
+ {
+ GetView().GetViewFrame().GetDispatcher()->Execute( FN_GOTO_NEXT_INPUTFLD );
+ eKeyState = SwKeyState::End;
+ }
+ else if( rSh.GetNumRuleAtCurrCursorPos()
+ && rSh.IsSttOfPara()
+ && !rSh.HasReadonlySel() )
+ {
+ if (numfunc::NumDownChangesIndent(rSh))
+ {
+ eKeyState = SwKeyState::NumDown;
+ }
+ else
+ {
+ eKeyState = SwKeyState::InsTab;
+ }
+ }
+ else if (rSh.GetSelectionType() &
+ (SelectionType::Graphic |
+ SelectionType::Frame |
+ SelectionType::Ole |
+ SelectionType::DrawObject |
+ SelectionType::DbForm))
+ {
+ eKeyState = SwKeyState::NextObject;
+ }
+ else if ( rSh.GetTableFormat() )
+ {
+ if( rSh.HasSelection() || rSh.HasReadonlySel() )
+ eKeyState = SwKeyState::NextCell;
+ else
+ {
+ eKeyState = SwKeyState::CheckAutoCorrect;
+ eNextKeyState = SwKeyState::NextCell;
+ }
+ }
+ else if (pTextContentControl)
+ {
+ auto pCC = pTextContentControl->GetContentControl().GetContentControl();
+ if (pCC)
+ {
+ switch (pCC->GetType())
+ {
+ case SwContentControlType::RICH_TEXT:
+ eKeyState = SwKeyState::InsTab;
+ break;
+ default:
+ eKeyState = SwKeyState::GotoNextFieldMark;
+ }
+ }
+ }
+ else
+ {
+ eKeyState = SwKeyState::InsTab;
+ if( rSh.IsSttOfPara() && !rSh.HasReadonlySel() )
+ {
+ SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
+ if( pColl &&
+
+ pColl->IsAssignedToListLevelOfOutlineStyle()
+ && MAXLEVEL-1 > pColl->GetAssignedOutlineStyleLevel() )
+ eKeyState = SwKeyState::OutlineDown;
+ }
+ }
+ }
+ break;
+ case KEY_TAB | KEY_SHIFT:
+ {
+ SwTextContentControl* pTextContentControl = rSh.CursorInsideContentControl();
+ if ((rSh.IsFormProtected() && !pTextContentControl) ||
+ rSh.GetCurrentFieldmark()|| rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT)
+ {
+ eKeyState = SwKeyState::GotoPrevFieldMark;
+ }
+ else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
+ {
+ GetView().GetViewFrame().GetDispatcher()->Execute( FN_GOTO_PREV_INPUTFLD );
+ eKeyState = SwKeyState::End;
+ }
+ else if( rSh.GetNumRuleAtCurrCursorPos()
+ && rSh.IsSttOfPara()
+ && !rSh.HasReadonlySel() )
+ {
+ eKeyState = SwKeyState::NumUp;
+ }
+ else if (rSh.GetSelectionType() &
+ (SelectionType::Graphic |
+ SelectionType::Frame |
+ SelectionType::Ole |
+ SelectionType::DrawObject |
+ SelectionType::DbForm))
+ {
+ eKeyState = SwKeyState::PrevObject;
+ }
+ else if ( rSh.GetTableFormat() )
+ {
+ if( rSh.HasSelection() || rSh.HasReadonlySel() )
+ eKeyState = SwKeyState::PrevCell;
+ else
+ {
+ eKeyState = SwKeyState::CheckAutoCorrect;
+ eNextKeyState = SwKeyState::PrevCell;
+ }
+ }
+ else if (pTextContentControl)
+ {
+ eKeyState = SwKeyState::GotoPrevFieldMark;
+ }
+ else
+ {
+ eKeyState = SwKeyState::End;
+ if( rSh.IsSttOfPara() && !rSh.HasReadonlySel() )
+ {
+ SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
+ if( pColl &&
+ pColl->IsAssignedToListLevelOfOutlineStyle() &&
+ 0 < pColl->GetAssignedOutlineStyleLevel())
+ eKeyState = SwKeyState::OutlineUp;
+ }
+ }
+ }
+ break;
+ case KEY_TAB | KEY_MOD1:
+ case KEY_TAB | KEY_MOD2:
+ if( !rSh.HasReadonlySel() )
+ {
+ if( aTmpQHD.HasContent() && !rSh.HasSelection() )
+ {
+ // Next auto-complete suggestion
+ aTmpQHD.Next( pACorr &&
+ pACorr->GetSwFlags().bAutoCmpltEndless );
+ eKeyState = SwKeyState::NextPrevGlossary;
+ }
+ else if( rSh.GetTableFormat() )
+ eKeyState = SwKeyState::InsTab;
+ else if((rSh.GetSelectionType() &
+ (SelectionType::DrawObject|SelectionType::DbForm|
+ SelectionType::Frame|SelectionType::Ole|SelectionType::Graphic)) &&
+ rSh.GetDrawView()->AreObjectsMarked())
+ eKeyState = SwKeyState::EnterDrawHandleMode;
+ else
+ {
+ if ( !rSh.IsMultiSelection()
+ && numfunc::ChangeIndentOnTabAtFirstPosOfFirstListItem() )
+ eKeyState = SwKeyState::NumIndentInc;
+ }
+ }
+ break;
+
+ case KEY_TAB | KEY_MOD1 | KEY_SHIFT:
+ {
+ if( aTmpQHD.HasContent() && !rSh.HasSelection() &&
+ !rSh.HasReadonlySel() )
+ {
+ // Previous auto-complete suggestion.
+ aTmpQHD.Previous( pACorr &&
+ pACorr->GetSwFlags().bAutoCmpltEndless );
+ eKeyState = SwKeyState::NextPrevGlossary;
+ }
+ else if((rSh.GetSelectionType() & (SelectionType::DrawObject|SelectionType::DbForm|
+ SelectionType::Frame|SelectionType::Ole|SelectionType::Graphic)) &&
+ rSh.GetDrawView()->AreObjectsMarked())
+ {
+ eKeyState = SwKeyState::EnterDrawHandleMode;
+ }
+ else
+ {
+ if ( !rSh.IsMultiSelection()
+ && numfunc::ChangeIndentOnTabAtFirstPosOfFirstListItem() )
+ eKeyState = SwKeyState::NumIndentDec;
+ }
+ }
+ break;
+ case KEY_F2 :
+ if( !rSh.HasReadonlySel() )
+ {
+ const SelectionType nSelectionType = rSh.GetSelectionType();
+ if(nSelectionType & SelectionType::Frame)
+ eKeyState = SwKeyState::GoIntoFly;
+ else if(nSelectionType & SelectionType::DrawObject)
+ {
+ eKeyState = SwKeyState::GoIntoDrawing;
+ if (lcl_goIntoTextBox(*this, rSh))
+ eKeyState = SwKeyState::GoIntoFly;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ case SwKeyState::CheckDocReadOnlyKeys:
+ {
+ eKeyState = SwKeyState::KeyToView;
+ switch( rKeyCode.GetModifier() | rKeyCode.GetCode() )
+ {
+ case KEY_TAB:
+ case KEY_TAB | KEY_SHIFT:
+ bNormalChar = false;
+ eKeyState = SwKeyState::End;
+ if ( rSh.GetSelectionType() &
+ (SelectionType::Graphic |
+ SelectionType::Frame |
+ SelectionType::Ole |
+ SelectionType::DrawObject |
+ SelectionType::DbForm))
+
+ {
+ eKeyState = (rKeyCode.GetModifier() & KEY_SHIFT) ?
+ SwKeyState::PrevObject : SwKeyState::NextObject;
+ }
+ else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
+ {
+ GetView().GetViewFrame().GetDispatcher()->Execute(
+ KEY_SHIFT != rKeyCode.GetModifier() ? FN_GOTO_NEXT_INPUTFLD : FN_GOTO_PREV_INPUTFLD );
+ }
+ else
+ {
+ rSh.SelectNextPrevHyperlink( KEY_SHIFT != rKeyCode.GetModifier() );
+ }
+ break;
+ case KEY_RETURN:
+ {
+ const SelectionType nSelectionType = rSh.GetSelectionType();
+ if(nSelectionType & SelectionType::Frame)
+ eKeyState = SwKeyState::GoIntoFly;
+ else
+ {
+ SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(rSh.GetAttrPool());
+ rSh.GetCurAttr(aSet);
+ if(SfxItemState::SET == aSet.GetItemState(RES_TXTATR_INETFMT, false))
+ {
+ const SfxPoolItem& rItem = aSet.Get(RES_TXTATR_INETFMT);
+ bNormalChar = false;
+ eKeyState = SwKeyState::End;
+ rSh.ClickToINetAttr(static_cast<const SwFormatINetFormat&>(rItem));
+ }
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case SwKeyState::EnterCharCell:
+ {
+ eKeyState = SwKeyState::KeyToView;
+ switch ( rKeyCode.GetModifier() | rKeyCode.GetCode() )
+ {
+ case KEY_RIGHT | KEY_MOD2:
+ rSh.Right( SwCursorSkipMode::Chars, false, 1, false );
+ eKeyState = SwKeyState::End;
+ FlushInBuffer();
+ break;
+ case KEY_LEFT | KEY_MOD2:
+ rSh.Left( SwCursorSkipMode::Chars, false, 1, false );
+ eKeyState = SwKeyState::End;
+ FlushInBuffer();
+ break;
+ }
+ }
+ break;
+
+ case SwKeyState::KeyToView:
+ {
+ eKeyState = SwKeyState::End;
+ bNormalChar =
+ !rKeyCode.IsMod2() &&
+ rKeyCode.GetModifier() != KEY_MOD1 &&
+ rKeyCode.GetModifier() != (KEY_MOD1|KEY_SHIFT) &&
+ SW_ISPRINTABLE( aCh );
+
+ if( bNormalChar && rSh.IsInFrontOfLabel() )
+ {
+ rSh.NumOrNoNum();
+ }
+
+ if( !m_aInBuffer.isEmpty() && ( !bNormalChar || bIsDocReadOnly ))
+ FlushInBuffer();
+
+ if (rSh.HasReadonlySel()
+ && ( rKeyCode.GetFunction() == KeyFuncType::PASTE
+ || rKeyCode.GetFunction() == KeyFuncType::CUT))
+ {
+ rSh.InfoReadOnlyDialog(true);
+ eKeyState = SwKeyState::End;
+ }
+ else if( m_rView.KeyInput( aKeyEvent ) )
+ {
+ bFlushBuffer = true;
+ bNormalChar = false;
+ }
+ else
+ {
+ // Because Sfx accelerators are only called when they were
+ // enabled at the last status update, copy has to called
+ // 'forcefully' by us if necessary.
+ if( rKeyCode.GetFunction() == KeyFuncType::COPY )
+ GetView().GetViewFrame().GetBindings().Execute(SID_COPY);
+
+ if( !bIsDocReadOnly && bNormalChar )
+ {
+ const SelectionType nSelectionType = rSh.GetSelectionType();
+ const bool bDrawObject = (nSelectionType & SelectionType::DrawObject) &&
+ !(nSelectionType & SelectionType::DrawObjectEditMode) &&
+ rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1;
+
+ bool bTextBox = false;
+ if (bDrawObject && lcl_goIntoTextBox(*this, rSh))
+ // A draw shape was selected, but it has a TextBox,
+ // start editing that instead when the normal
+ // character is pressed.
+ bTextBox = true;
+
+ if (bDrawObject && !bTextBox)
+ {
+ SdrObject* pObj = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
+ if(pObj)
+ {
+ EnterDrawTextMode(pObj->GetLogicRect().Center());
+ if ( auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>( m_rView.GetCurShell() ) )
+ pSwDrawTextShell->Init();
+ rSh.GetDrawView()->KeyInput( rKEvt, this );
+ }
+ }
+ else if (nSelectionType & SelectionType::Frame || bTextBox)
+ {
+ rSh.UnSelectFrame();
+ rSh.LeaveSelFrameMode();
+ m_rView.AttrChangedNotify(nullptr);
+ rSh.MoveSection( GoCurrSection, fnSectionEnd );
+ }
+ eKeyState = SwKeyState::InsChar;
+ }
+ else
+ {
+ bNormalChar = false;
+ Window::KeyInput( aKeyEvent );
+ }
+ }
+ }
+ break;
+ case SwKeyState::LaunchOLEObject:
+ {
+ rSh.LaunchOLEObj();
+ eKeyState = SwKeyState::End;
+ }
+ break;
+ case SwKeyState::GoIntoFly:
+ {
+ rSh.UnSelectFrame();
+ rSh.LeaveSelFrameMode();
+ m_rView.AttrChangedNotify(nullptr);
+ rSh.MoveSection( GoCurrSection, fnSectionEnd );
+ eKeyState = SwKeyState::End;
+ }
+ break;
+ case SwKeyState::GoIntoDrawing:
+ {
+ if (SdrMark* pMark = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0))
+ {
+ SdrObject* pObj = pMark->GetMarkedSdrObj();
+ if(pObj)
+ {
+ EnterDrawTextMode(pObj->GetLogicRect().Center());
+ if (auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>( m_rView.GetCurShell() ) )
+ pSwDrawTextShell->Init();
+ }
+ }
+ eKeyState = SwKeyState::End;
+ }
+ break;
+ case SwKeyState::EnterDrawHandleMode:
+ {
+ const SdrHdlList& rHdlList = rSh.GetDrawView()->GetHdlList();
+ bool bForward(!aKeyEvent.GetKeyCode().IsShift());
+
+ const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward);
+ eKeyState = SwKeyState::End;
+ }
+ break;
+ case SwKeyState::InsTab:
+ if( dynamic_cast<const SwWebView*>( &m_rView) != nullptr) // no Tab for WebView
+ {
+ // then it should be passed along
+ Window::KeyInput( aKeyEvent );
+ eKeyState = SwKeyState::End;
+ break;
+ }
+ aCh = '\t';
+ [[fallthrough]];
+ case SwKeyState::InsChar:
+ {
+ if (rSh.CursorInsideContentControl())
+ {
+ const SwPosition* pStart = rSh.GetCursor()->Start();
+ SwTextNode* pTextNode = pStart->GetNode().GetTextNode();
+ if (pTextNode)
+ {
+ sal_Int32 nIndex = pStart->GetContentIndex();
+ SwTextAttr* pAttr = pTextNode->GetTextAttrAt(nIndex, RES_TXTATR_CONTENTCONTROL, ::sw::GetTextAttrMode::Parent);
+ if (pAttr)
+ {
+ auto pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr);
+ const SwFormatContentControl& rFormatContentControl = pTextContentControl->GetContentControl();
+ std::shared_ptr<SwContentControl> pContentControl = rFormatContentControl.GetContentControl();
+ if (pContentControl->IsInteractingCharacter(aCh))
+ {
+ rSh.GotoContentControl(rFormatContentControl);
+ eKeyState = SwKeyState::End;
+ break;
+ }
+ }
+ }
+ }
+
+ if (rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT)
+ {
+ ::sw::mark::ICheckboxFieldmark* pFieldmark =
+ dynamic_cast< ::sw::mark::ICheckboxFieldmark* >
+ (rSh.GetCurrentFieldmark());
+ OSL_ENSURE(pFieldmark,
+ "Where is my FieldMark??");
+ if(pFieldmark)
+ {
+ pFieldmark->SetChecked(!pFieldmark->IsChecked());
+ OSL_ENSURE(pFieldmark->IsExpanded(),
+ "where is the otherpos?");
+ if (pFieldmark->IsExpanded())
+ {
+ rSh.CalcLayout();
+ }
+ }
+ eKeyState = SwKeyState::End;
+ }
+ else if ( !rSh.HasReadonlySel()
+ || rSh.CursorInsideInputField() )
+ {
+ const bool bIsNormalChar =
+ GetAppCharClass().isLetterNumeric( OUString( aCh ), 0 );
+ if( bAppendSpace && bIsNormalChar &&
+ (!m_aInBuffer.isEmpty() || !rSh.IsSttPara() || !rSh.IsEndPara() ))
+ {
+ // insert a blank ahead of the character. this ends up
+ // between the expanded text and the new "non-word-separator".
+ m_aInBuffer += " ";
+ }
+
+ const bool bIsAutoCorrectChar = SvxAutoCorrect::IsAutoCorrectChar( aCh );
+ if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || rSh.IsNbspRunNext() ) &&
+ pACfg->IsAutoFormatByInput() &&
+ (( pACorr->IsAutoCorrFlag( ACFlags::ChgWeightUnderl ) &&
+ ( '*' == aCh || '_' == aCh ) ) ||
+ ( pACorr->IsAutoCorrFlag( ACFlags::ChgQuotes ) && ('\"' == aCh ))||
+ ( pACorr->IsAutoCorrFlag( ACFlags::ChgSglQuotes ) && ( '\'' == aCh))))
+ {
+ FlushInBuffer();
+ rSh.AutoCorrect( *pACorr, aCh );
+ if( '\"' != aCh && '\'' != aCh ) // only call when "*_"!
+ rSh.UpdateAttr();
+ }
+ else if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || rSh.IsNbspRunNext() ) &&
+ pACfg->IsAutoFormatByInput() &&
+ pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
+ ACFlags::ChgOrdinalNumber | ACFlags::AddNonBrkSpace |
+ ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr |
+ ACFlags::Autocorrect | ACFlags::TransliterateRTL |
+ ACFlags::SetDOIAttr ) &&
+ '\"' != aCh && '\'' != aCh && '*' != aCh && '_' != aCh
+ )
+ {
+ FlushInBuffer();
+ rSh.AutoCorrect( *pACorr, aCh );
+ }
+ else
+ {
+ OUStringBuffer aBuf(m_aInBuffer);
+ comphelper::string::padToLength(aBuf,
+ m_aInBuffer.getLength() + aKeyEvent.GetRepeat() + 1, aCh);
+ m_aInBuffer = aBuf.makeStringAndClear();
+ bool delayFlush = Application::AnyInput( VclInputFlags::KEYBOARD );
+ bFlushBuffer = !delayFlush;
+ if( delayFlush )
+ {
+ // Start the timer, make sure to not restart it.
+ keyInputFlushTimerStop.dismiss();
+ if( !m_aKeyInputFlushTimer.IsActive())
+ m_aKeyInputFlushTimer.Start();
+ }
+ }
+ eKeyState = SwKeyState::End;
+ }
+ else
+ {
+ rSh.InfoReadOnlyDialog(true);
+ eKeyState = SwKeyState::End;
+ }
+
+ bool bIsSpace = (aCh == ' ');
+ if (bIsSpace && pACorr && pACfg)
+ {
+ // do the formatting only for few starting characters (for "* " or "- " conversion)
+ SwPosition aPos(*rSh.GetCursor()->GetPoint());
+ if (aPos.nContent < 3)
+ {
+ SvxSwAutoFormatFlags& rFlags = pACorr->GetSwFlags();
+ if(pACfg->IsAutoFormatByInput() && rFlags.bSetNumRule && rFlags.bSetNumRuleAfterSpace)
+ rSh.AutoFormat(&rFlags, true);
+ }
+ }
+ }
+ break;
+
+ case SwKeyState::CheckAutoCorrect:
+ {
+ if( pACorr && pACfg->IsAutoFormatByInput() &&
+ pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
+ ACFlags::ChgOrdinalNumber | ACFlags::TransliterateRTL |
+ ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr |
+ ACFlags::Autocorrect | ACFlags::SetDOIAttr ) &&
+ !rSh.HasReadonlySel() )
+ {
+ FlushInBuffer();
+ rSh.AutoCorrect( *pACorr, u'\0' );
+ }
+ eKeyState = eNextKeyState;
+ }
+ break;
+
+ default:
+ {
+ sal_uInt16 nSlotId = 0;
+ FlushInBuffer();
+ switch( eKeyState )
+ {
+ case SwKeyState::SpecialInsert:
+ rSh.DoSpecialInsert();
+ break;
+
+ case SwKeyState::NoNum:
+ rSh.NoNum();
+ break;
+
+ case SwKeyState::NumOff:
+ // shell change - so record in advance
+ rSh.DelNumRules();
+ break;
+ case SwKeyState::OutlineLvOff: // delete autofmt outlinelevel later
+ break;
+
+ case SwKeyState::NumDown:
+ rSh.NumUpDown();
+ m_nKS_NUMDOWN_Count = 2;
+ break;
+ case SwKeyState::NumUp:
+ rSh.NumUpDown( false );
+ break;
+
+ case SwKeyState::NumIndentInc:
+ rSh.ChangeIndentOfAllListLevels(360);
+ m_nKS_NUMINDENTINC_Count = 2;
+ break;
+
+ case SwKeyState::GotoNextFieldMark:
+ {
+ rSh.GotoFormControl(/*bNext=*/true);
+ }
+ break;
+
+ case SwKeyState::GotoPrevFieldMark:
+ {
+ rSh.GotoFormControl(/*bNext=*/false);
+ }
+ break;
+
+ case SwKeyState::NumIndentDec:
+ rSh.ChangeIndentOfAllListLevels(-360);
+ break;
+
+ case SwKeyState::OutlineDown:
+ rSh.OutlineUpDown();
+ break;
+ case SwKeyState::OutlineUp:
+ rSh.OutlineUpDown( -1 );
+ break;
+
+ case SwKeyState::NextCell:
+ // always 'flush' in tables
+ rSh.GoNextCell(!rSh.HasReadonlySel());
+ nSlotId = FN_GOTO_NEXT_CELL;
+ break;
+ case SwKeyState::PrevCell:
+ rSh.GoPrevCell();
+ nSlotId = FN_GOTO_PREV_CELL;
+ break;
+ case SwKeyState::AutoFormatByInput:
+ rSh.SplitNode( true );
+ break;
+
+ case SwKeyState::NextObject:
+ case SwKeyState::PrevObject:
+ if(rSh.GotoObj( SwKeyState::NextObject == eKeyState, GotoObjFlags::Any))
+ {
+ if( rSh.IsFrameSelected() &&
+ m_rView.GetDrawFuncPtr() )
+ {
+ m_rView.GetDrawFuncPtr()->Deactivate();
+ m_rView.SetDrawFuncPtr(nullptr);
+ m_rView.LeaveDrawCreate();
+ m_rView.AttrChangedNotify(nullptr);
+ }
+ rSh.HideCursor();
+ rSh.EnterSelFrameMode();
+ }
+ break;
+ case SwKeyState::GlossaryExpand:
+ {
+ // replace the word or abbreviation with the auto text
+ rSh.StartUndo( SwUndoId::START );
+
+ OUString sFnd(aTmpQHD.CurStr());
+ if( aTmpQHD.m_bIsAutoText )
+ {
+ SwGlossaryList* pList = ::GetGlossaryList();
+ OUString sShrtNm;
+ OUString sGroup;
+ if(pList->GetShortName( sFnd, sShrtNm, sGroup))
+ {
+ rSh.SttSelect();
+ rSh.ExtendSelection(false, aTmpQHD.CurLen());
+ SwGlossaryHdl* pGlosHdl = GetView().GetGlosHdl();
+ pGlosHdl->SetCurGroup(sGroup, true);
+ pGlosHdl->InsertGlossary( sShrtNm);
+ s_pQuickHlpData->m_bAppendSpace = true;
+ }
+ }
+ else
+ {
+ sFnd = sFnd.copy(aTmpQHD.CurLen());
+ rSh.Insert( sFnd );
+ s_pQuickHlpData->m_bAppendSpace = !pACorr ||
+ pACorr->GetSwFlags().bAutoCmpltAppendBlank;
+ }
+ rSh.EndUndo( SwUndoId::END );
+ }
+ break;
+
+ case SwKeyState::NextPrevGlossary:
+ s_pQuickHlpData->Move( aTmpQHD );
+ s_pQuickHlpData->Start(rSh, false);
+ break;
+
+ case SwKeyState::EditFormula:
+ {
+ const sal_uInt16 nId = SwInputChild::GetChildWindowId();
+
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+ rVFrame.ToggleChildWindow( nId );
+ SwInputChild* pChildWin = static_cast<SwInputChild*>(rVFrame.
+ GetChildWindow( nId ));
+ if( pChildWin )
+ pChildWin->SetFormula( sFormulaEntry );
+ }
+ break;
+
+ case SwKeyState::ColLeftBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColLeft|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
+ case SwKeyState::ColRightBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColRight|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
+ case SwKeyState::ColLeftSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColLeft, pModOpt->GetTableHMove() ); break;
+ case SwKeyState::ColRightSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColRight, pModOpt->GetTableHMove() ); break;
+ case SwKeyState::ColBottomBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::RowBottom|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
+ case SwKeyState::ColBottomSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::RowBottom, pModOpt->GetTableVMove() ); break;
+ case SwKeyState::CellLeftBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellLeft|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
+ case SwKeyState::CellRightBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellRight|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
+ case SwKeyState::CellLeftSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellLeft, pModOpt->GetTableHMove() ); break;
+ case SwKeyState::CellRightSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellRight, pModOpt->GetTableHMove() ); break;
+ case SwKeyState::CellTopBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellTop|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
+ case SwKeyState::CellBottomBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellBottom|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
+ case SwKeyState::CellTopSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellTop, pModOpt->GetTableVMove() ); break;
+ case SwKeyState::CellBottomSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellBottom, pModOpt->GetTableVMove() ); break;
+
+ case SwKeyState::Fly_Change:
+ {
+ SdrView *pSdrView = rSh.GetDrawView();
+ const SdrHdlList& rHdlList = pSdrView->GetHdlList();
+ if(rHdlList.GetFocusHdl())
+ ChangeDrawing( nDir );
+ else
+ ChangeFly( nDir, dynamic_cast<const SwWebView*>( &m_rView) != nullptr );
+ }
+ break;
+ case SwKeyState::Draw_Change :
+ ChangeDrawing( nDir );
+ break;
+ default:
+ break;
+ }
+ if( nSlotId && m_rView.GetViewFrame().GetBindings().GetRecorder().is() )
+ {
+ SfxRequest aReq(m_rView.GetViewFrame(), nSlotId);
+ aReq.Done();
+ }
+ eKeyState = SwKeyState::End;
+ }
+ }
+ }
+
+ // update the page number in the statusbar
+ nKey = rKEvt.GetKeyCode().GetCode();
+ if( KEY_UP == nKey || KEY_DOWN == nKey || KEY_PAGEUP == nKey || KEY_PAGEDOWN == nKey )
+ GetView().GetViewFrame().GetBindings().Update( FN_STAT_PAGE );
+
+ // in case the buffered characters are inserted
+ if( bFlushBuffer && !m_aInBuffer.isEmpty() )
+ {
+ FlushInBuffer();
+
+ // maybe show Tip-Help
+ if (bNormalChar)
+ {
+ const bool bAutoTextShown
+ = pACfg && pACfg->IsAutoTextTip() && ShowAutoText(rSh.GetChunkForAutoText());
+ if (!bAutoTextShown && pACorr && pACorr->GetSwFlags().bAutoCompleteWords)
+ ShowAutoCorrectQuickHelp(rSh.GetPrevAutoCorrWord(*pACorr), *pACorr);
+ }
+ }
+
+ // get the word count dialog to update itself
+ SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame().GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
+ if( pWrdCnt )
+ pWrdCnt->UpdateCounts();
+
+}
+
+/**
+ * MouseEvents
+ */
+void SwEditWin::ResetMouseButtonDownFlags()
+{
+ // Not on all systems a MouseButtonUp is used ahead
+ // of the modal dialog (like on WINDOWS).
+ // So reset the statuses here and release the mouse
+ // for the dialog.
+ m_bMBPressed = false;
+ g_bNoInterrupt = false;
+ EnterArea();
+ ReleaseMouse();
+}
+
+/**
+ * Determines if the current position has a clickable url over a background
+ * frame. In that case, ctrl-click should select the url, not the frame.
+ */
+static bool lcl_urlOverBackground(SwWrtShell& rSh, const Point& rDocPos)
+{
+ SwContentAtPos aSwContentAtPos(IsAttrAtPos::InetAttr);
+ SdrObject* pSelectableObj = rSh.GetObjAt(rDocPos);
+
+ return rSh.GetContentAtPos(rDocPos, aSwContentAtPos) && pSelectableObj->GetLayer() == rSh.GetDoc()->getIDocumentDrawModelAccess().GetHellId();
+}
+
+void SwEditWin::MoveCursor( SwWrtShell &rSh, const Point& rDocPos,
+ const bool bOnlyText, bool bLockView )
+{
+ const bool bTmpNoInterrupt = g_bNoInterrupt;
+ g_bNoInterrupt = false;
+
+ int nTmpSetCursor = 0;
+
+ if( !rSh.IsViewLocked() && bLockView )
+ rSh.LockView( true );
+ else
+ bLockView = false;
+
+ {
+ // only temporary generate move context because otherwise
+ // the query to the content form doesn't work!!!
+ SwMvContext aMvContext( &rSh );
+ nTmpSetCursor = rSh.CallSetCursor(&rDocPos, bOnlyText);
+ g_bValidCursorPos = !(CRSR_POSCHG & nTmpSetCursor);
+ }
+
+ // notify the edit window that from now on we do not use the input language
+ if ( !(CRSR_POSOLD & nTmpSetCursor) )
+ SetUseInputLanguage( false );
+
+ if( bLockView )
+ rSh.LockView( false );
+
+ g_bNoInterrupt = bTmpNoInterrupt;
+}
+
+void SwEditWin::MouseButtonDown(const MouseEvent& _rMEvt)
+{
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ const SwField *pCursorField = rSh.CursorInsideInputField() ? rSh.GetCurField( true ) : nullptr;
+
+ // We have to check if a context menu is shown and we have an UI
+ // active inplace client. In that case we have to ignore the mouse
+ // button down event. Otherwise we would crash (context menu has been
+ // opened by inplace client and we would deactivate the inplace client,
+ // the context menu is closed by VCL asynchronously which in the end
+ // would work on deleted objects or the context menu has no parent anymore)
+ SfxInPlaceClient* pIPClient = rSh.GetSfxViewShell()->GetIPClient();
+ bool bIsOleActive = ( pIPClient && pIPClient->IsObjectInPlaceActive() );
+
+ if (bIsOleActive && vcl::IsInPopupMenuExecute())
+ return;
+
+ MouseEvent aMEvt(_rMEvt);
+
+ if (m_rView.GetPostItMgr()->IsHit(aMEvt.GetPosPixel()))
+ return;
+
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(aMEvt.GetPosPixel()))
+ {
+ pWindow->MouseButtonDown(aMEvt);
+ return;
+ }
+ }
+
+ m_rView.GetPostItMgr()->SetActiveSidebarWin(nullptr);
+
+ GrabFocus();
+ rSh.addCurrentPosition();
+
+ //ignore key modifiers for format paintbrush
+ {
+ bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard
+ && m_pApplyTempl->m_pFormatClipboard->HasContent();
+ if( bExecFormatPaintbrush )
+ aMEvt = MouseEvent(_rMEvt.GetPosPixel(), _rMEvt.GetClicks(), _rMEvt.GetMode(),
+ _rMEvt.GetButtons());
+ }
+
+ m_bWasShdwCursor = nullptr != m_pShadCursor;
+ m_pShadCursor.reset();
+
+ const Point aDocPos(PixelToLogic(aMEvt.GetPosPixel()));
+
+ FrameControlType eControl;
+ bool bOverFly = false;
+ bool bPageAnchored = false;
+ bool bOverHeaderFooterFly = IsOverHeaderFooterFly( aDocPos, eControl, bOverFly, bPageAnchored );
+
+ bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly();
+ if (bOverHeaderFooterFly && (!bIsDocReadOnly && rSh.GetCurField()))
+ // We have a field here, that should have priority over header/footer fly.
+ bOverHeaderFooterFly = false;
+
+ // Are we clicking on a blank header/footer area?
+ if ( IsInHeaderFooter( aDocPos, eControl ) || bOverHeaderFooterFly )
+ {
+ const SwPageFrame* pPageFrame = rSh.GetLayout()->GetPageAtPos( aDocPos );
+
+ if ( pPageFrame )
+ {
+ // Is it active?
+ bool bActive = true;
+ const SwPageDesc* pDesc = pPageFrame->GetPageDesc();
+
+ const SwFrameFormat* pFormat = pDesc->GetLeftFormat();
+ if ( pPageFrame->OnRightPage() )
+ pFormat = pDesc->GetRightFormat();
+
+ if ( pFormat )
+ {
+ if ( eControl == FrameControlType::Header )
+ bActive = pFormat->GetHeader().IsActive();
+ else
+ bActive = pFormat->GetFooter().IsActive();
+ }
+
+ if ( !bActive )
+ {
+ // HeaderFooter menu implies header/footer controls, so only do this with IsUseHeaderFooterMenu enabled.
+ // But, additionally, when in Hide-Whitespace mode, we don't want those controls.
+ if (rSh.GetViewOptions()->IsUseHeaderFooterMenu() && !rSh.GetViewOptions()->IsHideWhitespaceMode())
+ {
+ SwPaM aPam(*rSh.GetCurrentShellCursor().GetPoint());
+ const bool bWasInHeader = aPam.GetPoint()->GetNode().FindHeaderStartNode() != nullptr;
+ const bool bWasInFooter = aPam.GetPoint()->GetNode().FindFooterStartNode() != nullptr;
+
+ // Is the cursor in a part like similar to the one we clicked on? For example,
+ // if the cursor is in a header and we click on an empty header... don't change anything to
+ // keep consistent behaviour due to header edit mode (and the same for the footer as well).
+
+ // Otherwise, we hide the header/footer control if a separator is shown, and vice versa.
+ if (!(bWasInHeader && eControl == FrameControlType::Header) &&
+ !(bWasInFooter && eControl == FrameControlType::Footer))
+ {
+ const bool bSeparatorWasVisible = rSh.IsShowHeaderFooterSeparator(eControl);
+ rSh.SetShowHeaderFooterSeparator(eControl, !bSeparatorWasVisible);
+
+ // Repaint everything
+ Invalidate();
+
+ // tdf#84929. If the footer control had not been showing, do not change the cursor position,
+ // because the user may have scrolled to turn on the separator control and
+ // if the cursor cannot be positioned on-screen, then the user would need to scroll back again to use the control.
+ // This should only be done for the footer. The cursor can always be re-positioned near the header. tdf#134023.
+ if ( eControl == FrameControlType::Footer && !bSeparatorWasVisible
+ && !Application::IsHeadlessModeEnabled() )
+ return;
+ }
+ }
+ }
+ else
+ {
+ // Make sure we have the proper Header/Footer separators shown
+ // as these may be changed if clicking on an empty Header/Footer
+ rSh.SetShowHeaderFooterSeparator( FrameControlType::Header, eControl == FrameControlType::Header );
+ rSh.SetShowHeaderFooterSeparator( FrameControlType::Footer, eControl == FrameControlType::Footer );
+
+ if ( !rSh.IsHeaderFooterEdit() )
+ rSh.ToggleHeaderFooterEdit();
+ }
+ }
+ }
+ else
+ {
+ if ( rSh.IsHeaderFooterEdit( ) )
+ rSh.ToggleHeaderFooterEdit( );
+ else
+ {
+ // Make sure that the separators are hidden
+ rSh.SetShowHeaderFooterSeparator( FrameControlType::Header, false );
+ rSh.SetShowHeaderFooterSeparator( FrameControlType::Footer, false );
+ }
+
+ // Toggle Hide-Whitespace if between pages.
+ if (rSh.GetViewOptions()->CanHideWhitespace() &&
+ rSh.GetLayout()->IsBetweenPages(aDocPos))
+ {
+ if (_rMEvt.GetClicks() >= 2)
+ {
+ SwViewOption aOpt(*rSh.GetViewOptions());
+ aOpt.SetHideWhitespaceMode(!aOpt.IsHideWhitespaceMode());
+ rSh.ApplyViewOptions(aOpt);
+ }
+
+ return;
+ }
+ }
+
+ if ( IsChainMode() )
+ {
+ SetChainMode( false );
+ SwRect aDummy;
+ SwFlyFrameFormat *pFormat = static_cast<SwFlyFrameFormat*>(rSh.GetFlyFrameFormat());
+ if ( rSh.Chainable( aDummy, *pFormat, aDocPos ) == SwChainRet::OK )
+ rSh.Chain( *pFormat, aDocPos );
+ UpdatePointer(aDocPos, aMEvt.GetModifier());
+ return;
+ }
+
+ // After GrabFocus a shell should be pushed. That should actually
+ // work but in practice ...
+ m_rView.SelectShellForDrop();
+
+ bool bCallBase = true;
+
+ if( s_pQuickHlpData->m_bIsDisplayed )
+ s_pQuickHlpData->Stop( rSh );
+ s_pQuickHlpData->m_bAppendSpace = false;
+
+ if( rSh.FinishOLEObj() )
+ return; // end InPlace and the click doesn't count anymore
+
+ CurrShell aCurr( &rSh );
+
+ SdrView *pSdrView = rSh.GetDrawView();
+ if ( pSdrView )
+ {
+ if (pSdrView->MouseButtonDown(aMEvt, GetOutDev()))
+ {
+ rSh.GetView().GetViewFrame().GetBindings().InvalidateAll(false);
+ return; // SdrView's event evaluated
+ }
+ }
+
+ m_bIsInMove = false;
+ m_aStartPos = aMEvt.GetPosPixel();
+ m_aRszMvHdlPt.setX( 0 );
+ m_aRszMvHdlPt.setY( 0 );
+
+ SwTab nMouseTabCol = SwTab::COL_NONE;
+ const bool bTmp = !rSh.IsDrawCreate() && !m_pApplyTempl && !rSh.IsInSelect()
+ && aMEvt.GetClicks() == 1 && MOUSE_LEFT == aMEvt.GetButtons();
+ if ( bTmp &&
+ SwTab::COL_NONE != (nMouseTabCol = rSh.WhichMouseTabCol( aDocPos ) ) &&
+ !rSh.IsObjSelectable( aDocPos ) )
+ {
+ // Enhanced table selection
+ if ( SwTab::SEL_HORI <= nMouseTabCol && SwTab::COLSEL_VERT >= nMouseTabCol )
+ {
+ rSh.EnterStdMode();
+ rSh.SelectTableRowCol( aDocPos );
+ if( SwTab::SEL_HORI != nMouseTabCol && SwTab::SEL_HORI_RTL != nMouseTabCol)
+ {
+ m_xRowColumnSelectionStart = aDocPos;
+ m_bIsRowDrag = SwTab::ROWSEL_HORI == nMouseTabCol||
+ SwTab::ROWSEL_HORI_RTL == nMouseTabCol ||
+ SwTab::COLSEL_VERT == nMouseTabCol;
+ m_bMBPressed = true;
+ CaptureMouse();
+ }
+ return;
+ }
+
+ if ( !rSh.IsTableMode() )
+ {
+ // comes from table columns out of the document.
+ if(SwTab::COL_VERT == nMouseTabCol || SwTab::COL_HORI == nMouseTabCol)
+ m_rView.SetTabColFromDoc( true );
+ else
+ m_rView.SetTabRowFromDoc( true );
+
+ m_rView.SetTabColFromDocPos( aDocPos );
+ m_rView.InvalidateRulerPos();
+ SfxBindings& rBind = m_rView.GetViewFrame().GetBindings();
+ rBind.Update();
+ if (RulerColumnDrag(
+ aMEvt, (SwTab::COL_VERT == nMouseTabCol || SwTab::ROW_HORI == nMouseTabCol)))
+ {
+ m_rView.SetTabColFromDoc( false );
+ m_rView.SetTabRowFromDoc( false );
+ m_rView.InvalidateRulerPos();
+ rBind.Update();
+ bCallBase = false;
+ }
+ else
+ {
+ return;
+ }
+ }
+ }
+ else if (bTmp &&
+ rSh.IsNumLabel(aDocPos))
+ {
+ SwTextNode* pNodeAtPos = rSh.GetNumRuleNodeAtPos( aDocPos );
+ m_rView.SetNumRuleNodeFromDoc( pNodeAtPos );
+ m_rView.InvalidateRulerPos();
+ SfxBindings& rBind = m_rView.GetViewFrame().GetBindings();
+ rBind.Update();
+
+ if (RulerMarginDrag(aMEvt, SwFEShell::IsVerticalModeAtNdAndPos(*pNodeAtPos, aDocPos)))
+ {
+ m_rView.SetNumRuleNodeFromDoc( nullptr );
+ m_rView.InvalidateRulerPos();
+ rBind.Update();
+ bCallBase = false;
+ }
+ else
+ {
+ // Make sure the pointer is set to 0, otherwise it may point to
+ // nowhere after deleting the corresponding text node.
+ m_rView.SetNumRuleNodeFromDoc( nullptr );
+ return;
+ }
+ }
+
+ if ( rSh.IsInSelect() )
+ rSh.EndSelect();
+
+ // query against LEFT because otherwise for example also a right
+ // click releases the selection.
+ if (MOUSE_LEFT == aMEvt.GetButtons())
+ {
+ bool bOnlyText = false;
+ m_bMBPressed = true;
+ g_bNoInterrupt = true;
+ m_nKS_NUMDOWN_Count = 0;
+
+ CaptureMouse();
+
+ // reset cursor position if applicable
+ rSh.ResetCursorStack();
+
+ switch (aMEvt.GetModifier() + aMEvt.GetButtons())
+ {
+ case MOUSE_LEFT:
+ case MOUSE_LEFT + KEY_SHIFT:
+ case MOUSE_LEFT + KEY_MOD2:
+ if( rSh.IsObjSelected() )
+ {
+ SdrHdl* pHdl;
+ if( !bIsDocReadOnly &&
+ !m_pAnchorMarker &&
+ pSdrView &&
+ nullptr != ( pHdl = pSdrView->PickHandle(aDocPos) ) &&
+ ( pHdl->GetKind() == SdrHdlKind::Anchor ||
+ pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
+ {
+ // #i121463# Set selected during drag
+ pHdl->SetSelected();
+ m_pAnchorMarker.reset( new SwAnchorMarker( pHdl ) );
+ UpdatePointer(aDocPos, aMEvt.GetModifier());
+ return;
+ }
+ }
+ if (EnterDrawMode(aMEvt, aDocPos))
+ {
+ g_bNoInterrupt = false;
+ return;
+ }
+ else if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
+ {
+ StopInsFrame();
+ rSh.Edit();
+ }
+
+ // Without SHIFT because otherwise Toggle doesn't work at selection
+ if (aMEvt.GetClicks() == 1)
+ {
+ if ( rSh.IsSelFrameMode())
+ {
+ SdrHdl* pHdl = rSh.GetDrawView()->PickHandle(aDocPos);
+ bool bHitHandle = pHdl && pHdl->GetKind() != SdrHdlKind::Anchor &&
+ pHdl->GetKind() != SdrHdlKind::Anchor_TR;
+
+ if ((rSh.IsInsideSelectedObj(aDocPos) || bHitHandle)
+ && (aMEvt.GetModifier() != KEY_SHIFT || bHitHandle))
+ {
+ rSh.EnterSelFrameMode( &aDocPos );
+ if ( !m_pApplyTempl )
+ {
+ // only if no position to size was hit.
+ if (!bHitHandle)
+ {
+ StartDDTimer();
+ SwEditWin::s_nDDStartPosY = aDocPos.Y();
+ SwEditWin::s_nDDStartPosX = aDocPos.X();
+ }
+ g_bFrameDrag = true;
+ }
+ g_bNoInterrupt = false;
+ return;
+ }
+ }
+ }
+ }
+
+ bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
+ if ( !bExecHyperlinks )
+ {
+ const bool bSecureOption = SvtSecurityOptions::IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink );
+ if ((bSecureOption && aMEvt.GetModifier() == KEY_MOD1)
+ || (!bSecureOption && aMEvt.GetModifier() != KEY_MOD1))
+ bExecHyperlinks = true;
+ }
+
+ // Enhanced selection
+ sal_uInt8 nNumberOfClicks = static_cast<sal_uInt8>(aMEvt.GetClicks() % 4);
+ if (0 == nNumberOfClicks && 0 < aMEvt.GetClicks())
+ nNumberOfClicks = 4;
+
+ bool bExecDrawTextLink = false;
+
+ switch (aMEvt.GetModifier() + aMEvt.GetButtons())
+ {
+ case MOUSE_LEFT:
+ case MOUSE_LEFT + KEY_MOD1:
+ case MOUSE_LEFT + KEY_MOD2:
+ {
+
+ // fdo#79604: first, check if a link has been clicked - do not
+ // select fly in this case!
+ if (1 == nNumberOfClicks)
+ {
+ UpdatePointer(aDocPos, aMEvt.GetModifier());
+ SwEditWin::s_nDDStartPosY = aDocPos.Y();
+ SwEditWin::s_nDDStartPosX = aDocPos.X();
+
+ // hit a URL in DrawText object?
+ if (bExecHyperlinks && pSdrView)
+ {
+ SdrViewEvent aVEvt;
+ pSdrView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
+
+ if (aVEvt.meEvent == SdrEventKind::ExecuteUrl)
+ bExecDrawTextLink = true;
+ }
+ }
+
+ if (1 == nNumberOfClicks && !bExecDrawTextLink)
+ {
+ // only try to select frame, if pointer already was
+ // switched accordingly
+ if ( m_aActHitType != SdrHitKind::NONE && !rSh.IsSelFrameMode() &&
+ !GetView().GetViewFrame().GetDispatcher()->IsLocked())
+ {
+ // Test if there is a draw object at that position and if it should be selected.
+ bool bShould = rSh.ShouldObjectBeSelected(aDocPos);
+
+ if(bShould)
+ {
+ m_rView.NoRotate();
+ rSh.HideCursor();
+
+ bool bUnLockView = !rSh.IsViewLocked();
+ rSh.LockView( true );
+ bool bSelObj
+ = rSh.SelectObj(aDocPos, aMEvt.IsMod1() ? SW_ENTER_GROUP : 0);
+ if( bUnLockView )
+ rSh.LockView( false );
+
+ if( bSelObj )
+ {
+ // if the frame was deselected in the macro
+ // the cursor just has to be displayed again
+ if( FrameTypeFlags::NONE == rSh.GetSelFrameType() )
+ rSh.ShowCursor();
+ else
+ {
+ if (rSh.IsFrameSelected() && m_rView.GetDrawFuncPtr())
+ {
+ m_rView.GetDrawFuncPtr()->Deactivate();
+ m_rView.SetDrawFuncPtr(nullptr);
+ m_rView.LeaveDrawCreate();
+ m_rView.AttrChangedNotify(nullptr);
+ }
+
+ rSh.EnterSelFrameMode( &aDocPos );
+ g_bFrameDrag = true;
+ UpdatePointer(aDocPos, aMEvt.GetModifier());
+ }
+ return;
+ }
+ else
+ bOnlyText = rSh.IsObjSelectable( aDocPos );
+
+ if (!m_rView.GetDrawFuncPtr())
+ rSh.ShowCursor();
+ }
+ else
+ bOnlyText = KEY_MOD1 != aMEvt.GetModifier();
+ }
+ else if ( rSh.IsSelFrameMode() &&
+ (m_aActHitType == SdrHitKind::NONE ||
+ !rSh.IsInsideSelectedObj( aDocPos )))
+ {
+ m_rView.NoRotate();
+ SdrHdl *pHdl;
+ if( !bIsDocReadOnly && !m_pAnchorMarker && nullptr !=
+ ( pHdl = pSdrView->PickHandle(aDocPos) ) &&
+ ( pHdl->GetKind() == SdrHdlKind::Anchor ||
+ pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
+ {
+ m_pAnchorMarker.reset( new SwAnchorMarker( pHdl ) );
+ UpdatePointer(aDocPos, aMEvt.GetModifier());
+ return;
+ }
+ else
+ {
+ bool bUnLockView = !rSh.IsViewLocked();
+ rSh.LockView( true );
+ sal_uInt8 nFlag = aMEvt.IsShift() ? SW_ADD_SELECT : 0;
+ if (aMEvt.IsMod1())
+ nFlag = nFlag | SW_ENTER_GROUP;
+
+ if ( rSh.IsSelFrameMode() )
+ {
+ rSh.UnSelectFrame();
+ rSh.LeaveSelFrameMode();
+ m_rView.AttrChangedNotify(nullptr);
+ }
+
+ bool bSelObj = rSh.SelectObj( aDocPos, nFlag );
+ if( bUnLockView )
+ rSh.LockView( false );
+
+ if( !bSelObj )
+ {
+ // move cursor here so that it is not drawn in the
+ // frame first; ShowCursor() happens in LeaveSelFrameMode()
+ g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
+ rSh.LeaveSelFrameMode();
+ m_rView.AttrChangedNotify(nullptr);
+ bCallBase = false;
+ }
+ else
+ {
+ rSh.HideCursor();
+ rSh.EnterSelFrameMode( &aDocPos );
+ rSh.SelFlyGrabCursor();
+ rSh.MakeSelVisible();
+ g_bFrameDrag = true;
+ if( rSh.IsFrameSelected() &&
+ m_rView.GetDrawFuncPtr() )
+ {
+ m_rView.GetDrawFuncPtr()->Deactivate();
+ m_rView.SetDrawFuncPtr(nullptr);
+ m_rView.LeaveDrawCreate();
+ m_rView.AttrChangedNotify(nullptr);
+ }
+ UpdatePointer(aDocPos, aMEvt.GetModifier());
+ return;
+ }
+ }
+ }
+ }
+
+ switch ( nNumberOfClicks )
+ {
+ case 1:
+ break;
+ case 2:
+ {
+ g_bFrameDrag = false;
+ if (!bIsDocReadOnly && rSh.IsInsideSelectedObj(aDocPos)
+ && (FlyProtectFlags::NONE
+ == rSh.IsSelObjProtected(FlyProtectFlags::Content
+ | FlyProtectFlags::Parent)
+ || rSh.GetSelectionType() == SelectionType::Ole))
+ {
+ /* This is no good: on the one hand GetSelectionType is used as flag field
+ * (take a look into the GetSelectionType method) and on the other hand the
+ * return value is used in a switch without proper masking (very nice), this must lead to trouble
+ */
+ switch ( rSh.GetSelectionType() & ~SelectionType( SelectionType::FontWork | SelectionType::ExtrudedCustomShape ) )
+ {
+ case SelectionType::Graphic:
+ ResetMouseButtonDownFlags();
+ if (!comphelper::LibreOfficeKit::isActive())
+ {
+ GetView().GetViewFrame().GetBindings().Execute(
+ FN_FORMAT_GRAFIC_DLG, nullptr,
+ SfxCallMode::RECORD|SfxCallMode::SLOT);
+ }
+ return;
+
+ // double click on OLE object --> OLE-InPlace
+ case SelectionType::Ole:
+ ResetMouseButtonDownFlags();
+ rSh.LaunchOLEObj();
+ return;
+
+ case SelectionType::Frame:
+ ResetMouseButtonDownFlags();
+ if (!comphelper::LibreOfficeKit::isActive())
+ {
+ GetView().GetViewFrame().GetBindings().Execute(
+ FN_FORMAT_FRAME_DLG, nullptr,
+ SfxCallMode::RECORD|SfxCallMode::SLOT);
+ }
+ return;
+
+ case SelectionType::DrawObject:
+ ResetMouseButtonDownFlags();
+ EnterDrawTextMode(aDocPos);
+ if ( auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>( m_rView.GetCurShell() ) )
+ pSwDrawTextShell->Init();
+ return;
+
+ default: break;
+ }
+ }
+
+ // if the cursor position was corrected or if a Fly
+ // was selected in ReadOnlyMode, no word selection, except when tiled rendering.
+ if ((!g_bValidCursorPos || rSh.IsFrameSelected()) && !comphelper::LibreOfficeKit::isActive())
+ return;
+
+ SwField *pField;
+ bool bFootnote = false;
+
+ if( !bIsDocReadOnly &&
+ (nullptr != (pField = rSh.GetCurField(true)) ||
+ ( bFootnote = rSh.GetCurFootnote() ) ) )
+ {
+ ResetMouseButtonDownFlags();
+ if( bFootnote )
+ GetView().GetViewFrame().GetBindings().Execute( FN_EDIT_FOOTNOTE );
+ else
+ {
+ SwFieldTypesEnum nTypeId = pField->GetTypeId();
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+ switch( nTypeId )
+ {
+ case SwFieldTypesEnum::Postit:
+ case SwFieldTypesEnum::Script:
+ {
+ // if it's a Readonly region, status has to be enabled
+ sal_uInt16 nSlot = SwFieldTypesEnum::Postit == nTypeId ? FN_POSTIT : FN_JAVAEDIT;
+ SfxBoolItem aItem(nSlot, true);
+ rVFrame.GetBindings().SetState(aItem);
+ rVFrame.GetBindings().Execute(nSlot);
+ break;
+ }
+ case SwFieldTypesEnum::Authority :
+ rVFrame.GetBindings().Execute(FN_EDIT_AUTH_ENTRY_DLG);
+ break;
+ case SwFieldTypesEnum::Input:
+ case SwFieldTypesEnum::Dropdown:
+ case SwFieldTypesEnum::SetInput:
+ rVFrame.GetBindings().Execute(FN_UPDATE_INPUTFIELDS);
+ break;
+ default:
+ rVFrame.GetBindings().Execute(FN_EDIT_FIELD);
+ }
+ }
+ return;
+ }
+ // in extended mode double and triple
+ // click has no effect.
+ if ( rSh.IsExtMode() || rSh.IsBlockMode() )
+ return;
+
+ // select word, AdditionalMode if applicable
+ if (KEY_MOD1 == aMEvt.GetModifier() && !rSh.IsAddMode())
+ {
+ rSh.EnterAddMode();
+ rSh.SelWrd( &aDocPos );
+ rSh.LeaveAddMode();
+ }
+ else
+ {
+ if (!rSh.SelWrd(&aDocPos) && comphelper::LibreOfficeKit::isActive())
+ // Double click did not select any word: try to
+ // select the current cell in case we are in a
+ // table.
+ rSh.SelTableBox();
+ }
+
+ SwContentAtPos aContentAtPos(IsAttrAtPos::FormControl);
+ if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) &&
+ aContentAtPos.aFnd.pFieldmark != nullptr)
+ {
+ IFieldmark *pFieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark );
+ if ( pFieldBM->GetFieldname( ) == ODF_FORMDROPDOWN || pFieldBM->GetFieldname( ) == ODF_FORMDATE )
+ {
+ ResetMouseButtonDownFlags();
+ rSh.getIDocumentMarkAccess()->ClearFieldActivation();
+ GetView().GetViewFrame().GetBindings().Execute(SID_FM_CTL_PROPERTIES);
+ return;
+ }
+ }
+
+ // tdf#143158 - handle alphabetical index entries
+ SwContentAtPos aToxContentAtPos(IsAttrAtPos::ToxMark);
+ if (rSh.GetContentAtPos(aDocPos, aToxContentAtPos))
+ {
+ const OUString sToxText = aToxContentAtPos.sStr;
+ if (!sToxText.isEmpty() && aToxContentAtPos.pFndTextAttr)
+ {
+ const SwTOXType* pTType
+ = aToxContentAtPos.pFndTextAttr->GetTOXMark().GetTOXType();
+ if (pTType && pTType->GetType() == TOXTypes::TOX_INDEX)
+ {
+ ResetMouseButtonDownFlags();
+ GetView().GetViewFrame().GetBindings().Execute(
+ FN_EDIT_IDX_ENTRY_DLG);
+ return;
+ }
+ }
+ }
+
+ g_bHoldSelection = true;
+ return;
+ }
+ case 3:
+ case 4:
+ {
+ g_bFrameDrag = false;
+ // in extended mode double and triple
+ // click has no effect.
+ if ( rSh.IsExtMode() )
+ return;
+
+ // if the cursor position was corrected or if a Fly
+ // was selected in ReadOnlyMode, no word selection.
+ if ( !g_bValidCursorPos || rSh.IsFrameSelected() )
+ return;
+
+ // select line, AdditionalMode if applicable
+ const bool bMod = KEY_MOD1 == aMEvt.GetModifier() && !rSh.IsAddMode();
+
+ if ( bMod )
+ rSh.EnterAddMode();
+
+ // Enhanced selection
+ if ( 3 == nNumberOfClicks )
+ rSh.SelSentence( &aDocPos );
+ else
+ rSh.SelPara( &aDocPos );
+
+ if ( bMod )
+ rSh.LeaveAddMode();
+
+ g_bHoldSelection = true;
+ return;
+ }
+
+ default:
+ return;
+ }
+
+ [[fallthrough]];
+ }
+ case MOUSE_LEFT + KEY_SHIFT:
+ case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
+ {
+ bool bLockView = m_bWasShdwCursor;
+
+ switch (aMEvt.GetModifier())
+ {
+ case KEY_MOD1 + KEY_SHIFT:
+ {
+ if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) )
+ {
+ m_rView.NoRotate();
+ rSh.HideCursor();
+ if ( rSh.IsSelFrameMode() )
+ rSh.SelectObj(aDocPos, SW_ADD_SELECT | SW_ENTER_GROUP);
+ else
+ { if ( rSh.SelectObj( aDocPos, SW_ADD_SELECT | SW_ENTER_GROUP ) )
+ {
+ rSh.EnterSelFrameMode( &aDocPos );
+ SwEditWin::s_nDDStartPosY = aDocPos.Y();
+ SwEditWin::s_nDDStartPosX = aDocPos.X();
+ g_bFrameDrag = true;
+ return;
+ }
+ }
+ }
+ else if( rSh.IsSelFrameMode() &&
+ rSh.GetDrawView()->PickHandle( aDocPos ))
+ {
+ g_bFrameDrag = true;
+ g_bNoInterrupt = false;
+ return;
+ }
+ }
+ break;
+ case KEY_MOD1:
+ if ( !bExecDrawTextLink )
+ {
+ if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ {
+ // ctrl+left-click on outline node frame
+ SwContentAtPos aContentAtPos(IsAttrAtPos::Outline);
+ if(rSh.GetContentAtPos(aDocPos, aContentAtPos))
+ {
+ SwOutlineNodes::size_type nPos;
+ if (rSh.GetNodes().GetOutLineNds().Seek_Entry(aContentAtPos.aFnd.pNode, &nPos))
+ {
+ ToggleOutlineContentVisibility(nPos, false);
+ return;
+ }
+ }
+ }
+ if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) && !lcl_urlOverBackground( rSh, aDocPos ) )
+ {
+ m_rView.NoRotate();
+ rSh.HideCursor();
+ if ( rSh.IsSelFrameMode() )
+ rSh.SelectObj(aDocPos, SW_ENTER_GROUP);
+ else
+ { if ( rSh.SelectObj( aDocPos, SW_ENTER_GROUP ) )
+ {
+ rSh.EnterSelFrameMode( &aDocPos );
+ SwEditWin::s_nDDStartPosY = aDocPos.Y();
+ SwEditWin::s_nDDStartPosX = aDocPos.X();
+ g_bFrameDrag = true;
+ return;
+ }
+ }
+ }
+ else if( rSh.IsSelFrameMode() &&
+ rSh.GetDrawView()->PickHandle( aDocPos ))
+ {
+ g_bFrameDrag = true;
+ g_bNoInterrupt = false;
+ return;
+ }
+ else
+ {
+ if ( !rSh.IsAddMode() && !rSh.IsExtMode() && !rSh.IsBlockMode() )
+ {
+ rSh.PushMode();
+ g_bModePushed = true;
+
+ bool bUnLockView = !rSh.IsViewLocked();
+ rSh.LockView( true );
+ rSh.EnterAddMode();
+ if( bUnLockView )
+ rSh.LockView( false );
+ }
+ bCallBase = false;
+ }
+ }
+ break;
+ case KEY_MOD2:
+ {
+ if ( !rSh.IsAddMode() && !rSh.IsExtMode() && !rSh.IsBlockMode() )
+ {
+ rSh.PushMode();
+ g_bModePushed = true;
+ bool bUnLockView = !rSh.IsViewLocked();
+ rSh.LockView( true );
+ rSh.EnterBlockMode();
+ if( bUnLockView )
+ rSh.LockView( false );
+ }
+ bCallBase = false;
+ }
+ break;
+ case KEY_SHIFT:
+ {
+ if (nNumberOfClicks == 2)
+ {
+ // Left mouse button, shift, double-click: see if we have a graphic and
+ // dispatch its dialog in this case.
+ if (rSh.GetSelectionType() == SelectionType::Graphic)
+ {
+ GetView().GetViewFrame().GetBindings().Execute(
+ FN_FORMAT_GRAFIC_DLG, nullptr,
+ SfxCallMode::RECORD | SfxCallMode::SLOT);
+ return;
+ }
+ }
+
+ if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) )
+ {
+ m_rView.NoRotate();
+ rSh.HideCursor();
+ if ( rSh.IsSelFrameMode() )
+ {
+ rSh.SelectObj(aDocPos, SW_ADD_SELECT);
+
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ if (rMarkList.GetMark(0) == nullptr)
+ {
+ rSh.LeaveSelFrameMode();
+ m_rView.AttrChangedNotify(nullptr);
+ g_bFrameDrag = false;
+ }
+ }
+ else
+ { if ( rSh.SelectObj( aDocPos ) )
+ {
+ rSh.EnterSelFrameMode( &aDocPos );
+ SwEditWin::s_nDDStartPosY = aDocPos.Y();
+ SwEditWin::s_nDDStartPosX = aDocPos.X();
+ g_bFrameDrag = true;
+ return;
+ }
+ }
+ }
+ else
+ {
+ bool bShould = rSh.ShouldObjectBeSelected(aDocPos);
+ if (bShould)
+ {
+ // Left mouse button, shift, non-double-click, not a draw object and
+ // have an object to select: select it.
+ rSh.HideCursor();
+ bool bSelObj = rSh.SelectObj(aDocPos);
+ if (bSelObj)
+ {
+ rSh.EnterSelFrameMode(&aDocPos);
+ }
+ return;
+ }
+
+ if ( rSh.IsSelFrameMode() &&
+ rSh.IsInsideSelectedObj( aDocPos ) )
+ {
+ rSh.EnterSelFrameMode( &aDocPos );
+ SwEditWin::s_nDDStartPosY = aDocPos.Y();
+ SwEditWin::s_nDDStartPosX = aDocPos.X();
+ g_bFrameDrag = true;
+ return;
+ }
+ if ( rSh.IsSelFrameMode() )
+ {
+ rSh.UnSelectFrame();
+ rSh.LeaveSelFrameMode();
+ m_rView.AttrChangedNotify(nullptr);
+ g_bFrameDrag = false;
+ }
+ if ( !rSh.IsExtMode() )
+ {
+ // don't start a selection when an
+ // URL field or a graphic is clicked
+ bool bSttSelect = rSh.HasSelection() ||
+ PointerStyle::RefHand != GetPointer();
+
+ if( !bSttSelect )
+ {
+ bSttSelect = true;
+ if( bExecHyperlinks )
+ {
+ SwContentAtPos aContentAtPos(
+ IsAttrAtPos::Ftn |
+ IsAttrAtPos::InetAttr );
+
+ if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) )
+ {
+ if( !rSh.IsViewLocked() &&
+ !rSh.IsReadOnlyAvailable() &&
+ aContentAtPos.IsInProtectSect() )
+ bLockView = true;
+
+ bSttSelect = false;
+ }
+ else if( rSh.IsURLGrfAtPos( aDocPos ))
+ bSttSelect = false;
+ }
+ }
+
+ if( bSttSelect )
+ rSh.SttSelect();
+ }
+ }
+ bCallBase = false;
+ break;
+ }
+ default:
+ if( !rSh.IsViewLocked() )
+ {
+ SwContentAtPos aContentAtPos( IsAttrAtPos::ClickField |
+ IsAttrAtPos::InetAttr );
+ if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) &&
+ !rSh.IsReadOnlyAvailable() &&
+ aContentAtPos.IsInProtectSect() )
+ bLockView = true;
+ }
+ }
+
+ if ( rSh.IsGCAttr() )
+ {
+ rSh.GCAttr();
+ rSh.ClearGCAttr();
+ }
+
+ SwContentAtPos aFieldAtPos(IsAttrAtPos::Field);
+ bool bEditableFieldClicked = false;
+
+ // Are we clicking on a field?
+ if (rSh.GetContentAtPos(aDocPos, aFieldAtPos))
+ {
+ bool bEditableField = (aFieldAtPos.pFndTextAttr != nullptr
+ && aFieldAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD);
+
+ if (!bEditableField)
+ {
+ rSh.CallSetCursor(&aDocPos, bOnlyText);
+ // Unfortunately the cursor may be on field
+ // position or on position after field depending on which
+ // half of the field was clicked on.
+ SwTextAttr const*const pTextField(aFieldAtPos.pFndTextAttr);
+ if (pTextField &&
+ rSh.GetCurrentShellCursor().GetPoint()->GetContentIndex() != pTextField->GetStart())
+ {
+ assert(rSh.GetCurrentShellCursor().GetPoint()->GetContentIndex() == (pTextField->GetStart() + 1));
+ rSh.Left( SwCursorSkipMode::Chars, false, 1, false );
+ }
+ // don't go into the !bOverSelect block below - it moves
+ // the cursor
+ break;
+ }
+ else
+ {
+ bEditableFieldClicked = true;
+ }
+ }
+
+ bool bOverSelect = rSh.TestCurrPam( aDocPos );
+ bool bOverURLGrf = false;
+ if( !bOverSelect )
+ bOverURLGrf = bOverSelect = nullptr != rSh.IsURLGrfAtPos( aDocPos );
+
+ if ( !bOverSelect || rSh.IsInSelect() )
+ {
+ MoveCursor( rSh, aDocPos, bOnlyText, bLockView );
+ bCallBase = false;
+ }
+ if (!bOverURLGrf && !bExecDrawTextLink && !bOnlyText)
+ {
+ const SelectionType nSelType = rSh.GetSelectionType();
+ // Check in general, if an object is selectable at given position.
+ // Thus, also text fly frames in background become selectable via Ctrl-Click.
+ if ( ( nSelType & SelectionType::Ole ||
+ nSelType & SelectionType::Graphic ||
+ rSh.IsObjSelectable( aDocPos ) ) && !lcl_urlOverBackground( rSh, aDocPos ) )
+ {
+ SwMvContext aMvContext( &rSh );
+ rSh.EnterSelFrameMode();
+ bCallBase = false;
+ }
+ }
+ if ( !bOverSelect && bEditableFieldClicked && (!pCursorField ||
+ pCursorField != aFieldAtPos.pFndTextAttr->GetFormatField().GetField()))
+ {
+ // select content of Input Field, but exclude CH_TXT_ATR_INPUTFIELDSTART
+ // and CH_TXT_ATR_INPUTFIELDEND
+ rSh.SttSelect();
+ rSh.SelectTextModel( aFieldAtPos.pFndTextAttr->GetStart() + 1,
+ *(aFieldAtPos.pFndTextAttr->End()) - 1 );
+ }
+ // don't reset here any longer so that, in case through MouseMove
+ // with pressed Ctrl key a multiple-selection should happen,
+ // the previous selection is not released in Drag.
+ break;
+ }
+ }
+ }
+ else if (MOUSE_RIGHT == aMEvt.GetButtons())
+ {
+ if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton()
+ && aMEvt.GetModifier() == KEY_MOD1)
+ {
+ // ctrl+right-click on outline node frame
+ SwContentAtPos aContentAtPos(IsAttrAtPos::Outline);
+ if(rSh.GetContentAtPos(aDocPos, aContentAtPos))
+ {
+ SwOutlineNodes::size_type nPos;
+ if (rSh.GetNodes().GetOutLineNds().Seek_Entry(aContentAtPos.aFnd.pNode, &nPos))
+ {
+ ToggleOutlineContentVisibility(nPos, !rSh.GetViewOptions()->IsTreatSubOutlineLevelsAsContent());
+ return;
+ }
+ }
+ }
+ else if (!aMEvt.GetModifier() && static_cast<sal_uInt8>(aMEvt.GetClicks() % 4) == 1
+ && !rSh.TestCurrPam(aDocPos))
+ {
+ SwContentAtPos aFieldAtPos(IsAttrAtPos::Field);
+
+ // Are we clicking on a field?
+ if (g_bValidCursorPos
+ && rSh.GetContentAtPos(aDocPos, aFieldAtPos)
+ && aFieldAtPos.pFndTextAttr != nullptr
+ && aFieldAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD
+ && (!pCursorField || pCursorField != aFieldAtPos.pFndTextAttr->GetFormatField().GetField()))
+ {
+ // Move the cursor
+ MoveCursor( rSh, aDocPos, rSh.IsObjSelectable( aDocPos ), m_bWasShdwCursor );
+ bCallBase = false;
+
+ // select content of Input Field, but exclude CH_TXT_ATR_INPUTFIELDSTART
+ // and CH_TXT_ATR_INPUTFIELDEND
+ rSh.SttSelect();
+ rSh.SelectTextModel( aFieldAtPos.pFndTextAttr->GetStart() + 1,
+ *(aFieldAtPos.pFndTextAttr->End()) - 1 );
+ }
+ }
+ }
+
+ if (bCallBase)
+ Window::MouseButtonDown(aMEvt);
+}
+
+bool SwEditWin::changeMousePointer(Point const & rDocPoint)
+{
+ SwWrtShell & rShell = m_rView.GetWrtShell();
+
+ SwTab nMouseTabCol;
+ if ( SwTab::COL_NONE != (nMouseTabCol = rShell.WhichMouseTabCol( rDocPoint ) ) &&
+ !rShell.IsObjSelectable( rDocPoint ) )
+ {
+ PointerStyle nPointer = PointerStyle::Null;
+ bool bChkTableSel = false;
+
+ switch ( nMouseTabCol )
+ {
+ case SwTab::COL_VERT :
+ case SwTab::ROW_HORI :
+ nPointer = PointerStyle::VSizeBar;
+ bChkTableSel = true;
+ break;
+ case SwTab::ROW_VERT :
+ case SwTab::COL_HORI :
+ nPointer = PointerStyle::HSizeBar;
+ bChkTableSel = true;
+ break;
+ // Enhanced table selection
+ case SwTab::SEL_HORI :
+ nPointer = PointerStyle::TabSelectSE;
+ break;
+ case SwTab::SEL_HORI_RTL :
+ case SwTab::SEL_VERT :
+ nPointer = PointerStyle::TabSelectSW;
+ break;
+ case SwTab::COLSEL_HORI :
+ case SwTab::ROWSEL_VERT :
+ nPointer = PointerStyle::TabSelectS;
+ break;
+ case SwTab::ROWSEL_HORI :
+ nPointer = PointerStyle::TabSelectE;
+ break;
+ case SwTab::ROWSEL_HORI_RTL :
+ case SwTab::COLSEL_VERT :
+ nPointer = PointerStyle::TabSelectW;
+ break;
+ default: break; // prevent compiler warning
+ }
+
+ if ( PointerStyle::Null != nPointer &&
+ // i#35543 - Enhanced table selection is explicitly allowed in table mode
+ ( !bChkTableSel || !rShell.IsTableMode() ) &&
+ !comphelper::LibreOfficeKit::isActive() )
+ {
+ SetPointer( nPointer );
+ }
+
+ return true;
+ }
+ else if (rShell.IsNumLabel(rDocPoint, RULER_MOUSE_MARGINWIDTH))
+ {
+ // i#42921 - consider vertical mode
+ SwTextNode* pNodeAtPos = rShell.GetNumRuleNodeAtPos( rDocPoint );
+ const PointerStyle nPointer =
+ SwFEShell::IsVerticalModeAtNdAndPos( *pNodeAtPos, rDocPoint )
+ ? PointerStyle::VSizeBar
+ : PointerStyle::HSizeBar;
+ SetPointer( nPointer );
+
+ return true;
+ }
+ return false;
+}
+
+void SwEditWin::MouseMove(const MouseEvent& _rMEvt)
+{
+ MouseEvent rMEvt(_rMEvt);
+
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
+ {
+ pWindow->MouseMove(rMEvt);
+ return;
+ }
+ }
+
+ //ignore key modifiers for format paintbrush
+ {
+ bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard
+ && m_pApplyTempl->m_pFormatClipboard->HasContent();
+ if( bExecFormatPaintbrush )
+ rMEvt = MouseEvent( _rMEvt.GetPosPixel(), _rMEvt.GetClicks(),
+ _rMEvt.GetMode(), _rMEvt.GetButtons() );
+ }
+
+ // as long as an action is running the MouseMove should be disconnected
+ // otherwise bug 40102 occurs
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ if( rSh.ActionPend() )
+ return ;
+
+ if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ {
+ // add/remove outline content hide button
+ const SwNodes& rNds = rSh.GetDoc()->GetNodes();
+ SwOutlineNodes::size_type nPos;
+ SwContentAtPos aSwContentAtPos(IsAttrAtPos::Outline);
+ if (rSh.GetContentAtPos(PixelToLogic(rMEvt.GetPosPixel()), aSwContentAtPos))
+ {
+ // mouse pointer is on an outline paragraph node
+ if(aSwContentAtPos.aFnd.pNode && aSwContentAtPos.aFnd.pNode->IsTextNode())
+ {
+ // Get the outline paragraph frame and compare it to the saved outline frame. If they
+ // are not the same, remove the fold button from the saved outline frame, if not
+ // already removed, and then add a fold button to the mouse over outline frame if
+ // the content is not folded.
+ SwContentFrame* pContentFrame =
+ aSwContentAtPos.aFnd.pNode->GetTextNode()->getLayoutFrame(rSh.GetLayout());
+ if (pContentFrame != m_pSavedOutlineFrame)
+ {
+ if (m_pSavedOutlineFrame)
+ {
+ if (m_pSavedOutlineFrame->isFrameAreaDefinitionValid())
+ {
+ SwTextNode* pTextNode = m_pSavedOutlineFrame->GetTextNodeFirst();
+ if (pTextNode && rNds.GetOutLineNds().Seek_Entry(pTextNode, &nPos) &&
+ rSh.GetAttrOutlineContentVisible(nPos))
+ {
+ GetFrameControlsManager().RemoveControlsByType(
+ FrameControlType::Outline, m_pSavedOutlineFrame);
+ }
+ }
+ }
+ m_pSavedOutlineFrame = static_cast<SwTextFrame*>(pContentFrame);
+ }
+ // show fold button if outline content is visible
+ if (rNds.GetOutLineNds().Seek_Entry(aSwContentAtPos.aFnd.pNode->GetTextNode(), &nPos) &&
+ rSh.GetAttrOutlineContentVisible(nPos))
+ GetFrameControlsManager().SetOutlineContentVisibilityButton(pContentFrame);
+ }
+ }
+ else if (m_pSavedOutlineFrame)
+ {
+ // The saved frame may not still be in the document, e.g., when an outline paragraph
+ // is deleted. This causes the call to GetTextNodeFirst to behave badly. Use
+ // isFrameAreaDefinitionValid to check if the frame is still in the document.
+ if (m_pSavedOutlineFrame->isFrameAreaDefinitionValid())
+ {
+ // current pointer pos is not over an outline frame
+ // previous pointer pos was over an outline frame
+ // remove outline content visibility button if showing
+ SwTextNode* pTextNode = m_pSavedOutlineFrame->GetTextNodeFirst();
+ if (pTextNode && rNds.GetOutLineNds().Seek_Entry(pTextNode, &nPos) &&
+ rSh.GetAttrOutlineContentVisible(nPos))
+ {
+ GetFrameControlsManager().RemoveControlsByType(
+ FrameControlType::Outline, m_pSavedOutlineFrame);
+ }
+ }
+ m_pSavedOutlineFrame = nullptr;
+ }
+ }
+
+ if( m_pShadCursor && 0 != (rMEvt.GetModifier() + rMEvt.GetButtons() ) )
+ {
+ m_pShadCursor.reset();
+ }
+
+ bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly();
+
+ CurrShell aCurr( &rSh );
+
+ //aPixPt == Point in Pixel, relative to ChildWin
+ //aDocPt == Point in Twips, document coordinates
+ const Point aPixPt( rMEvt.GetPosPixel() );
+ const Point aDocPt( PixelToLogic( aPixPt ) );
+
+ if ( IsChainMode() )
+ {
+ UpdatePointer( aDocPt, rMEvt.GetModifier() );
+ return;
+ }
+
+ SdrView *pSdrView = rSh.GetDrawView();
+
+ const SwCallMouseEvent aLastCallEvent( m_aSaveCallEvent );
+ m_aSaveCallEvent.Clear();
+
+ if ( !bIsDocReadOnly && pSdrView && pSdrView->MouseMove(rMEvt,GetOutDev()) )
+ {
+ SetPointer( PointerStyle::Text );
+ return; // evaluate SdrView's event
+ }
+
+ const Point aOldPt( rSh.VisArea().Pos() );
+ const bool bInsWin = rSh.VisArea().Contains( aDocPt ) || comphelper::LibreOfficeKit::isActive();
+
+ if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ {
+ if (m_pSavedOutlineFrame && !bInsWin)
+ {
+ // the mouse pointer has left the building (edit window)
+ // remove the outline content visibility button if showing
+ if (m_pSavedOutlineFrame->isFrameAreaDefinitionValid())
+ {
+ const SwNodes& rNds = rSh.GetDoc()->GetNodes();
+ SwOutlineNodes::size_type nPos;
+ SwTextNode* pTextNode = m_pSavedOutlineFrame->GetTextNodeFirst();
+ if (pTextNode && rNds.GetOutLineNds().Seek_Entry(pTextNode, &nPos) &&
+ rSh.GetAttrOutlineContentVisible(nPos))
+ {
+ GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline,
+ m_pSavedOutlineFrame);
+ }
+ }
+ m_pSavedOutlineFrame = nullptr;
+ }
+ }
+
+ if( m_pShadCursor && !bInsWin )
+ {
+ m_pShadCursor.reset();
+ }
+
+ if( bInsWin && m_xRowColumnSelectionStart )
+ {
+ EnterArea();
+ Point aPos( aDocPt );
+ if( rSh.SelectTableRowCol( *m_xRowColumnSelectionStart, &aPos, m_bIsRowDrag ))
+ return;
+ }
+
+ // position is necessary for OS/2 because obviously after a MB-Down
+ // a MB-Move is called immediately.
+ if( g_bDDTimerStarted )
+ {
+ Point aDD( SwEditWin::s_nDDStartPosX, SwEditWin::s_nDDStartPosY );
+ aDD = LogicToPixel( aDD );
+ tools::Rectangle aRect( aDD.X()-3, aDD.Y()-3, aDD.X()+3, aDD.Y()+3 );
+ if ( !aRect.Contains( aPixPt ) )
+ StopDDTimer( &rSh, aDocPt );
+ }
+
+ if(m_rView.GetDrawFuncPtr())
+ {
+ if( m_bInsDraw )
+ {
+ m_rView.GetDrawFuncPtr()->MouseMove( rMEvt );
+ if ( !bInsWin )
+ {
+ Point aTmp( aDocPt );
+ aTmp += rSh.VisArea().Pos() - aOldPt;
+ LeaveArea( aTmp );
+ }
+ else
+ EnterArea();
+ return;
+ }
+ else if(!rSh.IsFrameSelected() && !rSh.IsObjSelected())
+ {
+ SfxBindings &rBnd = rSh.GetView().GetViewFrame().GetBindings();
+ Point aRelPos = rSh.GetRelativePagePosition(aDocPt);
+ if(aRelPos.X() >= 0)
+ {
+ FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( &GetView()) != nullptr );
+ SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)));
+ const SfxPointItem aTmp1( SID_ATTR_POSITION, aRelPos );
+ rBnd.SetState( aTmp1 );
+ }
+ else
+ {
+ rBnd.Invalidate(SID_ATTR_POSITION);
+ }
+ rBnd.Invalidate(SID_ATTR_SIZE);
+ const SvxStatusItem aCell( SID_TABLE_CELL, OUString(), StatusCategory::NONE );
+ rBnd.SetState( aCell );
+ }
+ }
+
+ // determine if we only change the mouse pointer and return
+ if (!bIsDocReadOnly && bInsWin && !m_pApplyTempl && !rSh.IsInSelect() && changeMousePointer(aDocPt))
+ {
+ return;
+ }
+
+ bool bDelShadCursor = true;
+
+ switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
+ {
+ case MOUSE_LEFT:
+ if( m_pAnchorMarker )
+ {
+ // Now we need to refresh the SdrHdl pointer of m_pAnchorMarker.
+ // This looks a little bit tricky, but it solves the following
+ // problem: the m_pAnchorMarker contains a pointer to an SdrHdl,
+ // if the FindAnchorPos-call cause a scrolling of the visible
+ // area, it's possible that the SdrHdl will be destroyed and a
+ // new one will initialized at the original position(GetHdlPos).
+ // So the m_pAnchorMarker has to find the right SdrHdl, if it's
+ // the old one, it will find it with position aOld, if this one
+ // is destroyed, it will find a new one at position GetHdlPos().
+
+ const Point aOld = m_pAnchorMarker->GetPosForHitTest( *(rSh.GetOut()) );
+ Point aNew = rSh.FindAnchorPos( aDocPt );
+ SdrHdl* pHdl;
+ if( pSdrView && (nullptr!=( pHdl = pSdrView->PickHandle( aOld ) )||
+ nullptr !=(pHdl = pSdrView->PickHandle( m_pAnchorMarker->GetHdlPos()) ) ) &&
+ ( pHdl->GetKind() == SdrHdlKind::Anchor ||
+ pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
+ {
+ m_pAnchorMarker->ChgHdl( pHdl );
+ if( aNew.X() || aNew.Y() )
+ {
+ m_pAnchorMarker->SetPos( aNew );
+ m_pAnchorMarker->SetLastPos( aDocPt );
+ }
+ }
+ else
+ {
+ m_pAnchorMarker.reset();
+ }
+ }
+ if ( m_bInsDraw )
+ {
+ if ( !m_bMBPressed )
+ break;
+ if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) )
+ {
+ if ( !bInsWin )
+ LeaveArea( aDocPt );
+ else
+ EnterArea();
+ if ( m_rView.GetDrawFuncPtr() )
+ {
+ pSdrView->SetOrtho(false);
+ m_rView.GetDrawFuncPtr()->MouseMove( rMEvt );
+ }
+ m_bIsInMove = true;
+ }
+ return;
+ }
+
+ {
+ SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame().GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
+ if (pWrdCnt)
+ pWrdCnt->UpdateCounts();
+ }
+ [[fallthrough]];
+
+ case MOUSE_LEFT + KEY_SHIFT:
+ case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
+ if ( !m_bMBPressed )
+ break;
+ [[fallthrough]];
+ case MOUSE_LEFT + KEY_MOD1:
+ if ( g_bFrameDrag && rSh.IsSelFrameMode() )
+ {
+ if( !m_bMBPressed )
+ break;
+
+ if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) )
+ {
+ // event processing for resizing
+ if (pSdrView && pSdrView->AreObjectsMarked())
+ {
+ const Point aSttPt( PixelToLogic( m_aStartPos ) );
+
+ // can we start?
+ if( SdrHdlKind::User == g_eSdrMoveHdl )
+ {
+ SdrHdl* pHdl = pSdrView->PickHandle( aSttPt );
+ g_eSdrMoveHdl = pHdl ? pHdl->GetKind() : SdrHdlKind::Move;
+ }
+
+ const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat());
+ const SvxMacro* pMacro = nullptr;
+
+ SvMacroItemId nEvent = SdrHdlKind::Move == g_eSdrMoveHdl
+ ? SvMacroItemId::SwFrmMove
+ : SvMacroItemId::SwFrmResize;
+
+ if (nullptr != pFlyFormat)
+ pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent);
+ if (nullptr != pMacro &&
+ // or notify only e.g. every 20 Twip?
+ m_aRszMvHdlPt != aDocPt )
+ {
+ m_aRszMvHdlPt = aDocPt;
+ sal_uInt32 nPos = 0;
+ SbxArrayRef xArgs = new SbxArray;
+ SbxVariableRef xVar = new SbxVariable;
+ xVar->PutString( pFlyFormat->GetName() );
+ xArgs->Put(xVar.get(), ++nPos);
+
+ if( SvMacroItemId::SwFrmResize == nEvent )
+ {
+ xVar = new SbxVariable;
+ xVar->PutUShort( static_cast< sal_uInt16 >(g_eSdrMoveHdl) );
+ xArgs->Put(xVar.get(), ++nPos);
+ }
+
+ xVar = new SbxVariable;
+ xVar->PutLong( aDocPt.X() - aSttPt.X() );
+ xArgs->Put(xVar.get(), ++nPos);
+ xVar = new SbxVariable;
+ xVar->PutLong( aDocPt.Y() - aSttPt.Y() );
+ xArgs->Put(xVar.get(), ++nPos);
+
+ OUString sRet;
+
+ ReleaseMouse();
+
+ rSh.ExecMacro( *pMacro, &sRet, xArgs.get() );
+
+ CaptureMouse();
+
+ if( !sRet.isEmpty() && sRet.toInt32()!=0 )
+ return ;
+ }
+ }
+ // event processing for resizing
+
+ if( bIsDocReadOnly )
+ break;
+
+ bool bResizeKeepRatio = rSh.GetSelectionType() & SelectionType::Graphic ||
+ rSh.GetSelectionType() & SelectionType::Media ||
+ rSh.GetSelectionType() & SelectionType::Ole;
+ bool bisResize = g_eSdrMoveHdl != SdrHdlKind::Move;
+
+ if (pSdrView)
+ {
+ // Resize proportionally when media is selected and the user drags on a corner
+ const Point aSttPt(PixelToLogic(m_aStartPos));
+ SdrHdl* pHdl = pSdrView->PickHandle(aSttPt);
+ if (pHdl)
+ bResizeKeepRatio = bResizeKeepRatio && pHdl->IsCornerHdl();
+
+ if (pSdrView->GetDragMode() == SdrDragMode::Crop)
+ bisResize = false;
+ if (rMEvt.IsShift())
+ {
+ pSdrView->SetAngleSnapEnabled(!bResizeKeepRatio);
+ if (bisResize)
+ pSdrView->SetOrtho(!bResizeKeepRatio);
+ else
+ pSdrView->SetOrtho(true);
+ }
+ else
+ {
+ pSdrView->SetAngleSnapEnabled(bResizeKeepRatio);
+ if (bisResize)
+ pSdrView->SetOrtho(bResizeKeepRatio);
+ else
+ pSdrView->SetOrtho(false);
+ }
+ }
+
+ rSh.Drag( &aDocPt, rMEvt.IsShift() );
+ m_bIsInMove = true;
+ }
+ else if( bIsDocReadOnly )
+ break;
+
+ if ( !bInsWin )
+ {
+ Point aTmp( aDocPt );
+ aTmp += rSh.VisArea().Pos() - aOldPt;
+ LeaveArea( aTmp );
+ }
+ else if(m_bIsInMove)
+ EnterArea();
+ return;
+ }
+ if ( !rSh.IsSelFrameMode() && !g_bDDINetAttr &&
+ (IsMinMove( m_aStartPos,aPixPt ) || m_bIsInMove) &&
+ (rSh.IsInSelect() || !rSh.TestCurrPam( aDocPt )) )
+ {
+ if ( pSdrView )
+ {
+ if ( rMEvt.IsShift() )
+ pSdrView->SetOrtho(true);
+ else
+ pSdrView->SetOrtho(false);
+ }
+ if ( !bInsWin )
+ {
+ Point aTmp( aDocPt );
+ aTmp += rSh.VisArea().Pos() - aOldPt;
+ LeaveArea( aTmp );
+ }
+ else
+ {
+ if( !rMEvt.IsSynthetic() &&
+ ( MOUSE_LEFT != rMEvt.GetButtons() ||
+ KEY_MOD1 != rMEvt.GetModifier() ||
+ !rSh.Is_FnDragEQBeginDrag() ||
+ rSh.IsAddMode() ) )
+ {
+ rSh.Drag( &aDocPt, false );
+
+ g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false));
+ EnterArea();
+ }
+ }
+ }
+ g_bDDINetAttr = false;
+ break;
+ case 0:
+ {
+ if ( m_pApplyTempl )
+ {
+ UpdatePointer(aDocPt); // maybe a frame has to be marked here
+ break;
+ }
+ // change ui if mouse is over SwPostItField
+ // TODO: do the same thing for redlines IsAttrAtPos::Redline
+ SwContentAtPos aContentAtPos( IsAttrAtPos::Field);
+ if (rSh.GetContentAtPos(aDocPt, aContentAtPos, false))
+ {
+ const SwField* pField = aContentAtPos.aFnd.pField;
+ if (pField->Which()== SwFieldIds::Postit)
+ {
+ m_rView.GetPostItMgr()->SetShadowState(reinterpret_cast<const SwPostItField*>(pField),false);
+ }
+ else
+ m_rView.GetPostItMgr()->SetShadowState(nullptr,false);
+ }
+ else
+ m_rView.GetPostItMgr()->SetShadowState(nullptr,false);
+ [[fallthrough]];
+ }
+ case KEY_SHIFT:
+ case KEY_MOD2:
+ case KEY_MOD1:
+ if ( !m_bInsDraw )
+ {
+ bool bTstShdwCursor = true;
+
+ UpdatePointer( aDocPt, rMEvt.GetModifier() );
+
+ const SwFrameFormat* pFormat = nullptr;
+ const SwFormatINetFormat* pINet = nullptr;
+ SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );
+ if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) )
+ pINet = static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr);
+
+ const void* pTmp = pINet;
+
+ if( pINet ||
+ nullptr != ( pTmp = pFormat = rSh.GetFormatFromAnyObj( aDocPt )))
+ {
+ bTstShdwCursor = false;
+ if( pTmp == pINet )
+ m_aSaveCallEvent.Set( pINet );
+ else
+ {
+ IMapObject* pIMapObj = pFormat->GetIMapObject( aDocPt );
+ if( pIMapObj )
+ m_aSaveCallEvent.Set( pFormat, pIMapObj );
+ else
+ m_aSaveCallEvent.Set( EVENT_OBJECT_URLITEM, pFormat );
+ }
+
+ // should be over an InternetField with an
+ // embedded macro?
+ if( m_aSaveCallEvent != aLastCallEvent )
+ {
+ if( aLastCallEvent.HasEvent() )
+ rSh.CallEvent( SvMacroItemId::OnMouseOut,
+ aLastCallEvent, true );
+ // 0 says that the object doesn't have any table
+ if( !rSh.CallEvent( SvMacroItemId::OnMouseOver,
+ m_aSaveCallEvent ))
+ m_aSaveCallEvent.Clear();
+ }
+ }
+ else if( aLastCallEvent.HasEvent() )
+ {
+ // cursor was on an object
+ rSh.CallEvent( SvMacroItemId::OnMouseOut,
+ aLastCallEvent, true );
+ }
+
+ if( bTstShdwCursor && bInsWin && !bIsDocReadOnly &&
+ !m_bInsFrame &&
+ !rSh.GetViewOptions()->getBrowseMode() &&
+ rSh.GetViewOptions()->IsShadowCursor() &&
+ !(rMEvt.GetModifier() + rMEvt.GetButtons()) &&
+ !rSh.HasSelection() && !GetOutDev()->GetConnectMetaFile() )
+ {
+ SwRect aRect;
+
+ SwFillMode eMode = rSh.GetViewOptions()->GetShdwCursorFillMode();
+ if( rSh.GetShadowCursorPos( aDocPt, eMode, aRect, m_eOrient ))
+ {
+ if( !m_pShadCursor )
+ m_pShadCursor.reset( new SwShadowCursor( *this ) );
+ if( text::HoriOrientation::RIGHT != m_eOrient && text::HoriOrientation::CENTER != m_eOrient )
+ m_eOrient = text::HoriOrientation::LEFT;
+ m_pShadCursor->SetPos( aRect.Pos(), aRect.Height(), static_cast< sal_uInt16 >(m_eOrient) );
+ bDelShadCursor = false;
+ }
+ }
+ }
+ break;
+ case MOUSE_LEFT + KEY_MOD2:
+ if( rSh.IsBlockMode() && !rMEvt.IsSynthetic() )
+ {
+ rSh.Drag( &aDocPt, false );
+ g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false));
+ EnterArea();
+ }
+ break;
+ }
+
+ if( bDelShadCursor && m_pShadCursor )
+ {
+ m_pShadCursor.reset();
+ }
+ m_bWasShdwCursor = false;
+}
+
+/**
+ * Button Up
+ */
+void SwEditWin::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
+ {
+ pWindow->MouseButtonUp(rMEvt);
+ return;
+ }
+ }
+
+ bool bCallBase = true;
+
+ bool bCallShadowCursor = m_bWasShdwCursor;
+ m_bWasShdwCursor = false;
+ if( m_pShadCursor )
+ {
+ m_pShadCursor.reset();
+ }
+
+ m_xRowColumnSelectionStart.reset();
+
+ SdrHdlKind eOldSdrMoveHdl = g_eSdrMoveHdl;
+ g_eSdrMoveHdl = SdrHdlKind::User; // for MoveEvents - reset again
+
+ // preventively reset
+ m_rView.SetTabColFromDoc( false );
+ m_rView.SetNumRuleNodeFromDoc(nullptr);
+
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ CurrShell aCurr( &rSh );
+ SdrView *pSdrView = rSh.GetDrawView();
+ if ( pSdrView )
+ {
+ // tdf34555: ortho was always reset before being used in EndSdrDrag
+ // Now, it is reset only if not in Crop mode.
+ if (pSdrView->GetDragMode() != SdrDragMode::Crop && !rMEvt.IsShift())
+ pSdrView->SetOrtho(false);
+
+ if ( pSdrView->MouseButtonUp( rMEvt,GetOutDev() ) )
+ {
+ rSh.GetView().GetViewFrame().GetBindings().InvalidateAll(false);
+ return; // SdrView's event evaluated
+ }
+ }
+ // only process MouseButtonUp when the Down went to that windows as well.
+ if ( !m_bMBPressed )
+ {
+ // Undo for the watering can is already in CommandHdl
+ // that's the way it should be!
+
+ return;
+ }
+
+ Point aDocPt( PixelToLogic( rMEvt.GetPosPixel() ) );
+
+ if ( g_bDDTimerStarted )
+ {
+ StopDDTimer( &rSh, aDocPt );
+ m_bMBPressed = false;
+ if ( rSh.IsSelFrameMode() )
+ {
+ rSh.EndDrag( &aDocPt, false );
+ g_bFrameDrag = false;
+ }
+ g_bNoInterrupt = false;
+ const Point aDocPos( PixelToLogic( rMEvt.GetPosPixel() ) );
+ if ((PixelToLogic(m_aStartPos).Y() == (aDocPos.Y())) && (PixelToLogic(m_aStartPos).X() == (aDocPos.X())))//To make sure it was not moved
+ {
+ SdrPageView* pPV = nullptr;
+ SdrObject* pObj = pSdrView ? pSdrView->PickObj(aDocPos, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER) : nullptr;
+ if (pObj)
+ {
+ SwFrameFormat* pFormat = GetUserCall(pObj)->GetFormat();
+ SwFrameFormat* pShapeFormat = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_FLYFRMFMT);
+ if (!pShapeFormat)
+ {
+ pSdrView->UnmarkAllObj();
+ pSdrView->MarkObj(pObj,pPV);
+ }
+ else
+ {
+ // If the fly frame is a textbox of a shape, then select the shape instead.
+ SdrObject* pShape = pShapeFormat->FindSdrObject();
+ pSdrView->UnmarkAllObj();
+ pSdrView->MarkObj(pShape, pPV);
+ }
+ }
+ }
+ ReleaseMouse();
+ return;
+ }
+
+ if( m_pAnchorMarker )
+ {
+ if(m_pAnchorMarker->GetHdl())
+ {
+ // #i121463# delete selected after drag
+ m_pAnchorMarker->GetHdl()->SetSelected(false);
+ }
+
+ Point aPnt( m_pAnchorMarker->GetLastPos() );
+ m_pAnchorMarker.reset();
+ if( aPnt.X() || aPnt.Y() )
+ rSh.FindAnchorPos( aPnt, true );
+ }
+ if ( m_bInsDraw && m_rView.GetDrawFuncPtr() )
+ {
+ if ( m_rView.GetDrawFuncPtr()->MouseButtonUp( rMEvt ) )
+ {
+ if (m_rView.GetDrawFuncPtr()) // could have been destroyed in MouseButtonUp
+ {
+ m_rView.GetDrawFuncPtr()->Deactivate();
+
+ if (!m_rView.IsDrawMode())
+ {
+ m_rView.SetDrawFuncPtr(nullptr);
+ SfxBindings& rBind = m_rView.GetViewFrame().GetBindings();
+ rBind.Invalidate( SID_ATTR_SIZE );
+ rBind.Invalidate( SID_TABLE_CELL );
+ }
+ }
+
+ if ( rSh.IsObjSelected() )
+ {
+ rSh.EnterSelFrameMode();
+ if (!m_rView.GetDrawFuncPtr())
+ StdDrawMode( SdrObjKind::NONE, true );
+ }
+ else if ( rSh.IsFrameSelected() )
+ {
+ rSh.EnterSelFrameMode();
+ StopInsFrame();
+ }
+ else
+ {
+ const Point aDocPos( PixelToLogic( m_aStartPos ) );
+ g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
+ rSh.Edit();
+ }
+
+ m_rView.AttrChangedNotify(nullptr);
+ }
+ else if (rMEvt.GetButtons() == MOUSE_RIGHT && rSh.IsDrawCreate())
+ m_rView.GetDrawFuncPtr()->BreakCreate(); // abort drawing
+
+ g_bNoInterrupt = false;
+ if (IsMouseCaptured())
+ ReleaseMouse();
+ return;
+ }
+ bool bPopMode = false;
+ switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
+ {
+ case MOUSE_LEFT:
+ if ( m_bInsDraw && rSh.IsDrawCreate() )
+ {
+ if ( m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->MouseButtonUp(rMEvt) )
+ {
+ m_rView.GetDrawFuncPtr()->Deactivate();
+ m_rView.AttrChangedNotify(nullptr);
+ if ( rSh.IsObjSelected() )
+ rSh.EnterSelFrameMode();
+ if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
+ StopInsFrame();
+ }
+ bCallBase = false;
+ break;
+ }
+ [[fallthrough]];
+ case MOUSE_LEFT + KEY_MOD1:
+ case MOUSE_LEFT + KEY_MOD2:
+ case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
+ if ( g_bFrameDrag && rSh.IsSelFrameMode() )
+ {
+ if ( rMEvt.IsMod1() ) // copy and don't move.
+ {
+ // abort drag, use internal Copy instead
+ tools::Rectangle aRect;
+ rSh.GetDrawView()->TakeActionRect( aRect );
+ if (!aRect.IsEmpty())
+ {
+ rSh.BreakDrag();
+ Point aEndPt, aSttPt;
+ if ( rSh.GetSelFrameType() & FrameTypeFlags::FLY_ATCNT )
+ {
+ aEndPt = aRect.TopLeft();
+ aSttPt = rSh.GetDrawView()->GetAllMarkedRect().TopLeft();
+ }
+ else
+ {
+ aEndPt = aRect.Center();
+ aSttPt = rSh.GetDrawView()->GetAllMarkedRect().Center();
+ }
+ if ( aSttPt != aEndPt )
+ {
+ rSh.StartUndo( SwUndoId::UI_DRAG_AND_COPY );
+ rSh.Copy(rSh, aSttPt, aEndPt);
+ rSh.EndUndo( SwUndoId::UI_DRAG_AND_COPY );
+ }
+ }
+ else {
+ rSh.EndDrag( &aDocPt, false );
+ }
+ }
+ else
+ {
+ {
+ const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat());
+ const SvxMacro* pMacro = nullptr;
+
+ SvMacroItemId nEvent = SdrHdlKind::Move == eOldSdrMoveHdl
+ ? SvMacroItemId::SwFrmMove
+ : SvMacroItemId::SwFrmResize;
+
+ if (nullptr != pFlyFormat)
+ pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent);
+ if (nullptr != pMacro)
+ {
+ const Point aSttPt( PixelToLogic( m_aStartPos ) );
+ m_aRszMvHdlPt = aDocPt;
+ sal_uInt32 nPos = 0;
+ SbxArrayRef xArgs = new SbxArray;
+ SbxVariableRef xVar = new SbxVariable;
+ xVar->PutString( pFlyFormat->GetName() );
+ xArgs->Put(xVar.get(), ++nPos);
+
+ if( SvMacroItemId::SwFrmResize == nEvent )
+ {
+ xVar = new SbxVariable;
+ xVar->PutUShort( static_cast< sal_uInt16 >(eOldSdrMoveHdl) );
+ xArgs->Put(xVar.get(), ++nPos);
+ }
+
+ xVar = new SbxVariable;
+ xVar->PutLong( aDocPt.X() - aSttPt.X() );
+ xArgs->Put(xVar.get(), ++nPos);
+ xVar = new SbxVariable;
+ xVar->PutLong( aDocPt.Y() - aSttPt.Y() );
+ xArgs->Put(xVar.get(), ++nPos);
+
+ xVar = new SbxVariable;
+ xVar->PutUShort( 1 );
+ xArgs->Put(xVar.get(), ++nPos);
+
+ ReleaseMouse();
+
+ rSh.ExecMacro( *pMacro, nullptr, xArgs.get() );
+
+ CaptureMouse();
+ }
+
+ if (pFlyFormat)
+ {
+ // See if the fly frame's anchor is in a content control. If so,
+ // interact with it.
+ const SwFormatAnchor& rFormatAnchor = pFlyFormat->GetAnchor();
+ SwNode* pAnchorNode = rFormatAnchor.GetAnchorNode();
+ if (pAnchorNode)
+ {
+ SwTextNode* pTextNode = pAnchorNode->GetTextNode();
+ if (pTextNode)
+ {
+ SwTextAttr* pAttr = pTextNode->GetTextAttrAt(
+ rFormatAnchor.GetAnchorContentOffset(), RES_TXTATR_CONTENTCONTROL,
+ ::sw::GetTextAttrMode::Parent);
+ if (pAttr)
+ {
+ SwTextContentControl* pTextContentControl
+ = static_txtattr_cast<SwTextContentControl*>(pAttr);
+ const SwFormatContentControl& rFormatContentControl
+ = pTextContentControl->GetContentControl();
+ rSh.GotoContentControl(rFormatContentControl);
+ }
+ }
+ }
+ }
+ }
+ rSh.EndDrag( &aDocPt, false );
+ }
+ g_bFrameDrag = false;
+ bCallBase = false;
+ break;
+ }
+ bPopMode = true;
+ [[fallthrough]];
+ case MOUSE_LEFT + KEY_SHIFT:
+ if (rSh.IsSelFrameMode())
+ {
+
+ rSh.EndDrag( &aDocPt, false );
+ g_bFrameDrag = false;
+ bCallBase = false;
+ break;
+ }
+
+ if( g_bHoldSelection )
+ {
+ // the EndDrag should be called in any case
+ g_bHoldSelection = false;
+ rSh.EndDrag( &aDocPt, false );
+ }
+ else
+ {
+ SwContentAtPos aFieldAtPos ( IsAttrAtPos::Field );
+ if ( !rSh.IsInSelect() && rSh.TestCurrPam( aDocPt ) &&
+ !rSh.GetContentAtPos( aDocPt, aFieldAtPos ) )
+ {
+ const bool bTmpNoInterrupt = g_bNoInterrupt;
+ g_bNoInterrupt = false;
+ { // create only temporary move context because otherwise
+ // the query to the content form doesn't work!!!
+ SwMvContext aMvContext( &rSh );
+ const Point aDocPos( PixelToLogic( m_aStartPos ) );
+ g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
+ }
+ g_bNoInterrupt = bTmpNoInterrupt;
+
+ }
+ else
+ {
+ bool bInSel = rSh.IsInSelect();
+ rSh.EndDrag( &aDocPt, false );
+
+ // Internetfield? --> call link (load doc!!)
+ if( !bInSel )
+ {
+ LoadUrlFlags nFilter = LoadUrlFlags::NONE;
+ if( KEY_MOD1 == rMEvt.GetModifier() )
+ nFilter |= LoadUrlFlags::NewView;
+
+ bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
+ if ( !bExecHyperlinks )
+ {
+ const bool bSecureOption = SvtSecurityOptions::IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink );
+ if ( ( bSecureOption && rMEvt.GetModifier() == KEY_MOD1 ) ||
+ ( !bSecureOption && rMEvt.GetModifier() != KEY_MOD1 ) )
+ bExecHyperlinks = true;
+ }
+
+ const bool bExecSmarttags = rMEvt.GetModifier() == KEY_MOD1;
+
+ if(m_pApplyTempl)
+ bExecHyperlinks = false;
+
+ SwContentAtPos aContentAtPos( IsAttrAtPos::Field |
+ IsAttrAtPos::InetAttr |
+ IsAttrAtPos::SmartTag | IsAttrAtPos::FormControl |
+ IsAttrAtPos::ContentControl);
+
+ if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) )
+ {
+ // Do it again if we're not on a field/hyperlink to update the cursor accordingly
+ if ( IsAttrAtPos::Field != aContentAtPos.eContentAtPos
+ && IsAttrAtPos::InetAttr != aContentAtPos.eContentAtPos )
+ rSh.GetContentAtPos( aDocPt, aContentAtPos, true );
+
+ bool bViewLocked = rSh.IsViewLocked();
+ if( !bViewLocked && !rSh.IsReadOnlyAvailable() &&
+ aContentAtPos.IsInProtectSect() )
+ rSh.LockView( true );
+
+ ReleaseMouse();
+
+ if( IsAttrAtPos::Field == aContentAtPos.eContentAtPos )
+ {
+ bool bAddMode(false);
+ // AdditionalMode if applicable
+ if (KEY_MOD1 == rMEvt.GetModifier()
+ && !rSh.IsAddMode())
+ {
+ bAddMode = true;
+ rSh.EnterAddMode();
+ }
+ if ( aContentAtPos.pFndTextAttr != nullptr
+ && aContentAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD )
+ {
+ if (!rSh.IsInSelect())
+ {
+ // create only temporary move context because otherwise
+ // the query to the content form doesn't work!!!
+ SwMvContext aMvContext( &rSh );
+ const Point aDocPos( PixelToLogic( m_aStartPos ) );
+ g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
+ }
+ else
+ {
+ g_bValidCursorPos = true;
+ }
+ }
+ else
+ {
+ rSh.ClickToField(*aContentAtPos.aFnd.pField, bExecHyperlinks);
+ // a bit of a mystery what this is good for?
+ // in this case we assume it's valid since we
+ // just selected a field
+ g_bValidCursorPos = true;
+ }
+ if (bAddMode)
+ {
+ rSh.LeaveAddMode();
+ }
+ }
+ else if (aContentAtPos.eContentAtPos == IsAttrAtPos::ContentControl)
+ {
+ auto pTextContentControl
+ = static_txtattr_cast<const SwTextContentControl*>(
+ aContentAtPos.pFndTextAttr);
+ const SwFormatContentControl& rFormatContentControl
+ = pTextContentControl->GetContentControl();
+ rSh.GotoContentControl(rFormatContentControl);
+ }
+ else if ( IsAttrAtPos::SmartTag == aContentAtPos.eContentAtPos )
+ {
+ // execute smarttag menu
+ if ( bExecSmarttags && SwSmartTagMgr::Get().IsSmartTagsEnabled() )
+ m_rView.ExecSmartTagPopup( aDocPt );
+ }
+ else if ( IsAttrAtPos::FormControl == aContentAtPos.eContentAtPos )
+ {
+ OSL_ENSURE( aContentAtPos.aFnd.pFieldmark != nullptr, "where is my field ptr???");
+ if ( aContentAtPos.aFnd.pFieldmark != nullptr)
+ {
+ IFieldmark *fieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark );
+ if ( fieldBM->GetFieldname( ) == ODF_FORMCHECKBOX )
+ {
+ ICheckboxFieldmark& rCheckboxFm = dynamic_cast<ICheckboxFieldmark&>(*fieldBM);
+ rCheckboxFm.SetChecked(!rCheckboxFm.IsChecked());
+ rCheckboxFm.Invalidate();
+ rSh.InvalidateWindows( SwRect(m_rView.GetVisArea()) );
+ }
+ }
+ }
+ else if ( IsAttrAtPos::InetAttr == aContentAtPos.eContentAtPos )
+ {
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ OUString val((*static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr)).GetValue());
+ if (val.startsWith("#"))
+ bExecHyperlinks = true;
+ }
+ if ( bExecHyperlinks && aContentAtPos.aFnd.pAttr )
+ rSh.ClickToINetAttr( *static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr), nFilter );
+ }
+
+ rSh.LockView( bViewLocked );
+ bCallShadowCursor = false;
+ }
+ else
+ {
+ aContentAtPos = SwContentAtPos( IsAttrAtPos::Ftn );
+ if( !rSh.GetContentAtPos( aDocPt, aContentAtPos, true ) && bExecHyperlinks )
+ {
+ SdrViewEvent aVEvt;
+
+ if (pSdrView)
+ pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
+
+ if (pSdrView && aVEvt.meEvent == SdrEventKind::ExecuteUrl)
+ {
+ // hit URL field
+ const SvxURLField *pField = aVEvt.mpURLField;
+ if (pField)
+ {
+ const OUString& sURL(pField->GetURL());
+ const OUString& sTarget(pField->GetTargetFrame());
+ ::LoadURL(rSh, sURL, nFilter, sTarget);
+ }
+ bCallShadowCursor = false;
+ }
+ else
+ {
+ // hit graphic
+ ReleaseMouse();
+ if( rSh.ClickToINetGrf( aDocPt, nFilter ))
+ bCallShadowCursor = false;
+ }
+ }
+ }
+
+ if( bCallShadowCursor &&
+ rSh.GetViewOptions()->IsShadowCursor() &&
+ MOUSE_LEFT == (rMEvt.GetModifier() + rMEvt.GetButtons()) &&
+ !rSh.HasSelection() &&
+ !GetOutDev()->GetConnectMetaFile() &&
+ rSh.VisArea().Contains( aDocPt ))
+ {
+ SwUndoId nLastUndoId(SwUndoId::EMPTY);
+ if (rSh.GetLastUndoInfo(nullptr, & nLastUndoId))
+ {
+ if (SwUndoId::INS_FROM_SHADOWCRSR == nLastUndoId)
+ {
+ rSh.Undo();
+ }
+ }
+ SwFillMode eMode = rSh.GetViewOptions()->GetShdwCursorFillMode();
+ rSh.SetShadowCursorPos( aDocPt, eMode );
+ }
+ }
+ }
+ bCallBase = false;
+
+ }
+
+ // reset pushed mode in Down again if applicable
+ if ( bPopMode && g_bModePushed )
+ {
+ rSh.PopMode();
+ g_bModePushed = false;
+ bCallBase = false;
+ }
+ break;
+
+ default:
+ ReleaseMouse();
+ return;
+ }
+
+ if( m_pApplyTempl )
+ {
+ SelectionType eSelection = rSh.GetSelectionType();
+ SwFormatClipboard* pFormatClipboard = m_pApplyTempl->m_pFormatClipboard;
+ if( pFormatClipboard )//apply format paintbrush
+ {
+ //get some parameters
+ SwWrtShell& rWrtShell = m_rView.GetWrtShell();
+ SfxStyleSheetBasePool* pPool=nullptr;
+ bool bNoCharacterFormats = false;
+ // Paste paragraph properties if the selection contains a whole paragraph or
+ // there was no selection at all (i.e. just a left click)
+ bool bNoParagraphFormats = rSh.HasSelection() && rSh.IsSelOnePara() && !rSh.IsSelFullPara();
+
+ {
+ SwDocShell* pDocSh = m_rView.GetDocShell();
+ if(pDocSh)
+ pPool = pDocSh->GetStyleSheetPool();
+ if( (rMEvt.GetModifier()&KEY_MOD1) && (rMEvt.GetModifier()&KEY_SHIFT) )
+ {
+ bNoCharacterFormats = true;
+ bNoParagraphFormats = false;
+ }
+ else if( rMEvt.GetModifier() & KEY_MOD1 )
+ bNoParagraphFormats = true;
+ }
+ //execute paste
+ pFormatClipboard->Paste( rWrtShell, pPool, bNoCharacterFormats, bNoParagraphFormats );
+
+ //if the clipboard is empty after paste remove the ApplyTemplate
+ if(!pFormatClipboard->HasContent())
+ SetApplyTemplate(SwApplyTemplate());
+
+ //tdf#38101 remove temporary highlighting
+ m_pUserMarker.reset();
+ }
+ else if( m_pApplyTempl->nColor )
+ {
+ sal_uInt16 nId = 0;
+ switch( m_pApplyTempl->nColor )
+ {
+ case SID_ATTR_CHAR_COLOR_EXT:
+ nId = RES_CHRATR_COLOR;
+ break;
+ case SID_ATTR_CHAR_BACK_COLOR:
+ case SID_ATTR_CHAR_COLOR_BACKGROUND:
+ nId = RES_CHRATR_BACKGROUND;
+ break;
+ }
+ if( nId && (SelectionType::Text|SelectionType::Table) & eSelection)
+ {
+ if( rSh.IsSelection() && !rSh.HasReadonlySel() )
+ {
+ m_pApplyTempl->nUndo =
+ std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
+ if (nId == RES_CHRATR_BACKGROUND)
+ ApplyCharBackground(m_aWaterCanTextBackColor, model::ComplexColor(), rSh);
+ else
+ rSh.SetAttrItem( SvxColorItem( m_aWaterCanTextColor, nId ) );
+ rSh.UnSetVisibleCursor();
+ rSh.EnterStdMode();
+ rSh.SetVisibleCursor(aDocPt);
+ bCallBase = false;
+ m_aTemplateTimer.Stop();
+ }
+ else if(rMEvt.GetClicks() == 1)
+ {
+ // no selection -> so turn off watering can
+ m_aTemplateTimer.Start();
+ }
+ }
+ }
+ else
+ {
+ OUString aStyleName;
+ switch ( m_pApplyTempl->eType )
+ {
+ case SfxStyleFamily::Para:
+ if( (( SelectionType::Text | SelectionType::Table )
+ & eSelection ) && !rSh.HasReadonlySel() )
+ {
+ rSh.SetTextFormatColl( m_pApplyTempl->aColl.pTextColl );
+ m_pApplyTempl->nUndo =
+ std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
+ bCallBase = false;
+ if ( m_pApplyTempl->aColl.pTextColl )
+ aStyleName = m_pApplyTempl->aColl.pTextColl->GetName();
+ }
+ break;
+ case SfxStyleFamily::Char:
+ if( (( SelectionType::Text | SelectionType::Table )
+ & eSelection ) && !rSh.HasReadonlySel() )
+ {
+ rSh.SetAttrItem( SwFormatCharFormat(m_pApplyTempl->aColl.pCharFormat) );
+ rSh.UnSetVisibleCursor();
+ rSh.EnterStdMode();
+ rSh.SetVisibleCursor(aDocPt);
+ m_pApplyTempl->nUndo =
+ std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
+ bCallBase = false;
+ if ( m_pApplyTempl->aColl.pCharFormat )
+ aStyleName = m_pApplyTempl->aColl.pCharFormat->GetName();
+ }
+ break;
+ case SfxStyleFamily::Frame :
+ {
+ const SwFrameFormat* pFormat = rSh.GetFormatFromObj( aDocPt );
+ if(dynamic_cast<const SwFlyFrameFormat*>( pFormat) )
+ {
+ rSh.SetFrameFormat( m_pApplyTempl->aColl.pFrameFormat, false, &aDocPt );
+ m_pApplyTempl->nUndo =
+ std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
+ bCallBase = false;
+ if( m_pApplyTempl->aColl.pFrameFormat )
+ aStyleName = m_pApplyTempl->aColl.pFrameFormat->GetName();
+ }
+ break;
+ }
+ case SfxStyleFamily::Page:
+ // no Undo with page templates
+ rSh.ChgCurPageDesc( *m_pApplyTempl->aColl.pPageDesc );
+ if ( m_pApplyTempl->aColl.pPageDesc )
+ aStyleName = m_pApplyTempl->aColl.pPageDesc->GetName();
+ m_pApplyTempl->nUndo =
+ std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
+ bCallBase = false;
+ break;
+ case SfxStyleFamily::Pseudo:
+ if( !rSh.HasReadonlySel() )
+ {
+ rSh.SetCurNumRule( *m_pApplyTempl->aColl.pNumRule,
+ false,
+ m_pApplyTempl->aColl.pNumRule->GetDefaultListId() );
+ bCallBase = false;
+ m_pApplyTempl->nUndo =
+ std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
+ if( m_pApplyTempl->aColl.pNumRule )
+ aStyleName = m_pApplyTempl->aColl.pNumRule->GetName();
+ }
+ break;
+ default: break;
+ }
+
+ uno::Reference< frame::XDispatchRecorder > xRecorder =
+ m_rView.GetViewFrame().GetBindings().GetRecorder();
+ if ( !aStyleName.isEmpty() && xRecorder.is() )
+ {
+ SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView );
+ if ( pSfxShell )
+ {
+ SfxRequest aReq(m_rView.GetViewFrame(), SID_STYLE_APPLY);
+ aReq.AppendItem( SfxStringItem( SID_STYLE_APPLY, aStyleName ) );
+ aReq.AppendItem( SfxUInt16Item( SID_STYLE_FAMILY, static_cast<sal_uInt16>(m_pApplyTempl->eType) ) );
+ aReq.Done();
+ }
+ }
+ }
+
+ }
+ ReleaseMouse();
+ // Only processed MouseEvents arrive here; only at these this mode can
+ // be reset.
+ m_bMBPressed = false;
+
+ // Make this call just to be sure. Selecting has finished surely by now.
+ // Otherwise the timeout's timer could give problems.
+ EnterArea();
+ g_bNoInterrupt = false;
+
+ if (bCallBase)
+ Window::MouseButtonUp(rMEvt);
+
+ if (!(pSdrView && rMEvt.GetClicks() == 1 && comphelper::LibreOfficeKit::isActive()))
+ return;
+
+ // When tiled rendering, single click on a shape text starts editing already.
+ SdrViewEvent aViewEvent;
+ SdrHitKind eHit = pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONUP, aViewEvent);
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ if (eHit == SdrHitKind::TextEditObj && rMarkList.GetMarkCount() == 1)
+ {
+ if (SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj())
+ {
+ EnterDrawTextMode(pObj->GetLogicRect().Center());
+ if ( auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>( m_rView.GetCurShell() ) )
+ pSwDrawTextShell->Init();
+ }
+ }
+}
+
+/**
+ * Apply template
+ */
+void SwEditWin::SetApplyTemplate(const SwApplyTemplate &rTempl)
+{
+ static bool bIdle = false;
+ m_pApplyTempl.reset();
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+
+ if(rTempl.m_pFormatClipboard)
+ {
+ m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
+ m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
+ SetPointer( PointerStyle::Fill );//@todo #i20119# maybe better a new brush pointer here in future
+ rSh.NoEdit( false );
+ bIdle = rSh.GetViewOptions()->IsIdle();
+ rSh.GetViewOptions()->SetIdle( false );
+ }
+ else if(rTempl.nColor)
+ {
+ m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
+ m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
+ SetPointer( PointerStyle::Fill );
+ rSh.NoEdit( false );
+ bIdle = rSh.GetViewOptions()->IsIdle();
+ rSh.GetViewOptions()->SetIdle( false );
+ }
+ else if( rTempl.eType != SfxStyleFamily::None )
+ {
+ m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
+ m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
+ SetPointer( PointerStyle::Fill );
+ rSh.NoEdit( false );
+ bIdle = rSh.GetViewOptions()->IsIdle();
+ rSh.GetViewOptions()->SetIdle( false );
+ }
+ else
+ {
+ SetPointer( PointerStyle::Text );
+ rSh.UnSetVisibleCursor();
+
+ rSh.GetViewOptions()->SetIdle( bIdle );
+ if ( !rSh.IsSelFrameMode() )
+ rSh.Edit();
+ }
+
+ static sal_uInt16 aInva[] =
+ {
+ SID_STYLE_WATERCAN,
+ SID_ATTR_CHAR_COLOR_EXT,
+ SID_ATTR_CHAR_COLOR_BACKGROUND_EXT,
+ 0
+ };
+ m_rView.GetViewFrame().GetBindings().Invalidate(aInva);
+}
+
+/**
+ * Ctor
+ */
+SwEditWin::SwEditWin(vcl::Window *pParent, SwView &rMyView):
+ DocWindow(pParent, WinBits(WB_CLIPCHILDREN | WB_DIALOGCONTROL)),
+ DropTargetHelper( this ),
+ DragSourceHelper( this ),
+
+ m_aTimer("SwEditWin"),
+ m_aKeyInputFlushTimer("SwEditWin m_aKeyInputFlushTimer"),
+ m_eBufferLanguage(LANGUAGE_DONTKNOW),
+ m_aTemplateTimer("SwEditWin m_aTemplateTimer"),
+ m_pUserMarkerObj( nullptr ),
+
+ m_rView( rMyView ),
+
+ m_aActHitType(SdrHitKind::NONE),
+ m_nDropFormat( SotClipboardFormatId::NONE ),
+ m_nDropAction( 0 ),
+ m_nDropDestination( SotExchangeDest::NONE ),
+
+ m_eBezierMode(SID_BEZIER_INSERT),
+ m_nInsFrameColCount( 1 ),
+ m_eDrawMode(SdrObjKind::NONE),
+
+ m_bMBPressed(false),
+ m_bInsDraw(false),
+ m_bInsFrame(false),
+ m_bIsInMove(false),
+ m_bIsInDrag(false),
+ m_bOldIdle(false),
+ m_bOldIdleSet(false),
+ m_bChainMode(false),
+ m_bWasShdwCursor(false),
+ m_bLockInput(false),
+ m_bIsRowDrag(false),
+ m_bUseInputLanguage(false),
+ m_bObjectSelect(false),
+ m_nKS_NUMDOWN_Count(0),
+ m_nKS_NUMINDENTINC_Count(0),
+ m_pFrameControlsManager(new SwFrameControlsManager(this))
+{
+ set_id("writer_edit");
+ SetHelpId(HID_EDIT_WIN);
+ EnableChildTransparentMode();
+ SetDialogControlFlags( DialogControlFlags::Return | DialogControlFlags::WantFocus );
+
+ m_bMBPressed = m_bInsDraw = m_bInsFrame =
+ m_bIsInDrag = m_bOldIdle = m_bOldIdleSet = m_bChainMode = m_bWasShdwCursor = false;
+ // initially use the input language
+ m_bUseInputLanguage = true;
+
+ SetMapMode(MapMode(MapUnit::MapTwip));
+
+ SetPointer( PointerStyle::Text );
+ m_aTimer.SetInvokeHandler(LINK(this, SwEditWin, TimerHandler));
+
+ m_aKeyInputFlushTimer.SetTimeout( 20 );
+ m_aKeyInputFlushTimer.SetInvokeHandler(LINK(this, SwEditWin, KeyInputFlushHandler));
+
+ // TemplatePointer for colors should be reset without
+ // selection after single click, but not after double-click (tdf#122442)
+ m_aTemplateTimer.SetTimeout(GetSettings().GetMouseSettings().GetDoubleClickTime());
+ m_aTemplateTimer.SetInvokeHandler(LINK(this, SwEditWin, TemplateTimerHdl));
+
+ // temporary solution!!! Should set the font of the current
+ // insert position at every cursor movement!
+ if( !rMyView.GetDocShell()->IsReadOnly() )
+ {
+ vcl::Font aFont;
+ SetInputContext( InputContext( aFont, InputContextFlags::Text |
+ InputContextFlags::ExtText ) );
+ }
+}
+
+SwEditWin::~SwEditWin()
+{
+ disposeOnce();
+}
+
+void SwEditWin::dispose()
+{
+ m_pShadCursor.reset();
+
+ if( s_pQuickHlpData->m_bIsDisplayed && m_rView.GetWrtShellPtr() )
+ s_pQuickHlpData->Stop( m_rView.GetWrtShell() );
+ g_bExecuteDrag = false;
+ m_pApplyTempl.reset();
+
+ m_rView.SetDrawFuncPtr(nullptr);
+
+ m_pUserMarker.reset();
+
+ m_pAnchorMarker.reset();
+
+ m_pFrameControlsManager->dispose();
+ m_pFrameControlsManager.reset();
+
+ DragSourceHelper::dispose();
+ DropTargetHelper::dispose();
+ vcl::Window::dispose();
+}
+
+/**
+ * Turn on DrawTextEditMode
+ */
+void SwEditWin::EnterDrawTextMode( const Point& aDocPos )
+{
+ if ( m_rView.EnterDrawTextMode(aDocPos) )
+ {
+ if (m_rView.GetDrawFuncPtr())
+ {
+ m_rView.GetDrawFuncPtr()->Deactivate();
+ m_rView.SetDrawFuncPtr(nullptr);
+ m_rView.LeaveDrawCreate();
+ }
+ m_rView.NoRotate();
+ m_rView.AttrChangedNotify(nullptr);
+ }
+}
+
+/**
+ * Turn on DrawMode
+ */
+bool SwEditWin::EnterDrawMode(const MouseEvent& rMEvt, const Point& aDocPos)
+{
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ SdrView *pSdrView = rSh.GetDrawView();
+
+ if ( m_rView.GetDrawFuncPtr() )
+ {
+ if (rSh.IsDrawCreate())
+ return true;
+
+ bool bRet = m_rView.GetDrawFuncPtr()->MouseButtonDown( rMEvt );
+ m_rView.AttrChangedNotify(nullptr);
+ return bRet;
+ }
+
+ if ( pSdrView && pSdrView->IsTextEdit() )
+ {
+ bool bUnLockView = !rSh.IsViewLocked();
+ rSh.LockView( true );
+
+ rSh.EndTextEdit(); // clicked aside, end Edit
+ rSh.SelectObj( aDocPos );
+ if ( !rSh.IsObjSelected() && !rSh.IsFrameSelected() )
+ rSh.LeaveSelFrameMode();
+ else
+ {
+ SwEditWin::s_nDDStartPosY = aDocPos.Y();
+ SwEditWin::s_nDDStartPosX = aDocPos.X();
+ g_bFrameDrag = true;
+ }
+ if( bUnLockView )
+ rSh.LockView( false );
+ m_rView.AttrChangedNotify(nullptr);
+ return true;
+ }
+ return false;
+}
+
+bool SwEditWin::IsDrawSelMode() const
+{
+ return IsObjectSelect();
+}
+
+void SwEditWin::GetFocus()
+{
+ if ( m_rView.GetPostItMgr()->HasActiveSidebarWin() )
+ {
+ m_rView.GetPostItMgr()->GrabFocusOnActiveSidebarWin();
+ }
+ else
+ {
+ m_rView.GotFocus();
+ Window::GetFocus();
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ m_rView.GetWrtShell().InvalidateAccessibleFocus();
+#endif
+ }
+}
+
+void SwEditWin::LoseFocus()
+{
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ if (m_rView.GetWrtShellPtr())
+ m_rView.GetWrtShell().InvalidateAccessibleFocus();
+#endif
+ Window::LoseFocus();
+ if( s_pQuickHlpData && s_pQuickHlpData->m_bIsDisplayed )
+ s_pQuickHlpData->Stop( m_rView.GetWrtShell() );
+}
+
+void SwEditWin::Command( const CommandEvent& rCEvt )
+{
+ if (isDisposed())
+ {
+ // If ViewFrame dies shortly, no popup anymore!
+ Window::Command(rCEvt);
+ return;
+ }
+
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+
+ // The command event is send to the window after a possible context
+ // menu from an inplace client has been closed. Now we have the chance
+ // to deactivate the inplace client without any problem regarding parent
+ // windows and code on the stack.
+ SfxInPlaceClient* pIPClient = rSh.GetSfxViewShell()->GetIPClient();
+ bool bIsOleActive = ( pIPClient && pIPClient->IsObjectInPlaceActive() );
+ if ( bIsOleActive && ( rCEvt.GetCommand() == CommandEventId::ContextMenu ))
+ {
+ rSh.FinishOLEObj();
+ return;
+ }
+
+ bool bCallBase = true;
+
+ switch ( rCEvt.GetCommand() )
+ {
+ case CommandEventId::ContextMenu:
+ {
+ const sal_uInt16 nId = SwInputChild::GetChildWindowId();
+ SwInputChild* pChildWin = static_cast<SwInputChild*>(GetView().GetViewFrame().
+ GetChildWindow( nId ));
+
+ if (m_rView.GetPostItMgr()->IsHit(rCEvt.GetMousePosPixel()))
+ return;
+
+ Point aDocPos( PixelToLogic( rCEvt.GetMousePosPixel() ) );
+ if ( !rCEvt.IsMouseEvent() )
+ aDocPos = rSh.GetCharRect().Center();
+
+ // Don't trigger the command on a frame anchored to header/footer is not editing it
+ FrameControlType eControl;
+ bool bOverFly = false;
+ bool bPageAnchored = false;
+ bool bOverHeaderFooterFly = IsOverHeaderFooterFly( aDocPos, eControl, bOverFly, bPageAnchored );
+ // !bOverHeaderFooterFly doesn't mean we have a frame to select
+ if ( !bPageAnchored && rCEvt.IsMouseEvent( ) &&
+ ( ( rSh.IsHeaderFooterEdit( ) && !bOverHeaderFooterFly && bOverFly ) ||
+ ( !rSh.IsHeaderFooterEdit( ) && bOverHeaderFooterFly ) ) )
+ {
+ return;
+ }
+
+ if((!pChildWin || pChildWin->GetView() != &m_rView) &&
+ !rSh.IsDrawCreate() && !IsDrawAction())
+ {
+ CurrShell aCurr( &rSh );
+ if (!m_pApplyTempl)
+ {
+ if (g_bNoInterrupt)
+ {
+ ReleaseMouse();
+ g_bNoInterrupt = false;
+ m_bMBPressed = false;
+ }
+ if ( rCEvt.IsMouseEvent() )
+ {
+ SelectMenuPosition(rSh, rCEvt.GetMousePosPixel());
+ m_rView.StopShellTimer();
+ }
+ const Point aPixPos = LogicToPixel( aDocPos );
+
+ if ( m_rView.GetDocShell()->IsReadOnly() )
+ {
+ SwReadOnlyPopup aROPopup(aDocPos, m_rView);
+
+ ui::ContextMenuExecuteEvent aEvent;
+ aEvent.SourceWindow = VCLUnoHelper::GetInterface( this );
+ aEvent.ExecutePosition.X = aPixPos.X();
+ aEvent.ExecutePosition.Y = aPixPos.Y();
+ rtl::Reference<VCLXPopupMenu> xMenu;
+ rtl::Reference<VCLXPopupMenu> xMenuInterface = aROPopup.CreateMenuInterface();
+ if (GetView().TryContextMenuInterception(xMenuInterface, "private:resource/ReadonlyContextMenu", xMenu, aEvent))
+ {
+ if (xMenu.is())
+ {
+ css::uno::Reference<css::awt::XWindowPeer> xParent(aEvent.SourceWindow, css::uno::UNO_QUERY);
+ sal_uInt16 nExecId = xMenu->execute(xParent, css::awt::Rectangle(aPixPos.X(), aPixPos.Y(), 1, 1),
+ css::awt::PopupMenuDirection::EXECUTE_DOWN);
+ if (!::ExecuteMenuCommand(xMenu, m_rView.GetViewFrame(), nExecId))
+ aROPopup.Execute(this, nExecId);
+ }
+ else
+ aROPopup.Execute(this, aPixPos);
+ }
+ }
+ else if ( !m_rView.ExecSpellPopup( aDocPos ) )
+ SfxDispatcher::ExecutePopup(this, &aPixPos);
+ }
+ else if (m_pApplyTempl->nUndo < rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount())
+ {
+ // Undo until we reach the point when we entered this context.
+ rSh.Do(SwWrtShell::UNDO);
+ }
+ bCallBase = false;
+ }
+ }
+ break;
+
+ case CommandEventId::Wheel:
+ case CommandEventId::StartAutoScroll:
+ case CommandEventId::AutoScroll:
+ if (m_pSavedOutlineFrame && rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ {
+ GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame);
+ m_pSavedOutlineFrame = nullptr;
+ }
+ m_pShadCursor.reset();
+ bCallBase = !m_rView.HandleWheelCommands( rCEvt );
+ break;
+
+ case CommandEventId::GestureZoom:
+ {
+ if (m_pSavedOutlineFrame && rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ {
+ GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame);
+ m_pSavedOutlineFrame = nullptr;
+ }
+ m_pShadCursor.reset();
+ bCallBase = !m_rView.HandleGestureZoomCommand(rCEvt);
+ break;
+ }
+
+ case CommandEventId::GestureLongPress:
+ case CommandEventId::GestureSwipe: //nothing yet
+ break;
+
+ case CommandEventId::StartExtTextInput:
+ {
+ bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
+ rSh.IsCursorReadonly();
+ if(!bIsDocReadOnly)
+ {
+ if( rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit() )
+ {
+ bCallBase = false;
+ rSh.GetDrawView()->GetTextEditOutlinerView()->Command( rCEvt );
+ }
+ else
+ {
+ if( rSh.HasSelection() )
+ rSh.DelRight();
+
+ bCallBase = false;
+ LanguageType eInputLanguage = GetInputLanguage();
+ rSh.CreateExtTextInput(eInputLanguage);
+ }
+ }
+ break;
+ }
+ case CommandEventId::EndExtTextInput:
+ {
+ bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
+ rSh.IsCursorReadonly();
+ if(!bIsDocReadOnly)
+ {
+ if( rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit() )
+ {
+ bCallBase = false;
+ rSh.GetDrawView()->GetTextEditOutlinerView()->Command( rCEvt );
+ }
+ else
+ {
+ bCallBase = false;
+ OUString sRecord = rSh.DeleteExtTextInput();
+ uno::Reference< frame::XDispatchRecorder > xRecorder =
+ m_rView.GetViewFrame().GetBindings().GetRecorder();
+
+ if ( !sRecord.isEmpty() )
+ {
+ // convert quotes in IME text
+ // works on the last input character, this is especially in Korean text often done
+ // quotes that are inside of the string are not replaced!
+ const sal_Unicode aCh = sRecord[sRecord.getLength() - 1];
+ SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get();
+ SvxAutoCorrect* pACorr = rACfg.GetAutoCorrect();
+ if(pACorr &&
+ (( pACorr->IsAutoCorrFlag( ACFlags::ChgQuotes ) && ('\"' == aCh ))||
+ ( pACorr->IsAutoCorrFlag( ACFlags::ChgSglQuotes ) && ( '\'' == aCh))))
+ {
+ rSh.DelLeft();
+ rSh.AutoCorrect( *pACorr, aCh );
+ }
+
+ if ( xRecorder.is() )
+ {
+ // determine Shell
+ SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView );
+ // generate request and record
+ if (pSfxShell)
+ {
+ SfxRequest aReq(m_rView.GetViewFrame(), FN_INSERT_STRING);
+ aReq.AppendItem( SfxStringItem( FN_INSERT_STRING, sRecord ) );
+ aReq.Done();
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case CommandEventId::ExtTextInput:
+ {
+ bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
+ rSh.IsCursorReadonly();
+ if (!bIsDocReadOnly && !rSh.HasReadonlySel())
+ {
+ if( s_pQuickHlpData->m_bIsDisplayed )
+ s_pQuickHlpData->Stop( rSh );
+
+ if( rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit() )
+ {
+ bCallBase = false;
+ rSh.GetDrawView()->GetTextEditOutlinerView()->Command( rCEvt );
+ }
+ else
+ {
+ const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData();
+ if( pData )
+ {
+ bCallBase = false;
+ rSh.SetExtTextInputData( *pData );
+ }
+ }
+ uno::Reference< frame::XDispatchRecorder > xRecorder =
+ m_rView.GetViewFrame().GetBindings().GetRecorder();
+ if(!xRecorder.is())
+ {
+ SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get();
+ if (!rACfg.IsAutoTextTip() || !ShowAutoText(rSh.GetChunkForAutoText()))
+ {
+ SvxAutoCorrect* pACorr = rACfg.GetAutoCorrect();
+ if (pACorr && pACorr->GetSwFlags().bAutoCompleteWords)
+ ShowAutoCorrectQuickHelp(rSh.GetPrevAutoCorrWord(*pACorr), *pACorr);
+ }
+ }
+ }
+
+ if (rSh.HasReadonlySel())
+ {
+ // Inform the user that the request has been ignored.
+ rSh.InfoReadOnlyDialog(true);
+ }
+ }
+ break;
+ case CommandEventId::CursorPos:
+ // will be handled by the base class
+ break;
+
+ case CommandEventId::PasteSelection:
+ if( !m_rView.GetDocShell()->IsReadOnly() )
+ {
+ TransferableDataHelper aDataHelper(
+ TransferableDataHelper::CreateFromPrimarySelection());
+ if( !aDataHelper.GetXTransferable().is() )
+ break;
+
+ SotExchangeDest nDropDestination = GetDropDestination( rCEvt.GetMousePosPixel() );
+ if( nDropDestination == SotExchangeDest::NONE )
+ break;
+ SotClipboardFormatId nDropFormat;
+ sal_uInt8 nEventAction, nDropAction;
+ SotExchangeActionFlags nActionFlags;
+ nDropAction = SotExchange::GetExchangeAction(
+ aDataHelper.GetDataFlavorExVector(),
+ nDropDestination, EXCHG_IN_ACTION_COPY,
+ EXCHG_IN_ACTION_COPY, nDropFormat,
+ nEventAction,
+ SotClipboardFormatId::NONE, nullptr,
+ &nActionFlags );
+ if( EXCHG_INOUT_ACTION_NONE != nDropAction )
+ {
+ const Point aDocPt( PixelToLogic( rCEvt.GetMousePosPixel() ) );
+ SwTransferable::PasteData( aDataHelper, rSh, nDropAction, nActionFlags,
+ nDropFormat, nDropDestination, false,
+ false, &aDocPt, EXCHG_IN_ACTION_COPY,
+ true );
+ }
+ }
+ break;
+ case CommandEventId::ModKeyChange :
+ {
+ const CommandModKeyData* pCommandData = rCEvt.GetModKeyData();
+ if (!pCommandData->IsDown() && pCommandData->IsMod1() && !pCommandData->IsMod2())
+ {
+ sal_uInt16 nSlot = 0;
+ if(pCommandData->IsLeftShift() && !pCommandData->IsRightShift())
+ nSlot = SID_ATTR_PARA_LEFT_TO_RIGHT;
+ else if(!pCommandData->IsLeftShift() && pCommandData->IsRightShift())
+ nSlot = SID_ATTR_PARA_RIGHT_TO_LEFT;
+ if(nSlot && SvtCTLOptions::IsCTLFontEnabled())
+ GetView().GetViewFrame().GetDispatcher()->Execute(nSlot);
+ }
+ }
+ break;
+ case CommandEventId::InputLanguageChange :
+ // i#42732 - update state of fontname if input language changes
+ g_bInputLanguageSwitched = true;
+ SetUseInputLanguage( true );
+ break;
+ case CommandEventId::SelectionChange:
+ {
+ const CommandSelectionChangeData *pData = rCEvt.GetSelectionChangeData();
+ rSh.SttCursorMove();
+ rSh.GoStartSentence();
+ rSh.GetCursor()->GetPoint()->AdjustContent(sal::static_int_cast<sal_uInt16, sal_uLong>(pData->GetStart()));
+ rSh.SetMark();
+ rSh.GetCursor()->GetMark()->AdjustContent(sal::static_int_cast<sal_uInt16, sal_uLong>(pData->GetEnd() - pData->GetStart()));
+ rSh.EndCursorMove( true );
+ }
+ break;
+ case CommandEventId::PrepareReconversion:
+ if( rSh.HasSelection() )
+ {
+ SwPaM *pCursor = rSh.GetCursor();
+
+ if( rSh.IsMultiSelection() )
+ {
+ if (pCursor && !pCursor->HasMark() &&
+ pCursor->GetPoint() == pCursor->GetMark())
+ {
+ rSh.GoPrevCursor();
+ pCursor = rSh.GetCursor();
+ }
+
+ // Cancel all selections other than the last selected one.
+ while( rSh.GetCursor()->GetNext() != rSh.GetCursor() )
+ delete rSh.GetCursor()->GetNext();
+ }
+
+ if( pCursor )
+ {
+ SwNodeOffset nPosNodeIdx = pCursor->GetPoint()->GetNodeIndex();
+ const sal_Int32 nPosIdx = pCursor->GetPoint()->GetContentIndex();
+ SwNodeOffset nMarkNodeIdx = pCursor->GetMark()->GetNodeIndex();
+ const sal_Int32 nMarkIdx = pCursor->GetMark()->GetContentIndex();
+
+ if( !rSh.GetCursor()->HasMark() )
+ rSh.GetCursor()->SetMark();
+
+ rSh.SttCursorMove();
+
+ if( nPosNodeIdx < nMarkNodeIdx )
+ {
+ rSh.GetCursor()->GetPoint()->Assign(nPosNodeIdx, nPosIdx);
+ rSh.GetCursor()->GetMark()->Assign(nPosNodeIdx,
+ rSh.GetCursor()->GetPointContentNode()->Len());
+ }
+ else if( nPosNodeIdx == nMarkNodeIdx )
+ {
+ rSh.GetCursor()->GetPoint()->Assign(nPosNodeIdx, nPosIdx);
+ rSh.GetCursor()->GetMark()->Assign(nMarkNodeIdx, nMarkIdx);
+ }
+ else
+ {
+ rSh.GetCursor()->GetMark()->Assign(nMarkNodeIdx, nMarkIdx);
+ rSh.GetCursor()->GetPoint()->Assign(nMarkNodeIdx,
+ rSh.GetCursor()->GetMarkContentNode()->Len());
+ }
+
+ rSh.EndCursorMove( true );
+ }
+ }
+ break;
+ case CommandEventId::QueryCharPosition:
+ {
+ bool bVertical = rSh.IsInVerticalText();
+ const SwPosition& rPos = *rSh.GetCursor()->GetPoint();
+ SwDocShell* pDocSh = m_rView.GetDocShell();
+ SwDoc *pDoc = pDocSh->GetDoc();
+ SwExtTextInput* pInput = pDoc->GetExtTextInput( rPos.GetNode(), rPos.GetContentIndex() );
+ if ( pInput )
+ {
+ const SwPosition& rStart = *pInput->Start();
+ const SwPosition& rEnd = *pInput->End();
+ sal_Int32 nSize = rEnd.GetContentIndex() - rStart.GetContentIndex();
+ vcl::Window& rWin = rSh.GetView().GetEditWin();
+ if ( nSize == 0 )
+ {
+ // When the composition does not exist, use Caret rect instead.
+ const SwRect& aCaretRect ( rSh.GetCharRect() );
+ tools::Rectangle aRect( aCaretRect.Left(), aCaretRect.Top(), aCaretRect.Right(), aCaretRect.Bottom() );
+ rWin.SetCompositionCharRect( &aRect, 1, bVertical );
+ }
+ else
+ {
+ std::unique_ptr<tools::Rectangle[]> aRects(new tools::Rectangle[ nSize ]);
+ int nRectIndex = 0;
+ for ( sal_Int32 nIndex = rStart.GetContentIndex(); nIndex < rEnd.GetContentIndex(); ++nIndex )
+ {
+ const SwPosition aPos( rStart.GetNode(), rStart.GetNode().GetContentNode(), nIndex );
+ SwRect aRect ( rSh.GetCharRect() );
+ rSh.GetCharRectAt( aRect, &aPos );
+ aRects[ nRectIndex ] = tools::Rectangle( aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom() );
+ ++nRectIndex;
+ }
+ rWin.SetCompositionCharRect( aRects.get(), nSize, bVertical );
+ }
+ }
+ bCallBase = false;
+ }
+ break;
+ default:
+ SAL_WARN("sw.ui", "unknown command.");
+ break;
+ }
+ if (bCallBase)
+ Window::Command(rCEvt);
+}
+
+/* i#18686 select the object/cursor at the mouse
+ position of the context menu request */
+void SwEditWin::SelectMenuPosition(SwWrtShell& rSh, const Point& rMousePos )
+{
+ const Point aDocPos( PixelToLogic( rMousePos ) );
+ const bool bIsInsideSelectedObj( rSh.IsInsideSelectedObj( aDocPos ) );
+ //create a synthetic mouse event out of the coordinates
+ MouseEvent aMEvt(rMousePos);
+ SdrView *pSdrView = rSh.GetDrawView();
+ if ( pSdrView )
+ {
+ // no close of insert_draw and reset of
+ // draw mode, if context menu position is inside a selected object.
+ if ( !bIsInsideSelectedObj && m_rView.GetDrawFuncPtr() )
+ {
+
+ m_rView.GetDrawFuncPtr()->Deactivate();
+ m_rView.SetDrawFuncPtr(nullptr);
+ m_rView.LeaveDrawCreate();
+ SfxBindings& rBind = m_rView.GetViewFrame().GetBindings();
+ rBind.Invalidate( SID_ATTR_SIZE );
+ rBind.Invalidate( SID_TABLE_CELL );
+ }
+
+ // if draw text is active and there's a text selection
+ // at the mouse position then do nothing
+ if(rSh.GetSelectionType() & SelectionType::DrawObjectEditMode)
+ {
+ OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
+ ESelection aSelection = pOLV->GetSelection();
+ if(!aSelection.IsZero())
+ {
+ SdrOutliner* pOutliner = pSdrView->GetTextEditOutliner();
+ bool bVertical = pOutliner->IsVertical();
+ const EditEngine& rEditEng = pOutliner->GetEditEngine();
+ Point aEEPos(aDocPos);
+ const tools::Rectangle& rOutputArea = pOLV->GetOutputArea();
+ // regard vertical mode
+ if(bVertical)
+ {
+ aEEPos -= rOutputArea.TopRight();
+ //invert the horizontal direction and exchange X and Y
+ tools::Long nTemp = -aEEPos.X();
+ aEEPos.setX( aEEPos.Y() );
+ aEEPos.setY( nTemp );
+ }
+ else
+ aEEPos -= rOutputArea.TopLeft();
+
+ EPosition aDocPosition = rEditEng.FindDocPosition(aEEPos);
+ ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
+ // make it a forward selection - otherwise the IsLess/IsGreater do not work :-(
+ aSelection.Adjust();
+ if(!(aCompare < aSelection) && !(aCompare > aSelection))
+ {
+ return;
+ }
+ }
+
+ }
+
+ if (pSdrView->MouseButtonDown( aMEvt, GetOutDev() ) )
+ {
+ pSdrView->MouseButtonUp( aMEvt, GetOutDev() );
+ rSh.GetView().GetViewFrame().GetBindings().InvalidateAll(false);
+ return;
+ }
+ }
+ rSh.ResetCursorStack();
+
+ if ( EnterDrawMode( aMEvt, aDocPos ) )
+ {
+ return;
+ }
+ if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
+ {
+ StopInsFrame();
+ rSh.Edit();
+ }
+
+ UpdatePointer( aDocPos );
+
+ if( !rSh.IsSelFrameMode() &&
+ !GetView().GetViewFrame().GetDispatcher()->IsLocked() )
+ {
+ // Test if there is a draw object at that position and if it should be selected.
+ bool bShould = rSh.ShouldObjectBeSelected(aDocPos);
+
+ if(bShould)
+ {
+ m_rView.NoRotate();
+ rSh.HideCursor();
+
+ bool bUnLockView = !rSh.IsViewLocked();
+ rSh.LockView( true );
+ bool bSelObj = rSh.SelectObj( aDocPos );
+ if( bUnLockView )
+ rSh.LockView( false );
+
+ if( bSelObj )
+ {
+ // in case the frame was deselected in the macro
+ // just the cursor has to be displayed again.
+ if( FrameTypeFlags::NONE == rSh.GetSelFrameType() )
+ rSh.ShowCursor();
+ else
+ {
+ if (rSh.IsFrameSelected() && m_rView.GetDrawFuncPtr())
+ {
+ m_rView.GetDrawFuncPtr()->Deactivate();
+ m_rView.SetDrawFuncPtr(nullptr);
+ m_rView.LeaveDrawCreate();
+ m_rView.AttrChangedNotify(nullptr);
+ }
+
+ rSh.EnterSelFrameMode( &aDocPos );
+ g_bFrameDrag = true;
+ UpdatePointer( aDocPos );
+ return;
+ }
+ }
+
+ if (!m_rView.GetDrawFuncPtr())
+ rSh.ShowCursor();
+ }
+ }
+ else if ( rSh.IsSelFrameMode() &&
+ (m_aActHitType == SdrHitKind::NONE ||
+ !bIsInsideSelectedObj))
+ {
+ m_rView.NoRotate();
+ bool bUnLockView = !rSh.IsViewLocked();
+ rSh.LockView( true );
+
+ if ( rSh.IsSelFrameMode() )
+ {
+ rSh.UnSelectFrame();
+ rSh.LeaveSelFrameMode();
+ m_rView.AttrChangedNotify(nullptr);
+ }
+
+ bool bSelObj = rSh.SelectObj( aDocPos, 0/*nFlag*/ );
+ if( bUnLockView )
+ rSh.LockView( false );
+
+ if( !bSelObj )
+ {
+ // move cursor here so that it is not drawn in the
+ // frame at first; ShowCursor() happens in LeaveSelFrameMode()
+ g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
+ rSh.LeaveSelFrameMode();
+ m_rView.LeaveDrawCreate();
+ m_rView.AttrChangedNotify(nullptr);
+ }
+ else
+ {
+ rSh.HideCursor();
+ rSh.EnterSelFrameMode( &aDocPos );
+ rSh.SelFlyGrabCursor();
+ rSh.MakeSelVisible();
+ g_bFrameDrag = true;
+ if( rSh.IsFrameSelected() &&
+ m_rView.GetDrawFuncPtr() )
+ {
+ m_rView.GetDrawFuncPtr()->Deactivate();
+ m_rView.SetDrawFuncPtr(nullptr);
+ m_rView.LeaveDrawCreate();
+ m_rView.AttrChangedNotify(nullptr);
+ }
+ UpdatePointer( aDocPos );
+ }
+ }
+ else if ( rSh.IsSelFrameMode() && bIsInsideSelectedObj )
+ {
+ // Object at the mouse cursor is already selected - do nothing
+ return;
+ }
+
+ if ( rSh.IsGCAttr() )
+ {
+ rSh.GCAttr();
+ rSh.ClearGCAttr();
+ }
+
+ bool bOverSelect = rSh.TestCurrPam( aDocPos );
+ bool bOverURLGrf = false;
+ if( !bOverSelect )
+ bOverURLGrf = bOverSelect = nullptr != rSh.IsURLGrfAtPos( aDocPos );
+
+ if ( !bOverSelect )
+ {
+ // create only temporary move context because otherwise
+ // the query against the content form doesn't work!!!
+ SwMvContext aMvContext( &rSh );
+ rSh.CallSetCursor(&aDocPos, false);
+ }
+ if( !bOverURLGrf )
+ {
+ const SelectionType nSelType = rSh.GetSelectionType();
+ if( nSelType == SelectionType::Ole ||
+ nSelType == SelectionType::Graphic )
+ {
+ SwMvContext aMvContext( &rSh );
+ if( !rSh.IsFrameSelected() )
+ rSh.GotoNextFly();
+ rSh.EnterSelFrameMode();
+ }
+ }
+}
+
+static SfxShell* lcl_GetTextShellFromDispatcher( SwView const & rView )
+{
+ // determine Shell
+ SfxShell* pShell;
+ SfxDispatcher* pDispatcher = rView.GetViewFrame().GetDispatcher();
+ for(sal_uInt16 i = 0; true; ++i )
+ {
+ pShell = pDispatcher->GetShell( i );
+ if( !pShell || dynamic_cast< const SwTextShell *>( pShell ) != nullptr )
+ break;
+ }
+ return pShell;
+}
+
+IMPL_LINK_NOARG(SwEditWin, KeyInputFlushHandler, Timer *, void)
+{
+ FlushInBuffer();
+}
+
+void SwEditWin::InitStaticData()
+{
+ s_pQuickHlpData = new QuickHelpData();
+}
+
+void SwEditWin::FinitStaticData()
+{
+ delete s_pQuickHlpData;
+}
+/* i#3370 - remove quick help to prevent saving
+ * of autocorrection suggestions */
+void SwEditWin::StopQuickHelp()
+{
+ if( HasFocus() && s_pQuickHlpData && s_pQuickHlpData->m_bIsDisplayed )
+ s_pQuickHlpData->Stop( m_rView.GetWrtShell() );
+}
+
+IMPL_LINK_NOARG(SwEditWin, TemplateTimerHdl, Timer *, void)
+{
+ SetApplyTemplate(SwApplyTemplate());
+}
+
+void SwEditWin::SetChainMode( bool bOn )
+{
+ if ( !m_bChainMode )
+ StopInsFrame();
+
+ m_pUserMarker.reset();
+
+ m_bChainMode = bOn;
+
+ static sal_uInt16 aInva[] =
+ {
+ FN_FRAME_CHAIN, FN_FRAME_UNCHAIN, 0
+ };
+ m_rView.GetViewFrame().GetBindings().Invalidate(aInva);
+}
+
+uno::Reference< css::accessibility::XAccessible > SwEditWin::CreateAccessible()
+{
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ SolarMutexGuard aGuard; // this should have happened already!!!
+ SwWrtShell *pSh = m_rView.GetWrtShellPtr();
+ OSL_ENSURE( pSh, "no writer shell, no accessible object" );
+ uno::Reference<
+ css::accessibility::XAccessible > xAcc;
+ if( pSh )
+ xAcc = pSh->CreateAccessible();
+
+ return xAcc;
+#else
+ return nullptr;
+#endif
+}
+
+void QuickHelpData::Move( QuickHelpData& rCpy )
+{
+ m_aHelpStrings.clear();
+ m_aHelpStrings.swap( rCpy.m_aHelpStrings );
+
+ m_bIsDisplayed = rCpy.m_bIsDisplayed;
+ nCurArrPos = rCpy.nCurArrPos;
+ m_bAppendSpace = rCpy.m_bAppendSpace;
+ m_bIsTip = rCpy.m_bIsTip;
+ m_bIsAutoText = rCpy.m_bIsAutoText;
+}
+
+void QuickHelpData::ClearContent()
+{
+ nCurArrPos = nNoPos;
+ m_bIsDisplayed = m_bAppendSpace = false;
+ nTipId = nullptr;
+ m_aHelpStrings.clear();
+ m_bIsTip = true;
+ m_bIsAutoText = true;
+}
+
+void QuickHelpData::Start(SwWrtShell& rSh, const bool bRestart)
+{
+ if (bRestart)
+ {
+ nCurArrPos = 0;
+ }
+ m_bIsDisplayed = true;
+
+ vcl::Window& rWin = rSh.GetView().GetEditWin();
+ if( m_bIsTip )
+ {
+ Point aPt( rWin.OutputToScreenPixel( rWin.LogicToPixel(
+ rSh.GetCharRect().Pos() )));
+ aPt.AdjustY( -3 );
+ nTipId = Help::ShowPopover(&rWin, tools::Rectangle( aPt, Size( 1, 1 )),
+ CurStr(),
+ QuickHelpFlags::Left | QuickHelpFlags::Bottom);
+ }
+ else
+ {
+ OUString sStr(CurStr());
+ sStr = sStr.copy(CurLen());
+ sal_uInt16 nL = sStr.getLength();
+ const ExtTextInputAttr nVal = ExtTextInputAttr::DottedUnderline |
+ ExtTextInputAttr::Highlight;
+ const std::vector<ExtTextInputAttr> aAttrs( nL, nVal );
+ CommandExtTextInputData aCETID( sStr, aAttrs.data(), nL,
+ 0, false );
+
+ //fdo#33092. If the current input language is the default
+ //language that text would appear in if typed, then don't
+ //force a language on for the ExtTextInput.
+ LanguageType eInputLanguage = rWin.GetInputLanguage();
+ if (lcl_isNonDefaultLanguage(eInputLanguage,
+ rSh.GetView(), sStr) == INVALID_HINT)
+ {
+ eInputLanguage = LANGUAGE_DONTKNOW;
+ }
+
+ rSh.CreateExtTextInput(eInputLanguage);
+ rSh.SetExtTextInputData( aCETID );
+ }
+}
+
+void QuickHelpData::Stop( SwWrtShell& rSh )
+{
+ if( !m_bIsTip )
+ rSh.DeleteExtTextInput( false );
+ else if( nTipId )
+ {
+ vcl::Window& rWin = rSh.GetView().GetEditWin();
+ Help::HidePopover(&rWin, nTipId);
+ }
+ ClearContent();
+}
+
+void QuickHelpData::FillStrArr( SwWrtShell const & rSh, const OUString& rWord )
+{
+ enum Capitalization { CASE_LOWER, CASE_UPPER, CASE_SENTENCE, CASE_OTHER };
+
+ // Determine word capitalization
+ const CharClass& rCC = GetAppCharClass();
+ const OUString sWordLower = rCC.lowercase( rWord );
+ Capitalization aWordCase = CASE_OTHER;
+ if ( !rWord.isEmpty() )
+ {
+ if ( rWord[0] == sWordLower[0] )
+ {
+ if ( rWord == sWordLower )
+ aWordCase = CASE_LOWER;
+ }
+ else
+ {
+ // First character is not lower case i.e. assume upper or title case
+ OUString sWordSentence = sWordLower.replaceAt( 0, 1, rtl::OUStringChar(rWord[0]) );
+ if ( rWord == sWordSentence )
+ aWordCase = CASE_SENTENCE;
+ else
+ {
+ if ( rWord == rCC.uppercase( rWord ) )
+ aWordCase = CASE_UPPER;
+ }
+ }
+ }
+
+ SwCalendarWrapper& rCalendar = s_getCalendarWrapper();
+ rCalendar.LoadDefaultCalendar( rSh.GetCurLang() );
+
+ // Add matching calendar month and day names
+ for ( const auto& aNames : { rCalendar.getMonths(), rCalendar.getDays() } )
+ {
+ for ( const auto& rName : aNames )
+ {
+ const OUString& rStr( rName.FullName );
+ // Check string longer than word and case insensitive match
+ if( rStr.getLength() > rWord.getLength() &&
+ rCC.lowercase( rStr, 0, rWord.getLength() ) == sWordLower )
+ {
+ OUString sStr;
+
+ //fdo#61251 if it's an exact match, ensure unchanged replacement
+ //exists as a candidate
+ if (rStr.startsWith(rWord))
+ m_aHelpStrings.emplace_back(rStr, rWord.getLength());
+ else
+ sStr = rStr; // to be added if no case conversion is performed below
+
+ if ( aWordCase == CASE_LOWER )
+ sStr = rCC.lowercase(rStr);
+ else if ( aWordCase == CASE_SENTENCE )
+ sStr = rCC.lowercase(rStr).replaceAt(0, 1, rtl::OUStringChar(rStr[0]));
+ else if ( aWordCase == CASE_UPPER )
+ sStr = rCC.uppercase(rStr);
+
+ if (!sStr.isEmpty())
+ m_aHelpStrings.emplace_back(sStr, rWord.getLength());
+ }
+ }
+ }
+
+ // Add matching current date in ISO 8601 format, for example 2016-01-30
+ OUString rStrToday;
+
+ // do not suggest for single years, for example for "2016",
+ // only for "201" or "2016-..." (to avoid unintentional text
+ // insertion at line ending, for example typing "30 January 2016")
+ if (!rWord.isEmpty() && rWord.getLength() != 4 && rWord[0] == '2')
+ {
+ rStrToday = utl::toISO8601(DateTime(Date(Date::SYSTEM)).GetUNODateTime());
+ if (rStrToday.startsWith(rWord))
+ m_aHelpStrings.emplace_back(rStrToday, rWord.getLength());
+ }
+
+ // Add matching words from AutoCompleteWord list
+ const SwAutoCompleteWord& rACList = SwEditShell::GetAutoCompleteWords();
+ std::vector<OUString> strings;
+
+ if ( !rACList.GetWordsMatching( rWord, strings ) )
+ return;
+
+ for (const OUString & aCompletedString : strings)
+ {
+ // when we have a matching current date, avoid to suggest
+ // other words with the same matching starting characters,
+ // for example 2016-01-3 instead of 2016-01-30
+ if (!rStrToday.isEmpty() && aCompletedString.startsWith(rWord))
+ continue;
+
+ OUString sStr;
+
+ //fdo#61251 if it's an exact match, ensure unchanged replacement
+ //exists as a candidate
+ if (aCompletedString.startsWith(rWord))
+ m_aHelpStrings.emplace_back(aCompletedString, rWord.getLength());
+ else
+ sStr = aCompletedString; // to be added if no case conversion is performed below
+
+ if (aWordCase == CASE_LOWER)
+ sStr = rCC.lowercase(aCompletedString);
+ else if (aWordCase == CASE_SENTENCE)
+ sStr = rCC.lowercase(aCompletedString)
+ .replaceAt(0, 1, rtl::OUStringChar(aCompletedString[0]));
+ else if (aWordCase == CASE_UPPER)
+ sStr = rCC.uppercase(aCompletedString);
+
+ if (!sStr.isEmpty())
+ m_aHelpStrings.emplace_back(aCompletedString, rWord.getLength());
+ }
+}
+
+namespace {
+
+class CompareIgnoreCaseAsciiFavorExact
+{
+ const OUString &m_rOrigWord;
+public:
+ explicit CompareIgnoreCaseAsciiFavorExact(const OUString& rOrigWord)
+ : m_rOrigWord(rOrigWord)
+ {
+ }
+
+ bool operator()(const std::pair<OUString, sal_uInt16>& s1,
+ const std::pair<OUString, sal_uInt16>& s2) const
+ {
+ int nRet = s1.first.compareToIgnoreAsciiCase(s2.first);
+ if (nRet == 0)
+ {
+ //fdo#61251 sort stuff that starts with the exact rOrigWord before
+ //another ignore-case candidate
+ int n1StartsWithOrig = s1.first.startsWith(m_rOrigWord) ? 0 : 1;
+ int n2StartsWithOrig = s2.first.startsWith(m_rOrigWord) ? 0 : 1;
+ return n1StartsWithOrig < n2StartsWithOrig;
+ }
+ return nRet < 0;
+ }
+};
+
+struct EqualIgnoreCaseAscii
+{
+ bool operator()(const std::pair<OUString, sal_uInt16>& s1,
+ const std::pair<OUString, sal_uInt16>& s2) const
+ {
+ return s1.first.equalsIgnoreAsciiCase(s2.first);
+ }
+};
+
+} // anonymous namespace
+
+// TODO Implement an i18n aware sort
+void QuickHelpData::SortAndFilter(const OUString &rOrigWord)
+{
+ std::sort( m_aHelpStrings.begin(),
+ m_aHelpStrings.end(),
+ CompareIgnoreCaseAsciiFavorExact(rOrigWord) );
+
+ const auto& it
+ = std::unique(m_aHelpStrings.begin(), m_aHelpStrings.end(), EqualIgnoreCaseAscii());
+ m_aHelpStrings.erase( it, m_aHelpStrings.end() );
+
+ nCurArrPos = 0;
+}
+
+// For a given chunk of typed text between 3 and 9 characters long that may start at a word boundary
+// or in a whitespace and may include whitespaces, SwEditShell::GetChunkForAutoTextcreates a list of
+// possible candidates for long AutoText names. Let's say, we have typed text "lorem ipsum dr f";
+// and the cursor is right after the "f". SwEditShell::GetChunkForAutoText would take " dr f",
+// since it's the longest chunk to the left of the cursor no longer than 9 characters, not starting
+// in the middle of a word. Then it would create this list from it (in this order, longest first):
+// " dr f"
+// " dr f"
+// "dr f"
+// It cannot add "r f", because it starts in the middle of the word "dr"; also it cannot give " f",
+// because it's only 2 characters long.
+// Now the result of SwEditShell::GetChunkForAutoText is passed here to SwEditWin::ShowAutoText, and
+// then to SwGlossaryList::HasLongName, where all existing autotext entries' long names are tested
+// if they start with one of the list elements. The matches are sorted according the position of the
+// candidate that matched first, then alphabetically inside the group of suggestions for a given
+// candidate. Say, if we have these AutoText entry long names:
+// "Dr Frodo"
+// "Dr Credo"
+// "Or Bilbo"
+// "dr foo"
+// " Dr Fuzz"
+// " dr Faust"
+// the resulting list would be:
+// " Dr Fuzz" -> matches the first (longest) item in the candidates list
+// " dr Faust" -> matches the second candidate item
+// "Dr Foo" -> first item of the two matching the third candidate; alphabetically sorted
+// "Dr Frodo" -> second item of the two matching the third candidate; alphabetically sorted
+// Each of the resulting suggestions knows the length of the candidate it replaces, so accepting the
+// first suggestion would replace 6 characters before cursor, while tabbing to and accepting the
+// last suggestion would replace only 4 characters to the left of cursor.
+bool SwEditWin::ShowAutoText(const std::vector<OUString>& rChunkCandidates)
+{
+ s_pQuickHlpData->ClearContent();
+ if (!rChunkCandidates.empty())
+ {
+ SwGlossaryList* pList = ::GetGlossaryList();
+ pList->HasLongName(rChunkCandidates, s_pQuickHlpData->m_aHelpStrings);
+ }
+
+ if (!s_pQuickHlpData->m_aHelpStrings.empty())
+ {
+ s_pQuickHlpData->Start(m_rView.GetWrtShell(), true);
+ }
+ return !s_pQuickHlpData->m_aHelpStrings.empty();
+}
+
+void SwEditWin::ShowAutoCorrectQuickHelp(
+ const OUString& rWord, SvxAutoCorrect& rACorr )
+{
+ if (rWord.isEmpty())
+ return;
+ SwWrtShell& rSh = m_rView.GetWrtShell();
+ s_pQuickHlpData->ClearContent();
+
+ if( s_pQuickHlpData->m_aHelpStrings.empty() &&
+ rACorr.GetSwFlags().bAutoCompleteWords )
+ {
+ s_pQuickHlpData->m_bIsAutoText = false;
+ s_pQuickHlpData->m_bIsTip = rACorr.GetSwFlags().bAutoCmpltShowAsTip;
+
+ // Get the necessary data to show help text.
+ s_pQuickHlpData->FillStrArr( rSh, rWord );
+ }
+
+ if( !s_pQuickHlpData->m_aHelpStrings.empty() )
+ {
+ s_pQuickHlpData->SortAndFilter(rWord);
+ s_pQuickHlpData->Start(rSh, true);
+ }
+}
+
+bool SwEditWin::IsInHeaderFooter( const Point &rDocPt, FrameControlType &rControl ) const
+{
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ const SwPageFrame* pPageFrame = rSh.GetLayout()->GetPageAtPos( rDocPt );
+
+ if ( pPageFrame && pPageFrame->IsOverHeaderFooterArea( rDocPt, rControl ) )
+ return true;
+
+ if ( rSh.IsShowHeaderFooterSeparator( FrameControlType::Header ) || rSh.IsShowHeaderFooterSeparator( FrameControlType::Footer ) )
+ {
+ SwFrameControlsManager &rMgr = rSh.GetView().GetEditWin().GetFrameControlsManager();
+ Point aPoint( LogicToPixel( rDocPt ) );
+
+ if ( rSh.IsShowHeaderFooterSeparator( FrameControlType::Header ) )
+ {
+ SwFrameControlPtr pControl = rMgr.GetControl( FrameControlType::Header, pPageFrame );
+ if ( pControl && pControl->Contains( aPoint ) )
+ {
+ rControl = FrameControlType::Header;
+ return true;
+ }
+ }
+
+ if ( rSh.IsShowHeaderFooterSeparator( FrameControlType::Footer ) )
+ {
+ SwFrameControlPtr pControl = rMgr.GetControl( FrameControlType::Footer, pPageFrame );
+ if ( pControl && pControl->Contains( aPoint ) )
+ {
+ rControl = FrameControlType::Footer;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool SwEditWin::IsOverHeaderFooterFly( const Point& rDocPos, FrameControlType& rControl, bool& bOverFly, bool& bPageAnchored ) const
+{
+ bool bRet = false;
+ Point aPt( rDocPos );
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ SwPaM aPam( *rSh.GetCurrentShellCursor().GetPoint() );
+ rSh.GetLayout()->GetModelPositionForViewPoint( aPam.GetPoint(), aPt, nullptr, true );
+
+ const SwStartNode* pStartFly = aPam.GetPoint()->GetNode().FindFlyStartNode();
+ if ( pStartFly )
+ {
+ bOverFly = true;
+ SwFrameFormat* pFlyFormat = pStartFly->GetFlyFormat( );
+ if ( pFlyFormat )
+ {
+ const SwNode* pAnchorNode = pFlyFormat->GetAnchor( ).GetAnchorNode( );
+ if ( pAnchorNode )
+ {
+ bool bInHeader = pAnchorNode->FindHeaderStartNode( ) != nullptr;
+ bool bInFooter = pAnchorNode->FindFooterStartNode( ) != nullptr;
+
+ bRet = bInHeader || bInFooter;
+ if ( bInHeader )
+ rControl = FrameControlType::Header;
+ else if ( bInFooter )
+ rControl = FrameControlType::Footer;
+ }
+ else
+ bPageAnchored = pFlyFormat->GetAnchor( ).GetAnchorId( ) == RndStdIds::FLY_AT_PAGE;
+ }
+ }
+ else
+ bOverFly = false;
+ return bRet;
+}
+
+void SwEditWin::SetUseInputLanguage( bool bNew )
+{
+ if ( bNew || m_bUseInputLanguage )
+ {
+ SfxBindings& rBind = GetView().GetViewFrame().GetBindings();
+ rBind.Invalidate( SID_ATTR_CHAR_FONT );
+ rBind.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
+ }
+ m_bUseInputLanguage = bNew;
+}
+
+OUString SwEditWin::GetSurroundingText() const
+{
+ SwWrtShell& rSh = m_rView.GetWrtShell();
+
+ if (rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit())
+ return rSh.GetDrawView()->GetTextEditOutlinerView()->GetSurroundingText();
+
+ OUString sReturn;
+ if( rSh.HasSelection() && !rSh.IsMultiSelection() && rSh.IsSelOnePara() )
+ rSh.GetSelectedText( sReturn, ParaBreakType::ToOnlyCR );
+ else if( !rSh.HasSelection() )
+ {
+ bool bUnLockView = !rSh.IsViewLocked();
+ rSh.LockView(true);
+
+ // store shell state *before* Push
+ ::std::optional<SwCallLink> aLink(std::in_place, rSh);
+ rSh.Push();
+
+ // disable accessible events for internal-only helper cursor
+ const bool bSendAccessibleEventOld = rSh.IsSendAccessibleCursorEvents();
+ rSh.SetSendAccessibleCursorEvents(false);
+
+ // get the sentence around the cursor
+ rSh.HideCursor();
+ rSh.GoStartSentence();
+ rSh.SetMark();
+ rSh.GoEndSentence();
+ rSh.GetSelectedText( sReturn, ParaBreakType::ToOnlyCR );
+
+ rSh.Pop(SwCursorShell::PopMode::DeleteCurrent, aLink);
+ rSh.SetSendAccessibleCursorEvents(bSendAccessibleEventOld);
+ rSh.HideCursor();
+
+ if (bUnLockView)
+ rSh.LockView(false);
+ }
+
+ return sReturn;
+}
+
+Selection SwEditWin::GetSurroundingTextSelection() const
+{
+ SwWrtShell& rSh = m_rView.GetWrtShell();
+
+ if (rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit())
+ return rSh.GetDrawView()->GetTextEditOutlinerView()->GetSurroundingTextSelection();
+
+ Selection aSel(0, 0);
+ if( rSh.HasSelection() )
+ {
+ OUString sReturn;
+ rSh.GetSelectedText( sReturn, ParaBreakType::ToOnlyCR );
+ aSel = Selection( 0, sReturn.getLength() );
+ }
+ else if (rSh.GetCursor()->GetPoint()->GetNode().GetTextNode())
+ {
+ bool bUnLockView = !rSh.IsViewLocked();
+ rSh.LockView(true);
+
+ // Return the position of the visible cursor in the sentence
+ // around the visible cursor.
+ TextFrameIndex const nPos(rSh.GetCursorPointAsViewIndex());
+
+ // store shell state *before* Push
+ ::std::optional<SwCallLink> aLink(std::in_place, rSh);
+ rSh.Push();
+
+ // disable accessible events for internal-only helper cursor
+ const bool bSendAccessibleEventOld = rSh.IsSendAccessibleCursorEvents();
+ rSh.SetSendAccessibleCursorEvents(false);
+
+ rSh.HideCursor();
+ rSh.GoStartSentence();
+ TextFrameIndex const nStartPos(rSh.GetCursorPointAsViewIndex());
+
+ rSh.Pop(SwCursorShell::PopMode::DeleteCurrent, aLink);
+ rSh.SetSendAccessibleCursorEvents(bSendAccessibleEventOld);
+ rSh.ShowCursor();
+
+ if (bUnLockView)
+ rSh.LockView(false);
+
+ aSel = Selection(sal_Int32(nPos - nStartPos), sal_Int32(nPos - nStartPos));
+ }
+
+ return aSel;
+}
+
+bool SwEditWin::DeleteSurroundingText(const Selection& rSelection)
+{
+ SwWrtShell& rSh = m_rView.GetWrtShell();
+
+ if (rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit())
+ return rSh.GetDrawView()->GetTextEditOutlinerView()->DeleteSurroundingText(rSelection);
+
+ if (rSh.HasSelection())
+ return false;
+
+ // rSelection is relative to the start of the sentence, so find that and
+ // adjust the range by it
+ rSh.Push();
+
+ // disable accessible events for internal-only helper cursor
+ const bool bSendAccessibleEventOld = rSh.IsSendAccessibleCursorEvents();
+ rSh.SetSendAccessibleCursorEvents(false);
+
+ rSh.HideCursor();
+ rSh.GoStartSentence();
+ TextFrameIndex const nStartPos(rSh.GetCursorPointAsViewIndex());
+
+ rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+ rSh.SetSendAccessibleCursorEvents(bSendAccessibleEventOld);
+ rSh.ShowCursor();
+
+ if (rSh.SelectTextView(nStartPos + TextFrameIndex(rSelection.Min()), nStartPos + TextFrameIndex(rSelection.Max())))
+ {
+ rSh.Delete(false);
+ return true;
+ }
+
+ return false;
+}
+
+void SwEditWin::LogicInvalidate(const tools::Rectangle* pRectangle)
+{
+ SfxLokHelper::notifyInvalidation(&m_rView, pRectangle);
+}
+
+void SwEditWin::SetCursorTwipPosition(const Point& rPosition, bool bPoint, bool bClearMark)
+{
+ if (SdrView* pSdrView = m_rView.GetWrtShell().GetDrawView())
+ {
+ // Editing shape text, then route the call to editeng.
+ if (pSdrView->GetTextEditObject())
+ {
+ EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView();
+ rEditView.SetCursorLogicPosition(rPosition, bPoint, bClearMark);
+ return;
+ }
+ }
+
+ if (m_rView.GetPostItMgr())
+ {
+ if (sw::annotation::SwAnnotationWin* pWin = m_rView.GetPostItMgr()->GetActiveSidebarWin())
+ {
+ // Editing postit text.
+ pWin->SetCursorLogicPosition(rPosition, bPoint, bClearMark);
+ return;
+ }
+ }
+
+ // Not an SwWrtShell, as that would make SwCursorShell::GetCursor() inaccessible.
+ SwEditShell& rShell = m_rView.GetWrtShell();
+
+ bool bCreateSelection = false;
+ {
+ SwMvContext aMvContext(&rShell);
+ if (bClearMark)
+ rShell.ClearMark();
+ else
+ bCreateSelection = !rShell.HasMark();
+
+ if (bCreateSelection)
+ m_rView.GetWrtShell().SttSelect();
+
+ // If the mark is to be updated, then exchange the point and mark before
+ // and after, as we can't easily set the mark.
+ if (!bPoint)
+ rShell.getShellCursor(/*bBlock=*/false)->Exchange();
+ rShell.SetCursor(rPosition);
+ if (!bPoint)
+ rShell.getShellCursor(/*bBlock=*/false)->Exchange();
+ }
+
+ if (bCreateSelection)
+ m_rView.GetWrtShell().EndSelect();
+}
+
+void SwEditWin::SetGraphicTwipPosition(bool bStart, const Point& rPosition)
+{
+ if (bStart)
+ {
+ MouseEvent aClickEvent(rPosition, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
+ MouseButtonDown(aClickEvent);
+ MouseEvent aMoveEvent(Point(rPosition.getX() + MIN_MOVE + 1, rPosition.getY()), 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
+ MouseMove(aMoveEvent);
+ }
+ else
+ {
+ MouseEvent aMoveEvent(Point(rPosition.getX() - MIN_MOVE - 1, rPosition.getY()), 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
+ MouseMove(aMoveEvent);
+ MouseEvent aClickEvent(rPosition, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
+ MouseButtonUp(aClickEvent);
+ }
+}
+
+SwFrameControlsManager& SwEditWin::GetFrameControlsManager()
+{
+ return *m_pFrameControlsManager;
+}
+
+void SwEditWin::ToggleOutlineContentVisibility(const size_t nOutlinePos, const bool bSubs)
+{
+ // bSubs purpose is to set all sub level outline content to the same visibility as
+ // nOutlinePos outline content visibility is toggled. It is only applicable when not treating
+ // sub outline levels as content.
+ SwWrtShell& rSh = GetView().GetWrtShell();
+
+ if (GetView().GetDrawView()->IsTextEdit())
+ rSh.EndTextEdit();
+ if (GetView().IsDrawMode())
+ GetView().LeaveDrawCreate();
+ rSh.EnterStdMode();
+
+ if (!bSubs || rSh.GetViewOptions()->IsTreatSubOutlineLevelsAsContent())
+ {
+ SwNode* pNode = rSh.GetNodes().GetOutLineNds()[nOutlinePos];
+ bool bVisible = true;
+ pNode->GetTextNode()->GetAttrOutlineContentVisible(bVisible);
+ pNode->GetTextNode()->SetAttrOutlineContentVisible(!bVisible);
+ }
+ else if (bSubs)
+ {
+ // also toggle sub levels to the same content visibility
+ SwOutlineNodes::size_type nPos = nOutlinePos;
+ SwOutlineNodes::size_type nOutlineNodesCount
+ = rSh.getIDocumentOutlineNodesAccess()->getOutlineNodesCount();
+ int nLevel = rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nOutlinePos);
+ bool bVisible = rSh.IsOutlineContentVisible(nOutlinePos);
+ do
+ {
+ if (rSh.IsOutlineContentVisible(nPos) == bVisible)
+ rSh.GetNodes().GetOutLineNds()[nPos]->GetTextNode()->SetAttrOutlineContentVisible(!bVisible);
+ } while (++nPos < nOutlineNodesCount
+ && rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nLevel);
+ }
+
+ rSh.InvalidateOutlineContentVisibility();
+ rSh.GotoOutline(nOutlinePos);
+ rSh.SetModified();
+ GetView().GetDocShell()->Broadcast(SfxHint(SfxHintId::DocChanged));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/edtwin2.cxx b/sw/source/uibase/docvw/edtwin2.cxx
new file mode 100644
index 0000000000..0c47b2ec55
--- /dev/null
+++ b/sw/source/uibase/docvw/edtwin2.cxx
@@ -0,0 +1,685 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <doc.hxx>
+#include <osl/diagnose.h>
+#include <osl/thread.h>
+#include <vcl/help.hxx>
+#include <tools/urlobj.hxx>
+#include <fmtrfmrk.hxx>
+#include <svl/urihelper.hxx>
+#include <sfx2/sfxhelp.hxx>
+#include <svx/svdview.hxx>
+#include <svx/svdpagv.hxx>
+#include <swmodule.hxx>
+#include <modcfg.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <docsh.hxx>
+#include <edtwin.hxx>
+#include <dpage.hxx>
+#include <docufld.hxx>
+#include <reffld.hxx>
+#include <cellatr.hxx>
+#include <shdwcrsr.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtftn.hxx>
+#include <redline.hxx>
+#include <tox.hxx>
+#include <txatbase.hxx>
+#include <uitool.hxx>
+#include <viewopt.hxx>
+#include <strings.hrc>
+
+#include <IDocumentMarkAccess.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <txtfrm.hxx>
+#include <ndtxt.hxx>
+#include <comphelper/lok.hxx>
+#include <authfld.hxx>
+
+#include <com/sun/star/text/XTextRange.hpp>
+#include <unotextrange.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <unoprnms.hxx>
+#include <editeng/unoprnms.hxx>
+#include <rootfrm.hxx>
+#include <unomap.hxx>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+
+namespace {
+
+bool HasValidPropertyValue(const uno::Any& rAny)
+{
+ if (bool bValue; rAny >>= bValue)
+ {
+ return true;
+ }
+ else if (OUString aValue; (rAny >>= aValue) && !(aValue.isEmpty()))
+ {
+ return true;
+ }
+ else if (awt::FontSlant eValue; rAny >>= eValue)
+ {
+ return true;
+ }
+ else if (tools::Long nValueLong; rAny >>= nValueLong)
+ {
+ return true;
+ }
+ else if (double fValue; rAny >>= fValue)
+ {
+ return true;
+ }
+ else if (short nValueShort; rAny >>= nValueShort)
+ {
+ return true;
+ }
+ else
+ return false;
+}
+
+bool PSCSDFPropsQuickHelp(const HelpEvent &rEvt, SwWrtShell& rSh)
+{
+ OUString sText;
+ SwView& rView = rSh.GetView();
+
+ if (rView.IsHighlightCharDF() || rView.GetStylesHighlighterParaColorMap().size()
+ || rView.GetStylesHighlighterCharColorMap().size())
+ {
+ SwPosition aPos(rSh.GetDoc()->GetNodes());
+ Point aPt(rSh.GetWin()->PixelToLogic(
+ rSh.GetWin()->ScreenToOutputPixel(rEvt.GetMousePosPixel())));
+
+ rSh.GetLayout()->GetModelPositionForViewPoint(&aPos, aPt);
+
+ if (!aPos.GetContentNode()->IsTextNode())
+ return false;
+
+ rtl::Reference<SwXTextRange> xRange(
+ SwXTextRange::CreateXTextRange(*(rView.GetDocShell()->GetDoc()),
+ aPos, &aPos));
+ if (!xRange)
+ throw uno::RuntimeException();
+
+ SwContentFrame* pContentFrame = aPos.GetContentNode()->GetTextNode()->getLayoutFrame(
+ rSh.GetLayout());
+
+ SwRect aFrameAreaRect;
+
+ bool bContainsPt = false;
+ do
+ {
+ aFrameAreaRect = pContentFrame->getFrameArea();
+ if (aFrameAreaRect.Contains(aPt))
+ {
+ bContainsPt = true;
+ break;
+ }
+ } while((pContentFrame = pContentFrame->GetFollow()));
+
+ if (bContainsPt)
+ {
+ if (rView.GetStylesHighlighterCharColorMap().size())
+ {
+ // check if in CS formatting highlighted area
+ OUString sCharStyle;
+ xRange->getPropertyValue("CharStyleName") >>= sCharStyle;
+ if (!sCharStyle.isEmpty())
+ sText = SwStyleNameMapper::GetUIName(sCharStyle, SwGetPoolIdFromName::ChrFmt);
+ }
+
+ if (sText.isEmpty() && rView.IsHighlightCharDF())
+ {
+ // check if in direct formatting highlighted area
+ const std::vector<OUString> aHiddenProperties{ UNO_NAME_RSID,
+ UNO_NAME_PARA_IS_NUMBERING_RESTART,
+ UNO_NAME_PARA_STYLE_NAME,
+ UNO_NAME_PARA_CONDITIONAL_STYLE_NAME,
+ UNO_NAME_PAGE_STYLE_NAME,
+ UNO_NAME_NUMBERING_START_VALUE,
+ UNO_NAME_NUMBERING_IS_NUMBER,
+ UNO_NAME_PARA_CONTINUEING_PREVIOUS_SUB_TREE,
+ UNO_NAME_CHAR_STYLE_NAME,
+ UNO_NAME_NUMBERING_LEVEL,
+ UNO_NAME_SORTED_TEXT_ID,
+ UNO_NAME_PARRSID,
+ UNO_NAME_CHAR_COLOR_THEME,
+ UNO_NAME_CHAR_COLOR_TINT_OR_SHADE };
+
+ SfxItemPropertySet const& rPropSet(
+ *aSwMapProvider.GetPropertySet(PROPERTY_MAP_CHAR_AUTO_STYLE));
+ SfxItemPropertyMap const& rMap(rPropSet.getPropertyMap());
+
+ const uno::Sequence<beans::Property> aProperties
+ = xRange->getPropertySetInfo()->getProperties();
+
+ for (const beans::Property& rProperty : aProperties)
+ {
+ const OUString& rPropName = rProperty.Name;
+
+ if (!rMap.hasPropertyByName(rPropName))
+ continue;
+
+ if (std::find(aHiddenProperties.begin(), aHiddenProperties.end(), rPropName)
+ != aHiddenProperties.end())
+ continue;
+
+ if (xRange->getPropertyState(rPropName)
+ == beans::PropertyState_DIRECT_VALUE)
+ {
+ const uno::Any aAny = xRange->getPropertyValue(rPropName);
+ if (HasValidPropertyValue(aAny))
+ {
+ sText = SwResId(STR_CHARACTER_DIRECT_FORMATTING);
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if (rView.GetStylesHighlighterParaColorMap().size())
+ {
+ // check if in paragraph style formatting highlighted area
+ pContentFrame = aPos.GetContentNode()->GetTextNode()->getLayoutFrame(
+ rSh.GetLayout());
+ do
+ {
+ aFrameAreaRect = pContentFrame->getFrameArea();
+ if (pContentFrame->IsRightToLeft())
+ {
+ aFrameAreaRect.AddRight(375);
+ aFrameAreaRect.Left(aFrameAreaRect.Right() - 300);
+ }
+ else
+ {
+ aFrameAreaRect.AddLeft(-375);
+ aFrameAreaRect.Right(aFrameAreaRect.Left() + 300);
+ }
+ if (aFrameAreaRect.Contains(aPt))
+ {
+ OUString sParaStyle;
+ xRange->getPropertyValue("ParaStyleName") >>= sParaStyle;
+ sText = SwStyleNameMapper::GetUIName(sParaStyle, SwGetPoolIdFromName::TxtColl);
+ // check for paragraph direct formatting
+ if (SwDoc::HasParagraphDirectFormatting(aPos))
+ sText = sText + " + " + SwResId(STR_PARAGRAPH_DIRECT_FORMATTING);
+ break;
+ }
+ } while((pContentFrame = pContentFrame->GetFollow()));
+ }
+ }
+
+ if (!sText.isEmpty())
+ {
+ tools::Rectangle aRect(rSh.GetWin()->PixelToLogic(
+ rSh.GetWin()->ScreenToOutputPixel(rEvt.GetMousePosPixel())),
+ Size(1, 1));
+ Point aPt(rSh.GetWin()->OutputToScreenPixel(rSh.GetWin()->LogicToPixel(aRect.TopLeft())));
+ aRect.SetLeft(aPt.X());
+ aRect.SetTop(aPt.Y());
+ aPt = rSh.GetWin()->OutputToScreenPixel(rSh.GetWin()->LogicToPixel(aRect.BottomRight()));
+ aRect.SetRight(aPt.X());
+ aRect.SetBottom(aPt.Y());
+
+ // tdf#136336 ensure tooltip area surrounds the current mouse position with at least a pixel margin
+ aRect.Union(tools::Rectangle(rEvt.GetMousePosPixel(), Size(1, 1)));
+ aRect.AdjustLeft(-1);
+ aRect.AdjustRight(1);
+ aRect.AdjustTop(-1);
+ aRect.AdjustBottom(1);
+
+ QuickHelpFlags nStyle = QuickHelpFlags::NONE; //TipStyleBalloon;
+ Help::ShowQuickHelp(rSh.GetWin(), aRect, sText, nStyle);
+ }
+
+ return !sText.isEmpty();
+}
+}
+
+static OUString lcl_GetRedlineHelp( const SwRangeRedline& rRedl, bool bBalloon,
+ bool bTableChange, bool bTableColChange )
+{
+ TranslateId pResId;
+ switch( rRedl.GetType() )
+ {
+ case RedlineType::Insert: pResId = bTableChange
+ ? !bTableColChange
+ ? STR_REDLINE_TABLE_ROW_INSERT
+ : STR_REDLINE_TABLE_COLUMN_INSERT
+ : rRedl.IsMoved()
+ ? STR_REDLINE_INSERT_MOVED
+ : STR_REDLINE_INSERT;
+ break;
+ case RedlineType::Delete: pResId = bTableChange
+ ? !bTableColChange
+ ? STR_REDLINE_TABLE_ROW_DELETE
+ : STR_REDLINE_TABLE_COLUMN_DELETE
+ : rRedl.IsMoved()
+ ? STR_REDLINE_DELETE_MOVED
+ : STR_REDLINE_DELETE;
+ break;
+ case RedlineType::Format: pResId = STR_REDLINE_FORMAT; break;
+ case RedlineType::Table: pResId = STR_REDLINE_TABLE; break;
+ case RedlineType::FmtColl: pResId = STR_REDLINE_FMTCOLL; break;
+ case RedlineType::ParagraphFormat: pResId = STR_REDLINE_PARAGRAPH_FORMAT; break;
+ case RedlineType::TableRowInsert: pResId = STR_REDLINE_TABLE_ROW_INSERT; break;
+ case RedlineType::TableRowDelete: pResId = STR_REDLINE_TABLE_ROW_DELETE; break;
+ case RedlineType::TableCellInsert: pResId = STR_REDLINE_TABLE_CELL_INSERT; break;
+ case RedlineType::TableCellDelete: pResId = STR_REDLINE_TABLE_CELL_DELETE; break;
+ default: break;
+ }
+
+ if (!pResId)
+ return OUString();
+ OUStringBuffer sBuf(SwResId(pResId)
+ + ": "
+ + rRedl.GetAuthorString()
+ + " - "
+ + GetAppLangDateTimeString(rRedl.GetTimeStamp()));
+ if( bBalloon && !rRedl.GetComment().isEmpty() )
+ sBuf.append("\n" + rRedl.GetComment());
+ return sBuf.makeStringAndClear();
+}
+
+OUString SwEditWin::ClipLongToolTip(const OUString& rText)
+{
+ OUString sDisplayText(rText);
+ tools::Long nTextWidth = GetTextWidth(sDisplayText);
+ tools::Long nMaxWidth = GetDesktopRectPixel().GetWidth() * 2 / 3;
+ nMaxWidth = PixelToLogic(Size(nMaxWidth, 0)).Width();
+ if (nTextWidth > nMaxWidth)
+ sDisplayText = GetOutDev()->GetEllipsisString(sDisplayText, nMaxWidth, DrawTextFlags::CenterEllipsis);
+ return sDisplayText;
+}
+
+void SwEditWin::RequestHelp(const HelpEvent &rEvt)
+{
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+
+ if (PSCSDFPropsQuickHelp(rEvt, rSh))
+ return;
+
+ bool bQuickBalloon = bool(rEvt.GetMode() & ( HelpEventMode::QUICK | HelpEventMode::BALLOON ));
+ if(bQuickBalloon && !rSh.GetViewOptions()->IsShowContentTips())
+ return;
+ bool bContinue = true;
+ CurrShell aCurr(&rSh);
+ OUString sText;
+ Point aPos( PixelToLogic( ScreenToOutputPixel( rEvt.GetMousePosPixel() ) ));
+ bool bBalloon = bool(rEvt.GetMode() & HelpEventMode::BALLOON);
+
+ SdrView *pSdrView = rSh.GetDrawView();
+
+ if( bQuickBalloon && pSdrView )
+ {
+ SdrPageView* pPV = pSdrView->GetSdrPageView();
+ SwDPage* pPage = pPV ? static_cast<SwDPage*>(pPV->GetPage()) : nullptr;
+ bContinue = pPage && pPage->RequestHelp(this, pSdrView, rEvt);
+ }
+
+ if( bContinue && bQuickBalloon)
+ {
+ SwRect aFieldRect;
+ SwContentAtPos aContentAtPos( IsAttrAtPos::Field |
+ IsAttrAtPos::InetAttr |
+ IsAttrAtPos::Ftn |
+ IsAttrAtPos::Redline |
+ IsAttrAtPos::ToxMark |
+ IsAttrAtPos::RefMark |
+ IsAttrAtPos::SmartTag |
+#ifdef DBG_UTIL
+ IsAttrAtPos::TableBoxValue |
+ ( bBalloon ? IsAttrAtPos::CurrAttrs : IsAttrAtPos::NONE) |
+#endif
+ IsAttrAtPos::TableBoxFml |
+ IsAttrAtPos::TableRedline |
+ IsAttrAtPos::TableColRedline );
+
+ if( rSh.GetContentAtPos( aPos, aContentAtPos, false, &aFieldRect ) )
+ {
+ QuickHelpFlags nStyle = QuickHelpFlags::NONE; // style of quick help
+ switch( aContentAtPos.eContentAtPos )
+ {
+ case IsAttrAtPos::TableBoxFml:
+ sText = "= " + static_cast<const SwTableBoxFormula*>(aContentAtPos.aFnd.pAttr)->GetFormula();
+ break;
+#ifdef DBG_UTIL
+ case IsAttrAtPos::TableBoxValue:
+ {
+ if(aContentAtPos.aFnd.pAttr)
+ {
+ sText = OUString::number(
+ static_cast<const SwTableBoxValue*>(aContentAtPos.aFnd.pAttr)->GetValue());
+ }
+ break;
+ }
+ case IsAttrAtPos::CurrAttrs:
+ sText = aContentAtPos.sStr;
+ break;
+#endif
+
+ case IsAttrAtPos::InetAttr:
+ {
+ sText = static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr)->GetValue();
+ sText = URIHelper::removePassword( sText,
+ INetURLObject::EncodeMechanism::WasEncoded,
+ INetURLObject::DecodeMechanism::Unambiguous);
+ //#i63832# remove the link target type
+ sal_Int32 nFound = sText.indexOf(cMarkSeparator);
+ if( nFound != -1 && (++nFound) < sText.getLength() )
+ {
+ std::u16string_view sSuffix( sText.subView(nFound) );
+ if( sSuffix == u"table" ||
+ sSuffix == u"frame" ||
+ sSuffix == u"region" ||
+ sSuffix == u"outline" ||
+ sSuffix == u"text" ||
+ sSuffix == u"graphic" ||
+ sSuffix == u"ole" ||
+ sSuffix == u"drawingobject" )
+ sText = sText.copy( 0, nFound - 1);
+ }
+ // #i104300#
+ // special handling if target is a cross-reference bookmark
+ {
+ OUString sTmpSearchStr = sText.copy( 1 );
+ IDocumentMarkAccess* pMarkAccess = rSh.getIDocumentMarkAccess();
+ IDocumentMarkAccess::const_iterator_t ppBkmk =
+ pMarkAccess->findBookmark( sTmpSearchStr );
+ if ( ppBkmk != pMarkAccess->getBookmarksEnd() &&
+ IDocumentMarkAccess::GetType(**ppBkmk)
+ == IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK )
+ {
+ SwTextNode* pTextNode = (*ppBkmk)->GetMarkStart().GetNode().GetTextNode();
+ if ( pTextNode )
+ {
+ sText = sw::GetExpandTextMerged(rSh.GetLayout(), *pTextNode, true, false, ExpandMode(0));
+
+ if( !sText.isEmpty() )
+ {
+ OUStringBuffer sTmp(sText.replaceAll(u"\u00ad", ""));
+ for (sal_Int32 i = 0; i < sTmp.getLength(); ++i)
+ {
+ if (sTmp[i] < 0x20)
+ sTmp[i] = 0x20;
+ else if (sTmp[i] == 0x2011)
+ sTmp[i] = '-';
+ }
+ sText = sTmp.makeStringAndClear();
+ }
+ }
+ }
+ }
+ // #i80029#
+ bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
+ if ( !bExecHyperlinks )
+ {
+ sText = SfxHelp::GetURLHelpText(sText);
+ }
+ break;
+ }
+ case IsAttrAtPos::SmartTag:
+ {
+ vcl::KeyCode aCode( KEY_SPACE );
+ vcl::KeyCode aModifiedCode( KEY_SPACE, KEY_MOD1 );
+ OUString aModStr( aModifiedCode.GetName() );
+ aModStr = aModStr.replaceFirst(aCode.GetName(), "");
+ aModStr = aModStr.replaceAll("+", "");
+ sText = SwResId(STR_SMARTTAG_CLICK).replaceAll("%s", aModStr);
+ break;
+ }
+
+ case IsAttrAtPos::Ftn:
+ if( aContentAtPos.pFndTextAttr && aContentAtPos.aFnd.pAttr )
+ {
+ const SwFormatFootnote* pFootnote = static_cast<const SwFormatFootnote*>(aContentAtPos.aFnd.pAttr);
+ OUString sTmp(pFootnote->GetFootnoteText(*rSh.GetLayout()));
+ sText = SwResId( pFootnote->IsEndNote()
+ ? STR_ENDNOTE : STR_FTNNOTE ) + sTmp;
+ bBalloon = true;
+ if( aContentAtPos.IsInRTLText() )
+ nStyle |= QuickHelpFlags::BiDiRtl;
+ }
+ break;
+
+ case IsAttrAtPos::TableRedline:
+ case IsAttrAtPos::TableColRedline:
+ case IsAttrAtPos::Redline:
+ {
+ const bool bShowTrackChanges = IDocumentRedlineAccess::IsShowChanges( m_rView.GetDocShell()->GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags() );
+ const bool bShowInlineTooltips = rSh.GetViewOptions()->IsShowInlineTooltips();
+ if ( bShowTrackChanges && bShowInlineTooltips )
+ {
+ sText = lcl_GetRedlineHelp(*aContentAtPos.aFnd.pRedl, bBalloon,
+ IsAttrAtPos::TableRedline == aContentAtPos.eContentAtPos ||
+ IsAttrAtPos::TableColRedline == aContentAtPos.eContentAtPos,
+ IsAttrAtPos::TableColRedline == aContentAtPos.eContentAtPos);
+ }
+ break;
+ }
+
+ case IsAttrAtPos::ToxMark:
+ sText = aContentAtPos.sStr;
+ if( !sText.isEmpty() && aContentAtPos.pFndTextAttr )
+ {
+ const SwTOXType* pTType = aContentAtPos.pFndTextAttr->
+ GetTOXMark().GetTOXType();
+ if( pTType && !pTType->GetTypeName().isEmpty() )
+ {
+ sText = ": " + sText;
+ sText = pTType->GetTypeName() + sText;
+ }
+ }
+ break;
+
+ case IsAttrAtPos::RefMark:
+ if(aContentAtPos.aFnd.pAttr)
+ {
+ sText = SwResId(STR_CONTENT_TYPE_SINGLE_REFERENCE) + ": " +
+ static_cast<const SwFormatRefMark*>(aContentAtPos.aFnd.pAttr)->GetRefName();
+ }
+ break;
+
+ default:
+ {
+ SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig();
+ if(!pModOpt->IsHideFieldTips())
+ {
+ const SwField* pField = aContentAtPos.aFnd.pField;
+ switch( pField->Which() )
+ {
+ case SwFieldIds::SetExp:
+ case SwFieldIds::Table:
+ case SwFieldIds::GetExp:
+ {
+ sal_uInt16 nOldSubType = pField->GetSubType();
+ const_cast<SwField*>(pField)->SetSubType(nsSwExtendedSubType::SUB_CMD);
+ sText = pField->ExpandField(true, rSh.GetLayout());
+ const_cast<SwField*>(pField)->SetSubType(nOldSubType);
+ }
+ break;
+
+ case SwFieldIds::Postit:
+ {
+ break;
+ }
+ case SwFieldIds::Input: // BubbleHelp, because the suggestion could be quite long
+ bBalloon = true;
+ [[fallthrough]];
+ case SwFieldIds::Dropdown:
+ case SwFieldIds::JumpEdit:
+ sText = pField->GetPar2();
+ break;
+
+ case SwFieldIds::Database:
+ sText = pField->GetFieldName();
+ break;
+
+ case SwFieldIds::User:
+ {
+ OUString aTitle = pField->GetTitle();
+ if (!aTitle.isEmpty())
+ {
+ sText = aTitle;
+ }
+ else
+ {
+ sText = pField->GetPar1();
+ }
+ break;
+ }
+ case SwFieldIds::HiddenText:
+ sText = pField->GetPar1();
+ break;
+
+ case SwFieldIds::DocStat:
+ break;
+
+ case SwFieldIds::Macro:
+ sText = static_cast<const SwMacroField*>(pField)->GetMacro();
+ break;
+
+ case SwFieldIds::GetRef:
+ {
+ // #i85090#
+ const SwGetRefField* pRefField( dynamic_cast<const SwGetRefField*>(pField) );
+ OSL_ENSURE( pRefField,
+ "<SwEditWin::RequestHelp(..)> - unexpected type of <pField>" );
+ if ( pRefField )
+ {
+ if ( pRefField->IsRefToHeadingCrossRefBookmark() ||
+ pRefField->IsRefToNumItemCrossRefBookmark() )
+ {
+ sText = pRefField->GetExpandedTextOfReferencedTextNode(*rSh.GetLayout(), nullptr, nullptr);
+ if ( sText.getLength() > 80 )
+ {
+ sText = OUString::Concat(sText.subView(0, 80)) + "...";
+ }
+ }
+ else
+ {
+ sText = pRefField->GetSetRefName();
+ }
+ }
+ break;
+ }
+ case SwFieldIds::TableOfAuthorities:
+ {
+ const auto pAuthorityField = static_cast<const SwAuthorityField*>(pField);
+ sText = pAuthorityField->GetAuthority(rSh.GetLayout());
+
+ if (auto t = pAuthorityField->GetTargetType();
+ t == SwAuthorityField::TargetType::UseDisplayURL
+ || t == SwAuthorityField::TargetType::UseTargetURL)
+ {
+ const OUString& rURL = pAuthorityField->GetAbsoluteURL();
+ sText += "\n" + SfxHelp::GetURLHelpText(rURL);
+ }
+
+ break;
+ }
+
+ default: break;
+ }
+ }
+
+ if( sText.isEmpty() )
+ {
+ const bool bShowTrackChanges = IDocumentRedlineAccess::IsShowChanges( m_rView.GetDocShell()->GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags() );
+ const bool bShowInlineTooltips = rSh.GetViewOptions()->IsShowInlineTooltips();
+ if ( bShowTrackChanges && bShowInlineTooltips )
+ {
+ aContentAtPos.eContentAtPos = IsAttrAtPos::Redline;
+ if( rSh.GetContentAtPos( aPos, aContentAtPos, false, &aFieldRect ) )
+ sText = lcl_GetRedlineHelp(*aContentAtPos.aFnd.pRedl, bBalloon, /*bTableChange=*/false, /*bTableColChange=*/false);
+ }
+ }
+ }
+ }
+ if (!sText.isEmpty())
+ {
+ tools::Rectangle aRect( aFieldRect.SVRect() );
+ Point aPt( OutputToScreenPixel( LogicToPixel( aRect.TopLeft() )));
+ aRect.SetLeft( aPt.X() );
+ aRect.SetTop( aPt.Y() );
+ aPt = OutputToScreenPixel( LogicToPixel( aRect.BottomRight() ));
+ aRect.SetRight( aPt.X() );
+ aRect.SetBottom( aPt.Y() );
+
+ // tdf#136336 ensure tooltip area surrounds the current mouse position with at least a pixel margin
+ aRect.Union(tools::Rectangle(rEvt.GetMousePosPixel(), Size(1, 1)));
+ aRect.AdjustLeft(-1);
+ aRect.AdjustRight(1);
+ aRect.AdjustTop(-1);
+ aRect.AdjustBottom(1);
+
+ if( bBalloon )
+ Help::ShowBalloon( this, rEvt.GetMousePosPixel(), aRect, sText );
+ else
+ {
+ // the show the help
+ OUString sDisplayText(ClipLongToolTip(sText));
+ Help::ShowQuickHelp(this, aRect, sDisplayText, nStyle);
+ }
+ }
+
+ bContinue = false;
+ }
+
+ }
+
+ if( bContinue )
+ Window::RequestHelp( rEvt );
+}
+
+void SwEditWin::PrePaint(vcl::RenderContext& /*rRenderContext*/)
+{
+ if (SwWrtShell* pWrtShell = GetView().GetWrtShellPtr())
+ pWrtShell->PrePaint();
+}
+
+void SwEditWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ SwWrtShell* pWrtShell = GetView().GetWrtShellPtr();
+ if(!pWrtShell)
+ return;
+
+ if ( GetView().GetVisArea().GetWidth() <= 0 ||
+ GetView().GetVisArea().GetHeight() <= 0 )
+ Invalidate( rRect );
+ else
+ {
+ pWrtShell->setOutputToWindow(true);
+ bool bTiledPainting = false;
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ bTiledPainting = comphelper::LibreOfficeKit::isTiledPainting();
+ comphelper::LibreOfficeKit::setTiledPainting(true);
+ }
+ pWrtShell->Paint(rRenderContext, rRect);
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ comphelper::LibreOfficeKit::setTiledPainting(bTiledPainting);
+ }
+ pWrtShell->setOutputToWindow(false);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/edtwin3.cxx b/sw/source/uibase/docvw/edtwin3.cxx
new file mode 100644
index 0000000000..2b9d1a7f1e
--- /dev/null
+++ b/sw/source/uibase/docvw/edtwin3.cxx
@@ -0,0 +1,175 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/event.hxx>
+#include <vcl/settings.hxx>
+#include <svx/ruler.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <basesh.hxx>
+#include <pview.hxx>
+#include <mdiexp.hxx>
+#include <edtwin.hxx>
+#include <swmodule.hxx>
+#include <modcfg.hxx>
+#include <docsh.hxx>
+#include <uiobject.hxx>
+
+// Core-Notify
+void ScrollMDI( SwViewShell const * pVwSh, const SwRect &rRect,
+ sal_uInt16 nRangeX, sal_uInt16 nRangeY)
+{
+ SfxViewShell *pSfxViewShell = pVwSh->GetSfxViewShell();
+
+ if (SwView* pSwView = dynamic_cast<SwView *>(pSfxViewShell))
+ pSwView->Scroll(rRect.SVRect(), nRangeX, nRangeY);
+}
+
+// Docmdi - movable
+bool IsScrollMDI( SwViewShell const * pVwSh, const SwRect &rRect )
+{
+ SfxViewShell *pSfxViewShell = pVwSh->GetSfxViewShell();
+
+ if (SwView* pSwView = dynamic_cast<SwView *>(pSfxViewShell))
+ return pSwView->IsScroll(rRect.SVRect());
+
+ return false;
+}
+
+// Notify for size change
+void SizeNotify(SwViewShell const * pVwSh, const Size &rSize)
+{
+ SfxViewShell *pSfxViewShell = pVwSh->GetSfxViewShell();
+
+ if (SwView* pSwView = dynamic_cast<SwView *>(pSfxViewShell))
+ pSwView->DocSzChgd(rSize);
+ else if (SwPagePreview* pSwPageView = dynamic_cast<SwPagePreview *>(pSfxViewShell))
+ pSwPageView->DocSzChgd(rSize);
+}
+
+// Notify for page number update
+void PageNumNotify(SwViewShell const * pVwSh)
+{
+ SfxViewShell *pSfxViewShell = pVwSh->GetSfxViewShell();
+
+ if (SwView* pSwView = dynamic_cast<SwView *>(pSfxViewShell))
+ {
+ if (pSwView->GetCurShell())
+ pSwView->UpdatePageNums();
+ }
+}
+
+void FrameNotify( SwViewShell* pVwSh, FlyMode eMode )
+{
+ if (SwWrtShell* pWrtShell = dynamic_cast<SwWrtShell *>(pVwSh))
+ SwBaseShell::SetFrameMode(eMode, pWrtShell);
+}
+
+// Notify for page number update
+bool SwEditWin::RulerColumnDrag( const MouseEvent& rMEvt, bool bVerticalMode)
+{
+ SvxRuler& rRuler = bVerticalMode ? m_rView.GetVRuler() : m_rView.GetHRuler();
+ return (!rRuler.StartDocDrag( rMEvt, RulerType::Border ) &&
+ !rRuler.StartDocDrag( rMEvt, RulerType::Margin1) &&
+ !rRuler.StartDocDrag( rMEvt, RulerType::Margin2));
+}
+
+// #i23726#
+// #i42921# - add 3rd parameter <bVerticalMode> in order
+// to consider vertical layout
+bool SwEditWin::RulerMarginDrag( const MouseEvent& rMEvt,
+ const bool bVerticalMode )
+{
+ SvxRuler& rRuler = bVerticalMode ? m_rView.GetVRuler() : m_rView.GetHRuler();
+ return !rRuler.StartDocDrag( rMEvt, RulerType::Indent);
+}
+
+TableChgMode GetTableChgDefaultMode()
+{
+ SwModuleOptions* pOpt = SW_MOD()->GetModuleConfig();
+ return pOpt ? pOpt->GetTableMode() : TableChgMode::VarWidthChangeAbs;
+}
+
+void RepaintPagePreview( SwViewShell const * pVwSh, const SwRect& rRect )
+{
+ SfxViewShell *pSfxViewShell = pVwSh->GetSfxViewShell();
+
+ if (SwPagePreview* pSwPagePreview = dynamic_cast<SwPagePreview *>(pSfxViewShell))
+ pSwPagePreview->RepaintCoreRect(rRect);
+}
+
+bool JumpToSwMark( SwViewShell const * pVwSh, std::u16string_view rMark )
+{
+ SfxViewShell *pSfxViewShell = pVwSh->GetSfxViewShell();
+
+ if (SwView* pSwView = dynamic_cast<SwView *>(pSfxViewShell))
+ return pSwView->JumpToSwMark(rMark);
+
+ return false;
+}
+
+void SwEditWin::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ SwWrtShell* pSh = GetView().GetWrtShellPtr();
+ // DataChanged() is sometimes called prior to creating
+ // the SwWrtShell
+ if(!pSh)
+ return;
+ bool bViewWasLocked = pSh->IsViewLocked(), bUnlockPaint = false;
+ pSh->LockView( true );
+ switch( rDCEvt.GetType() )
+ {
+ case DataChangedEventType::SETTINGS:
+ // rearrange ScrollBars, respectively trigger resize, because
+ // the ScrollBar size can have change. For that, in the reset
+ // handler, the size of the ScrollBars also has to be queried
+ // from the settings.
+ if( rDCEvt.GetFlags() & AllSettingsFlags::STYLE )
+ {
+ pSh->LockPaint(LockPaintReason::DataChanged);
+ bUnlockPaint = true;
+ pSh->DeleteReplacementBitmaps();
+ GetView().InvalidateBorder(); //Scrollbar work
+ }
+ break;
+
+ case DataChangedEventType::PRINTER:
+ case DataChangedEventType::DISPLAY:
+ case DataChangedEventType::FONTS:
+ case DataChangedEventType::FONTSUBSTITUTION:
+ pSh->LockPaint(LockPaintReason::DataChanged);
+ bUnlockPaint = true;
+ GetView().GetDocShell()->UpdateFontList(); //e.g. printer change
+ pSh->InvalidateLayout(true);
+ break;
+ default: break;
+ }
+ pSh->LockView( bViewWasLocked );
+ if( bUnlockPaint )
+ pSh->UnlockPaint();
+}
+
+FactoryFunction SwEditWin::GetUITestFactory() const
+{
+ return SwEditWinUIObject::create;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/frmsidebarwincontainer.cxx b/sw/source/uibase/docvw/frmsidebarwincontainer.cxx
new file mode 100644
index 0000000000..17da0beee4
--- /dev/null
+++ b/sw/source/uibase/docvw/frmsidebarwincontainer.cxx
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "frmsidebarwincontainer.hxx"
+
+#include <map>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <AnnotationWin.hxx>
+
+namespace {
+ struct SidebarWinKey
+ {
+ const sal_Int32 mnIndex;
+
+ explicit SidebarWinKey( const sal_Int32 nIndex )
+ : mnIndex( nIndex )
+ {}
+
+ bool operator < ( const SidebarWinKey& rSidebarWinKey ) const
+ {
+ return mnIndex < rSidebarWinKey.mnIndex;
+ }
+ };
+
+ typedef std::map < SidebarWinKey, VclPtr<sw::annotation::SwAnnotationWin> > SidebarWinContainer;
+
+ struct FrameKey
+ {
+ const SwFrame* mpFrame;
+
+ explicit FrameKey( const SwFrame* pFrame )
+ : mpFrame( pFrame )
+ {}
+
+ bool operator < ( const FrameKey& rFrameKey ) const
+ {
+ return mpFrame < rFrameKey.mpFrame;
+ }
+ };
+
+ typedef std::map < FrameKey, SidebarWinContainer > FrameSidebarWinContainer_;
+}
+
+namespace sw::sidebarwindows {
+
+class FrameSidebarWinContainer : public FrameSidebarWinContainer_
+{
+};
+
+SwFrameSidebarWinContainer::SwFrameSidebarWinContainer()
+ : mpFrameSidebarWinContainer( new FrameSidebarWinContainer )
+{}
+
+SwFrameSidebarWinContainer::~SwFrameSidebarWinContainer()
+{
+ mpFrameSidebarWinContainer->clear();
+ mpFrameSidebarWinContainer.reset();
+}
+
+bool SwFrameSidebarWinContainer::insert( const SwFrame& rFrame,
+ const SwFormatField& rFormatField,
+ sw::annotation::SwAnnotationWin& rSidebarWin )
+{
+ bool bInserted( false );
+
+ FrameKey aFrameKey( &rFrame );
+ SidebarWinContainer& rSidebarWinContainer = (*mpFrameSidebarWinContainer)[ aFrameKey ];
+
+ SidebarWinKey aSidebarWinKey( rFormatField.GetTextField()->GetStart() );
+ if ( rSidebarWinContainer.empty() ||
+ rSidebarWinContainer.find( aSidebarWinKey) == rSidebarWinContainer.end() )
+ {
+ rSidebarWinContainer[ aSidebarWinKey ] = &rSidebarWin;
+ bInserted = true;
+ }
+
+ return bInserted;
+}
+
+bool SwFrameSidebarWinContainer::remove( const SwFrame& rFrame,
+ const sw::annotation::SwAnnotationWin & rSidebarWin )
+{
+ bool bRemoved( false );
+
+ FrameKey aFrameKey( &rFrame );
+ FrameSidebarWinContainer::iterator aFrameIter = mpFrameSidebarWinContainer->find( aFrameKey );
+ if ( aFrameIter != mpFrameSidebarWinContainer->end() )
+ {
+ SidebarWinContainer& rSidebarWinContainer = (*aFrameIter).second;
+ auto aIter = std::find_if(rSidebarWinContainer.begin(), rSidebarWinContainer.end(),
+ [&rSidebarWin](const SidebarWinContainer::value_type& rEntry) { return rEntry.second == &rSidebarWin; });
+ if ( aIter != rSidebarWinContainer.end() )
+ {
+ rSidebarWinContainer.erase( aIter );
+ bRemoved = true;
+ }
+ }
+
+ return bRemoved;
+}
+
+bool SwFrameSidebarWinContainer::empty( const SwFrame& rFrame )
+{
+ bool bEmpty( true );
+
+ FrameKey aFrameKey( &rFrame );
+ FrameSidebarWinContainer::iterator aFrameIter = mpFrameSidebarWinContainer->find( aFrameKey );
+ if ( aFrameIter != mpFrameSidebarWinContainer->end() )
+ {
+ bEmpty = (*aFrameIter).second.empty();
+ }
+
+ return bEmpty;
+}
+
+sw::annotation::SwAnnotationWin* SwFrameSidebarWinContainer::get( const SwFrame& rFrame,
+ const sal_Int32 nIndex )
+{
+ sw::annotation::SwAnnotationWin* pRet( nullptr );
+
+ FrameKey aFrameKey( &rFrame );
+ FrameSidebarWinContainer::iterator aFrameIter = mpFrameSidebarWinContainer->find( aFrameKey );
+ if ( aFrameIter != mpFrameSidebarWinContainer->end() && nIndex >= 0 )
+ {
+ SidebarWinContainer& rSidebarWinContainer = (*aFrameIter).second;
+ if (nIndex < sal_Int32(rSidebarWinContainer.size()))
+ {
+ auto aIter = rSidebarWinContainer.begin();
+ std::advance(aIter, nIndex);
+ pRet = (*aIter).second;
+ }
+ }
+ return pRet;
+}
+
+void SwFrameSidebarWinContainer::getAll( const SwFrame& rFrame,
+ std::vector< vcl::Window* >* pSidebarWins )
+{
+ pSidebarWins->clear();
+
+ FrameKey aFrameKey( &rFrame );
+ FrameSidebarWinContainer::iterator aFrameIter = mpFrameSidebarWinContainer->find( aFrameKey );
+ if ( aFrameIter != mpFrameSidebarWinContainer->end() )
+ {
+ SidebarWinContainer& rSidebarWinContainer = (*aFrameIter).second;
+ for ( const auto& rEntry : rSidebarWinContainer )
+ {
+ pSidebarWins->push_back( rEntry.second );
+ }
+ }
+}
+
+} // eof of namespace sw::sidebarwindows
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/frmsidebarwincontainer.hxx b/sw/source/uibase/docvw/frmsidebarwincontainer.hxx
new file mode 100644
index 0000000000..33ae9a9d4d
--- /dev/null
+++ b/sw/source/uibase/docvw/frmsidebarwincontainer.hxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/types.h>
+#include <memory>
+#include <vector>
+
+class SwFrame;
+class SwFormatField;
+namespace vcl { class Window; }
+namespace sw::annotation { class SwAnnotationWin; }
+
+namespace sw::sidebarwindows {
+
+class FrameSidebarWinContainer;
+
+class SwFrameSidebarWinContainer
+{
+ public:
+ SwFrameSidebarWinContainer();
+ ~SwFrameSidebarWinContainer();
+
+ bool insert( const SwFrame& rFrame,
+ const SwFormatField& rFormatField,
+ sw::annotation::SwAnnotationWin& rSidebarWin );
+
+ bool remove( const SwFrame& rFrame,
+ const sw::annotation::SwAnnotationWin& rSidebarWin );
+
+ bool empty( const SwFrame& rFrame );
+
+ sw::annotation::SwAnnotationWin* get( const SwFrame& rFrame,
+ const sal_Int32 nIndex );
+
+ void getAll( const SwFrame& rFrame,
+ std::vector< vcl::Window* >* pSidebarWins );
+
+ private:
+ std::unique_ptr<FrameSidebarWinContainer> mpFrameSidebarWinContainer;
+};
+
+} // namespace sw::sidebarwindows
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/romenu.cxx b/sw/source/uibase/docvw/romenu.cxx
new file mode 100644
index 0000000000..05d352f181
--- /dev/null
+++ b/sw/source/uibase/docvw/romenu.cxx
@@ -0,0 +1,344 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <hintids.hxx>
+
+#include <svl/eitem.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/transfer.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svx/gallery.hxx>
+#include <svx/graphichelper.hxx>
+#include <editeng/brushitem.hxx>
+
+#include <fmtinfmt.hxx>
+#include <docsh.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <viewopt.hxx>
+#include <swmodule.hxx>
+#include "romenu.hxx"
+#include <pagedesc.hxx>
+#include <modcfg.hxx>
+
+#include <cmdid.h>
+
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::sfx2;
+
+SwReadOnlyPopup::~SwReadOnlyPopup()
+{
+ m_xMenu.disposeAndClear();
+}
+
+void SwReadOnlyPopup::Check( sal_uInt16 nMID, sal_uInt16 nSID, SfxDispatcher const &rDis )
+{
+ std::unique_ptr<SfxPoolItem> _pItem;
+ SfxItemState eState = rDis.GetBindings()->QueryState( nSID, _pItem );
+ if (eState >= SfxItemState::DEFAULT)
+ {
+ m_xMenu->EnableItem(nMID);
+ if (_pItem)
+ {
+ m_xMenu->CheckItem(nMID, !_pItem->isVoidItem() &&
+ dynamic_cast< const SfxBoolItem *>( _pItem.get() ) != nullptr &&
+ static_cast<SfxBoolItem*>(_pItem.get())->GetValue());
+ //remove full screen entry when not in full screen mode
+ if (SID_WIN_FULLSCREEN == nSID && !m_xMenu->IsItemChecked(m_nReadonlyFullscreen))
+ m_xMenu->EnableItem(nMID, false);
+ }
+ }
+ else
+ m_xMenu->EnableItem(nMID, false);
+}
+
+#define MN_READONLY_GRAPHICTOGALLERY 1000
+#define MN_READONLY_BACKGROUNDTOGALLERY 2000
+
+SwReadOnlyPopup::SwReadOnlyPopup(const Point &rDPos, SwView &rV)
+ : m_aBuilder(nullptr, AllSettings::GetUIRootDir(), "modules/swriter/ui/readonlymenu.ui", "")
+ , m_xMenu(m_aBuilder.get_menu(u"menu"))
+ , m_nReadonlyOpenurl(m_xMenu->GetItemId(u"openurl"))
+ , m_nReadonlyOpendoc(m_xMenu->GetItemId(u"opendoc"))
+ , m_nReadonlyEditdoc(m_xMenu->GetItemId(u"edit"))
+ , m_nReadonlySelectionMode(m_xMenu->GetItemId(u"selection"))
+ , m_nReadonlyReload(m_xMenu->GetItemId(u"reload"))
+ , m_nReadonlyReloadFrame(m_xMenu->GetItemId(u"reloadframe"))
+ , m_nReadonlySourceview(m_xMenu->GetItemId(u"html"))
+ , m_nReadonlyBrowseBackward(m_xMenu->GetItemId(u"backward"))
+ , m_nReadonlyBrowseForward(m_xMenu->GetItemId(u"forward"))
+ , m_nReadonlySaveGraphic(m_xMenu->GetItemId(u"savegraphic"))
+ , m_nReadonlyGraphictogallery(m_xMenu->GetItemId(u"graphictogallery"))
+ , m_nReadonlyTogallerylink(m_xMenu->GetItemId(u"graphicaslink"))
+ , m_nReadonlyTogallerycopy(m_xMenu->GetItemId(u"graphicascopy"))
+ , m_nReadonlySaveBackground(m_xMenu->GetItemId(u"savebackground"))
+ , m_nReadonlyBackgroundtogallery(m_xMenu->GetItemId(u"backgroundtogallery"))
+ , m_nReadonlyBackgroundTogallerylink(m_xMenu->GetItemId(u"backaslink"))
+ , m_nReadonlyBackgroundTogallerycopy(m_xMenu->GetItemId(u"backascopy"))
+ , m_nReadonlyCopylink(m_xMenu->GetItemId(u"copylink"))
+ , m_nReadonlyLoadGraphic(m_xMenu->GetItemId(u"loadgraphic"))
+ , m_nReadonlyGraphicoff(m_xMenu->GetItemId(u"imagesoff"))
+ , m_nReadonlyFullscreen(m_xMenu->GetItemId(u"fullscreen"))
+ , m_nReadonlyCopy(m_xMenu->GetItemId(u"copy"))
+ , m_rView(rV)
+ , m_xBrushItem(std::make_unique<SvxBrushItem>(RES_BACKGROUND))
+{
+ m_bGrfToGalleryAsLnk = SW_MOD()->GetModuleConfig()->IsGrfToGalleryAsLnk();
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ OUString sDescription;
+ rSh.IsURLGrfAtPos( rDPos, &m_sURL, &m_sTargetFrameName, &sDescription );
+ if ( m_sURL.isEmpty() )
+ {
+ SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );
+ if( rSh.GetContentAtPos( rDPos, aContentAtPos))
+ {
+ const SwFormatINetFormat &rIItem = *static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr);
+ m_sURL = rIItem.GetValue();
+ m_sTargetFrameName = rIItem.GetTargetFrame();
+ }
+ }
+
+ bool bLink = false;
+ const Graphic *pGrf = rSh.GetGrfAtPos( rDPos, m_sGrfName, bLink );
+ if ( nullptr == pGrf )
+ {
+ m_xMenu->EnableItem(m_nReadonlySaveGraphic, false);
+ }
+ else
+ {
+ m_aGraphic = *pGrf;
+ }
+
+ bool bEnableGraphicToGallery = bLink;
+ if ( bEnableGraphicToGallery )
+ {
+ if (GalleryExplorer::FillThemeList( m_aThemeList ))
+ {
+ PopupMenu *pMenu = m_xMenu->GetPopupMenu(m_nReadonlyGraphictogallery);
+ pMenu->CheckItem(m_nReadonlyTogallerylink, m_bGrfToGalleryAsLnk);
+ pMenu->CheckItem(m_nReadonlyTogallerycopy, !m_bGrfToGalleryAsLnk);
+
+ for ( size_t i=0; i < m_aThemeList.size(); ++i )
+ pMenu->InsertItem(MN_READONLY_GRAPHICTOGALLERY + i, m_aThemeList[i]);
+ }
+ else
+ bEnableGraphicToGallery = false;
+ }
+
+ m_xMenu->EnableItem(m_nReadonlyGraphictogallery, bEnableGraphicToGallery);
+
+ SfxViewFrame& rVFrame = rV.GetViewFrame();
+ SfxDispatcher &rDis = *rVFrame.GetDispatcher();
+ const SwPageDesc &rDesc = rSh.GetPageDesc( rSh.GetCurPageDesc() );
+ m_xBrushItem = rDesc.GetMaster().makeBackgroundBrushItem();
+ bool bEnableBackGallery = false,
+ bEnableBack = false;
+
+ if ( m_xBrushItem && GPOS_NONE != m_xBrushItem->GetGraphicPos() )
+ {
+ bEnableBack = true;
+ if ( !m_xBrushItem->GetGraphicLink().isEmpty() )
+ {
+ if ( m_aThemeList.empty() )
+ GalleryExplorer::FillThemeList( m_aThemeList );
+
+ if ( !m_aThemeList.empty() )
+ {
+ PopupMenu *pMenu = m_xMenu->GetPopupMenu(m_nReadonlyBackgroundtogallery);
+ pMenu->CheckItem(m_nReadonlyBackgroundTogallerylink, m_bGrfToGalleryAsLnk);
+ pMenu->CheckItem(m_nReadonlyBackgroundTogallerycopy, !m_bGrfToGalleryAsLnk);
+ bEnableBackGallery = true;
+
+ for ( size_t i=0; i < m_aThemeList.size(); ++i )
+ pMenu->InsertItem(MN_READONLY_BACKGROUNDTOGALLERY + i, m_aThemeList[i]);
+ }
+ }
+ }
+ m_xMenu->EnableItem(m_nReadonlySaveBackground, bEnableBack);
+ m_xMenu->EnableItem(m_nReadonlyBackgroundtogallery, bEnableBackGallery);
+
+ if ( !rSh.GetViewOptions()->IsGraphic() )
+ m_xMenu->CheckItem(m_nReadonlyGraphicoff);
+ else
+ m_xMenu->EnableItem(m_nReadonlyLoadGraphic, false);
+
+ m_xMenu->EnableItem(m_nReadonlyReloadFrame, false);
+ m_xMenu->EnableItem(m_nReadonlyReload);
+
+ Check(m_nReadonlyEditdoc, SID_EDITDOC, rDis);
+ Check(m_nReadonlySelectionMode, FN_READONLY_SELECTION_MODE, rDis);
+ Check(m_nReadonlySourceview, SID_SOURCEVIEW, rDis);
+ Check(m_nReadonlyBrowseBackward, SID_BROWSE_BACKWARD, rDis);
+ Check(m_nReadonlyBrowseForward,SID_BROWSE_FORWARD, rDis);
+ Check(m_nReadonlyOpenurl, SID_OPENDOC, rDis);
+ Check(m_nReadonlyOpendoc, SID_OPENDOC, rDis);
+
+ std::unique_ptr<SfxPoolItem> pState;
+
+ SfxItemState eState = rVFrame.GetBindings().QueryState( SID_COPY, pState );
+ Check(m_nReadonlyCopy, SID_COPY, rDis);
+ if (eState < SfxItemState::DEFAULT)
+ m_xMenu->EnableItem(m_nReadonlyCopy, false);
+
+ eState = rVFrame.GetBindings().QueryState( SID_EDITDOC, pState );
+ if (
+ eState < SfxItemState::DEFAULT ||
+ (rSh.IsGlobalDoc() && m_rView.GetDocShell()->IsReadOnlyUI())
+ )
+ {
+ m_xMenu->EnableItem(m_nReadonlyEditdoc, false);
+ }
+
+ if ( m_sURL.isEmpty() )
+ {
+ m_xMenu->EnableItem(m_nReadonlyOpenurl, false);
+ m_xMenu->EnableItem(m_nReadonlyOpendoc, false);
+ m_xMenu->EnableItem(m_nReadonlyCopylink, false);
+ }
+ Check(m_nReadonlyFullscreen, SID_WIN_FULLSCREEN, rDis);
+
+ m_xMenu->RemoveDisabledEntries( true );
+}
+
+void SwReadOnlyPopup::Execute( vcl::Window* pWin, const Point &rPixPos )
+{
+ sal_uInt16 nId = m_xMenu->Execute(pWin, rPixPos);
+ Execute(pWin, nId);
+}
+
+// execute the resulting ID only - necessary to support XContextMenuInterception
+void SwReadOnlyPopup::Execute( vcl::Window* pWin, sal_uInt16 nId )
+{
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ SfxDispatcher &rDis = *m_rView.GetViewFrame().GetDispatcher();
+ if (nId >= MN_READONLY_GRAPHICTOGALLERY)
+ {
+ OUString sTmp;
+ sal_uInt16 nSaveId;
+ if (m_xBrushItem && nId >= MN_READONLY_BACKGROUNDTOGALLERY)
+ {
+ nId -= MN_READONLY_BACKGROUNDTOGALLERY;
+ nSaveId = m_nReadonlySaveBackground;
+ sTmp = m_xBrushItem->GetGraphicLink();
+ }
+ else
+ {
+ nId -= MN_READONLY_GRAPHICTOGALLERY;
+ nSaveId = m_nReadonlySaveGraphic;
+ sTmp = m_sGrfName;
+ }
+ if ( !m_bGrfToGalleryAsLnk )
+ sTmp = SaveGraphic(nSaveId);
+
+ if ( !sTmp.isEmpty() )
+ GalleryExplorer::InsertURL( m_aThemeList[nId], sTmp );
+
+ return;
+ }
+
+ rtl::Reference<TransferDataContainer> pClipCntnr;
+
+ sal_uInt16 nExecId = USHRT_MAX;
+ bool bFilterSet = false;
+ LoadUrlFlags nFilter = LoadUrlFlags::NONE;
+ if (nId == m_nReadonlyFullscreen)
+ nExecId = SID_WIN_FULLSCREEN;
+ else if (nId == m_nReadonlyOpenurl)
+ {
+ nFilter = LoadUrlFlags::NONE;
+ bFilterSet = true;
+ }
+ else if (nId == m_nReadonlyOpendoc)
+ {
+ nFilter = LoadUrlFlags::NewView;
+ bFilterSet = true;
+ }
+ else if (nId == m_nReadonlyCopy)
+ nExecId = SID_COPY;
+ else if (nId == m_nReadonlyEditdoc)
+ nExecId = SID_EDITDOC;
+ else if (nId == m_nReadonlySelectionMode)
+ nExecId = FN_READONLY_SELECTION_MODE;
+ else if (nId == m_nReadonlyReload || nId == m_nReadonlyReloadFrame)
+ rSh.GetView().GetViewFrame().GetDispatcher()->Execute(SID_RELOAD);
+ else if (nId == m_nReadonlyBrowseBackward)
+ nExecId = SID_BROWSE_BACKWARD;
+ else if (nId == m_nReadonlyBrowseForward)
+ nExecId = SID_BROWSE_FORWARD;
+ else if (nId == m_nReadonlySourceview)
+ nExecId = SID_SOURCEVIEW;
+ else if (nId == m_nReadonlySaveGraphic || nId == m_nReadonlySaveBackground)
+ SaveGraphic(nId);
+ else if (nId == m_nReadonlyCopylink)
+ {
+ pClipCntnr = new TransferDataContainer;
+ pClipCntnr->CopyString( m_sURL );
+ }
+ else if (nId == m_nReadonlyLoadGraphic)
+ {
+ bool bModified = rSh.IsModified();
+ SwViewOption aOpt( *rSh.GetViewOptions() );
+ aOpt.SetGraphic( true );
+ rSh.ApplyViewOptions( aOpt );
+ if(!bModified)
+ rSh.ResetModified();
+ }
+ else if (nId == m_nReadonlyGraphicoff)
+ nExecId = FN_VIEW_GRAPHIC;
+ else if (nId == m_nReadonlyTogallerylink || nId == m_nReadonlyBackgroundTogallerylink)
+ SW_MOD()->GetModuleConfig()->SetGrfToGalleryAsLnk(true);
+ else if (nId == m_nReadonlyTogallerycopy || nId == m_nReadonlyBackgroundTogallerycopy)
+ SW_MOD()->GetModuleConfig()->SetGrfToGalleryAsLnk(false);
+
+ if( USHRT_MAX != nExecId )
+ rDis.GetBindings()->Execute( nExecId );
+ if( bFilterSet )
+ ::LoadURL(rSh, m_sURL, nFilter, m_sTargetFrameName);
+
+ if( pClipCntnr && pClipCntnr->HasAnyData() )
+ {
+ pClipCntnr->CopyToClipboard( pWin );
+ }
+}
+
+OUString SwReadOnlyPopup::SaveGraphic(sal_uInt16 nId)
+{
+ // fish out the graphic's name
+ if (nId == m_nReadonlySaveBackground)
+ {
+ if ( m_xBrushItem && !m_xBrushItem->GetGraphicLink().isEmpty() )
+ m_sGrfName = m_xBrushItem->GetGraphicLink();
+ const Graphic *pGrf = m_xBrushItem ? m_xBrushItem->GetGraphic() : nullptr;
+ if ( pGrf )
+ {
+ m_aGraphic = *pGrf;
+ if ( !m_xBrushItem->GetGraphicLink().isEmpty() )
+ m_sGrfName = m_xBrushItem->GetGraphicLink();
+ }
+ else
+ return OUString();
+ }
+ return GraphicHelper::ExportGraphic(m_rView.GetFrameWeld(), m_aGraphic, m_sGrfName);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/romenu.hxx b/sw/source/uibase/docvw/romenu.hxx
new file mode 100644
index 0000000000..1af58d3dee
--- /dev/null
+++ b/sw/source/uibase/docvw/romenu.hxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <editeng/brushitem.hxx>
+#include <toolkit/awt/vclxmenu.hxx>
+#include <vcl/builder.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/menu.hxx>
+
+class SwView;
+class SfxDispatcher;
+class ImageMap;
+class INetImage;
+
+class SwReadOnlyPopup
+{
+ VclBuilder m_aBuilder;
+ ScopedVclPtr<PopupMenu> m_xMenu;
+ sal_uInt16 m_nReadonlyOpenurl;
+ sal_uInt16 m_nReadonlyOpendoc;
+ sal_uInt16 m_nReadonlyEditdoc;
+ sal_uInt16 m_nReadonlySelectionMode;
+ sal_uInt16 m_nReadonlyReload;
+ sal_uInt16 m_nReadonlyReloadFrame;
+ sal_uInt16 m_nReadonlySourceview;
+ sal_uInt16 m_nReadonlyBrowseBackward;
+ sal_uInt16 m_nReadonlyBrowseForward;
+ sal_uInt16 m_nReadonlySaveGraphic;
+ sal_uInt16 m_nReadonlyGraphictogallery;
+ sal_uInt16 m_nReadonlyTogallerylink;
+ sal_uInt16 m_nReadonlyTogallerycopy;
+ sal_uInt16 m_nReadonlySaveBackground;
+ sal_uInt16 m_nReadonlyBackgroundtogallery;
+ sal_uInt16 m_nReadonlyBackgroundTogallerylink;
+ sal_uInt16 m_nReadonlyBackgroundTogallerycopy;
+ sal_uInt16 m_nReadonlyCopylink;
+ sal_uInt16 m_nReadonlyLoadGraphic;
+ sal_uInt16 m_nReadonlyGraphicoff;
+ sal_uInt16 m_nReadonlyFullscreen;
+ sal_uInt16 m_nReadonlyCopy;
+
+ SwView & m_rView;
+ std::unique_ptr<SvxBrushItem> m_xBrushItem;
+ Graphic m_aGraphic;
+ OUString m_sURL,
+ m_sTargetFrameName;
+ OUString m_sGrfName;
+ std::vector<OUString> m_aThemeList;
+ bool m_bGrfToGalleryAsLnk;
+
+ void Check( sal_uInt16 nMID, sal_uInt16 nSID, SfxDispatcher const &rDis );
+ OUString SaveGraphic( sal_uInt16 nId );
+
+public:
+ SwReadOnlyPopup(const Point &rDPos, SwView &rV);
+ rtl::Reference<VCLXPopupMenu> CreateMenuInterface() { return new VCLXPopupMenu(m_xMenu); }
+ ~SwReadOnlyPopup();
+
+ void Execute( vcl::Window* pWin, const Point &rPPos );
+ void Execute( vcl::Window* pWin, sal_uInt16 nId );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/srcedtw.cxx b/sw/source/uibase/docvw/srcedtw.cxx
new file mode 100644
index 0000000000..75cfe7bbd2
--- /dev/null
+++ b/sw/source/uibase/docvw/srcedtw.cxx
@@ -0,0 +1,979 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <hintids.hxx>
+#include <cmdid.h>
+
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XPropertiesChangeListener.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/event.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/textview.hxx>
+#include <vcl/ptrstyle.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svtools/htmltokn.h>
+#include <vcl/txtattr.hxx>
+#include <vcl/settings.hxx>
+#include <svtools/colorcfg.hxx>
+#include <editeng/flstitem.hxx>
+#include <vcl/metric.hxx>
+#include <svtools/ctrltool.hxx>
+#include <svtools/scrolladaptor.hxx>
+#include <tools/time.hxx>
+#include <swmodule.hxx>
+#include <docsh.hxx>
+#include <srcview.hxx>
+#include <helpids.h>
+#include <vector>
+
+namespace
+{
+
+struct TextPortion
+{
+ sal_uInt16 nStart, nEnd;
+ svtools::ColorConfigEntry eType;
+};
+
+}
+
+#define MAX_SYNTAX_HIGHLIGHT 20
+#define MAX_HIGHLIGHTTIME 200
+
+typedef std::vector<TextPortion> TextPortions;
+
+static void lcl_Highlight(std::u16string_view aSource, TextPortions& aPortionList)
+{
+ const sal_Unicode cOpenBracket = '<';
+ const sal_Unicode cCloseBracket= '>';
+ const sal_Unicode cSlash = '/';
+ const sal_Unicode cExclamation = '!';
+ const sal_Unicode cMinus = '-';
+ const sal_Unicode cSpace = ' ';
+ const sal_Unicode cTab = 0x09;
+ const sal_Unicode cLF = 0x0a;
+ const sal_Unicode cCR = 0x0d;
+
+ const sal_Int32 nStrLen = aSource.size();
+ sal_Int32 nInsert = 0; // number of inserted portions
+ sal_Int32 nActPos = 0; // position, where '<' was found
+ sal_Int32 nPortStart = SAL_MAX_INT32; // for the TextPortion
+ sal_Int32 nPortEnd = 0;
+ TextPortion aText;
+ while(nActPos < nStrLen)
+ {
+ if((nActPos < nStrLen - 2) && (aSource[nActPos] == cOpenBracket))
+ {
+ svtools::ColorConfigEntry eFoundType = svtools::HTMLUNKNOWN;
+ // insert 'empty' portion
+ if(nPortEnd < nActPos - 1 )
+ {
+ // don't move at the beginning
+ aText.nStart = nPortEnd;
+ if(nInsert)
+ aText.nStart += 1;
+ aText.nEnd = nActPos - 1;
+ aText.eType = svtools::HTMLUNKNOWN;
+ aPortionList.push_back( aText );
+ nInsert++;
+ }
+ sal_Unicode cFollowFirst = aSource[nActPos + 1];
+ sal_Unicode cFollowNext = aSource[nActPos + 2];
+ if(cExclamation == cFollowFirst)
+ {
+ // "<!" SGML or comment
+ if(cMinus == cFollowNext &&
+ nActPos < nStrLen - 3 && cMinus == aSource[nActPos + 3])
+ {
+ eFoundType = svtools::HTMLCOMMENT;
+ }
+ else
+ eFoundType = svtools::HTMLSGML;
+ nPortStart = nActPos;
+ nPortEnd = nActPos + 1;
+ }
+ else if(cSlash == cFollowFirst)
+ {
+ // "</" ignore slash
+ nPortStart = nActPos;
+ nActPos++;
+ }
+ if(svtools::HTMLUNKNOWN == eFoundType)
+ {
+ // now here a keyword could follow
+ sal_uInt16 nSrchPos = nActPos;
+ while(++nSrchPos < nStrLen - 1)
+ {
+ sal_Unicode cNext = aSource[nSrchPos];
+ if( cNext == cSpace ||
+ cNext == cTab ||
+ cNext == cLF ||
+ cNext == cCR)
+ break;
+ else if(cNext == cCloseBracket)
+ {
+ break;
+ }
+ }
+ if(nSrchPos > nActPos + 1)
+ {
+ // some string was found
+ OUString sToken( aSource.substr(nActPos + 1, nSrchPos - nActPos - 1 ) );
+ sToken = sToken.toAsciiUpperCase();
+ HtmlTokenId nToken = ::GetHTMLToken(sToken);
+ if(nToken != HtmlTokenId::NONE)
+ {
+ eFoundType = svtools::HTMLKEYWORD;
+ nPortEnd = nSrchPos;
+ nPortStart = nActPos;
+ }
+ else
+ SAL_WARN("sw", "HTML token " << sToken << " not recognised!");
+ }
+ }
+ // now we still have to look for '>'
+ if(svtools::HTMLUNKNOWN != eFoundType)
+ {
+ bool bFound = false;
+ for(sal_Int32 i = nPortEnd; i < nStrLen; i++)
+ if(cCloseBracket == aSource[i])
+ {
+ bFound = true;
+ nPortEnd = i;
+ break;
+ }
+ if(!bFound && (eFoundType == svtools::HTMLCOMMENT))
+ {
+ // comment without ending in this line
+ bFound = true;
+ nPortEnd = nStrLen - 1;
+ }
+
+ if(bFound ||(eFoundType == svtools::HTMLCOMMENT))
+ {
+ TextPortion aTextPortion;
+ aTextPortion.nStart = nPortStart + 1;
+ aTextPortion.nEnd = nPortEnd;
+ aTextPortion.eType = eFoundType;
+ aPortionList.push_back( aTextPortion );
+ nInsert++;
+ }
+
+ }
+ }
+ nActPos++;
+ }
+ if(nInsert && nPortEnd < nActPos - 1)
+ {
+ aText.nStart = nPortEnd + 1;
+ aText.nEnd = nActPos - 1;
+ aText.eType = svtools::HTMLUNKNOWN;
+ aPortionList.push_back( aText );
+ nInsert++;
+ }
+}
+
+class SwSrcEditWindow::ChangesListener:
+ public cppu::WeakImplHelper< css::beans::XPropertiesChangeListener >
+{
+public:
+ explicit ChangesListener(SwSrcEditWindow & editor): m_Editor(editor) {}
+
+private:
+ virtual ~ChangesListener() override {}
+
+ virtual void SAL_CALL disposing(css::lang::EventObject const &) override
+ {
+ std::unique_lock g(m_Editor.mutex_);
+ m_Editor.m_xNotifier.clear();
+ }
+
+ virtual void SAL_CALL propertiesChange(
+ css::uno::Sequence< css::beans::PropertyChangeEvent > const &) override
+ {
+ SolarMutexGuard g;
+ m_Editor.SetFont();
+ }
+
+ SwSrcEditWindow & m_Editor;
+};
+
+SwSrcEditWindow::SwSrcEditWindow( vcl::Window* pParent, SwSrcView* pParentView ) :
+ Window( pParent, WB_BORDER|WB_CLIPCHILDREN ),
+
+ m_pOutWin(nullptr),
+ m_pHScrollbar(nullptr),
+ m_pVScrollbar(nullptr),
+
+ m_pSrcView(pParentView),
+
+ m_nCurTextWidth(0),
+ m_nStartLine(USHRT_MAX),
+ m_eSourceEncoding(osl_getThreadTextEncoding()),
+ m_bReadonly(false),
+ m_bHighlighting(false),
+ m_aSyntaxIdle("sw uibase SwSrcEditWindow Syntax")
+{
+ SetHelpId(HID_SOURCE_EDITWIN);
+ CreateTextEngine();
+
+ // Using "this" in ctor is a little fishy, but should work here at least as
+ // long as there are no derivations:
+ m_xListener = new ChangesListener(*this);
+ css::uno::Reference< css::beans::XMultiPropertySet > n(
+ officecfg::Office::Common::Font::SourceViewFont::get(),
+ css::uno::UNO_QUERY_THROW);
+ {
+ std::unique_lock g(mutex_);
+ m_xNotifier = n;
+ }
+ n->addPropertiesChangeListener({ "FontHeight", "FontName" }, m_xListener);
+}
+
+SwSrcEditWindow::~SwSrcEditWindow()
+{
+ disposeOnce();
+}
+
+void SwSrcEditWindow::dispose()
+{
+ css::uno::Reference< css::beans::XMultiPropertySet > n;
+ {
+ std::unique_lock g(mutex_);
+ n = m_xNotifier;
+ }
+ if (n.is()) {
+ n->removePropertiesChangeListener(m_xListener);
+ }
+ m_aSyntaxIdle.Stop();
+ if ( m_pOutWin )
+ m_pOutWin->SetTextView( nullptr );
+
+ if ( m_pTextEngine )
+ {
+ EndListening( *m_pTextEngine );
+ m_pTextEngine->RemoveView( m_pTextView.get() );
+
+ m_pTextView.reset();
+ m_pTextEngine.reset();
+ }
+ m_pHScrollbar.disposeAndClear();
+ m_pVScrollbar.disposeAndClear();
+ m_pOutWin.disposeAndClear();
+ vcl::Window::dispose();
+}
+
+void SwSrcEditWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ switch ( rDCEvt.GetType() )
+ {
+ case DataChangedEventType::SETTINGS:
+ // newly rearrange ScrollBars or trigger Resize, because
+ // ScrollBar size could have changed. For this, in the
+ // Resize handler the size of ScrollBars has to be queried
+ // from the settings as well.
+ if( rDCEvt.GetFlags() & AllSettingsFlags::STYLE )
+ Resize();
+ break;
+ default: break;
+ }
+}
+
+void SwSrcEditWindow::Resize()
+{
+ // ScrollBars, etc. happens in Adjust...
+ if ( !m_pTextView )
+ return;
+
+ tools::Long nVisY = m_pTextView->GetStartDocPos().Y();
+ m_pTextView->ShowCursor();
+ Size aOutSz( GetOutputSizePixel() );
+ tools::Long nMaxVisAreaStart = m_pTextView->GetTextEngine()->GetTextHeight() - aOutSz.Height();
+ if ( nMaxVisAreaStart < 0 )
+ nMaxVisAreaStart = 0;
+ if ( m_pTextView->GetStartDocPos().Y() > nMaxVisAreaStart )
+ {
+ Point aStartDocPos( m_pTextView->GetStartDocPos() );
+ aStartDocPos.setY( nMaxVisAreaStart );
+ m_pTextView->SetStartDocPos( aStartDocPos );
+ m_pTextView->ShowCursor();
+ }
+ tools::Long nScrollStd = GetSettings().GetStyleSettings().GetScrollBarSize();
+ Size aScrollSz(aOutSz.Width() - nScrollStd, nScrollStd );
+ Point aScrollPos(0, aOutSz.Height() - nScrollStd);
+
+ m_pHScrollbar->SetPosSizePixel( aScrollPos, aScrollSz);
+
+ aScrollSz.setWidth( aScrollSz.Height() );
+ aScrollSz.setHeight( aOutSz.Height() );
+ aScrollPos = Point(aOutSz.Width() - nScrollStd, 0);
+
+ m_pVScrollbar->SetPosSizePixel( aScrollPos, aScrollSz);
+ aOutSz.AdjustWidth( -nScrollStd );
+ aOutSz.AdjustHeight( -nScrollStd );
+ m_pOutWin->SetOutputSizePixel(aOutSz);
+ InitScrollBars();
+
+ // set line in first Resize
+ if(USHRT_MAX != m_nStartLine)
+ {
+ if(m_nStartLine < m_pTextEngine->GetParagraphCount())
+ {
+ TextSelection aSel(TextPaM( m_nStartLine, 0 ), TextPaM( m_nStartLine, 0x0 ));
+ m_pTextView->SetSelection(aSel);
+ m_pTextView->ShowCursor();
+ }
+ m_nStartLine = USHRT_MAX;
+ }
+
+ if ( nVisY != m_pTextView->GetStartDocPos().Y() )
+ Invalidate();
+
+
+}
+
+void TextViewOutWin::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ switch( rDCEvt.GetType() )
+ {
+ case DataChangedEventType::SETTINGS:
+ // query settings
+ if( rDCEvt.GetFlags() & AllSettingsFlags::STYLE )
+ {
+ const Color &rCol = GetSettings().GetStyleSettings().GetWindowColor();
+ SetBackground( rCol );
+ vcl::Font aFont( m_pTextView->GetTextEngine()->GetFont() );
+ aFont.SetFillColor( rCol );
+ m_pTextView->GetTextEngine()->SetFont( aFont );
+ }
+ break;
+ default: break;
+ }
+}
+
+void TextViewOutWin::MouseMove( const MouseEvent &rEvt )
+{
+ if ( m_pTextView )
+ m_pTextView->MouseMove( rEvt );
+}
+
+void TextViewOutWin::MouseButtonUp( const MouseEvent &rEvt )
+{
+ if ( m_pTextView )
+ {
+ m_pTextView->MouseButtonUp( rEvt );
+ SfxViewFrame& rFrame = static_cast<SwSrcEditWindow*>(GetParent())->GetSrcView()->GetViewFrame();
+ SfxBindings& rBindings = rFrame.GetBindings();
+ rBindings.Invalidate( SID_TABLE_CELL );
+ rBindings.Invalidate( SID_CUT );
+ rBindings.Invalidate( SID_COPY );
+ }
+}
+
+void TextViewOutWin::MouseButtonDown( const MouseEvent &rEvt )
+{
+ GrabFocus();
+ if ( m_pTextView )
+ m_pTextView->MouseButtonDown( rEvt );
+}
+
+void TextViewOutWin::Command( const CommandEvent& rCEvt )
+{
+ switch(rCEvt.GetCommand())
+ {
+ case CommandEventId::ContextMenu:
+ SfxDispatcher::ExecutePopup();
+ break;
+ case CommandEventId::Wheel:
+ case CommandEventId::StartAutoScroll:
+ case CommandEventId::AutoScroll:
+ {
+ const CommandWheelData* pWData = rCEvt.GetWheelData();
+ if( !pWData || CommandWheelMode::ZOOM != pWData->GetMode() )
+ {
+ static_cast<SwSrcEditWindow*>(GetParent())->HandleWheelCommand( rCEvt );
+ }
+ }
+ break;
+
+ default:
+ if ( m_pTextView )
+ m_pTextView->Command( rCEvt );
+ else
+ Window::Command(rCEvt);
+ }
+}
+
+void TextViewOutWin::KeyInput( const KeyEvent& rKEvt )
+{
+ bool bDone = false;
+ SwSrcEditWindow* pSrcEditWin = static_cast<SwSrcEditWindow*>(GetParent());
+ bool bChange = !pSrcEditWin->IsReadonly() || !TextEngine::DoesKeyChangeText( rKEvt );
+ if(bChange)
+ bDone = m_pTextView->KeyInput( rKEvt );
+
+ SfxBindings& rBindings = static_cast<SwSrcEditWindow*>(GetParent())->GetSrcView()->GetViewFrame().GetBindings();
+ if ( !bDone )
+ {
+ if ( !SfxViewShell::Current()->KeyInput( rKEvt ) )
+ Window::KeyInput( rKEvt );
+ }
+ else
+ {
+ rBindings.Invalidate( SID_TABLE_CELL );
+ if ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_CURSOR )
+ rBindings.Update( SID_BASICIDE_STAT_POS );
+ if (pSrcEditWin->GetTextEngine()->IsModified() )
+ {
+ rBindings.Invalidate( SID_SAVEDOC );
+ rBindings.Invalidate( SID_DOC_MODIFIED );
+ }
+ if( rKEvt.GetKeyCode().GetCode() == KEY_INSERT )
+ rBindings.Invalidate( SID_ATTR_INSERT );
+ }
+
+ rBindings.Invalidate( SID_CUT );
+ rBindings.Invalidate( SID_COPY );
+
+ SwDocShell* pDocShell = pSrcEditWin->GetSrcView()->GetDocShell();
+ if(pSrcEditWin->GetTextEngine()->IsModified())
+ {
+ pDocShell->SetModified();
+ }
+}
+
+void TextViewOutWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ m_pTextView->Paint(rRenderContext, rRect);
+}
+
+void SwSrcEditWindow::CreateTextEngine()
+{
+ // FIXME RenderContext
+
+ const Color &rCol = GetSettings().GetStyleSettings().GetWindowColor();
+ m_pOutWin = VclPtr<TextViewOutWin>::Create(this, 0);
+ m_pOutWin->SetBackground(Wallpaper(rCol));
+ m_pOutWin->SetPointer(PointerStyle::Text);
+ m_pOutWin->Show();
+
+ // create Scrollbars
+ m_pHScrollbar = VclPtr<ScrollAdaptor>::Create(this, true);
+ m_pHScrollbar->EnableRTL( false );
+ m_pHScrollbar->SetScrollHdl(LINK(this, SwSrcEditWindow, HorzScrollHdl));
+ m_pHScrollbar->Show();
+
+ m_pVScrollbar = VclPtr<ScrollAdaptor>::Create(this, false);
+ m_pVScrollbar->EnableRTL( false );
+ m_pVScrollbar->SetScrollHdl(LINK(this, SwSrcEditWindow, VertScrollHdl));
+ m_pVScrollbar->Show();
+
+ m_pTextEngine.reset(new ExtTextEngine);
+ m_pTextView.reset(new TextView( m_pTextEngine.get(), m_pOutWin ));
+ m_pTextView->SetAutoIndentMode(true);
+ m_pOutWin->SetTextView(m_pTextView.get());
+
+ m_pTextEngine->SetUpdateMode( false );
+ m_pTextEngine->InsertView( m_pTextView.get() );
+
+ vcl::Font aFont;
+ aFont.SetTransparent( false );
+ aFont.SetFillColor( rCol );
+ SetPointFont(*GetOutDev(), aFont);
+ aFont = GetFont();
+ aFont.SetFillColor( rCol );
+ m_pOutWin->SetFont( aFont );
+ m_pTextEngine->SetFont( aFont );
+
+ m_aSyntaxIdle.SetInvokeHandler( LINK( this, SwSrcEditWindow, SyntaxTimerHdl ) );
+
+ m_pTextEngine->EnableUndo( true );
+ m_pTextEngine->SetUpdateMode( true );
+
+ m_pTextView->ShowCursor();
+ InitScrollBars();
+ StartListening( *m_pTextEngine );
+
+ SfxBindings& rBind = GetSrcView()->GetViewFrame().GetBindings();
+ rBind.Invalidate( SID_TABLE_CELL );
+}
+
+void SwSrcEditWindow::SetScrollBarRanges()
+{
+ // Extra method, not InitScrollBars, because also for TextEngine events.
+
+ m_pHScrollbar->SetRange( Range( 0, m_nCurTextWidth-1 ) );
+ m_pVScrollbar->SetRange( Range(0, m_pTextEngine->GetTextHeight()-1) );
+}
+
+void SwSrcEditWindow::InitScrollBars()
+{
+ SetScrollBarRanges();
+
+ Size aOutSz( m_pOutWin->GetOutputSizePixel() );
+ m_pVScrollbar->SetVisibleSize( aOutSz.Height() );
+ m_pVScrollbar->SetPageSize( aOutSz.Height() * 8 / 10 );
+ m_pVScrollbar->SetLineSize( m_pOutWin->GetTextHeight() );
+ m_pVScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().Y() );
+ m_pHScrollbar->SetVisibleSize( aOutSz.Width() );
+ m_pHScrollbar->SetPageSize( aOutSz.Width() * 8 / 10 );
+ m_pHScrollbar->SetLineSize( m_pOutWin->GetTextWidth(OUString('x')) );
+ m_pHScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().X() );
+
+}
+
+IMPL_LINK_NOARG(SwSrcEditWindow, HorzScrollHdl, weld::Scrollbar&, void)
+{
+ tools::Long nDiff = m_pTextView->GetStartDocPos().X() - m_pHScrollbar->GetThumbPos();
+ GetTextView()->Scroll( nDiff, 0 );
+ m_pTextView->ShowCursor( false );
+ m_pHScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().X() );
+ GetSrcView()->GetViewFrame().GetBindings().Invalidate( SID_TABLE_CELL );
+}
+
+IMPL_LINK_NOARG(SwSrcEditWindow, VertScrollHdl, weld::Scrollbar&, void)
+{
+ tools::Long nDiff = m_pTextView->GetStartDocPos().Y() - m_pVScrollbar->GetThumbPos();
+ GetTextView()->Scroll( 0, nDiff );
+ m_pTextView->ShowCursor( false );
+ m_pVScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().Y() );
+ GetSrcView()->GetViewFrame().GetBindings().Invalidate( SID_TABLE_CELL );
+}
+
+IMPL_LINK( SwSrcEditWindow, SyntaxTimerHdl, Timer*, pIdle, void )
+{
+ tools::Time aSyntaxCheckStart( tools::Time::SYSTEM );
+ SAL_WARN_IF(m_pTextView == nullptr, "sw", "No View yet, but syntax highlighting?!");
+
+ m_bHighlighting = true;
+ sal_uInt16 nCount = 0;
+ // at first the region around the cursor is processed
+ TextSelection aSel = m_pTextView->GetSelection();
+ sal_uInt16 nCur = o3tl::narrowing<sal_uInt16>(aSel.GetStart().GetPara());
+ if(nCur > 40)
+ nCur -= 40;
+ else
+ nCur = 0;
+ if(!m_aSyntaxLineTable.empty())
+ for(sal_uInt16 i = 0; i < 80 && nCount < 40; i++, nCur++)
+ {
+ if(m_aSyntaxLineTable.find(nCur) != m_aSyntaxLineTable.end())
+ {
+ DoSyntaxHighlight( nCur );
+ m_aSyntaxLineTable.erase( nCur );
+ nCount++;
+ if(m_aSyntaxLineTable.empty())
+ break;
+ if((tools::Time( tools::Time::SYSTEM ).GetTime() - aSyntaxCheckStart.GetTime()) > MAX_HIGHLIGHTTIME )
+ {
+ break;
+ }
+ }
+ }
+
+ // when there is still anything left by then, go on from the beginning
+ while ( !m_aSyntaxLineTable.empty() && nCount < MAX_SYNTAX_HIGHLIGHT)
+ {
+ sal_uInt16 nLine = *m_aSyntaxLineTable.begin();
+ DoSyntaxHighlight( nLine );
+ m_aSyntaxLineTable.erase(nLine);
+ nCount ++;
+ if(tools::Time( tools::Time::SYSTEM ).GetTime() - aSyntaxCheckStart.GetTime() > MAX_HIGHLIGHTTIME)
+ {
+ break;
+ }
+ }
+
+ if(!m_aSyntaxLineTable.empty() && !pIdle->IsActive())
+ pIdle->Start();
+ // SyntaxTimerHdl is called when text changed
+ // => good opportunity to determine text width!
+ tools::Long nPrevTextWidth = m_nCurTextWidth;
+ m_nCurTextWidth = m_pTextEngine->CalcTextWidth() + 25; // small tolerance
+ if ( m_nCurTextWidth != nPrevTextWidth )
+ SetScrollBarRanges();
+ m_bHighlighting = false;
+}
+
+void SwSrcEditWindow::DoSyntaxHighlight( sal_uInt16 nPara )
+{
+ // Because of DelayedSyntaxHighlight it could happen,
+ // that the line doesn't exist anymore!
+ if ( nPara >= m_pTextEngine->GetParagraphCount() )
+ return;
+
+ bool bTempModified = IsModified();
+ m_pTextEngine->RemoveAttribs( nPara );
+ OUString aSource( m_pTextEngine->GetText( nPara ) );
+ m_pTextEngine->SetUpdateMode( false );
+ ImpDoHighlight( aSource, nPara );
+ TextView* pTmp = m_pTextEngine->GetActiveView();
+ pTmp->SetAutoScroll(false);
+ m_pTextEngine->SetActiveView(nullptr);
+ m_pTextEngine->SetUpdateMode( true );
+ m_pTextEngine->SetActiveView(pTmp);
+ pTmp->SetAutoScroll(true);
+ pTmp->ShowCursor( false/*pTmp->IsAutoScroll()*/ );
+
+ if(!bTempModified)
+ ClearModifyFlag();
+
+}
+
+void SwSrcEditWindow::ImpDoHighlight( std::u16string_view aSource, sal_uInt16 nLineOff )
+{
+ TextPortions aPortionList;
+ lcl_Highlight(aSource, aPortionList);
+
+ size_t nCount = aPortionList.size();
+ if ( !nCount )
+ return;
+
+ TextPortion& rLast = aPortionList[nCount-1];
+ if ( rLast.nStart > rLast.nEnd ) // Only until Bug from MD is resolved
+ {
+ nCount--;
+ aPortionList.pop_back();
+ if ( !nCount )
+ return;
+ }
+
+ {
+ // Only blanks and tabs have to be attributed along.
+ // When two identical attributes are placed consecutively,
+ // it optimises the TextEngine.
+ sal_uInt16 nLastEnd = 0;
+
+ for ( size_t i = 0; i < nCount; i++ )
+ {
+ TextPortion& r = aPortionList[i];
+ if ( r.nStart > r.nEnd ) // only until Bug from MD is resolved
+ continue;
+
+ if ( r.nStart > nLastEnd )
+ {
+ // Can I rely on the fact that all except blank and tab
+ // are being highlighted?!
+ r.nStart = nLastEnd;
+ }
+ nLastEnd = r.nEnd+1;
+ if ( ( i == (nCount-1) ) && ( r.nEnd < aSource.size() ) )
+ r.nEnd = aSource.size();
+ }
+ }
+
+ for (TextPortion & r : aPortionList)
+ {
+ if ( r.nStart > r.nEnd ) // only until Bug from MD is resolved
+ continue;
+ if(r.eType != svtools::HTMLSGML &&
+ r.eType != svtools::HTMLCOMMENT &&
+ r.eType != svtools::HTMLKEYWORD &&
+ r.eType != svtools::HTMLUNKNOWN)
+ r.eType = svtools::HTMLUNKNOWN;
+ Color aColor(SW_MOD()->GetColorConfig().GetColorValue(r.eType).nColor);
+ m_pTextEngine->SetAttrib( TextAttribFontColor( aColor ), nLineOff, r.nStart, r.nEnd+1 );
+ }
+}
+
+void SwSrcEditWindow::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
+{
+ const TextHint* pTextHint = dynamic_cast<const TextHint*>(&rHint);
+ if (!pTextHint)
+ return;
+
+ switch (pTextHint->GetId())
+ {
+ case SfxHintId::TextViewScrolled:
+ m_pHScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().X() );
+ m_pVScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().Y() );
+ break;
+
+ case SfxHintId::TextHeightChanged:
+ if ( m_pTextEngine->GetTextHeight() < m_pOutWin->GetOutputSizePixel().Height() )
+ m_pTextView->Scroll( 0, m_pTextView->GetStartDocPos().Y() );
+ m_pVScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().Y() );
+ SetScrollBarRanges();
+ break;
+
+ case SfxHintId::TextParaInserted:
+ case SfxHintId::TextParaContentChanged:
+ if ( !m_bHighlighting )
+ {
+ m_aSyntaxLineTable.insert( o3tl::narrowing<sal_uInt16>(pTextHint->GetValue()) );
+ m_aSyntaxIdle.Start();
+ }
+ break;
+ default: break;
+ }
+}
+
+void SwSrcEditWindow::ImplInvalidate(const vcl::Region* pRegion, InvalidateFlags nFlags)
+{
+ m_pOutWin->Invalidate();
+ Window::ImplInvalidate(pRegion, nFlags);
+}
+
+void SwSrcEditWindow::Command( const CommandEvent& rCEvt )
+{
+ switch(rCEvt.GetCommand())
+ {
+ case CommandEventId::Wheel:
+ case CommandEventId::StartAutoScroll:
+ case CommandEventId::AutoScroll:
+ {
+ const CommandWheelData* pWData = rCEvt.GetWheelData();
+ if( !pWData || CommandWheelMode::ZOOM != pWData->GetMode() )
+ HandleScrollCommand( rCEvt, m_pHScrollbar, m_pVScrollbar );
+ }
+ break;
+ default:
+ Window::Command(rCEvt);
+ }
+}
+
+void SwSrcEditWindow::HandleWheelCommand( const CommandEvent& rCEvt )
+{
+ m_pTextView->Command(rCEvt);
+ HandleScrollCommand( rCEvt, m_pHScrollbar, m_pVScrollbar );
+}
+
+void SwSrcEditWindow::GetFocus()
+{
+ if (m_pOutWin)
+ m_pOutWin->GrabFocus();
+}
+
+static bool lcl_GetLanguagesForEncoding(rtl_TextEncoding eEnc, LanguageType aLanguages[])
+{
+ switch(eEnc)
+ {
+ case RTL_TEXTENCODING_UTF7 :
+ case RTL_TEXTENCODING_UTF8 :
+ // don#t fill - all LANGUAGE_SYSTEM means unicode font has to be used
+ break;
+
+ case RTL_TEXTENCODING_ISO_8859_3:
+ case RTL_TEXTENCODING_ISO_8859_1 :
+ case RTL_TEXTENCODING_MS_1252 :
+ case RTL_TEXTENCODING_APPLE_ROMAN :
+ case RTL_TEXTENCODING_IBM_850 :
+ case RTL_TEXTENCODING_ISO_8859_14 :
+ case RTL_TEXTENCODING_ISO_8859_15 :
+ //fill with western languages
+ aLanguages[0] = LANGUAGE_GERMAN;
+ aLanguages[1] = LANGUAGE_FRENCH;
+ aLanguages[2] = LANGUAGE_ITALIAN;
+ aLanguages[3] = LANGUAGE_SPANISH;
+ break;
+
+ case RTL_TEXTENCODING_IBM_865 :
+ //scandinavian
+ aLanguages[0] = LANGUAGE_FINNISH;
+ aLanguages[1] = LANGUAGE_NORWEGIAN;
+ aLanguages[2] = LANGUAGE_SWEDISH;
+ aLanguages[3] = LANGUAGE_DANISH;
+ break;
+
+ case RTL_TEXTENCODING_ISO_8859_10 :
+ case RTL_TEXTENCODING_ISO_8859_13 :
+ case RTL_TEXTENCODING_ISO_8859_2 :
+ case RTL_TEXTENCODING_IBM_852 :
+ case RTL_TEXTENCODING_MS_1250 :
+ case RTL_TEXTENCODING_APPLE_CENTEURO :
+ aLanguages[0] = LANGUAGE_POLISH;
+ aLanguages[1] = LANGUAGE_CZECH;
+ aLanguages[2] = LANGUAGE_HUNGARIAN;
+ aLanguages[3] = LANGUAGE_SLOVAK;
+ break;
+
+ case RTL_TEXTENCODING_ISO_8859_4 :
+ case RTL_TEXTENCODING_IBM_775 :
+ case RTL_TEXTENCODING_MS_1257 :
+ aLanguages[0] = LANGUAGE_LATVIAN ;
+ aLanguages[1] = LANGUAGE_LITHUANIAN;
+ aLanguages[2] = LANGUAGE_ESTONIAN ;
+ break;
+
+ case RTL_TEXTENCODING_IBM_863 : aLanguages[0] = LANGUAGE_FRENCH_CANADIAN; break;
+ case RTL_TEXTENCODING_APPLE_FARSI : aLanguages[0] = LANGUAGE_FARSI; break;
+ case RTL_TEXTENCODING_APPLE_ROMANIAN:aLanguages[0] = LANGUAGE_ROMANIAN; break;
+
+ case RTL_TEXTENCODING_IBM_861 :
+ case RTL_TEXTENCODING_APPLE_ICELAND :
+ aLanguages[0] = LANGUAGE_ICELANDIC;
+ break;
+
+ case RTL_TEXTENCODING_APPLE_CROATIAN:aLanguages[0] = LANGUAGE_CROATIAN; break;
+
+ case RTL_TEXTENCODING_IBM_437 :
+ case RTL_TEXTENCODING_ASCII_US : aLanguages[0] = LANGUAGE_ENGLISH; break;
+
+ case RTL_TEXTENCODING_IBM_862 :
+ case RTL_TEXTENCODING_MS_1255 :
+ case RTL_TEXTENCODING_APPLE_HEBREW :
+ case RTL_TEXTENCODING_ISO_8859_8 :
+ aLanguages[0] = LANGUAGE_HEBREW;
+ break;
+
+ case RTL_TEXTENCODING_IBM_857 :
+ case RTL_TEXTENCODING_MS_1254 :
+ case RTL_TEXTENCODING_APPLE_TURKISH:
+ case RTL_TEXTENCODING_ISO_8859_9 :
+ aLanguages[0] = LANGUAGE_TURKISH;
+ break;
+
+ case RTL_TEXTENCODING_IBM_860 :
+ aLanguages[0] = LANGUAGE_PORTUGUESE;
+ break;
+
+ case RTL_TEXTENCODING_IBM_869 :
+ case RTL_TEXTENCODING_MS_1253 :
+ case RTL_TEXTENCODING_APPLE_GREEK :
+ case RTL_TEXTENCODING_ISO_8859_7 :
+ case RTL_TEXTENCODING_IBM_737 :
+ aLanguages[0] = LANGUAGE_GREEK;
+ break;
+
+ case RTL_TEXTENCODING_KOI8_R :
+ case RTL_TEXTENCODING_ISO_8859_5 :
+ case RTL_TEXTENCODING_IBM_855 :
+ case RTL_TEXTENCODING_MS_1251 :
+ case RTL_TEXTENCODING_IBM_866 :
+ case RTL_TEXTENCODING_APPLE_CYRILLIC :
+ aLanguages[0] = LANGUAGE_RUSSIAN;
+ break;
+
+ case RTL_TEXTENCODING_APPLE_UKRAINIAN:
+ case RTL_TEXTENCODING_KOI8_U:
+ aLanguages[0] = LANGUAGE_UKRAINIAN;
+ break;
+
+ case RTL_TEXTENCODING_IBM_864 :
+ case RTL_TEXTENCODING_MS_1256 :
+ case RTL_TEXTENCODING_ISO_8859_6 :
+ case RTL_TEXTENCODING_APPLE_ARABIC :
+ aLanguages[0] = LANGUAGE_ARABIC_SAUDI_ARABIA;
+ break;
+
+ case RTL_TEXTENCODING_APPLE_CHINTRAD :
+ case RTL_TEXTENCODING_MS_950 :
+ case RTL_TEXTENCODING_GBT_12345 :
+ case RTL_TEXTENCODING_BIG5 :
+ case RTL_TEXTENCODING_EUC_TW :
+ case RTL_TEXTENCODING_BIG5_HKSCS :
+ aLanguages[0] = LANGUAGE_CHINESE_TRADITIONAL;
+ break;
+
+ case RTL_TEXTENCODING_EUC_JP :
+ case RTL_TEXTENCODING_ISO_2022_JP :
+ case RTL_TEXTENCODING_JIS_X_0201 :
+ case RTL_TEXTENCODING_JIS_X_0208 :
+ case RTL_TEXTENCODING_JIS_X_0212 :
+ case RTL_TEXTENCODING_APPLE_JAPANESE :
+ case RTL_TEXTENCODING_MS_932 :
+ case RTL_TEXTENCODING_SHIFT_JIS :
+ aLanguages[0] = LANGUAGE_JAPANESE;
+ break;
+
+ case RTL_TEXTENCODING_GB_2312 :
+ case RTL_TEXTENCODING_MS_936 :
+ case RTL_TEXTENCODING_GBK :
+ case RTL_TEXTENCODING_GB_18030 :
+ case RTL_TEXTENCODING_APPLE_CHINSIMP :
+ case RTL_TEXTENCODING_EUC_CN :
+ case RTL_TEXTENCODING_ISO_2022_CN :
+ aLanguages[0] = LANGUAGE_CHINESE_SIMPLIFIED;
+ break;
+
+ case RTL_TEXTENCODING_APPLE_KOREAN :
+ case RTL_TEXTENCODING_MS_949 :
+ case RTL_TEXTENCODING_EUC_KR :
+ case RTL_TEXTENCODING_ISO_2022_KR :
+ case RTL_TEXTENCODING_MS_1361 :
+ aLanguages[0] = LANGUAGE_KOREAN;
+ break;
+
+ case RTL_TEXTENCODING_APPLE_THAI :
+ case RTL_TEXTENCODING_MS_874 :
+ case RTL_TEXTENCODING_TIS_620 :
+ aLanguages[0] = LANGUAGE_THAI;
+ break;
+ default: aLanguages[0] = Application::GetSettings().GetUILanguageTag().getLanguageType();
+ }
+ return aLanguages[0] != LANGUAGE_SYSTEM;
+}
+void SwSrcEditWindow::SetFont()
+{
+ OUString sFontName(
+ officecfg::Office::Common::Font::SourceViewFont::FontName::get().
+ value_or(OUString()));
+ if(sFontName.isEmpty())
+ {
+ LanguageType aLanguages[5] =
+ {
+ LANGUAGE_SYSTEM, LANGUAGE_SYSTEM, LANGUAGE_SYSTEM, LANGUAGE_SYSTEM, LANGUAGE_SYSTEM
+ };
+ vcl::Font aFont;
+ if(lcl_GetLanguagesForEncoding(m_eSourceEncoding, aLanguages))
+ {
+ //TODO: check for multiple languages
+ aFont = OutputDevice::GetDefaultFont(DefaultFontType::FIXED, aLanguages[0], GetDefaultFontFlags::NONE, GetOutDev());
+ }
+ else
+ aFont = OutputDevice::GetDefaultFont(DefaultFontType::SANS_UNICODE,
+ Application::GetSettings().GetLanguageTag().getLanguageType(), GetDefaultFontFlags::NONE, GetOutDev());
+ sFontName = aFont.GetFamilyName();
+ }
+ const SvxFontListItem* pFontListItem =
+ static_cast<const SvxFontListItem* >(m_pSrcView->GetDocShell()->GetItem( SID_ATTR_CHAR_FONTLIST ));
+ const FontList* pList = pFontListItem->GetFontList();
+ FontMetric aFontMetric = pList->Get(sFontName,WEIGHT_NORMAL, ITALIC_NONE);
+
+ const vcl::Font& rFont = GetTextEngine()->GetFont();
+ vcl::Font aFont(aFontMetric);
+ Size aSize(rFont.GetFontSize());
+ //font height is stored in point and set in twip
+ aSize.setHeight(
+ officecfg::Office::Common::Font::SourceViewFont::FontHeight::get() * 20 );
+ aFont.SetFontSize(m_pOutWin->LogicToPixel(aSize, MapMode(MapUnit::MapTwip)));
+ GetTextEngine()->SetFont( aFont );
+ m_pOutWin->SetFont(aFont);
+}
+
+void SwSrcEditWindow::SetTextEncoding(rtl_TextEncoding eEncoding)
+{
+ m_eSourceEncoding = eEncoding;
+ SetFont();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/envelp/envimg.cxx b/sw/source/uibase/envelp/envimg.cxx
new file mode 100644
index 0000000000..b36cfdfa51
--- /dev/null
+++ b/sw/source/uibase/envelp/envimg.cxx
@@ -0,0 +1,333 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <o3tl/any.hxx>
+#include <o3tl/string_view.hxx>
+#include <osl/diagnose.h>
+#include <editeng/paperinf.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <tools/UnitConversion.hxx>
+#include <unotools/useroptions.hxx>
+#include <swmodule.hxx>
+#include <swtypes.hxx>
+#include <envimg.hxx>
+#include <strings.hrc>
+
+#include <cmdid.h>
+
+#include <unomid.h>
+
+using namespace utl;
+using namespace ::com::sun::star::uno;
+
+
+SfxPoolItem* SwEnvItem::CreateDefault() { return new SwEnvItem; }
+
+OUString MakeSender()
+{
+ SvtUserOptions& rUserOpt = SW_MOD()->GetUserOptions();
+
+ const OUString sSenderToken(SwResId(STR_SENDER_TOKENS));
+ if (sSenderToken.isEmpty())
+ return OUString();
+
+ OUStringBuffer sRet;
+ sal_Int32 nSttPos = 0;
+ bool bLastLength = true;
+ do {
+ std::u16string_view sToken = o3tl::getToken(sSenderToken, 0, ';', nSttPos );
+ if (sToken == u"COMPANY")
+ {
+ sal_Int32 nOldLen = sRet.getLength();
+ sRet.append(rUserOpt.GetCompany());
+ bLastLength = sRet.getLength() != nOldLen;
+ }
+ else if (sToken == u"CR")
+ {
+ if(bLastLength)
+ sRet.append(SAL_NEWLINE_STRING);
+ bLastLength = true;
+ }
+ else if (sToken == u"FIRSTNAME")
+ sRet.append(rUserOpt.GetFirstName());
+ else if (sToken == u"LASTNAME")
+ sRet.append(rUserOpt.GetLastName());
+ else if (sToken == u"ADDRESS")
+ sRet.append(rUserOpt.GetStreet());
+ else if (sToken == u"COUNTRY")
+ sRet.append(rUserOpt.GetCountry());
+ else if (sToken == u"POSTALCODE")
+ sRet.append(rUserOpt.GetZip());
+ else if (sToken == u"CITY")
+ sRet.append(rUserOpt.GetCity());
+ else if (sToken == u"STATEPROV")
+ sRet.append(rUserOpt.GetState());
+ else if (!sToken.empty()) //spaces
+ sRet.append(sToken);
+ } while (nSttPos>=0);
+ return sRet.makeStringAndClear();
+}
+
+SwEnvItem::SwEnvItem() :
+ SfxPoolItem(FN_ENVELOP)
+{
+ m_bSend = true;
+ m_aSendText = MakeSender();
+ m_nSendFromLeft = 566; // 1 cm
+ m_nSendFromTop = 566; // 1 cm
+ Size aEnvSz = SvxPaperInfo::GetPaperSize(PAPER_ENV_C65);
+ m_nWidth = aEnvSz.Width();
+ m_nHeight = aEnvSz.Height();
+ m_eAlign = ENV_HOR_LEFT;
+ m_bPrintFromAbove = true;
+ m_nShiftRight = 0;
+ m_nShiftDown = 0;
+
+ m_nAddrFromLeft = std::max(m_nWidth, m_nHeight) / 2;
+ m_nAddrFromTop = std::min(m_nWidth, m_nHeight) / 2;
+}
+
+SwEnvItem& SwEnvItem::operator =(const SwEnvItem& rItem)
+{
+ m_aAddrText = rItem.m_aAddrText;
+ m_bSend = rItem.m_bSend;
+ m_aSendText = rItem.m_aSendText;
+ m_nSendFromLeft = rItem.m_nSendFromLeft;
+ m_nSendFromTop = rItem.m_nSendFromTop;
+ m_nAddrFromLeft = rItem.m_nAddrFromLeft;
+ m_nAddrFromTop = rItem.m_nAddrFromTop;
+ m_nWidth = rItem.m_nWidth;
+ m_nHeight = rItem.m_nHeight;
+ m_eAlign = rItem.m_eAlign;
+ m_bPrintFromAbove = rItem.m_bPrintFromAbove;
+ m_nShiftRight = rItem.m_nShiftRight;
+ m_nShiftDown = rItem.m_nShiftDown;
+ return *this;
+}
+
+bool SwEnvItem::operator ==(const SfxPoolItem& rItem) const
+{
+ assert(SfxPoolItem::operator==(rItem));
+ const SwEnvItem& rEnv = static_cast<const SwEnvItem&>( rItem);
+
+ return m_aAddrText == rEnv.m_aAddrText &&
+ m_bSend == rEnv.m_bSend &&
+ m_aSendText == rEnv.m_aSendText &&
+ m_nSendFromLeft == rEnv.m_nSendFromLeft &&
+ m_nSendFromTop == rEnv.m_nSendFromTop &&
+ m_nAddrFromLeft == rEnv.m_nAddrFromLeft &&
+ m_nAddrFromTop == rEnv.m_nAddrFromTop &&
+ m_nWidth == rEnv.m_nWidth &&
+ m_nHeight == rEnv.m_nHeight &&
+ m_eAlign == rEnv.m_eAlign &&
+ m_bPrintFromAbove == rEnv.m_bPrintFromAbove &&
+ m_nShiftRight == rEnv.m_nShiftRight &&
+ m_nShiftDown == rEnv.m_nShiftDown;
+}
+
+SwEnvItem* SwEnvItem::Clone(SfxItemPool*) const
+{
+ return new SwEnvItem(*this);
+}
+
+SwEnvCfgItem::SwEnvCfgItem() :
+ ConfigItem("Office.Writer/Envelope")
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ EnableNotification(aNames);
+ const Any* pValues = aValues.getConstArray();
+ OSL_ENSURE(aValues.getLength() == aNames.getLength(), "GetProperties failed");
+ if(aValues.getLength() != aNames.getLength())
+ return;
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ if(pValues[nProp].hasValue())
+ {
+ switch(nProp)
+ {
+ case 0: pValues[nProp] >>= m_aEnvItem.m_aAddrText; break;// "Inscription/Addressee",
+ case 1: pValues[nProp] >>= m_aEnvItem.m_aSendText; break;// "Inscription/Sender",
+ case 2: m_aEnvItem.m_bSend = *o3tl::doAccess<bool>(pValues[nProp]); break;// "Inscription/UseSender",
+ case 3:
+ pValues[nProp] >>= m_aEnvItem.m_nAddrFromLeft;// "Format/AddresseeFromLeft",
+ m_aEnvItem.m_nAddrFromLeft = o3tl::toTwips(m_aEnvItem.m_nAddrFromLeft, o3tl::Length::mm100);
+ break;
+ case 4:
+ pValues[nProp] >>= m_aEnvItem.m_nAddrFromTop; // "Format/AddresseeFromTop",
+ m_aEnvItem.m_nAddrFromTop = o3tl::toTwips(m_aEnvItem.m_nAddrFromTop, o3tl::Length::mm100);
+ break;
+ case 5:
+ pValues[nProp] >>= m_aEnvItem.m_nSendFromLeft; // "Format/SenderFromLeft",
+ m_aEnvItem.m_nSendFromLeft = o3tl::toTwips(m_aEnvItem.m_nSendFromLeft, o3tl::Length::mm100);
+ break;
+ case 6:
+ pValues[nProp] >>= m_aEnvItem.m_nSendFromTop;// "Format/SenderFromTop",
+ m_aEnvItem.m_nSendFromTop = o3tl::toTwips(m_aEnvItem.m_nSendFromTop, o3tl::Length::mm100);
+ break;
+ case 7:
+ pValues[nProp] >>= m_aEnvItem.m_nWidth; // "Format/Width",
+ m_aEnvItem.m_nWidth = o3tl::toTwips(m_aEnvItem.m_nWidth, o3tl::Length::mm100);
+ break;
+ case 8:
+ pValues[nProp] >>= m_aEnvItem.m_nHeight; // "Format/Height",
+ m_aEnvItem.m_nHeight = o3tl::toTwips(m_aEnvItem.m_nHeight, o3tl::Length::mm100);
+ break;
+ case 9:
+ {
+ sal_Int32 nTemp = 0;
+ pValues[nProp] >>= nTemp; m_aEnvItem.m_eAlign = static_cast<SwEnvAlign>(nTemp); break;// "Print/Alignment",
+ }
+ case 10: m_aEnvItem.m_bPrintFromAbove = *o3tl::doAccess<bool>(pValues[nProp]); break;// "Print/FromAbove",
+ case 11:
+ pValues[nProp] >>= m_aEnvItem.m_nShiftRight;
+ m_aEnvItem.m_nShiftRight = o3tl::toTwips(m_aEnvItem.m_nShiftRight, o3tl::Length::mm100);// "Print/Right",
+ break;
+ case 12:
+ pValues[nProp] >>= m_aEnvItem.m_nShiftDown;
+ m_aEnvItem.m_nShiftDown = o3tl::toTwips(m_aEnvItem.m_nShiftDown, o3tl::Length::mm100);
+ break;// "Print/Down"
+ }
+ }
+ }
+}
+
+SwEnvCfgItem::~SwEnvCfgItem()
+{
+}
+
+void SwEnvCfgItem::ImplCommit()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case 0: pValues[nProp] <<= m_aEnvItem.m_aAddrText; break;// "Inscription/Addressee",
+ case 1: pValues[nProp] <<= m_aEnvItem.m_aSendText; break;// "Inscription/Sender",
+ case 2: pValues[nProp] <<= m_aEnvItem.m_bSend; break;// "Inscription/UseSender",
+ case 3: pValues[nProp] <<= static_cast <sal_Int32>(convertTwipToMm100(m_aEnvItem.m_nAddrFromLeft)) ; break;// "Format/AddresseeFromLeft",
+ case 4: pValues[nProp] <<= static_cast <sal_Int32>(convertTwipToMm100(m_aEnvItem.m_nAddrFromTop)) ; break;// "Format/AddresseeFromTop",
+ case 5: pValues[nProp] <<= static_cast <sal_Int32>(convertTwipToMm100(m_aEnvItem.m_nSendFromLeft)) ; break;// "Format/SenderFromLeft",
+ case 6: pValues[nProp] <<= static_cast <sal_Int32>(convertTwipToMm100(m_aEnvItem.m_nSendFromTop)) ; break;// "Format/SenderFromTop",
+ case 7: pValues[nProp] <<= static_cast <sal_Int32>(convertTwipToMm100(m_aEnvItem.m_nWidth)) ; break;// "Format/Width",
+ case 8: pValues[nProp] <<= static_cast <sal_Int32>(convertTwipToMm100(m_aEnvItem.m_nHeight)) ; break;// "Format/Height",
+ case 9: pValues[nProp] <<= sal_Int32(m_aEnvItem.m_eAlign); break;// "Print/Alignment",
+ case 10: pValues[nProp] <<= m_aEnvItem.m_bPrintFromAbove; break;// "Print/FromAbove",
+ case 11: pValues[nProp] <<= static_cast <sal_Int32>(convertTwipToMm100(m_aEnvItem.m_nShiftRight));break; // "Print/Right",
+ case 12: pValues[nProp] <<= static_cast <sal_Int32>(convertTwipToMm100(m_aEnvItem.m_nShiftDown)); break;// "Print/Down"
+ }
+ }
+ PutProperties(aNames, aValues);
+}
+
+void SwEnvCfgItem::Notify( const css::uno::Sequence< OUString >& ) {}
+
+Sequence<OUString> SwEnvCfgItem::GetPropertyNames()
+{
+ static const char* aPropNames[] =
+ {
+ "Inscription/Addressee", // 0
+ "Inscription/Sender", // 1
+ "Inscription/UseSender", // 2
+ "Format/AddresseeFromLeft", // 3
+ "Format/AddresseeFromTop", // 4
+ "Format/SenderFromLeft", // 5
+ "Format/SenderFromTop", // 6
+ "Format/Width", // 7
+ "Format/Height", // 8
+ "Print/Alignment", // 9
+ "Print/FromAbove", // 10
+ "Print/Right", // 11
+ "Print/Down" // 12
+ };
+ const int nCount = 13;
+ Sequence<OUString> aNames(nCount);
+ OUString* pNames = aNames.getArray();
+
+ for(int i = 0; i < nCount; i++)
+ pNames[i] = OUString::createFromAscii(aPropNames[i]);
+
+ return aNames;
+}
+
+bool SwEnvItem::QueryValue( Any& rVal, sal_uInt8 nMemberId ) const
+{
+ bool bRet = true;
+ switch(nMemberId & ~CONVERT_TWIPS)
+ {
+ case MID_ENV_ADDR_TEXT : rVal <<= m_aAddrText; break;
+ case MID_ENV_SEND : rVal <<= m_bSend; break;
+ case MID_SEND_TEXT : rVal <<= m_aSendText; break;
+ case MID_ENV_ADDR_FROM_LEFT : rVal <<= m_nAddrFromLeft; break;
+ case MID_ENV_ADDR_FROM_TOP : rVal <<= m_nAddrFromTop; break;
+ case MID_ENV_SEND_FROM_LEFT : rVal <<= m_nSendFromLeft; break;
+ case MID_ENV_SEND_FROM_TOP : rVal <<= m_nSendFromTop; break;
+ case MID_ENV_WIDTH : rVal <<= m_nWidth; break;
+ case MID_ENV_HEIGHT : rVal <<= m_nHeight; break;
+ case MID_ENV_ALIGN : rVal <<= static_cast<sal_Int16>(m_eAlign); break;
+ case MID_ENV_PRINT_FROM_ABOVE : rVal <<= m_bPrintFromAbove; break;
+ case MID_ENV_SHIFT_RIGHT : rVal <<= m_nShiftRight; break;
+ case MID_ENV_SHIFT_DOWN : rVal <<= m_nShiftDown; break;
+ default:
+ OSL_FAIL("Wrong memberId");
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwEnvItem::PutValue(const Any& rVal, sal_uInt8 nMemberId)
+{
+ bool bRet = false;
+ switch(nMemberId & ~CONVERT_TWIPS)
+ {
+ case MID_ENV_ADDR_TEXT : bRet = (rVal >>= m_aAddrText); break;
+ case MID_ENV_SEND : bRet = (rVal >>= m_bSend); break;
+ case MID_SEND_TEXT : bRet = (rVal >>= m_aSendText); break;
+ case MID_ENV_ADDR_FROM_LEFT : bRet = (rVal >>= m_nAddrFromLeft); break;
+ case MID_ENV_ADDR_FROM_TOP : bRet = (rVal >>= m_nAddrFromTop); break;
+ case MID_ENV_SEND_FROM_LEFT : bRet = (rVal >>= m_nSendFromLeft); break;
+ case MID_ENV_SEND_FROM_TOP : bRet = (rVal >>= m_nSendFromTop); break;
+ case MID_ENV_WIDTH : bRet = (rVal >>= m_nWidth); break;
+ case MID_ENV_HEIGHT : bRet = (rVal >>= m_nHeight); break;
+ case MID_ENV_ALIGN :
+ {
+ sal_Int16 nTemp = 0;
+ bRet = (rVal >>= nTemp);
+ if (bRet)
+ m_eAlign = SwEnvAlign(nTemp);
+ break;
+ }
+ case MID_ENV_PRINT_FROM_ABOVE : bRet = (rVal >>= m_bPrintFromAbove); break;
+ case MID_ENV_SHIFT_RIGHT : bRet = (rVal >>= m_nShiftRight); break;
+ case MID_ENV_SHIFT_DOWN : bRet = (rVal >>= m_nShiftDown); break;
+ default:
+ OSL_FAIL("Wrong memberId");
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/envelp/labelcfg.cxx b/sw/source/uibase/envelp/labelcfg.cxx
new file mode 100644
index 0000000000..f974a3e799
--- /dev/null
+++ b/sw/source/uibase/envelp/labelcfg.cxx
@@ -0,0 +1,330 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <string_view>
+#include <config_folders.h>
+
+#include <swtypes.hxx>
+#include <labelcfg.hxx>
+#include <rtl/bootstrap.hxx>
+#include <tools/UnitConversion.hxx>
+#include <unotools/configpaths.hxx>
+#include <xmlreader/xmlreader.hxx>
+#include <comphelper/sequence.hxx>
+#include <osl/diagnose.h>
+#include <o3tl/string_view.hxx>
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+using namespace utl;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+
+static void lcl_assertEndingItem(xmlreader::XmlReader& reader)
+{
+ int nsId;
+ xmlreader::Span name;
+ xmlreader::XmlReader::Result res;
+ res = reader.nextItem(xmlreader::XmlReader::Text::NONE, &name, &nsId);
+ assert(res == xmlreader::XmlReader::Result::End);
+ (void) res;
+}
+
+static OUString lcl_getValue(xmlreader::XmlReader& reader,
+ const xmlreader::Span& span)
+{
+ int nsId;
+ xmlreader::Span name;
+ xmlreader::XmlReader::Result res;
+ res = reader.nextItem(xmlreader::XmlReader::Text::NONE, &name, &nsId);
+ assert(res == xmlreader::XmlReader::Result::Begin && name == span);
+ res = reader.nextItem(xmlreader::XmlReader::Text::Raw, &name, &nsId);
+ assert(res == xmlreader::XmlReader::Result::Text);
+ (void) res; (void) span;
+ OUString sTmp = name.convertFromUtf8();
+ lcl_assertEndingItem(reader);
+ return sTmp;
+}
+
+static Sequence<OUString> lcl_CreatePropertyNames(const OUString& rPrefix)
+{
+ return { OUString::Concat(rPrefix) + "Name", OUString::Concat(rPrefix) + "Measure" };
+}
+
+SwLabelConfig::SwLabelConfig() :
+ ConfigItem("Office.Labels/Manufacturer")
+{
+ OUString uri("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/labels/labels.xml");
+ rtl::Bootstrap::expandMacros(uri);
+ xmlreader::XmlReader reader(uri);
+ int nsId;
+ xmlreader::Span name;
+ xmlreader::XmlReader::Result res;
+ OUString sManufacturer;
+ OUString sName;
+ OUString sMeasure;
+
+ // fill m_aLabels and m_aManufacturers with the predefined labels
+ res = reader.nextItem(
+ xmlreader::XmlReader::Text::NONE, &name, &nsId);
+ assert(
+ res == xmlreader::XmlReader::Result::Begin
+ && name == "manufacturers");
+ res = reader.nextItem(
+ xmlreader::XmlReader::Text::NONE, &name, &nsId);
+ while (res != xmlreader::XmlReader::Result::End)
+ {
+ // Opening manufacturer
+ assert(
+ res == xmlreader::XmlReader::Result::Begin
+ && name == "manufacturer");
+ // Get the name
+ (void)reader.nextAttribute(&nsId, &name);
+ assert(
+ nsId == xmlreader::XmlReader::NAMESPACE_NONE
+ && name == "name");
+ sManufacturer = reader.getAttributeValue(false).convertFromUtf8();
+
+ for(;;) {
+ // Opening label or ending manufacturer
+ res = reader.nextItem(
+ xmlreader::XmlReader::Text::NONE, &name, &nsId);
+ if (res == xmlreader::XmlReader::Result::End)
+ break;
+ assert(
+ res == xmlreader::XmlReader::Result::Begin
+ && name == "label");
+ // Get name value
+ sName = lcl_getValue(reader, xmlreader::Span("name"));
+ // Get measure value
+ sMeasure = lcl_getValue(reader, xmlreader::Span("measure"));
+ // Ending label mark
+ lcl_assertEndingItem(reader);
+ if ( m_aLabels.find( sManufacturer ) == m_aLabels.end() )
+ m_aManufacturers.push_back( sManufacturer );
+ m_aLabels[sManufacturer][sName].m_aMeasure = sMeasure;
+ m_aLabels[sManufacturer][sName].m_bPredefined = true;
+ }
+ // Get next manufacturer or end
+ res = reader.nextItem(
+ xmlreader::XmlReader::Text::NONE, &name, &nsId);
+ };
+ res = reader.nextItem(
+ xmlreader::XmlReader::Text::NONE, &name, &nsId);
+ assert(res == xmlreader::XmlReader::Result::Done);
+
+ // add to m_aLabels and m_aManufacturers the custom labels
+ const Sequence<OUString>& rMan = GetNodeNames( OUString() );
+ for ( const OUString& rManufacturer : rMan )
+ {
+ const Sequence<OUString> aLabels = GetNodeNames( rManufacturer );
+ for( const OUString& rLabel : aLabels )
+ {
+ OUString sPrefix = rManufacturer + "/" + rLabel + "/";
+ Sequence<OUString> aPropNames = lcl_CreatePropertyNames( sPrefix );
+ Sequence<Any> aValues = GetProperties( aPropNames );
+ const Any* pValues = aValues.getConstArray();
+ if (aValues.getLength() >= 1)
+ if(pValues[0].hasValue())
+ pValues[0] >>= sName;
+ if (aValues.getLength() >= 2)
+ if(pValues[1].hasValue())
+ pValues[1] >>= sMeasure;
+ if ( m_aLabels.find( rManufacturer ) == m_aLabels.end() )
+ m_aManufacturers.push_back( rManufacturer );
+ m_aLabels[rManufacturer][sName].m_aMeasure = sMeasure;
+ m_aLabels[rManufacturer][sName].m_bPredefined = false;
+ }
+ }
+}
+
+SwLabelConfig::~SwLabelConfig()
+{
+}
+
+// the config item is not writable ?:
+void SwLabelConfig::ImplCommit() {}
+
+void SwLabelConfig::Notify( const css::uno::Sequence< OUString >& ) {}
+
+static std::unique_ptr<SwLabRec> lcl_CreateSwLabRec(const OUString& rType, std::u16string_view rMeasure, const OUString& rManufacturer)
+{
+ std::unique_ptr<SwLabRec> pNewRec(new SwLabRec);
+ pNewRec->m_aMake = rManufacturer;
+ pNewRec->m_nPWidth = 0;
+ pNewRec->m_nPHeight = 0;
+ pNewRec->m_aType = rType;
+ //all values are contained as colon-separated 1/100 mm values
+ //except for the continuous flag ('C'/'S') and nCols, nRows (sal_Int32)
+ sal_Int32 nTok{0};
+ sal_Int32 nIdx{rMeasure.empty() ? -1 : 0};
+ while (nIdx>=0)
+ {
+ const std::u16string_view sToken(o3tl::getToken(rMeasure, 0, ';', nIdx));
+ int nVal = o3tl::toInt32(sToken);
+ switch(nTok++)
+ {
+ case 0 : pNewRec->m_bCont = sToken[0] == 'C'; break;
+ case 1 : pNewRec->m_nHDist = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
+ case 2 : pNewRec->m_nVDist = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
+ case 3 : pNewRec->m_nWidth = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
+ case 4 : pNewRec->m_nHeight = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
+ case 5 : pNewRec->m_nLeft = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
+ case 6 : pNewRec->m_nUpper = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
+ case 7 : pNewRec->m_nCols = nVal; break;
+ case 8 : pNewRec->m_nRows = nVal; break;
+ case 9 : pNewRec->m_nPWidth = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
+ case 10 : pNewRec->m_nPHeight = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
+ }
+ }
+ // lines added for compatibility with custom label definitions saved before patch fdo#44516
+ if (pNewRec->m_nPWidth == 0 || pNewRec->m_nPHeight == 0)
+ {
+ // old style definition (no paper dimensions), calculate probable values
+ pNewRec->m_nPWidth = 2 * pNewRec->m_nLeft + (pNewRec->m_nCols - 1) * pNewRec->m_nHDist + pNewRec->m_nWidth;
+ pNewRec->m_nPHeight = ( pNewRec->m_bCont ? pNewRec->m_nRows * pNewRec->m_nVDist : 2 * pNewRec->m_nUpper + (pNewRec->m_nRows - 1) * pNewRec->m_nVDist + pNewRec->m_nHeight );
+ }
+ return pNewRec;
+}
+
+static Sequence<PropertyValue> lcl_CreateProperties(
+ Sequence<OUString> const & rPropNames, OUString& rMeasure, const SwLabRec& rRec)
+{
+ const OUString* pNames = rPropNames.getConstArray();
+ Sequence<PropertyValue> aRet(rPropNames.getLength());
+ PropertyValue* pValues = aRet.getArray();
+ OUString sColon(";");
+
+ for(sal_Int32 nProp = 0; nProp < rPropNames.getLength(); nProp++)
+ {
+ pValues[nProp].Name = pNames[nProp];
+ switch(nProp)
+ {
+ case 0: pValues[nProp].Value <<= rRec.m_aType; break;
+ case 1:
+ {
+ rMeasure.clear();
+ rMeasure += rRec.m_bCont ? std::u16string_view( u"C" ) : std::u16string_view( u"S" ); rMeasure += sColon;
+ rMeasure += OUString::number( convertTwipToMm100( rRec.m_nHDist ) ); rMeasure += sColon;
+ rMeasure += OUString::number( convertTwipToMm100( rRec.m_nVDist ) ); rMeasure += sColon;
+ rMeasure += OUString::number( convertTwipToMm100( rRec.m_nWidth ) ); rMeasure += sColon;
+ rMeasure += OUString::number( convertTwipToMm100( rRec.m_nHeight ) ); rMeasure += sColon;
+ rMeasure += OUString::number( convertTwipToMm100( rRec.m_nLeft ) ); rMeasure += sColon;
+ rMeasure += OUString::number( convertTwipToMm100( rRec.m_nUpper ) ); rMeasure += sColon;
+ rMeasure += OUString::number( rRec.m_nCols ); rMeasure += sColon;
+ rMeasure += OUString::number( rRec.m_nRows ); rMeasure += sColon;
+ rMeasure += OUString::number( convertTwipToMm100( rRec.m_nPWidth ) ); rMeasure += sColon;
+ rMeasure += OUString::number( convertTwipToMm100( rRec.m_nPHeight ) );
+ pValues[nProp].Value <<= rMeasure;
+ }
+ break;
+ }
+ }
+ return aRet;
+}
+
+// function fills SwLabDlg with label definitions for manufacturer rManufacturer
+void SwLabelConfig::FillLabels(const OUString& rManufacturer, SwLabRecs& rLabArr)
+{
+ if (m_aLabels.find(rManufacturer) == m_aLabels.end())
+ return;
+ for (const auto& rEntry : m_aLabels[rManufacturer])
+ rLabArr.push_back( lcl_CreateSwLabRec(rEntry.first, rEntry.second.m_aMeasure, rManufacturer) );
+}
+
+bool SwLabelConfig::HasLabel(const OUString& rManufacturer, const OUString& rType)
+{
+ auto it = m_aLabels.find(rManufacturer);
+ return ( it != m_aLabels.end() ) && ( it->second.find(rType) != it->second.end() );
+}
+
+// label is always saved as a custom label
+// predefined labels can NOT be overwritten by custom labels with same manufacturer/name
+void SwLabelConfig::SaveLabel( const OUString& rManufacturer,
+ const OUString& rType, const SwLabRec& rRec )
+{
+ OUString sFoundNode;
+ bool bManufacturerNodeFound;
+ if ( m_aLabels.find( rManufacturer ) == m_aLabels.end() ||
+ !GetNodeNames( rManufacturer ).hasElements() )
+ {
+ bManufacturerNodeFound = false;
+ // manufacturer node does not exist, add (and also to m_aManufacturers)
+ if ( !AddNode( OUString(), rManufacturer ) )
+ {
+ OSL_FAIL("New configuration node could not be created");
+ return ;
+ }
+ m_aManufacturers.push_back( rManufacturer );
+ }
+ else
+ bManufacturerNodeFound = true;
+
+ if ( !bManufacturerNodeFound ||
+ m_aLabels[rManufacturer].find( rType ) == m_aLabels[rManufacturer].end() )
+ {
+ // type does not yet exist, add to config
+ const Sequence<OUString> aLabels = GetNodeNames( rManufacturer );
+ sal_Int32 nIndex = aLabels.getLength();
+ OUString sPrefix( "Label" );
+ sFoundNode = sPrefix + OUString::number( nIndex );
+ while ( comphelper::findValue(aLabels, sFoundNode) != -1 )
+ {
+ sFoundNode = sPrefix + OUString::number(nIndex++);
+ }
+ }
+ else
+ {
+ // get the appropriate node
+ OUString sManufacturer( wrapConfigurationElementName( rManufacturer ) );
+ const Sequence<OUString> aLabels = GetNodeNames( sManufacturer );
+ for (const OUString& rLabel : aLabels)
+ {
+ OUString sPrefix = sManufacturer + "/" + rLabel + "/";
+ Sequence<OUString> aProperties { sPrefix };
+ aProperties.getArray()[0] += "Name";
+ Sequence<Any> aValues = GetProperties( aProperties );
+ const Any* pValues = aValues.getConstArray();
+ if ( pValues[0].hasValue() )
+ {
+ OUString sTmp;
+ pValues[0] >>= sTmp;
+ if ( rType == sTmp )
+ {
+ sFoundNode = rLabel;
+ break;
+ }
+ }
+ }
+ }
+
+ OUString sPrefix = wrapConfigurationElementName( rManufacturer ) +
+ "/" + sFoundNode + "/";
+ Sequence<OUString> aPropNames = lcl_CreatePropertyNames( sPrefix );
+ OUString sMeasure;
+ Sequence<PropertyValue> aPropValues = lcl_CreateProperties( aPropNames, sMeasure, rRec );
+ SetSetProperties( wrapConfigurationElementName( rManufacturer ), aPropValues );
+
+ //update m_aLabels
+ m_aLabels[rManufacturer][rType].m_aMeasure = sMeasure;
+ m_aLabels[rManufacturer][rType].m_bPredefined = false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/envelp/labimg.cxx b/sw/source/uibase/envelp/labimg.cxx
new file mode 100644
index 0000000000..b87f9bf5fb
--- /dev/null
+++ b/sw/source/uibase/envelp/labimg.cxx
@@ -0,0 +1,465 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <o3tl/any.hxx>
+#include <osl/diagnose.h>
+#include <tools/UnitConversion.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <unotools/useroptions.hxx>
+#include <swmodule.hxx>
+#include <labimg.hxx>
+#include <cmdid.h>
+
+using namespace utl;
+using namespace ::com::sun::star::uno;
+
+SwLabItem::SwLabItem() :
+
+ SfxPoolItem(FN_LABEL),
+ m_lLeft (0),
+ m_lUpper(0),
+ m_nCols (1),
+ m_nRows (1),
+ m_nCol (1),
+ m_nRow (1)
+{
+ m_bAddr =
+ m_bCont =
+ m_bSynchron = false;
+ m_bPage = true;
+ m_lHDist =
+ m_lVDist =
+ m_lWidth =
+ m_lHeight =
+ m_lPWidth =
+ m_lPHeight = 5669; // 10 cm
+}
+
+SwLabItem& SwLabItem::operator =(const SwLabItem& rItem)
+{
+ m_bAddr = rItem.m_bAddr;
+ m_aWriting = rItem.m_aWriting;
+ m_bCont = rItem.m_bCont;
+ m_sDBName = rItem.m_sDBName;
+ m_aLstMake = rItem.m_aLstMake;
+ m_aLstType = rItem.m_aLstType;
+ m_aMake = rItem.m_aMake;
+ m_aType = rItem.m_aType;
+ m_bPage = rItem.m_bPage;
+ m_bSynchron = rItem.m_bSynchron;
+ m_nCol = rItem.m_nCol;
+ m_nRow = rItem.m_nRow;
+ m_lHDist = rItem.m_lHDist;
+ m_lVDist = rItem.m_lVDist;
+ m_lWidth = rItem.m_lWidth;
+ m_lHeight = rItem.m_lHeight;
+ m_lLeft = rItem.m_lLeft;
+ m_lUpper = rItem.m_lUpper;
+ m_nCols = rItem.m_nCols;
+ m_nRows = rItem.m_nRows;
+ m_lPWidth = rItem.m_lPWidth;
+ m_lPHeight = rItem.m_lPHeight;
+ m_aPrivFirstName = rItem.m_aPrivFirstName;
+ m_aPrivName = rItem.m_aPrivName;
+ m_aPrivShortCut = rItem.m_aPrivShortCut;
+ m_aPrivFirstName2 = rItem.m_aPrivFirstName2;
+ m_aPrivName2 = rItem.m_aPrivName2;
+ m_aPrivShortCut2 = rItem.m_aPrivShortCut2;
+ m_aPrivStreet = rItem.m_aPrivStreet;
+ m_aPrivZip = rItem.m_aPrivZip;
+ m_aPrivCity = rItem.m_aPrivCity;
+ m_aPrivCountry = rItem.m_aPrivCountry;
+ m_aPrivState = rItem.m_aPrivState;
+ m_aPrivTitle = rItem.m_aPrivTitle;
+ m_aPrivProfession = rItem.m_aPrivProfession;
+ m_aPrivPhone = rItem.m_aPrivPhone;
+ m_aPrivMobile = rItem.m_aPrivMobile;
+ m_aPrivFax = rItem.m_aPrivFax;
+ m_aPrivWWW = rItem.m_aPrivWWW;
+ m_aPrivMail = rItem.m_aPrivMail;
+ m_aCompCompany = rItem.m_aCompCompany;
+ m_aCompCompanyExt = rItem.m_aCompCompanyExt;
+ m_aCompSlogan = rItem.m_aCompSlogan;
+ m_aCompStreet = rItem.m_aCompStreet;
+ m_aCompZip = rItem.m_aCompZip;
+ m_aCompCity = rItem.m_aCompCity;
+ m_aCompCountry = rItem.m_aCompCountry;
+ m_aCompState = rItem.m_aCompState;
+ m_aCompPosition = rItem.m_aCompPosition;
+ m_aCompPhone = rItem.m_aCompPhone;
+ m_aCompMobile = rItem.m_aCompMobile;
+ m_aCompFax = rItem.m_aCompFax;
+ m_aCompWWW = rItem.m_aCompWWW;
+ m_aCompMail = rItem.m_aCompMail;
+ m_sGlossaryGroup = rItem.m_sGlossaryGroup;
+ m_sGlossaryBlockName = rItem.m_sGlossaryBlockName;
+ return *this;
+}
+
+bool SwLabItem::operator ==(const SfxPoolItem& rItem) const
+{
+ assert(SfxPoolItem::operator==(rItem));
+ const SwLabItem& rLab = static_cast<const SwLabItem&>( rItem);
+
+ return m_bAddr == rLab.m_bAddr &&
+ m_bCont == rLab.m_bCont &&
+ m_bPage == rLab.m_bPage &&
+ m_bSynchron == rLab.m_bSynchron &&
+ m_nCol == rLab.m_nCol &&
+ m_nRow == rLab.m_nRow &&
+ m_lHDist == rLab.m_lHDist &&
+ m_lVDist == rLab.m_lVDist &&
+ m_lWidth == rLab.m_lWidth &&
+ m_lHeight == rLab.m_lHeight &&
+ m_lLeft == rLab.m_lLeft &&
+ m_lUpper == rLab.m_lUpper &&
+ m_nCols == rLab.m_nCols &&
+ m_nRows == rLab.m_nRows &&
+ m_lPWidth == rLab.m_lPWidth &&
+ m_lPHeight == rLab.m_lPHeight&&
+ m_aWriting == rLab.m_aWriting&&
+ m_aMake == rLab.m_aMake &&
+ m_aType == rLab.m_aType &&
+ m_aLstMake == rLab.m_aLstMake&&
+ m_aLstType == rLab.m_aLstType&&
+ m_sDBName == rLab.m_sDBName &&
+ m_aPrivFirstName == rLab.m_aPrivFirstName&&
+ m_aPrivName == rLab.m_aPrivName&&
+ m_aPrivShortCut == rLab.m_aPrivShortCut&&
+ m_aPrivFirstName2 == rLab.m_aPrivFirstName2&&
+ m_aPrivName2 == rLab.m_aPrivName2&&
+ m_aPrivShortCut2 == rLab.m_aPrivShortCut2&&
+ m_aPrivStreet == rLab.m_aPrivStreet&&
+ m_aPrivZip == rLab.m_aPrivZip&&
+ m_aPrivCity == rLab.m_aPrivCity&&
+ m_aPrivCountry == rLab.m_aPrivCountry&&
+ m_aPrivState == rLab.m_aPrivState&&
+ m_aPrivTitle == rLab.m_aPrivTitle&&
+ m_aPrivProfession == rLab.m_aPrivProfession&&
+ m_aPrivPhone == rLab.m_aPrivPhone&&
+ m_aPrivMobile == rLab.m_aPrivMobile&&
+ m_aPrivFax == rLab.m_aPrivFax&&
+ m_aPrivWWW == rLab.m_aPrivWWW&&
+ m_aPrivMail == rLab.m_aPrivMail&&
+ m_aCompCompany == rLab.m_aCompCompany&&
+ m_aCompCompanyExt == rLab.m_aCompCompanyExt&&
+ m_aCompSlogan == rLab.m_aCompSlogan&&
+ m_aCompStreet == rLab.m_aCompStreet&&
+ m_aCompZip == rLab.m_aCompZip&&
+ m_aCompCity == rLab.m_aCompCity&&
+ m_aCompCountry == rLab.m_aCompCountry&&
+ m_aCompState == rLab.m_aCompState&&
+ m_aCompPosition == rLab.m_aCompPosition&&
+ m_aCompPhone == rLab.m_aCompPhone&&
+ m_aCompMobile == rLab.m_aCompMobile&&
+ m_aCompFax == rLab.m_aCompFax&&
+ m_aCompWWW == rLab.m_aCompWWW&&
+ m_aCompMail == rLab.m_aCompMail &&
+ m_sGlossaryGroup == rLab.m_sGlossaryGroup &&
+ m_sGlossaryBlockName == rLab.m_sGlossaryBlockName;
+}
+
+SwLabItem* SwLabItem::Clone(SfxItemPool*) const
+{
+ return new SwLabItem(*this);
+}
+
+Sequence<OUString> SwLabCfgItem::GetPropertyNames() const
+{
+ static const char* aLabelPropNames[] =
+ {
+ "Medium/Continuous", // 0
+ "Medium/Brand", // 1
+ "Medium/Type", // 2
+ "Format/Column", // 3
+ "Format/Row", // 4
+ "Format/HorizontalDistance",// 5
+ "Format/VerticalDistance", // 6
+ "Format/Width", // 7
+ "Format/Height", // 8
+ "Format/LeftMargin", // 9
+ "Format/TopMargin", //10
+ "Format/PageWidth", //11
+ "Format/PageHeight", //12
+ "Option/Synchronize", //13
+ "Option/Page", //14
+ "Option/Column", //15
+ "Option/Row", //16
+ "Inscription/UseAddress", //17
+ "Inscription/Address", //18
+ "Inscription/Database" //19
+ };
+ static const char* aBusinessPropNames[] =
+ {
+ "PrivateAddress/FirstName", // 0
+ "PrivateAddress/Name", // 1
+ "PrivateAddress/ShortCut", // 2
+ "PrivateAddress/SecondFirstName", // 3
+ "PrivateAddress/SecondName", // 4
+ "PrivateAddress/SecondShortCut", // 5
+ "PrivateAddress/Street", // 6
+ "PrivateAddress/Zip", // 7
+ "PrivateAddress/City", // 8
+ "PrivateAddress/Country", // 9
+ "PrivateAddress/State", // 10
+ "PrivateAddress/Title", // 11
+ "PrivateAddress/Profession", // 12
+ "PrivateAddress/Phone", // 13
+ "PrivateAddress/Mobile", // 14
+ "PrivateAddress/Fax", // 15
+ "PrivateAddress/WebAddress", // 16
+ "PrivateAddress/Email", // 17
+ "BusinessAddress/Company", // 18
+ "BusinessAddress/CompanyExt", // 19
+ "BusinessAddress/Slogan", // 20
+ "BusinessAddress/Street", // 21
+ "BusinessAddress/Zip", // 22
+ "BusinessAddress/City", // 23
+ "BusinessAddress/Country", // 24
+ "BusinessAddress/State", // 25
+ "BusinessAddress/Position", // 26
+ "BusinessAddress/Phone", // 27
+ "BusinessAddress/Mobile", // 28
+ "BusinessAddress/Fax", // 29
+ "BusinessAddress/WebAddress", // 30
+ "BusinessAddress/Email", // 31
+ "AutoText/Group", // 32
+ "AutoText/Block" // 33
+ };
+ const int nBusinessCount = m_bIsLabel ? 0 : 34;
+ const int nLabelCount = m_bIsLabel ? 20 : 17;
+ Sequence<OUString> aNames(nBusinessCount + nLabelCount);
+ OUString* pNames = aNames.getArray();
+ int nIndex = 0;
+ for(int nLabel = 0; nLabel < nLabelCount; nLabel++)
+ pNames[nIndex++] = OUString::createFromAscii(aLabelPropNames[nLabel]);
+ for(int nBusiness = 0; nBusiness < nBusinessCount; nBusiness++)
+ pNames[nIndex++] = OUString::createFromAscii(aBusinessPropNames[nBusiness]);
+ return aNames;
+}
+
+SwLabCfgItem::SwLabCfgItem(bool bLabel) :
+ ConfigItem(bLabel ? OUString("Office.Writer/Label") : OUString("Office.Writer/BusinessCard")),
+ m_bIsLabel(bLabel)
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ EnableNotification(aNames);
+ const Any* pValues = aValues.getConstArray();
+ OSL_ENSURE(aValues.getLength() == aNames.getLength(), "GetProperties failed");
+ bool bNoConfigValues = true;
+ if(aValues.getLength() == aNames.getLength())
+ {
+ for(int nProp = 0, nProperty = 0; nProp < aNames.getLength(); nProp++, nProperty++)
+ {
+
+ if(pValues[nProp].hasValue())
+ {
+ //to have a continuous switch an offset is added
+ if(nProp == 17 && !m_bIsLabel)
+ nProperty += 3;
+ if(nProperty >= 20)
+ bNoConfigValues = false;
+ switch(nProperty)
+ {
+ case 0: m_aItem.m_bCont = *o3tl::doAccess<bool>(pValues[nProp]); break;// "Medium/Continuous",
+ case 1: pValues[nProp] >>= m_aItem.m_aMake; break;// "Medium/Brand",
+ case 2: pValues[nProp] >>= m_aItem.m_aType; break;// "Medium/Type",
+ case 3: pValues[nProp] >>= m_aItem.m_nCols; break;// "Format/Column",
+ case 4: pValues[nProp] >>= m_aItem.m_nRows; break;// "Format/Row",
+ case 5:
+ pValues[nProp] >>= m_aItem.m_lHDist;
+ m_aItem.m_lHDist = o3tl::toTwips(m_aItem.m_lHDist, o3tl::Length::mm100);
+ break;// "Format/HorizontalDistance",
+ case 6:
+ pValues[nProp] >>= m_aItem.m_lVDist;
+ m_aItem.m_lVDist = o3tl::toTwips(m_aItem.m_lVDist, o3tl::Length::mm100);
+ break;// "Format/VerticalDistance",
+ case 7:
+ pValues[nProp] >>= m_aItem.m_lWidth;
+ m_aItem.m_lWidth = o3tl::toTwips(m_aItem.m_lWidth, o3tl::Length::mm100);
+ break;// "Format/Width",
+ case 8:
+ pValues[nProp] >>= m_aItem.m_lHeight;
+ m_aItem.m_lHeight = o3tl::toTwips(m_aItem.m_lHeight, o3tl::Length::mm100);
+ break;// "Format/Height",
+ case 9:
+ pValues[nProp] >>= m_aItem.m_lLeft;
+ m_aItem.m_lLeft = o3tl::toTwips(m_aItem.m_lLeft, o3tl::Length::mm100);
+ break;// "Format/LeftMargin",
+ case 10:
+ pValues[nProp] >>= m_aItem.m_lUpper;
+ m_aItem.m_lUpper = o3tl::toTwips(m_aItem.m_lUpper, o3tl::Length::mm100);
+ break;// "Format/TopMargin",
+ case 11:
+ pValues[nProp] >>= m_aItem.m_lPWidth;
+ m_aItem.m_lPWidth = o3tl::toTwips(m_aItem.m_lPWidth, o3tl::Length::mm100);
+ break;// "Format/PageWidth",
+ case 12:
+ pValues[nProp] >>= m_aItem.m_lPHeight;
+ m_aItem.m_lPHeight = o3tl::toTwips(m_aItem.m_lPHeight, o3tl::Length::mm100);
+ break;// "Format/PageHeight",
+ case 13: m_aItem.m_bSynchron = *o3tl::doAccess<bool>(pValues[nProp]); break;// "Option/Synchronize",
+ case 14: m_aItem.m_bPage = *o3tl::doAccess<bool>(pValues[nProp]); break;// "Option/Page",
+ case 15: pValues[nProp] >>= m_aItem.m_nCol; break;// "Option/Column",
+ case 16: pValues[nProp] >>= m_aItem.m_nRow; break;// "Option/Row"
+ case 17: m_aItem.m_bAddr = *o3tl::doAccess<bool>(pValues[nProp]); break;// "Inscription/UseAddress",
+ case 18: pValues[nProp] >>= m_aItem.m_aWriting; break;// "Inscription/Address",
+ case 19: pValues[nProp] >>= m_aItem.m_sDBName; break;// "Inscription/Database"
+ case 20: pValues[nProp] >>= m_aItem.m_aPrivFirstName; break;// "PrivateAddress/FirstName",
+ case 21: pValues[nProp] >>= m_aItem.m_aPrivName; break;// "PrivateAddress/Name",
+ case 22: pValues[nProp] >>= m_aItem.m_aPrivShortCut; break;// "PrivateAddress/ShortCut",
+ case 23: pValues[nProp] >>= m_aItem.m_aPrivFirstName2; break;// "PrivateAddress/SecondFirstName",
+ case 24: pValues[nProp] >>= m_aItem.m_aPrivName2; break;// "PrivateAddress/SecondName",
+ case 25: pValues[nProp] >>= m_aItem.m_aPrivShortCut2; break;// "PrivateAddress/SecondShortCut",
+ case 26: pValues[nProp] >>= m_aItem.m_aPrivStreet; break;// "PrivateAddress/Street",
+ case 27: pValues[nProp] >>= m_aItem.m_aPrivZip; break;// "PrivateAddress/Zip",
+ case 28: pValues[nProp] >>= m_aItem.m_aPrivCity; break;// "PrivateAddress/City",
+ case 29: pValues[nProp] >>= m_aItem.m_aPrivCountry; break;// "PrivateAddress/Country",
+ case 30: pValues[nProp] >>= m_aItem.m_aPrivState; break;// "PrivateAddress/State",
+ case 31: pValues[nProp] >>= m_aItem.m_aPrivTitle; break;// "PrivateAddress/Title",
+ case 32: pValues[nProp] >>= m_aItem.m_aPrivProfession; break;// "PrivateAddress/Profession",
+ case 33: pValues[nProp] >>= m_aItem.m_aPrivPhone; break;// "PrivateAddress/Phone",
+ case 34: pValues[nProp] >>= m_aItem.m_aPrivMobile; break;// "PrivateAddress/Mobile",
+ case 35: pValues[nProp] >>= m_aItem.m_aPrivFax; break;// "PrivateAddress/Fax",
+ case 36: pValues[nProp] >>= m_aItem.m_aPrivWWW; break;// "PrivateAddress/WebAddress",
+ case 37: pValues[nProp] >>= m_aItem.m_aPrivMail; break;// "PrivateAddress/Email",
+ case 38: pValues[nProp] >>= m_aItem.m_aCompCompany; break;// "BusinessAddress/Company",
+ case 39: pValues[nProp] >>= m_aItem.m_aCompCompanyExt; break;// "BusinessAddress/CompanyExt",
+ case 40: pValues[nProp] >>= m_aItem.m_aCompSlogan; break;// "BusinessAddress/Slogan",
+ case 41: pValues[nProp] >>= m_aItem.m_aCompStreet; break;// "BusinessAddress/Street",
+ case 42: pValues[nProp] >>= m_aItem.m_aCompZip; break;// "BusinessAddress/Zip",
+ case 43: pValues[nProp] >>= m_aItem.m_aCompCity; break;// "BusinessAddress/City",
+ case 44: pValues[nProp] >>= m_aItem.m_aCompCountry; break;// "BusinessAddress/Country",
+ case 45: pValues[nProp] >>= m_aItem.m_aCompState; break;// "BusinessAddress/State",
+ case 46: pValues[nProp] >>= m_aItem.m_aCompPosition; break;// "BusinessAddress/Position",
+ case 47: pValues[nProp] >>= m_aItem.m_aCompPhone; break;// "BusinessAddress/Phone",
+ case 48: pValues[nProp] >>= m_aItem.m_aCompMobile; break;// "BusinessAddress/Mobile",
+ case 49: pValues[nProp] >>= m_aItem.m_aCompFax; break;// "BusinessAddress/Fax",
+ case 50: pValues[nProp] >>= m_aItem.m_aCompWWW; break;// "BusinessAddress/WebAddress",
+ case 51: pValues[nProp] >>= m_aItem.m_aCompMail; break;// "BusinessAddress/Email",
+ case 52: pValues[nProp] >>= m_aItem.m_sGlossaryGroup; break;// "AutoText/Group"
+ case 53: pValues[nProp] >>= m_aItem.m_sGlossaryBlockName; break;// "AutoText/Block"
+ }
+ }
+ }
+ }
+
+ if(m_bIsLabel || !bNoConfigValues)
+ return;
+
+ SvtUserOptions& rUserOpt = SW_MOD()->GetUserOptions();
+ m_aItem.m_aPrivFirstName = rUserOpt.GetFirstName();
+ m_aItem.m_aPrivName = rUserOpt.GetLastName();
+ m_aItem.m_aPrivShortCut = rUserOpt.GetID();
+ m_aItem.m_aCompCompany = rUserOpt.GetCompany();
+ m_aItem.m_aCompStreet = m_aItem.m_aPrivStreet = rUserOpt.GetStreet();
+
+ m_aItem.m_aCompCountry = m_aItem.m_aPrivCountry = rUserOpt.GetCountry();
+ m_aItem.m_aCompZip = m_aItem.m_aPrivZip= rUserOpt.GetZip();
+ m_aItem.m_aCompCity = m_aItem.m_aPrivCity = rUserOpt.GetCity();
+ m_aItem.m_aPrivTitle = rUserOpt.GetTitle();
+ m_aItem.m_aCompPosition = rUserOpt.GetPosition();
+ m_aItem.m_aPrivPhone = rUserOpt.GetTelephoneHome();
+ m_aItem.m_aCompPhone = rUserOpt.GetTelephoneWork();
+ m_aItem.m_aCompFax = m_aItem.m_aPrivFax = rUserOpt.GetFax();
+ m_aItem.m_aCompMail = m_aItem.m_aPrivMail = rUserOpt.GetEmail();
+ m_aItem.m_aCompState = m_aItem.m_aPrivState = rUserOpt.GetState();
+ m_aItem.m_bSynchron = true;
+ SetModified();
+
+}
+
+void SwLabCfgItem::Notify( const css::uno::Sequence< OUString >& ) {}
+
+void SwLabCfgItem::ImplCommit()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ for(int nProp = 0, nProperty = 0; nProp < aNames.getLength(); nProp++, nProperty++)
+ {
+ //to have a continuous switch an offset is added
+ if(nProp == 17 && !m_bIsLabel)
+ nProperty += 3;
+ switch(nProperty)
+ {
+ case 0: pValues[nProp] <<= m_aItem.m_bCont; break;// "Medium/Continuous",
+ case 1: pValues[nProp] <<= m_aItem.m_aMake; break;// "Medium/Brand",
+ case 2: pValues[nProp] <<= m_aItem.m_aType; break;// "Medium/Type",
+ case 3: pValues[nProp] <<= m_aItem.m_nCols; break;// "Format/Column",
+ case 4: pValues[nProp] <<= m_aItem.m_nRows; break;// "Format/Row",
+ case 5: pValues[nProp] <<= static_cast<sal_Int32>(convertTwipToMm100(m_aItem.m_lHDist));break;// "Format/HorizontalDistance",
+ case 6: pValues[nProp] <<= static_cast<sal_Int32>(convertTwipToMm100(m_aItem.m_lVDist));break;// "Format/VerticalDistance",
+ case 7: pValues[nProp] <<= static_cast<sal_Int32>(convertTwipToMm100(m_aItem.m_lWidth)); break;// "Format/Width",
+ case 8: pValues[nProp] <<= static_cast<sal_Int32>(convertTwipToMm100(m_aItem.m_lHeight)); break;// "Format/Height",
+ case 9: pValues[nProp] <<= static_cast<sal_Int32>(convertTwipToMm100(m_aItem.m_lLeft)); break;// "Format/LeftMargin",
+ case 10: pValues[nProp] <<= static_cast<sal_Int32>(convertTwipToMm100(m_aItem.m_lUpper)); break;// "Format/TopMargin",
+ case 11: pValues[nProp] <<= static_cast<sal_Int32>(convertTwipToMm100(m_aItem.m_lPWidth)); break;// "Format/Page Width",
+ case 12: pValues[nProp] <<= static_cast<sal_Int32>(convertTwipToMm100(m_aItem.m_lPHeight)); break;// "Format/PageHeight",
+ case 13: pValues[nProp] <<= m_aItem.m_bSynchron; break;// "Option/Synchronize",
+ case 14: pValues[nProp] <<= m_aItem.m_bPage; break;// "Option/Page",
+ case 15: pValues[nProp] <<= m_aItem.m_nCol; break;// "Option/Column",
+ case 16: pValues[nProp] <<= m_aItem.m_nRow; break;// "Option/Row"
+ case 17: pValues[nProp] <<= m_aItem.m_bAddr; break;// "Inscription/UseAddress",
+ case 18: pValues[nProp] <<= m_aItem.m_aWriting; break;// "Inscription/Address",
+ case 19: pValues[nProp] <<= m_aItem.m_sDBName; break;// "Inscription/Database"
+ case 20: pValues[nProp] <<= m_aItem.m_aPrivFirstName; break;// "PrivateAddress/FirstName",
+ case 21: pValues[nProp] <<= m_aItem.m_aPrivName; break;// "PrivateAddress/Name",
+ case 22: pValues[nProp] <<= m_aItem.m_aPrivShortCut; break;// "PrivateAddress/ShortCut",
+ case 23: pValues[nProp] <<= m_aItem.m_aPrivFirstName2; break;// "PrivateAddress/SecondFirstName",
+ case 24: pValues[nProp] <<= m_aItem.m_aPrivName2; break;// "PrivateAddress/SecondName",
+ case 25: pValues[nProp] <<= m_aItem.m_aPrivShortCut2; break;// "PrivateAddress/SecondShortCut",
+ case 26: pValues[nProp] <<= m_aItem.m_aPrivStreet; break;// "PrivateAddress/Street",
+ case 27: pValues[nProp] <<= m_aItem.m_aPrivZip; break;// "PrivateAddress/Zip",
+ case 28: pValues[nProp] <<= m_aItem.m_aPrivCity; break;// "PrivateAddress/City",
+ case 29: pValues[nProp] <<= m_aItem.m_aPrivCountry; break;// "PrivateAddress/Country",
+ case 30: pValues[nProp] <<= m_aItem.m_aPrivState; break;// "PrivateAddress/State",
+ case 31: pValues[nProp] <<= m_aItem.m_aPrivTitle; break;// "PrivateAddress/Title",
+ case 32: pValues[nProp] <<= m_aItem.m_aPrivProfession; break;// "PrivateAddress/Profession",
+ case 33: pValues[nProp] <<= m_aItem.m_aPrivPhone; break;// "PrivateAddress/Phone",
+ case 34: pValues[nProp] <<= m_aItem.m_aPrivMobile; break;// "PrivateAddress/Mobile",
+ case 35: pValues[nProp] <<= m_aItem.m_aPrivFax; break;// "PrivateAddress/Fax",
+ case 36: pValues[nProp] <<= m_aItem.m_aPrivWWW; break;// "PrivateAddress/WebAddress",
+ case 37: pValues[nProp] <<= m_aItem.m_aPrivMail; break;// "PrivateAddress/Email",
+ case 38: pValues[nProp] <<= m_aItem.m_aCompCompany; break;// "BusinessAddress/Company",
+ case 39: pValues[nProp] <<= m_aItem.m_aCompCompanyExt; break;// "BusinessAddress/CompanyExt",
+ case 40: pValues[nProp] <<= m_aItem.m_aCompSlogan; break;// "BusinessAddress/Slogan",
+ case 41: pValues[nProp] <<= m_aItem.m_aCompStreet; break;// "BusinessAddress/Street",
+ case 42: pValues[nProp] <<= m_aItem.m_aCompZip; break;// "BusinessAddress/Zip",
+ case 43: pValues[nProp] <<= m_aItem.m_aCompCity; break;// "BusinessAddress/City",
+ case 44: pValues[nProp] <<= m_aItem.m_aCompCountry; break;// "BusinessAddress/Country",
+ case 45: pValues[nProp] <<= m_aItem.m_aCompState; break;// "BusinessAddress/State",
+ case 46: pValues[nProp] <<= m_aItem.m_aCompPosition; break;// "BusinessAddress/Position",
+ case 47: pValues[nProp] <<= m_aItem.m_aCompPhone; break;// "BusinessAddress/Phone",
+ case 48: pValues[nProp] <<= m_aItem.m_aCompMobile; break;// "BusinessAddress/Mobile",
+ case 49: pValues[nProp] <<= m_aItem.m_aCompFax; break;// "BusinessAddress/Fax",
+ case 50: pValues[nProp] <<= m_aItem.m_aCompWWW; break;// "BusinessAddress/WebAddress",
+ case 51: pValues[nProp] <<= m_aItem.m_aCompMail; break;// "BusinessAddress/Email",
+ case 52: pValues[nProp] <<= m_aItem.m_sGlossaryGroup; break;// "AutoText/Group"
+ case 53: pValues[nProp] <<= m_aItem.m_sGlossaryBlockName; break;// "AutoText/Block"
+ }
+ }
+ PutProperties(aNames, aValues);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/envelp/syncbtn.cxx b/sw/source/uibase/envelp/syncbtn.cxx
new file mode 100644
index 0000000000..715d769633
--- /dev/null
+++ b/sw/source/uibase/envelp/syncbtn.cxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/dispatch.hxx>
+#include <vcl/windowstate.hxx>
+
+#include <cmdid.h>
+#include <swmodule.hxx>
+#include <view.hxx>
+#include <edtwin.hxx>
+
+#include <syncbtn.hxx>
+
+SFX_IMPL_MODELESSDIALOGCONTOLLER(SwSyncChildWin, FN_SYNC_LABELS)
+
+SwSyncChildWin::SwSyncChildWin(vcl::Window* _pParent,
+ sal_uInt16 nId,
+ SfxBindings* pBindings,
+ SfxChildWinInfo* pInfo)
+ : SfxChildWindow(_pParent, nId)
+{
+ SetController(std::make_shared<SwSyncBtnDlg>(pBindings, this, _pParent->GetFrameWeld()));
+ SwSyncBtnDlg* pBtnDlg = static_cast<SwSyncBtnDlg*>(GetController().get());
+
+ if (!pInfo->aSize.Width() || !pInfo->aSize.Height())
+ {
+ weld::Dialog* pDlg = pBtnDlg->getDialog();
+ Point aPos;
+
+ if (SwView* pActiveView = GetActiveView())
+ {
+ const SwEditWin &rEditWin = pActiveView->GetEditWin();
+ aPos = rEditWin.OutputToScreenPixel(Point(0, 0));
+ }
+ else
+ aPos = _pParent->OutputToScreenPixel(Point(0, 0));
+
+ vcl::WindowData aState;
+ aState.setMask(vcl::WindowDataMask::Pos);
+ aState.setPos(aPos);
+ pDlg->set_window_state(aState.toStr());
+
+ pInfo->aPos = pDlg->get_position();
+ pInfo->aSize = pDlg->get_size();
+ }
+
+ pBtnDlg->Initialize(pInfo);
+}
+
+SwSyncBtnDlg::SwSyncBtnDlg(SfxBindings* pBindings,
+ SfxChildWindow* pChild,
+ weld::Window *pParent)
+ : SfxModelessDialogController(pBindings, pChild, pParent, "modules/swriter/ui/floatingsync.ui", "FloatingSync")
+ , m_xSyncBtn(m_xBuilder->weld_button("sync"))
+{
+ m_xSyncBtn->connect_clicked(LINK(this, SwSyncBtnDlg, BtnHdl));
+}
+
+SwSyncBtnDlg::~SwSyncBtnDlg()
+{
+}
+
+IMPL_STATIC_LINK_NOARG(SwSyncBtnDlg, BtnHdl, weld::Button&, void)
+{
+ if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
+ pViewFrm->GetDispatcher()->Execute(FN_UPDATE_ALL_LINKS, SfxCallMode::ASYNCHRON);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/fldui/fldmgr.cxx b/sw/source/uibase/fldui/fldmgr.cxx
new file mode 100644
index 0000000000..ec509c92cd
--- /dev/null
+++ b/sw/source/uibase/fldui/fldmgr.cxx
@@ -0,0 +1,1932 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+#include <config_fuzzers.h>
+
+#include <cmdid.h>
+#include <hintids.hxx>
+#include <svl/numformat.hxx>
+#include <svl/stritem.hxx>
+#include <com/sun/star/text/DefaultNumberingProvider.hpp>
+#include <com/sun/star/text/XDefaultNumberingProvider.hpp>
+#include <com/sun/star/text/XNumberingTypeInfo.hpp>
+#include <com/sun/star/style/NumberingType.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/uri/UriReferenceFactory.hpp>
+#include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/string.hxx>
+#include <o3tl/string_view.hxx>
+#include <tools/resary.hxx>
+#include <osl/diagnose.h>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svx/strarray.hxx>
+#include <fmtrfmrk.hxx>
+#include <svl/zforlist.hxx>
+#include <svl/zformat.hxx>
+#include <vcl/mnemonic.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <doc.hxx>
+#include <swmodule.hxx>
+#include <fmtinfmt.hxx>
+#include <cellatr.hxx>
+#include <dbmgr.hxx>
+#include <shellres.hxx>
+#include <fldbas.hxx>
+#include <docufld.hxx>
+#include <chpfld.hxx>
+#include <ddefld.hxx>
+#include <expfld.hxx>
+#include <reffld.hxx>
+#include <usrfld.hxx>
+#include <dbfld.hxx>
+#include <authfld.hxx>
+#include <flddat.hxx>
+#include <fldmgr.hxx>
+#include <ndtxt.hxx>
+#include <cntfrm.hxx>
+#include <flddropdown.hxx>
+#include <strings.hrc>
+#include <tox.hxx>
+#include <viewopt.hxx>
+#include <txmsrt.hxx>
+#include <unotools/useroptions.hxx>
+#include <IDocumentContentOperations.hxx>
+#include <translatehelper.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::container;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::text;
+using namespace com::sun::star::style;
+using namespace com::sun::star::sdbc;
+using namespace ::com::sun::star;
+using namespace nsSwDocInfoSubType;
+
+// groups of fields
+enum
+{
+ GRP_DOC_BEGIN = 0,
+ GRP_DOC_END = GRP_DOC_BEGIN + 12,
+
+ GRP_FKT_BEGIN = GRP_DOC_END,
+ GRP_FKT_END = GRP_FKT_BEGIN + 8,
+
+ GRP_REF_BEGIN = GRP_FKT_END,
+ GRP_REF_END = GRP_REF_BEGIN + 2,
+
+ GRP_REG_BEGIN = GRP_REF_END,
+ GRP_REG_END = GRP_REG_BEGIN + 1,
+
+ GRP_DB_BEGIN = GRP_REG_END,
+ GRP_DB_END = GRP_DB_BEGIN + 5,
+
+ GRP_VAR_BEGIN = GRP_DB_END,
+ GRP_VAR_END = GRP_VAR_BEGIN + 9
+};
+
+enum
+{
+ GRP_WEB_DOC_BEGIN = 0,
+ GRP_WEB_DOC_END = GRP_WEB_DOC_BEGIN + 9,
+
+ GRP_WEB_FKT_BEGIN = GRP_WEB_DOC_END + 2,
+ GRP_WEB_FKT_END = GRP_WEB_FKT_BEGIN + 0, // the group is empty!
+
+ GRP_WEB_REF_BEGIN = GRP_WEB_FKT_END + 6, // the group is empty!
+ GRP_WEB_REF_END = GRP_WEB_REF_BEGIN + 0,
+
+ GRP_WEB_REG_BEGIN = GRP_WEB_REF_END + 2,
+ GRP_WEB_REG_END = GRP_WEB_REG_BEGIN + 1,
+
+ GRP_WEB_DB_BEGIN = GRP_WEB_REG_END, // the group is empty!
+ GRP_WEB_DB_END = GRP_WEB_DB_BEGIN + 0,
+
+ GRP_WEB_VAR_BEGIN = GRP_WEB_DB_END + 5,
+ GRP_WEB_VAR_END = GRP_WEB_VAR_BEGIN + 1
+};
+
+const sal_uInt16 VF_COUNT = 1; // { 0 }
+const sal_uInt16 VF_USR_COUNT = 2; // { 0, nsSwExtendedSubType::SUB_CMD }
+const sal_uInt16 VF_DB_COUNT = 1; // { nsSwExtendedSubType::SUB_OWN_FMT }
+
+const TranslateId FLD_EU_ARY[] =
+{
+ FLD_EU_COMPANY,
+ FLD_EU_GIVENNAME,
+ FLD_EU_SURNAME,
+ FLD_EU_INITIALS,
+ FLD_EU_STREET,
+ FLD_EU_COUNTRY,
+ FLD_EU_POSTCODE,
+ FLD_EU_TOWN,
+ FLD_EU_TITLE,
+ FLD_EU_POS,
+ FLD_EU_TELPERSONAL,
+ FLD_EU_TELWORK,
+ FLD_EU_FAX,
+ FLD_EU_EMAIL,
+ FLD_EU_REGION
+};
+
+const TranslateId FMT_AUTHOR_ARY[] =
+{
+ FMT_AUTHOR_NAME,
+ FMT_AUTHOR_SCUT
+};
+
+const TranslateId FLD_DATE_ARY[] =
+{
+ FLD_DATE_FIX,
+ FLD_DATE_STD,
+};
+
+const TranslateId FLD_TIME_ARY[] =
+{
+ FLD_TIME_FIX,
+ FLD_TIME_STD
+};
+
+const TranslateId FMT_NUM_ARY[] =
+{
+ FMT_NUM_ABC,
+ FMT_NUM_SABC,
+ FMT_NUM_ABC_N,
+ FMT_NUM_SABC_N,
+ FMT_NUM_ROMAN,
+ FMT_NUM_SROMAN,
+ FMT_NUM_ARABIC,
+ FMT_NUM_PAGEDESC,
+ FMT_NUM_PAGESPECIAL
+};
+
+const TranslateId FMT_FF_ARY[] =
+{
+ FMT_FF_NAME,
+ FMT_FF_PATHNAME,
+ FMT_FF_PATH,
+ FMT_FF_NAME_NOEXT,
+ FMT_FF_UI_NAME,
+ FMT_FF_UI_RANGE
+};
+
+const TranslateId FLD_STAT_ARY[] =
+{
+ FLD_STAT_PAGE,
+ FLD_STAT_PARA,
+ FLD_STAT_WORD,
+ FLD_STAT_CHAR,
+ FLD_STAT_TABLE,
+ FLD_STAT_GRF,
+ FLD_STAT_OBJ
+};
+
+const TranslateId FMT_CHAPTER_ARY[] =
+{
+ FMT_CHAPTER_NO,
+ FMT_CHAPTER_NAME,
+ FMT_CHAPTER_NAMENO,
+ FMT_CHAPTER_NO_NOSEPARATOR
+};
+
+const TranslateId FLD_INPUT_ARY[] =
+{
+ FLD_INPUT_TEXT
+};
+
+const TranslateId FMT_MARK_ARY[] =
+{
+ FMT_MARK_TEXT,
+ FMT_MARK_TABLE,
+ FMT_MARK_FRAME,
+ FMT_MARK_GRAFIC,
+ FMT_MARK_OLE
+};
+
+const TranslateId FMT_REF_ARY[] =
+{
+ FMT_REF_PAGE,
+ FMT_REF_CHAPTER,
+ FMT_REF_TEXT,
+ FMT_REF_UPDOWN,
+ FMT_REF_PAGE_PGDSC,
+ FMT_REF_ONLYNUMBER,
+ FMT_REF_ONLYCAPTION,
+ FMT_REF_ONLYSEQNO,
+ FMT_REF_NUMBER,
+ FMT_REF_NUMBER_NO_CONTEXT,
+ FMT_REF_NUMBER_FULL_CONTEXT
+};
+
+const TranslateId FMT_REG_ARY[] =
+{
+ FMT_REG_AUTHOR,
+ FMT_REG_TIME,
+ FMT_REG_DATE
+};
+
+const TranslateId FMT_DBFLD_ARY[] =
+{
+ FMT_DBFLD_DB,
+ FMT_DBFLD_SYS
+};
+
+const TranslateId FMT_SETVAR_ARY[] =
+{
+ FMT_SETVAR_SYS,
+ FMT_SETVAR_TEXT
+};
+
+const TranslateId FMT_GETVAR_ARY[] =
+{
+ FMT_GETVAR_TEXT,
+ FMT_GETVAR_NAME
+};
+
+const TranslateId FMT_DDE_ARY[] =
+{
+ FMT_DDE_NORMAL,
+ FMT_DDE_HOT
+};
+
+const TranslateId FLD_PAGEREF_ARY[] =
+{
+ FLD_PAGEREF_OFF,
+ FLD_PAGEREF_ON
+};
+
+const TranslateId FMT_USERVAR_ARY[] =
+{
+ FMT_USERVAR_TEXT,
+ FMT_USERVAR_CMD
+};
+
+namespace {
+
+// field types and subtypes
+struct SwFieldPack
+{
+ SwFieldTypesEnum nTypeId;
+
+ const TranslateId* pSubTypeResIds;
+ size_t nSubTypeLength;
+
+ const TranslateId* pFormatResIds;
+ size_t nFormatLength;
+};
+
+}
+
+// strings and formats
+const SwFieldPack aSwFields[] =
+{
+ // Document
+ { SwFieldTypesEnum::ExtendedUser, FLD_EU_ARY, std::size(FLD_EU_ARY), nullptr, 0 },
+ { SwFieldTypesEnum::Author, nullptr, 0, FMT_AUTHOR_ARY, std::size(FMT_AUTHOR_ARY) },
+ { SwFieldTypesEnum::Date, FLD_DATE_ARY, std::size(FLD_DATE_ARY), nullptr, 0 },
+ { SwFieldTypesEnum::Time, FLD_TIME_ARY, std::size(FLD_TIME_ARY), nullptr, 0 },
+ { SwFieldTypesEnum::PageNumber, nullptr, 0, FMT_NUM_ARY, std::size(FMT_NUM_ARY) -1 },
+ { SwFieldTypesEnum::NextPage, nullptr, 0, FMT_NUM_ARY, std::size(FMT_NUM_ARY) },
+ { SwFieldTypesEnum::PreviousPage, nullptr, 0, FMT_NUM_ARY, std::size(FMT_NUM_ARY) },
+ { SwFieldTypesEnum::Filename, nullptr, 0, FMT_FF_ARY, std::size(FMT_FF_ARY) },
+ { SwFieldTypesEnum::DocumentStatistics, FLD_STAT_ARY, std::size(FLD_STAT_ARY), FMT_NUM_ARY, std::size(FMT_NUM_ARY) -1 },
+
+ { SwFieldTypesEnum::Chapter, nullptr, 0, FMT_CHAPTER_ARY, std::size(FMT_CHAPTER_ARY) },
+ { SwFieldTypesEnum::TemplateName, nullptr, 0, FMT_FF_ARY, std::size(FMT_FF_ARY) },
+ { SwFieldTypesEnum::ParagraphSignature, nullptr, 0, nullptr, 0 },
+
+ // Functions
+ { SwFieldTypesEnum::ConditionalText, nullptr, 0, nullptr, 0 },
+ { SwFieldTypesEnum::Dropdown, nullptr, 0, nullptr, 0 },
+ { SwFieldTypesEnum::Input, FLD_INPUT_ARY, std::size(FLD_INPUT_ARY), nullptr, 0 },
+ { SwFieldTypesEnum::Macro, nullptr, 0, nullptr, 0 },
+ { SwFieldTypesEnum::JumpEdit, nullptr, 0, FMT_MARK_ARY, std::size(FMT_MARK_ARY) },
+ { SwFieldTypesEnum::CombinedChars, nullptr, 0, nullptr, 0 },
+ { SwFieldTypesEnum::HiddenText, nullptr, 0, nullptr, 0 },
+ { SwFieldTypesEnum::HiddenParagraph, nullptr, 0, nullptr, 0 },
+
+ // Cross-References
+ { SwFieldTypesEnum::SetRef, nullptr, 0, nullptr, 0 },
+ { SwFieldTypesEnum::GetRef, nullptr, 0, FMT_REF_ARY, std::size(FMT_REF_ARY) },
+
+ // DocInformation
+ { SwFieldTypesEnum::DocumentInfo, nullptr, 0, FMT_REG_ARY, std::size(FMT_REG_ARY) },
+
+ // Database
+ { SwFieldTypesEnum::Database, nullptr, 0, FMT_DBFLD_ARY, std::size(FMT_DBFLD_ARY) },
+ { SwFieldTypesEnum::DatabaseNextSet, nullptr, 0, nullptr, 0 },
+ { SwFieldTypesEnum::DatabaseNumberSet, nullptr, 0, nullptr, 0 },
+ { SwFieldTypesEnum::DatabaseSetNumber, nullptr, 0, FMT_NUM_ARY, std::size(FMT_NUM_ARY) - 2 },
+ { SwFieldTypesEnum::DatabaseName, nullptr, 0, nullptr, 0 },
+
+ // Variables
+ { SwFieldTypesEnum::Set, nullptr, 0, FMT_SETVAR_ARY, std::size(FMT_SETVAR_ARY) },
+
+ { SwFieldTypesEnum::Get, nullptr, 0, FMT_GETVAR_ARY, std::size(FMT_GETVAR_ARY) },
+ { SwFieldTypesEnum::DDE, nullptr, 0, FMT_DDE_ARY, std::size(FMT_DDE_ARY) },
+ { SwFieldTypesEnum::Formel, nullptr, 0, FMT_GETVAR_ARY, std::size(FMT_GETVAR_ARY) },
+ { SwFieldTypesEnum::Input, FLD_INPUT_ARY, std::size(FLD_INPUT_ARY), nullptr, 0 },
+ { SwFieldTypesEnum::Sequence, nullptr, 0, FMT_NUM_ARY, std::size(FMT_NUM_ARY) - 2 },
+ { SwFieldTypesEnum::SetRefPage, FLD_PAGEREF_ARY, std::size(FLD_PAGEREF_ARY),nullptr, 0 },
+ { SwFieldTypesEnum::GetRefPage, nullptr, 0, FMT_NUM_ARY, std::size(FMT_NUM_ARY) - 1 },
+ { SwFieldTypesEnum::User, nullptr, 0, FMT_USERVAR_ARY, std::size(FMT_USERVAR_ARY) }
+};
+
+// access to the shell
+static SwWrtShell* lcl_GetShell()
+{
+ if (SwView* pView = GetActiveView())
+ return pView->GetWrtShellPtr();
+ return nullptr;
+}
+
+static sal_uInt16 GetPackCount() { return SAL_N_ELEMENTS(aSwFields); }
+
+// FieldManager controls inserting and updating of fields
+SwFieldMgr::SwFieldMgr(SwWrtShell* pSh ) :
+ m_pWrtShell(pSh),
+ m_bEvalExp(true)
+{
+ // determine current field if existing
+ GetCurField();
+}
+
+SwFieldMgr::~SwFieldMgr()
+{
+}
+
+// organise RefMark by names
+bool SwFieldMgr::CanInsertRefMark( std::u16string_view rStr )
+{
+ bool bRet = false;
+ SwWrtShell *pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
+ OSL_ENSURE(pSh, "no SwWrtShell found");
+ if(pSh)
+ {
+ sal_uInt16 nCnt = pSh->GetCursorCnt();
+
+ // the last Cursor doesn't have to be a spanned selection
+ if( 1 < nCnt && !pSh->SwCursorShell::HasSelection() )
+ --nCnt;
+
+ bRet = 2 > nCnt && nullptr == pSh->GetRefMark( rStr );
+ }
+ return bRet;
+}
+
+// access over ResIds
+void SwFieldMgr::RemoveFieldType(SwFieldIds nResId, const OUString& rName )
+{
+ SwWrtShell * pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
+ OSL_ENSURE(pSh, "no SwWrtShell found");
+ if( pSh )
+ pSh->RemoveFieldType(nResId, rName);
+}
+
+size_t SwFieldMgr::GetFieldTypeCount() const
+{
+ SwWrtShell * pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
+ OSL_ENSURE(pSh, "no SwWrtShell found");
+ return pSh ? pSh->GetFieldTypeCount() : 0;
+}
+
+SwFieldType* SwFieldMgr::GetFieldType(SwFieldIds nResId, size_t nField) const
+{
+ SwWrtShell * pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
+ OSL_ENSURE(pSh, "no SwWrtShell found");
+ return pSh ? pSh->GetFieldType(nField, nResId) : nullptr;
+}
+
+SwFieldType* SwFieldMgr::GetFieldType(SwFieldIds nResId, const OUString& rName) const
+{
+ SwWrtShell * pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
+ OSL_ENSURE(pSh, "no SwWrtShell found");
+ return pSh ? pSh->GetFieldType(nResId, rName) : nullptr;
+}
+
+// determine current field
+SwField* SwFieldMgr::GetCurField()
+{
+ SwWrtShell *pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
+ if ( pSh )
+ m_pCurField = pSh->GetCurField( true );
+ else
+ m_pCurField = nullptr;
+
+ // initialise strings and format
+ m_aCurPar1.clear();
+ m_aCurPar2.clear();
+ m_sCurFrame.clear();
+
+ if(!m_pCurField)
+ return nullptr;
+
+ // preprocess current values; determine parameter 1 and parameter 2
+
+ m_aCurPar1 = m_pCurField->GetPar1();
+ m_aCurPar2 = m_pCurField->GetPar2();
+
+ return m_pCurField;
+}
+
+// provide group range
+const SwFieldGroupRgn& SwFieldMgr::GetGroupRange(bool bHtmlMode, sal_uInt16 nGrpId)
+{
+ static SwFieldGroupRgn const aRanges[] =
+ {
+ { /* Document */ GRP_DOC_BEGIN, GRP_DOC_END },
+ { /* Functions */ GRP_FKT_BEGIN, GRP_FKT_END },
+ { /* Cross-Refs */ GRP_REF_BEGIN, GRP_REF_END },
+ { /* DocInfos */ GRP_REG_BEGIN, GRP_REG_END },
+ { /* Database */ GRP_DB_BEGIN, GRP_DB_END },
+ { /* User */ GRP_VAR_BEGIN, GRP_VAR_END }
+ };
+ static SwFieldGroupRgn const aWebRanges[] =
+ {
+ { /* Document */ GRP_WEB_DOC_BEGIN, GRP_WEB_DOC_END },
+ { /* Functions */ GRP_WEB_FKT_BEGIN, GRP_WEB_FKT_END },
+ { /* Cross-Refs */ GRP_WEB_REF_BEGIN, GRP_WEB_REF_END },
+ { /* DocInfos */ GRP_WEB_REG_BEGIN, GRP_WEB_REG_END },
+ { /* Database */ GRP_WEB_DB_BEGIN, GRP_WEB_DB_END },
+ { /* User */ GRP_WEB_VAR_BEGIN, GRP_WEB_VAR_END }
+ };
+
+ if (bHtmlMode)
+ return aWebRanges[nGrpId];
+ else
+ return aRanges[nGrpId];
+}
+
+// determine GroupId
+sal_uInt16 SwFieldMgr::GetGroup(SwFieldTypesEnum nTypeId, sal_uInt16 nSubType)
+{
+ if (nTypeId == SwFieldTypesEnum::SetInput)
+ nTypeId = SwFieldTypesEnum::Set;
+
+ if (nTypeId == SwFieldTypesEnum::Input && (nSubType & INP_USR))
+ nTypeId = SwFieldTypesEnum::User;
+
+ if (nTypeId == SwFieldTypesEnum::FixedDate)
+ nTypeId = SwFieldTypesEnum::Date;
+
+ if (nTypeId == SwFieldTypesEnum::FixedTime)
+ nTypeId = SwFieldTypesEnum::Time;
+
+ for (sal_uInt16 i = GRP_DOC; i <= GRP_VAR; i++)
+ {
+ const SwFieldGroupRgn& rRange = GetGroupRange(false/*bHtmlMode*/, i);
+ for (sal_uInt16 nPos = rRange.nStart; nPos < rRange.nEnd; nPos++)
+ {
+ if (aSwFields[nPos].nTypeId == nTypeId)
+ return i;
+ }
+ }
+ return USHRT_MAX;
+}
+
+// determine names to TypeId
+// ACCESS over TYP_...
+SwFieldTypesEnum SwFieldMgr::GetTypeId(sal_uInt16 nPos)
+{
+ OSL_ENSURE(nPos < ::GetPackCount(), "forbidden Pos");
+ return aSwFields[ nPos ].nTypeId;
+}
+
+const OUString & SwFieldMgr::GetTypeStr(sal_uInt16 nPos)
+{
+ OSL_ENSURE(nPos < ::GetPackCount(), "forbidden TypeId");
+
+ SwFieldTypesEnum nFieldWh = aSwFields[ nPos ].nTypeId;
+
+ // special treatment for date/time fields (without var/fix)
+ if( SwFieldTypesEnum::Date == nFieldWh )
+ {
+ static OUString g_aDate( SwResId( STR_DATEFLD ) );
+ return g_aDate;
+ }
+ if( SwFieldTypesEnum::Time == nFieldWh )
+ {
+ static OUString g_aTime( SwResId( STR_TIMEFLD ) );
+ return g_aTime;
+ }
+
+ return SwFieldType::GetTypeStr( nFieldWh );
+}
+
+// determine Pos in the list
+sal_uInt16 SwFieldMgr::GetPos(SwFieldTypesEnum nTypeId)
+{
+ switch( nTypeId )
+ {
+ case SwFieldTypesEnum::FixedDate: nTypeId = SwFieldTypesEnum::Date; break;
+ case SwFieldTypesEnum::FixedTime: nTypeId = SwFieldTypesEnum::Time; break;
+ case SwFieldTypesEnum::SetInput: nTypeId = SwFieldTypesEnum::Set; break;
+ case SwFieldTypesEnum::UserInput: nTypeId = SwFieldTypesEnum::User; break;
+ default: break;
+ }
+
+ for(sal_uInt16 i = 0; i < GetPackCount(); i++)
+ if(aSwFields[i].nTypeId == nTypeId)
+ return i;
+
+ return USHRT_MAX;
+}
+
+// localise subtypes of a field
+void SwFieldMgr::GetSubTypes(SwFieldTypesEnum nTypeId, std::vector<OUString>& rToFill)
+{
+ SwWrtShell *pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
+ OSL_ENSURE(pSh, "no SwWrtShell found");
+ if(!pSh)
+ return;
+
+ const sal_uInt16 nPos = GetPos(nTypeId);
+
+ switch(nTypeId)
+ {
+ case SwFieldTypesEnum::SetRef:
+ case SwFieldTypesEnum::GetRef:
+ {
+ // references are no fields
+ pSh->GetRefMarks( &rToFill );
+ break;
+ }
+ case SwFieldTypesEnum::Macro:
+ {
+ break;
+ }
+ case SwFieldTypesEnum::Input:
+ {
+ rToFill.push_back(SwResId(aSwFields[nPos].pSubTypeResIds[0]));
+ [[fallthrough]]; // move on at generic types
+ }
+ case SwFieldTypesEnum::DDE:
+ case SwFieldTypesEnum::Sequence:
+ case SwFieldTypesEnum::Formel:
+ case SwFieldTypesEnum::Get:
+ case SwFieldTypesEnum::Set:
+ case SwFieldTypesEnum::User:
+ {
+
+ const size_t nCount = pSh->GetFieldTypeCount();
+ for(size_t i = 0; i < nCount; ++i)
+ {
+ SwFieldType* pFieldType = pSh->GetFieldType( i );
+ const SwFieldIds nWhich = pFieldType->Which();
+
+ if((nTypeId == SwFieldTypesEnum::DDE && pFieldType->Which() == SwFieldIds::Dde) ||
+
+ (nTypeId == SwFieldTypesEnum::User && nWhich == SwFieldIds::User) ||
+
+ (nTypeId == SwFieldTypesEnum::Get && nWhich == SwFieldIds::SetExp &&
+ !(static_cast<SwSetExpFieldType*>(pFieldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) ||
+
+ (nTypeId == SwFieldTypesEnum::Set && nWhich == SwFieldIds::SetExp &&
+ !(static_cast<SwSetExpFieldType*>(pFieldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) ||
+
+ (nTypeId == SwFieldTypesEnum::Sequence && nWhich == SwFieldIds::SetExp &&
+ (static_cast<SwSetExpFieldType*>(pFieldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) ||
+
+ ((nTypeId == SwFieldTypesEnum::Input || nTypeId == SwFieldTypesEnum::Formel) &&
+ (nWhich == SwFieldIds::User ||
+ (nWhich == SwFieldIds::SetExp &&
+ !(static_cast<SwSetExpFieldType*>(pFieldType)->GetType() & nsSwGetSetExpType::GSE_SEQ))) ) )
+ {
+ rToFill.push_back(pFieldType->GetName());
+ }
+ }
+ break;
+ }
+ case SwFieldTypesEnum::DatabaseNextSet:
+ case SwFieldTypesEnum::DatabaseNumberSet:
+ case SwFieldTypesEnum::DatabaseName:
+ case SwFieldTypesEnum::DatabaseSetNumber:
+ break;
+
+ default:
+ {
+ // static SubTypes
+ if(nPos != USHRT_MAX)
+ {
+ sal_uInt16 nCount;
+ if (nTypeId == SwFieldTypesEnum::DocumentInfo)
+ nCount = DI_SUBTYPE_END - DI_SUBTYPE_BEGIN;
+ else
+ nCount = aSwFields[nPos].nSubTypeLength;
+
+ for(sal_uInt16 i = 0; i < nCount; ++i)
+ {
+ OUString sNew;
+ if (nTypeId == SwFieldTypesEnum::DocumentInfo)
+ {
+ if ( i == DI_CUSTOM )
+ sNew = SwResId(STR_CUSTOM_FIELD);
+ else
+ sNew = SwViewShell::GetShellRes()->aDocInfoLst[i];
+ }
+ else
+ sNew = SwResId(aSwFields[nPos].pSubTypeResIds[i]);
+
+ rToFill.push_back(sNew);
+ }
+ }
+ }
+ }
+}
+
+// determine format
+// ACCESS over TYP_...
+sal_uInt16 SwFieldMgr::GetFormatCount(SwFieldTypesEnum nTypeId, bool bHtmlMode) const
+{
+ assert(nTypeId < SwFieldTypesEnum::LAST && "forbidden TypeId");
+ {
+ const sal_uInt16 nPos = GetPos(nTypeId);
+
+ if (nPos == USHRT_MAX || (bHtmlMode && nTypeId == SwFieldTypesEnum::Set))
+ return 0;
+
+ sal_uInt16 nCount = aSwFields[nPos].nFormatLength;
+
+ if (nTypeId == SwFieldTypesEnum::Filename)
+ nCount -= 2; // no range or template
+
+ const TranslateId* pStart = aSwFields[nPos].pFormatResIds;
+ if (!pStart)
+ return nCount;
+
+ if (*pStart == FMT_GETVAR_ARY[0] || *pStart == FMT_SETVAR_ARY[0])
+ return VF_COUNT;
+ else if (*pStart == FMT_USERVAR_ARY[0])
+ return VF_USR_COUNT;
+ else if (*pStart == FMT_DBFLD_ARY[0])
+ return VF_DB_COUNT;
+ else if (*pStart == FMT_NUM_ARY[0])
+ {
+ GetNumberingInfo();
+ if(m_xNumberingInfo.is())
+ {
+ const Sequence<sal_Int16> aTypes = m_xNumberingInfo->getSupportedNumberingTypes();
+ // #i28073# it's not necessarily a sorted sequence
+ //skip all values below or equal to CHARS_LOWER_LETTER_N
+ nCount += std::count_if(aTypes.begin(), aTypes.end(),
+ [](sal_Int16 nCurrent) { return nCurrent > NumberingType::CHARS_LOWER_LETTER_N; });
+ }
+ return nCount;
+ }
+
+ return nCount;
+ }
+}
+
+// determine FormatString to a type
+OUString SwFieldMgr::GetFormatStr(SwFieldTypesEnum nTypeId, sal_uInt32 nFormatId) const
+{
+ assert(nTypeId < SwFieldTypesEnum::LAST && "forbidden TypeId");
+ const sal_uInt16 nPos = GetPos(nTypeId);
+
+ if (nPos == USHRT_MAX)
+ return OUString();
+
+ const TranslateId* pStart = aSwFields[nPos].pFormatResIds;
+ if (!pStart)
+ return OUString();
+
+ if (SwFieldTypesEnum::Author == nTypeId || SwFieldTypesEnum::Filename == nTypeId)
+ nFormatId &= ~static_cast<sal_uInt32>(FF_FIXED); // mask out Fixed-Flag
+
+ if (nFormatId < aSwFields[nPos].nFormatLength)
+ return SwResId(pStart[nFormatId]);
+
+ OUString aRet;
+ if (*pStart == FMT_NUM_ARY[0])
+ {
+ if (m_xNumberingInfo.is())
+ {
+ const Sequence<sal_Int16> aTypes = m_xNumberingInfo->getSupportedNumberingTypes();
+ sal_Int32 nOffset = aSwFields[nPos].nFormatLength;
+ sal_uInt32 nValidEntry = 0;
+ for (const sal_Int16 nCurrent : aTypes)
+ {
+ if(nCurrent > NumberingType::CHARS_LOWER_LETTER_N &&
+ (nCurrent != (NumberingType::BITMAP | LINK_TOKEN)))
+ {
+ if (nValidEntry == nFormatId - nOffset)
+ {
+ sal_uInt32 n = SvxNumberingTypeTable::FindIndex(nCurrent);
+ if (n != RESARRAY_INDEX_NOTFOUND)
+ {
+ aRet = SvxNumberingTypeTable::GetString(n);
+ }
+ else
+ {
+ aRet = m_xNumberingInfo->getNumberingIdentifier( nCurrent );
+ }
+ break;
+ }
+ ++nValidEntry;
+ }
+ }
+ }
+ }
+
+ return aRet;
+}
+
+// determine FormatId from Pseudo-ID
+sal_uInt16 SwFieldMgr::GetFormatId(SwFieldTypesEnum nTypeId, sal_uInt32 nFormatId) const
+{
+ sal_uInt16 nId = o3tl::narrowing<sal_uInt16>(nFormatId);
+ switch( nTypeId )
+ {
+ case SwFieldTypesEnum::DocumentInfo:
+ {
+ TranslateId sId = aSwFields[GetPos(nTypeId)].pFormatResIds[nFormatId];
+ if (sId == FMT_REG_AUTHOR)
+ nId = DI_SUB_AUTHOR;
+ else if (sId == FMT_REG_TIME)
+ nId = DI_SUB_TIME;
+ else if (sId == FMT_REG_DATE)
+ nId = DI_SUB_DATE;
+ break;
+ }
+ case SwFieldTypesEnum::PageNumber:
+ case SwFieldTypesEnum::NextPage:
+ case SwFieldTypesEnum::PreviousPage:
+ case SwFieldTypesEnum::DocumentStatistics:
+ case SwFieldTypesEnum::DatabaseSetNumber:
+ case SwFieldTypesEnum::Sequence:
+ case SwFieldTypesEnum::GetRefPage:
+ {
+ sal_uInt16 nPos = GetPos(nTypeId);
+ if (nFormatId < aSwFields[nPos].nFormatLength)
+ {
+ const TranslateId sId = aSwFields[nPos].pFormatResIds[nFormatId];
+ if (sId == FMT_NUM_ABC)
+ nId = SVX_NUM_CHARS_UPPER_LETTER;
+ else if (sId == FMT_NUM_SABC)
+ nId = SVX_NUM_CHARS_LOWER_LETTER;
+ else if (sId == FMT_NUM_ROMAN)
+ nId = SVX_NUM_ROMAN_UPPER;
+ else if (sId == FMT_NUM_SROMAN)
+ nId = SVX_NUM_ROMAN_LOWER;
+ else if (sId == FMT_NUM_ARABIC)
+ nId = SVX_NUM_ARABIC;
+ else if (sId == FMT_NUM_PAGEDESC)
+ nId = SVX_NUM_PAGEDESC;
+ else if (sId == FMT_NUM_PAGESPECIAL)
+ nId = SVX_NUM_CHAR_SPECIAL;
+ else if (sId == FMT_NUM_ABC_N)
+ nId = SVX_NUM_CHARS_UPPER_LETTER_N;
+ else if (sId == FMT_NUM_SABC_N)
+ nId = SVX_NUM_CHARS_LOWER_LETTER_N;
+ }
+ else if (m_xNumberingInfo.is())
+ {
+ const Sequence<sal_Int16> aTypes = m_xNumberingInfo->getSupportedNumberingTypes();
+ sal_Int32 nOffset = aSwFields[nPos].nFormatLength;
+ sal_Int32 nValidEntry = 0;
+ for (const sal_Int16 nCurrent : aTypes)
+ {
+ if (nCurrent > NumberingType::CHARS_LOWER_LETTER_N)
+ {
+ if (nValidEntry == static_cast<sal_Int32>(nFormatId) - nOffset)
+ {
+ nId = nCurrent;
+ break;
+ }
+ ++nValidEntry;
+ }
+ }
+ }
+ break;
+ }
+ case SwFieldTypesEnum::DDE:
+ {
+ const TranslateId sId = aSwFields[GetPos(nTypeId)].pFormatResIds[nFormatId];
+ if (sId == FMT_DDE_NORMAL)
+ nId = static_cast<sal_uInt16>(SfxLinkUpdateMode::ONCALL);
+ else if (sId == FMT_DDE_HOT)
+ nId = static_cast<sal_uInt16>(SfxLinkUpdateMode::ALWAYS);
+ break;
+ }
+ default: break;
+ }
+ return nId;
+}
+
+// Traveling
+bool SwFieldMgr::GoNextPrev( bool bNext, SwFieldType* pTyp )
+{
+ SwWrtShell* pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
+ if(!pSh)
+ return false;
+
+ if( !pTyp && m_pCurField )
+ {
+ const SwFieldTypesEnum nTypeId = m_pCurField->GetTypeId();
+ if( SwFieldTypesEnum::SetInput == nTypeId || SwFieldTypesEnum::UserInput == nTypeId )
+ pTyp = pSh->GetFieldType( 0, SwFieldIds::Input );
+ else
+ pTyp = m_pCurField->GetTyp();
+ }
+
+ if (pTyp && pTyp->Which() == SwFieldIds::Database)
+ {
+ // for fieldcommand-edit (hop to all DB fields)
+ return pSh->MoveFieldType( nullptr, bNext, SwFieldIds::Database );
+ }
+
+ return pTyp && pSh->MoveFieldType(pTyp, bNext);
+}
+
+// insert field types
+void SwFieldMgr::InsertFieldType(SwFieldType const & rType)
+{
+ SwWrtShell* pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
+ OSL_ENSURE(pSh, "no SwWrtShell found");
+ if(pSh)
+ pSh->InsertFieldType(rType);
+}
+
+// determine current TypeId
+SwFieldTypesEnum SwFieldMgr::GetCurTypeId() const
+{
+ return m_pCurField ? m_pCurField->GetTypeId() : SwFieldTypesEnum::Unknown;
+}
+
+// Over string insert field or update
+bool SwFieldMgr::InsertField(
+ SwInsertField_Data& rData)
+{
+ std::unique_ptr<SwField> pField;
+ bool bExp = false;
+ bool bTable = false;
+ bool bPageVar = false;
+ sal_uInt32 nFormatId = rData.m_nFormatId;
+ sal_uInt16 nSubType = rData.m_nSubType;
+ sal_Unicode cSeparator = rData.m_cSeparator;
+ SwWrtShell* pCurShell = rData.m_pSh;
+ if(!pCurShell)
+ pCurShell = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
+ OSL_ENSURE(pCurShell, "no SwWrtShell found");
+ if(!pCurShell)
+ return false;
+
+ switch (rData.m_nTypeId)
+ { // ATTENTION this field is inserted by a separate dialog
+ case SwFieldTypesEnum::Postit:
+ {
+ SvtUserOptions aUserOpt;
+ SwPostItFieldType* pType = static_cast<SwPostItFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::Postit));
+ pField.reset(
+ new SwPostItField(
+ pType,
+ rData.m_sPar1, // author
+ rData.m_sPar2, // content
+ aUserOpt.GetID(), // author's initials
+ OUString(), // name
+ DateTime(DateTime::SYSTEM) ));
+ }
+ break;
+ case SwFieldTypesEnum::Script:
+ {
+ SwScriptFieldType* pType =
+ static_cast<SwScriptFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::Script));
+ pField.reset(new SwScriptField(pType, rData.m_sPar1, rData.m_sPar2, static_cast<bool>(nFormatId)));
+ break;
+ }
+
+ case SwFieldTypesEnum::CombinedChars:
+ {
+ SwCombinedCharFieldType* pType = static_cast<SwCombinedCharFieldType*>(
+ pCurShell->GetFieldType( 0, SwFieldIds::CombinedChars ));
+ pField.reset(new SwCombinedCharField( pType, rData.m_sPar1 ));
+ }
+ break;
+
+ case SwFieldTypesEnum::Authority:
+ {
+ SwAuthorityFieldType* pType =
+ static_cast<SwAuthorityFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::TableOfAuthorities));
+ if (!pType)
+ {
+ SwAuthorityFieldType const type(pCurShell->GetDoc());
+ pType = static_cast<SwAuthorityFieldType*>(
+ pCurShell->InsertFieldType(type));
+ }
+ pField.reset(new SwAuthorityField(pType, rData.m_sPar1));
+ }
+ break;
+
+ case SwFieldTypesEnum::Date:
+ case SwFieldTypesEnum::Time:
+ {
+ sal_uInt16 nSub = static_cast< sal_uInt16 >(rData.m_nTypeId == SwFieldTypesEnum::Date ? DATEFLD : TIMEFLD);
+ nSub |= nSubType == DATE_VAR ? 0 : FIXEDFLD;
+
+ SwDateTimeFieldType* pTyp =
+ static_cast<SwDateTimeFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::DateTime) );
+ pField.reset(new SwDateTimeField(pTyp, nSub, nFormatId));
+ pField->SetPar2(rData.m_sPar2);
+ break;
+ }
+
+ case SwFieldTypesEnum::Filename:
+ {
+ SwFileNameFieldType* pTyp =
+ static_cast<SwFileNameFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::Filename) );
+ pField.reset(new SwFileNameField(pTyp, nFormatId));
+ break;
+ }
+
+ case SwFieldTypesEnum::TemplateName:
+ {
+ SwTemplNameFieldType* pTyp =
+ static_cast<SwTemplNameFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::TemplateName) );
+ pField.reset(new SwTemplNameField(pTyp, nFormatId));
+ break;
+ }
+
+ case SwFieldTypesEnum::Chapter:
+ {
+ sal_uInt16 nByte = o3tl::narrowing<sal_uInt16>(rData.m_sPar2.toInt32());
+ SwChapterFieldType* pTyp =
+ static_cast<SwChapterFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::Chapter) );
+ pField.reset(new SwChapterField(pTyp, nFormatId));
+ nByte = std::max(sal_uInt16(1), nByte);
+ nByte = std::min(nByte, sal_uInt16(MAXLEVEL));
+ nByte -= 1;
+ static_cast<SwChapterField*>(pField.get())->SetLevel(static_cast<sal_uInt8>(nByte));
+ break;
+ }
+
+ case SwFieldTypesEnum::NextPage:
+ case SwFieldTypesEnum::PreviousPage:
+ case SwFieldTypesEnum::PageNumber:
+ {
+ short nOff = static_cast<short>(rData.m_sPar2.toInt32());
+
+ if(rData.m_nTypeId == SwFieldTypesEnum::NextPage)
+ {
+ if( SVX_NUM_CHAR_SPECIAL == nFormatId )
+ nOff = 1;
+ else
+ nOff += 1;
+ nSubType = PG_NEXT;
+ }
+ else if(rData.m_nTypeId == SwFieldTypesEnum::PreviousPage)
+ {
+ if( SVX_NUM_CHAR_SPECIAL == nFormatId )
+ nOff = -1;
+ else
+ nOff -= 1;
+ nSubType = PG_PREV;
+ }
+ else
+ nSubType = PG_RANDOM;
+
+ SwPageNumberFieldType* pTyp =
+ static_cast<SwPageNumberFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::PageNumber) );
+ pField.reset(new SwPageNumberField(pTyp, nSubType, nFormatId, nOff));
+
+ if( SVX_NUM_CHAR_SPECIAL == nFormatId &&
+ ( PG_PREV == nSubType || PG_NEXT == nSubType ) )
+ static_cast<SwPageNumberField*>(pField.get())->SetUserString( rData.m_sPar2 );
+ break;
+ }
+
+ case SwFieldTypesEnum::DocumentStatistics:
+ {
+ SwDocStatFieldType* pTyp =
+ static_cast<SwDocStatFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::DocStat) );
+ pField.reset(new SwDocStatField(pTyp, nSubType, nFormatId));
+ break;
+ }
+
+ case SwFieldTypesEnum::Author:
+ {
+ SwAuthorFieldType* pTyp =
+ static_cast<SwAuthorFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::Author) );
+ pField.reset(new SwAuthorField(pTyp, nFormatId));
+ break;
+ }
+
+ case SwFieldTypesEnum::ConditionalText:
+ case SwFieldTypesEnum::HiddenText:
+ {
+ SwHiddenTextFieldType* pTyp =
+ static_cast<SwHiddenTextFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::HiddenText) );
+ pField.reset(new SwHiddenTextField(pTyp, true, rData.m_sPar1, rData.m_sPar2, false, rData.m_nTypeId));
+ bExp = true;
+ break;
+ }
+
+ case SwFieldTypesEnum::HiddenParagraph:
+ {
+ SwHiddenParaFieldType* pTyp =
+ static_cast<SwHiddenParaFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::HiddenPara) );
+ pField.reset(new SwHiddenParaField(pTyp, rData.m_sPar1));
+ bExp = true;
+ break;
+ }
+
+ case SwFieldTypesEnum::SetRef:
+ {
+ if( !rData.m_sPar1.isEmpty() && CanInsertRefMark( rData.m_sPar1 ) )
+ {
+ const OUString& rRefmarkText = rData.m_sPar2;
+ SwPaM* pCursorPos = pCurShell->GetCursor();
+ pCurShell->StartAction();
+ bool bHadMark = pCursorPos->HasMark();
+ // If we have no selection and the refmark text is provided, then the text is
+ // expected to be HTML.
+ if (!bHadMark && !rRefmarkText.isEmpty())
+ {
+ // Split node to remember where the start position is.
+ bool bSuccess = pCurShell->GetDoc()->getIDocumentContentOperations().SplitNode(
+ *pCursorPos->GetPoint(), /*bChkTableStart=*/false);
+ if (bSuccess)
+ {
+ SwPaM aRefmarkPam(*pCursorPos->GetPoint());
+ aRefmarkPam.Move(fnMoveBackward, GoInContent);
+
+ // Paste HTML content.
+ SwTranslateHelper::PasteHTMLToPaM(
+ *pCurShell, pCursorPos, rRefmarkText.toUtf8());
+
+ // Undo the above SplitNode().
+ aRefmarkPam.SetMark();
+ aRefmarkPam.Move(fnMoveForward, GoInContent);
+ pCurShell->GetDoc()->getIDocumentContentOperations().DeleteAndJoin(
+ aRefmarkPam);
+ *aRefmarkPam.GetMark() = *pCursorPos->GetPoint();
+ *pCursorPos = aRefmarkPam;
+ }
+ }
+
+ pCurShell->SetAttrItem( SwFormatRefMark( rData.m_sPar1 ) );
+
+ if (!bHadMark && !rRefmarkText.isEmpty())
+ {
+ pCursorPos->DeleteMark();
+ }
+ pCurShell->EndAction();
+ return true;
+ }
+ return false;
+ }
+
+ case SwFieldTypesEnum::GetRef:
+ {
+ SwGetRefFieldType* pTyp =
+ static_cast<SwGetRefFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::GetRef) );
+
+ sal_uInt16 nSeqNo = 0;
+ sal_uInt16 nFlags = 0;
+
+ if (nSubType == REF_STYLE) nFlags = o3tl::narrowing<sal_uInt16>(rData.m_sPar2.toInt32());
+ else nSeqNo = o3tl::narrowing<sal_uInt16>(rData.m_sPar2.toInt32());
+
+ OUString sReferenceLanguage;
+ // handle language-variant formats
+ if (nFormatId >= SAL_N_ELEMENTS(FMT_REF_ARY))
+ {
+ LanguageType nLang = GetCurrLanguage();
+ if (nLang == LANGUAGE_HUNGARIAN)
+ {
+ if (nFormatId >= SAL_N_ELEMENTS(FMT_REF_ARY) * 2)
+ sReferenceLanguage = "Hu";
+ else
+ sReferenceLanguage = "hu";
+ }
+ nFormatId %= SAL_N_ELEMENTS(FMT_REF_ARY);
+ }
+
+ pField.reset(new SwGetRefField(pTyp, rData.m_sPar1, sReferenceLanguage, nSubType, nSeqNo, nFlags, nFormatId));
+ bExp = true;
+ break;
+ }
+
+ case SwFieldTypesEnum::DDE:
+ {
+ //JP 28.08.95: DDE-Topics/-Items can have blanks in their names!
+ // That's not yet considered here.
+ sal_Int32 nIndex = 0;
+ OUString sCmd = rData.m_sPar2.replaceFirst(" ", OUStringChar(sfx2::cTokenSeparator), &nIndex);
+ if (nIndex>=0 && ++nIndex<sCmd.getLength())
+ {
+ sCmd = sCmd.replaceFirst(" ", OUStringChar(sfx2::cTokenSeparator), &nIndex);
+ }
+
+ SwDDEFieldType aType( rData.m_sPar1, sCmd, static_cast<SfxLinkUpdateMode>(nFormatId) );
+ SwDDEFieldType* pTyp = static_cast<SwDDEFieldType*>( pCurShell->InsertFieldType( aType ) );
+ pField.reset(new SwDDEField( pTyp ));
+ break;
+ }
+
+ case SwFieldTypesEnum::Macro:
+ {
+ SwMacroFieldType* pTyp =
+ static_cast<SwMacroFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::Macro));
+
+ pField.reset(new SwMacroField(pTyp, rData.m_sPar1, rData.m_sPar2));
+
+ break;
+ }
+
+ case SwFieldTypesEnum::Internet:
+ {
+ SwFormatINetFormat aFormat( rData.m_sPar1, m_sCurFrame );
+ return pCurShell->InsertURL( aFormat, rData.m_sPar2 );
+ }
+
+ case SwFieldTypesEnum::JumpEdit:
+ {
+ SwJumpEditFieldType* pTyp =
+ static_cast<SwJumpEditFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::JumpEdit));
+
+ pField.reset(new SwJumpEditField(pTyp, nFormatId, rData.m_sPar1, rData.m_sPar2));
+ break;
+ }
+
+ case SwFieldTypesEnum::DocumentInfo:
+ {
+ SwDocInfoFieldType* pTyp = static_cast<SwDocInfoFieldType*>( pCurShell->GetFieldType(
+ 0, SwFieldIds::DocInfo ) );
+ pField.reset(new SwDocInfoField(pTyp, nSubType, rData.m_sPar1, nFormatId));
+ break;
+ }
+
+ case SwFieldTypesEnum::ExtendedUser:
+ {
+ SwExtUserFieldType* pTyp = static_cast<SwExtUserFieldType*>( pCurShell->GetFieldType(
+ 0, SwFieldIds::ExtUser) );
+ pField.reset(new SwExtUserField(pTyp, nSubType, nFormatId));
+ break;
+ }
+
+ case SwFieldTypesEnum::Database:
+ {
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+ SwDBData aDBData;
+ OUString sPar1;
+
+ if (rData.m_sPar1.indexOf(DB_DELIM)<0)
+ {
+ aDBData = pCurShell->GetDBData();
+ sPar1 = rData.m_sPar1;
+ }
+ else
+ {
+ sal_Int32 nIdx{ 0 };
+ aDBData.sDataSource = rData.m_sPar1.getToken(0, DB_DELIM, nIdx);
+ aDBData.sCommand = rData.m_sPar1.getToken(0, DB_DELIM, nIdx);
+ aDBData.nCommandType = o3tl::toInt32(o3tl::getToken(rData.m_sPar1, 0, DB_DELIM, nIdx));
+ sPar1 = rData.m_sPar1.getToken(0, DB_DELIM, nIdx);
+ }
+
+ if(!aDBData.sDataSource.isEmpty() && pCurShell->GetDBData() != aDBData)
+ pCurShell->ChgDBData(aDBData);
+
+ SwDBFieldType* pTyp = static_cast<SwDBFieldType*>(pCurShell->InsertFieldType(
+ SwDBFieldType(pCurShell->GetDoc(), sPar1, aDBData) ) );
+ pField.reset(new SwDBField(pTyp));
+ pField->SetSubType(nSubType);
+
+ if( !(nSubType & nsSwExtendedSubType::SUB_OWN_FMT) ) // determine database format
+ {
+ Reference< XDataSource> xSource;
+ rData.m_aDBDataSource >>= xSource;
+ Reference<XConnection> xConnection;
+ rData.m_aDBConnection >>= xConnection;
+ Reference<XPropertySet> xColumn;
+ rData.m_aDBColumn >>= xColumn;
+ if(xColumn.is())
+ {
+ nFormatId = SwDBManager::GetColumnFormat(xSource, xConnection, xColumn,
+ pCurShell->GetNumberFormatter(), GetCurrLanguage() );
+ }
+ else
+ nFormatId = pCurShell->GetDBManager()->GetColumnFormat(
+ aDBData.sDataSource, aDBData.sCommand, sPar1,
+ pCurShell->GetNumberFormatter(), GetCurrLanguage() );
+ }
+ pField->ChangeFormat( nFormatId );
+
+ bExp = true;
+#endif
+ break;
+ }
+
+ case SwFieldTypesEnum::DatabaseSetNumber:
+ case SwFieldTypesEnum::DatabaseNumberSet:
+ case SwFieldTypesEnum::DatabaseNextSet:
+ case SwFieldTypesEnum::DatabaseName:
+ {
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+ SwDBData aDBData;
+
+ // extract DBName from rData.m_sPar1. Format: DBName.TableName.CommandType.ExpStrg
+ sal_Int32 nTablePos = rData.m_sPar1.indexOf(DB_DELIM);
+ sal_Int32 nExpPos = -1;
+
+ if (nTablePos>=0)
+ {
+ aDBData.sDataSource = rData.m_sPar1.copy(0, nTablePos++);
+ sal_Int32 nCmdTypePos = rData.m_sPar1.indexOf(DB_DELIM, nTablePos);
+ if (nCmdTypePos>=0)
+ {
+ aDBData.sCommand = rData.m_sPar1.copy(nTablePos, nCmdTypePos++ - nTablePos);
+ nExpPos = rData.m_sPar1.indexOf(DB_DELIM, nCmdTypePos);
+ if (nExpPos>=0)
+ {
+ aDBData.nCommandType = o3tl::toInt32(rData.m_sPar1.subView(nCmdTypePos, nExpPos++ - nCmdTypePos));
+ }
+ }
+ }
+
+ sal_Int32 nPos = 0;
+ if (nExpPos>=0)
+ nPos = nExpPos;
+ else if (nTablePos>=0)
+ nPos = nTablePos;
+
+ OUString sPar1 = rData.m_sPar1.copy(nPos);
+
+ if (!aDBData.sDataSource.isEmpty() && pCurShell->GetDBData() != aDBData)
+ pCurShell->ChgDBData(aDBData);
+
+ switch(rData.m_nTypeId)
+ {
+ case SwFieldTypesEnum::DatabaseName:
+ {
+ SwDBNameFieldType* pTyp =
+ static_cast<SwDBNameFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::DatabaseName));
+ pField.reset(new SwDBNameField(pTyp, aDBData));
+
+ break;
+ }
+ case SwFieldTypesEnum::DatabaseNextSet:
+ {
+ SwDBNextSetFieldType* pTyp = static_cast<SwDBNextSetFieldType*>(pCurShell->GetFieldType(
+ 0, SwFieldIds::DbNextSet) );
+ pField.reset(new SwDBNextSetField(pTyp, sPar1, aDBData));
+ bExp = true;
+ break;
+ }
+ case SwFieldTypesEnum::DatabaseNumberSet:
+ {
+ SwDBNumSetFieldType* pTyp = static_cast<SwDBNumSetFieldType*>( pCurShell->GetFieldType(
+ 0, SwFieldIds::DbNumSet) );
+ pField.reset(new SwDBNumSetField( pTyp, sPar1, rData.m_sPar2, aDBData));
+ bExp = true;
+ break;
+ }
+ case SwFieldTypesEnum::DatabaseSetNumber:
+ {
+ SwDBSetNumberFieldType* pTyp = static_cast<SwDBSetNumberFieldType*>(
+ pCurShell->GetFieldType(0, SwFieldIds::DbSetNumber) );
+ pField.reset(new SwDBSetNumberField( pTyp, aDBData, nFormatId));
+ bExp = true;
+ break;
+ }
+ default: break;
+ }
+#endif
+ break;
+ }
+
+ case SwFieldTypesEnum::User:
+ {
+ SwUserFieldType* pTyp =
+ static_cast<SwUserFieldType*>( pCurShell->GetFieldType(SwFieldIds::User, rData.m_sPar1) );
+
+ // only if existing
+ if(!pTyp)
+ {
+ pTyp = static_cast<SwUserFieldType*>( pCurShell->InsertFieldType(
+ SwUserFieldType(pCurShell->GetDoc(), rData.m_sPar1)) );
+ }
+ if (pTyp->GetContent(nFormatId) != rData.m_sPar2)
+ pTyp->SetContent(rData.m_sPar2, nFormatId);
+ pField.reset(new SwUserField(pTyp, 0, nFormatId));
+ if (pField->GetSubType() != nSubType)
+ pField->SetSubType(nSubType);
+ bTable = true;
+ break;
+ }
+
+ case SwFieldTypesEnum::Input:
+ {
+ if ((nSubType & 0x00ff) == INP_VAR)
+ {
+ SwSetExpFieldType* pTyp = static_cast<SwSetExpFieldType*>(
+ pCurShell->GetFieldType(SwFieldIds::SetExp, rData.m_sPar1) );
+
+ // no Expression Type with this name existing -> create
+ if(pTyp)
+ {
+ std::unique_ptr<SwSetExpField> pExpField(
+ new SwSetExpField(pTyp, OUString(), nFormatId));
+
+ // Don't change type of SwSetExpFieldType:
+ sal_uInt16 nOldSubType = pExpField->GetSubType();
+ pExpField->SetSubType(nOldSubType | (nSubType & 0xff00));
+
+ pExpField->SetPromptText(rData.m_sPar2);
+ pExpField->SetInputFlag(true) ;
+ bExp = true;
+ pField = std::move(pExpField);
+ }
+ else
+ return false;
+ }
+ else
+ {
+ SwInputFieldType* pTyp =
+ static_cast<SwInputFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::Input) );
+
+ pField.reset(
+ new SwInputField( pTyp, rData.m_sPar1, rData.m_sPar2, nSubType|nsSwExtendedSubType::SUB_INVISIBLE, nFormatId));
+ }
+ break;
+ }
+
+ case SwFieldTypesEnum::Set:
+ {
+ if (rData.m_sPar2.isEmpty()) // empty variables are not allowed
+ return false;
+
+ SwSetExpFieldType* pTyp = static_cast<SwSetExpFieldType*>( pCurShell->InsertFieldType(
+ SwSetExpFieldType(pCurShell->GetDoc(), rData.m_sPar1) ) );
+
+ std::unique_ptr<SwSetExpField> pExpField(new SwSetExpField( pTyp, rData.m_sPar2, nFormatId));
+ pExpField->SetSubType(nSubType);
+ pExpField->SetPar2(rData.m_sPar2);
+ bExp = true;
+ pField = std::move(pExpField);
+ break;
+ }
+
+ case SwFieldTypesEnum::Sequence:
+ {
+ SwSetExpFieldType* pTyp = static_cast<SwSetExpFieldType*>( pCurShell->InsertFieldType(
+ SwSetExpFieldType(pCurShell->GetDoc(), rData.m_sPar1, nsSwGetSetExpType::GSE_SEQ)));
+
+ sal_uInt8 nLevel = static_cast< sal_uInt8 >(nSubType & 0xff);
+
+ pTyp->SetOutlineLvl(nLevel);
+ if (nLevel != 0x7f && cSeparator == 0)
+ cSeparator = '.';
+
+ pTyp->SetDelimiter(OUString(cSeparator));
+ pField.reset(new SwSetExpField(pTyp, rData.m_sPar2, nFormatId));
+ bExp = true;
+ break;
+ }
+
+ case SwFieldTypesEnum::Get:
+ {
+ // is there a corresponding SetField
+ SwSetExpFieldType* pSetTyp = static_cast<SwSetExpFieldType*>(
+ pCurShell->GetFieldType(SwFieldIds::SetExp, rData.m_sPar1));
+
+ if(pSetTyp)
+ {
+ SwGetExpFieldType* pTyp = static_cast<SwGetExpFieldType*>( pCurShell->GetFieldType(
+ 0, SwFieldIds::GetExp) );
+ pField.reset( new SwGetExpField(pTyp, rData.m_sPar1, pSetTyp->GetType(), nFormatId) );
+ pField->SetSubType(nSubType | pSetTyp->GetType());
+ bExp = true;
+ }
+ else
+ return false;
+ break;
+ }
+
+ case SwFieldTypesEnum::Formel:
+ {
+ if(pCurShell->GetFrameType(nullptr,false) & FrameTypeFlags::TABLE)
+ {
+ pCurShell->StartAllAction();
+
+ SvNumberFormatter* pFormatter = pCurShell->GetDoc()->GetNumberFormatter();
+ const SvNumberformat* pEntry = pFormatter->GetEntry(nFormatId);
+
+ if (pEntry)
+ {
+ SfxStringItem aFormat(FN_NUMBER_FORMAT, pEntry->GetFormatstring());
+ pCurShell->GetView().GetViewFrame().GetDispatcher()->
+ ExecuteList(FN_NUMBER_FORMAT, SfxCallMode::SYNCHRON,
+ { &aFormat });
+ }
+
+ SfxItemSetFixed<RES_BOXATR_FORMULA, RES_BOXATR_FORMULA> aBoxSet( pCurShell->GetAttrPool() );
+
+ OUString sFormula(comphelper::string::stripStart(rData.m_sPar2, ' '));
+ if ( sFormula.startsWith("=") )
+ {
+ sFormula = sFormula.copy(1);
+ }
+
+ aBoxSet.Put( SwTableBoxFormula( sFormula ));
+ pCurShell->SetTableBoxFormulaAttrs( aBoxSet );
+ pCurShell->UpdateTable();
+
+ pCurShell->EndAllAction();
+ return true;
+
+ }
+ else
+ {
+ SwGetExpFieldType* pTyp = static_cast<SwGetExpFieldType*>(
+ pCurShell->GetFieldType(0, SwFieldIds::GetExp) );
+ pField.reset( new SwGetExpField(pTyp, rData.m_sPar2, nsSwGetSetExpType::GSE_FORMULA, nFormatId) );
+ pField->SetSubType(nSubType);
+ bExp = true;
+ }
+ break;
+ }
+ case SwFieldTypesEnum::SetRefPage:
+ pField.reset( new SwRefPageSetField( static_cast<SwRefPageSetFieldType*>(
+ pCurShell->GetFieldType( 0, SwFieldIds::RefPageSet ) ),
+ static_cast<short>(rData.m_sPar2.toInt32()), 0 != nSubType ) );
+ bPageVar = true;
+ break;
+
+ case SwFieldTypesEnum::GetRefPage:
+ pField.reset( new SwRefPageGetField( static_cast<SwRefPageGetFieldType*>(
+ pCurShell->GetFieldType( 0, SwFieldIds::RefPageGet ) ), nFormatId ) );
+ bPageVar = true;
+ break;
+ case SwFieldTypesEnum::Dropdown :
+ {
+ pField.reset( new SwDropDownField(pCurShell->GetFieldType( 0, SwFieldIds::Dropdown )) );
+ const sal_Int32 nTokenCount = comphelper::string::getTokenCount(rData.m_sPar2, DB_DELIM);
+ Sequence<OUString> aEntries(nTokenCount);
+ OUString* pArray = aEntries.getArray();
+ for(sal_Int32 nToken = 0, nIdx = 0; nToken < nTokenCount; nToken++)
+ pArray[nToken] = rData.m_sPar2.getToken(0, DB_DELIM, nIdx);
+ static_cast<SwDropDownField*>(pField.get())->SetItems(aEntries);
+ static_cast<SwDropDownField*>(pField.get())->SetName(rData.m_sPar1);
+ }
+ break;
+
+ // Insert Paragraph Signature field by signing the paragraph.
+ // The resulting field is really a metadata field, created and added via signing.
+ case SwFieldTypesEnum::ParagraphSignature:
+ pCurShell->SignParagraph();
+ return true;
+
+ default:
+ { OSL_ENSURE(false, "wrong field type");
+ return false;
+ }
+ }
+ OSL_ENSURE(pField, "field not available");
+
+ //the auto language flag has to be set prior to the language!
+ pField->SetAutomaticLanguage(rData.m_bIsAutomaticLanguage);
+ LanguageType nLang = GetCurrLanguage();
+ pField->SetLanguage(nLang);
+
+ // insert
+ pCurShell->StartAllAction();
+
+ bool const isSuccess = pCurShell->InsertField2(*pField, rData.m_oAnnotationRange ? &*rData.m_oAnnotationRange : nullptr);
+
+ if (isSuccess)
+ {
+ if (SwFieldTypesEnum::Input == rData.m_nTypeId)
+ {
+ pCurShell->Push();
+
+ // start dialog, not before the field is inserted tdf#99529
+ pCurShell->Left(SwCursorSkipMode::Chars, false,
+ (INP_VAR == (nSubType & 0xff) || pCurShell->GetViewOptions()->IsFieldName()) ? 1 : 2,
+ false);
+ pCurShell->StartInputFieldDlg(pField.get(), false, true, rData.m_pParent);
+
+ pCurShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
+ }
+
+ if (bExp && m_bEvalExp)
+ {
+ pCurShell->UpdateExpFields(true);
+ }
+
+ if (bTable)
+ {
+ pCurShell->Left(SwCursorSkipMode::Chars, false, 1, false );
+ pCurShell->UpdateOneField(*pField);
+ pCurShell->Right(SwCursorSkipMode::Chars, false, 1, false );
+ }
+ else if (bPageVar)
+ {
+ static_cast<SwRefPageGetFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::RefPageGet))->UpdateFields();
+ }
+ else if (SwFieldTypesEnum::GetRef == rData.m_nTypeId)
+ {
+ pField->GetTyp()->UpdateFields();
+ }
+ }
+
+ // delete temporary field
+ pField.reset();
+
+ pCurShell->EndAllAction();
+ return isSuccess;
+}
+
+// fields update
+void SwFieldMgr::UpdateCurField(sal_uInt32 nFormat,
+ const OUString& rPar1,
+ const OUString& rPar2,
+ std::unique_ptr<SwField> pTmpField)
+{
+ // change format
+ OSL_ENSURE(m_pCurField, "no field at CursorPos");
+
+ if (!pTmpField)
+ pTmpField = m_pCurField->CopyField();
+
+ SwFieldType* pType = pTmpField->GetTyp();
+ const SwFieldTypesEnum nTypeId = pTmpField->GetTypeId();
+
+ SwWrtShell* pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
+ OSL_ENSURE(pSh, "no SwWrtShell found");
+ if(!pSh)
+ return;
+ pSh->StartAllAction();
+
+ bool bSetPar2 = true;
+ bool bSetPar1 = true;
+ OUString sPar2( rPar2 );
+
+ // Order to Format
+ switch( nTypeId )
+ {
+ case SwFieldTypesEnum::DDE:
+ {
+ // DDE-Topics/-Items can have blanks in their names!
+ // That's not yet considered here!
+ sal_Int32 nIndex = 0;
+ sPar2 = sPar2.replaceFirst(" ", OUStringChar(sfx2::cTokenSeparator), &nIndex );
+ if (nIndex>=0 && ++nIndex<sPar2.getLength())
+ {
+ sPar2 = sPar2.replaceFirst(" ", OUStringChar(sfx2::cTokenSeparator), &nIndex);
+ }
+ break;
+ }
+
+ case SwFieldTypesEnum::Chapter:
+ {
+ sal_uInt16 nByte = o3tl::narrowing<sal_uInt16>(rPar2.toInt32());
+ nByte = std::max(sal_uInt16(1), nByte);
+ nByte = std::min(nByte, sal_uInt16(MAXLEVEL));
+ nByte -= 1;
+ static_cast<SwChapterField*>(pTmpField.get())->SetLevel(static_cast<sal_uInt8>(nByte));
+ bSetPar2 = false;
+ break;
+ }
+
+ case SwFieldTypesEnum::Script:
+ static_cast<SwScriptField*>(pTmpField.get())->SetCodeURL(static_cast<bool>(nFormat));
+ break;
+
+ case SwFieldTypesEnum::NextPage:
+ if( SVX_NUM_CHAR_SPECIAL == nFormat )
+ {
+ static_cast<SwPageNumberField*>(m_pCurField)->SetUserString( sPar2 );
+ sPar2 = "1";
+ }
+ else
+ {
+ if( nFormat + 2 == SVX_NUM_PAGEDESC )
+ nFormat = SVX_NUM_PAGEDESC;
+ short nOff = static_cast<short>(sPar2.toInt32());
+ nOff += 1;
+ sPar2 = OUString::number(nOff);
+ }
+ break;
+
+ case SwFieldTypesEnum::PreviousPage:
+ if( SVX_NUM_CHAR_SPECIAL == nFormat )
+ {
+ static_cast<SwPageNumberField*>(m_pCurField)->SetUserString( sPar2 );
+ sPar2 = "-1";
+ }
+ else
+ {
+ if( nFormat + 2 == SVX_NUM_PAGEDESC )
+ nFormat = SVX_NUM_PAGEDESC;
+ short nOff = static_cast<short>(sPar2.toInt32());
+ nOff -= 1;
+ sPar2 = OUString::number(nOff);
+ }
+ break;
+
+ case SwFieldTypesEnum::PageNumber:
+ case SwFieldTypesEnum::GetRefPage:
+ if( nFormat + 2 == SVX_NUM_PAGEDESC )
+ nFormat = SVX_NUM_PAGEDESC;
+ break;
+
+ case SwFieldTypesEnum::GetRef:
+ {
+ bSetPar2 = false;
+ sal_Int16 nSubType = o3tl::narrowing<sal_uInt16>(rPar2.toInt32());
+ static_cast<SwGetRefField*>(pTmpField.get())->SetSubType( nSubType );
+ const sal_Int32 nPos = rPar2.indexOf( '|' );
+ if( nPos>=0 )
+ switch (nSubType) {
+ case REF_STYLE:
+ static_cast<SwGetRefField*>(pTmpField.get())->SetFlags( o3tl::narrowing<sal_uInt16>(o3tl::toInt32(rPar2.subView( nPos + 1 ))));
+ break;
+ default:
+ static_cast<SwGetRefField*>(pTmpField.get())->SetSeqNo( o3tl::narrowing<sal_uInt16>(o3tl::toInt32(rPar2.subView( nPos + 1 ))));
+ }
+ }
+ break;
+ case SwFieldTypesEnum::Dropdown:
+ {
+ sal_Int32 nTokenCount = comphelper::string::getTokenCount(sPar2, DB_DELIM);
+ Sequence<OUString> aEntries(nTokenCount);
+ OUString* pArray = aEntries.getArray();
+ for(sal_Int32 nToken = 0, nIdx = 0; nToken < nTokenCount; nToken++)
+ pArray[nToken] = sPar2.getToken(0, DB_DELIM, nIdx);
+ static_cast<SwDropDownField*>(pTmpField.get())->SetItems(aEntries);
+ static_cast<SwDropDownField*>(pTmpField.get())->SetName(rPar1);
+ bSetPar1 = bSetPar2 = false;
+ }
+ break;
+ case SwFieldTypesEnum::Authority :
+ {
+ //#i99069# changes to a bibliography field should change the field type
+ SwAuthorityField* pAuthorityField = static_cast<SwAuthorityField*>(pTmpField.get());
+ SwAuthorityFieldType* pAuthorityType = static_cast<SwAuthorityFieldType*>(pType);
+ rtl::Reference<SwAuthEntry> xTempEntry(new SwAuthEntry);
+ for( sal_Int32 i = 0, nIdx = 0; i < AUTH_FIELD_END; ++i )
+ xTempEntry->SetAuthorField( static_cast<ToxAuthorityField>(i),
+ rPar1.getToken( 0, TOX_STYLE_DELIMITER, nIdx ));
+
+ // If just the page number of the URL changed, then update the current field and not
+ // others.
+ bool bEquivalent = true;
+ for (int i = 0; i < AUTH_FIELD_END; ++i)
+ {
+ auto eField = static_cast<ToxAuthorityField>(i);
+ if (eField == AUTH_FIELD_URL)
+ {
+ if (SwTOXAuthority::GetSourceURL(xTempEntry->GetAuthorField(AUTH_FIELD_URL))
+ != SwTOXAuthority::GetSourceURL(
+ pAuthorityField->GetFieldText(AUTH_FIELD_URL)))
+ {
+ bEquivalent = false;
+ break;
+ }
+ }
+ else
+ {
+ if (xTempEntry->GetAuthorField(eField) != pAuthorityField->GetFieldText(eField))
+ {
+ bEquivalent = false;
+ break;
+ }
+ }
+ }
+
+ if (bEquivalent)
+ {
+ break;
+ }
+
+ if( pAuthorityType->ChangeEntryContent( xTempEntry.get() ) )
+ {
+ pType->UpdateFields();
+ pSh->SetModified();
+ }
+
+ if( xTempEntry->GetAuthorField( AUTH_FIELD_IDENTIFIER ) ==
+ pAuthorityField->GetFieldText( AUTH_FIELD_IDENTIFIER ) )
+ bSetPar1 = false; //otherwise it's a new or changed entry, the field needs to be updated
+ bSetPar2 = false;
+ }
+ break;
+ default: break;
+ }
+
+ // set format
+ // setup format before SetPar2 because of NumberFormatter!
+ pTmpField->ChangeFormat(nFormat);
+
+ if( bSetPar1 )
+ pTmpField->SetPar1( rPar1 );
+ if( bSetPar2 )
+ pTmpField->SetPar2( sPar2 );
+
+ // kick off update
+ if(nTypeId == SwFieldTypesEnum::DDE ||
+ nTypeId == SwFieldTypesEnum::User ||
+ nTypeId == SwFieldTypesEnum::UserInput)
+ {
+ pType->UpdateFields();
+ pSh->SetModified();
+ }
+ else {
+ // mb: #32157
+ pSh->SwEditShell::UpdateOneField(*pTmpField);
+ GetCurField();
+ }
+
+ pTmpField.reset();
+
+ pSh->EndAllAction();
+}
+
+// explicitly evaluate ExpressionFields
+void SwFieldMgr::EvalExpFields(SwWrtShell* pSh)
+{
+ if (pSh == nullptr)
+ pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
+
+ if(pSh)
+ {
+ pSh->StartAllAction();
+ pSh->UpdateExpFields(true);
+ pSh->EndAllAction();
+ }
+}
+LanguageType SwFieldMgr::GetCurrLanguage() const
+{
+ SwWrtShell* pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
+ if( pSh )
+ return pSh->GetCurLang();
+ return SvtSysLocale().GetLanguageTag().getLanguageType();
+}
+
+void SwFieldType::GetFieldName_()
+{
+ static const TranslateId coFieldNms[] =
+ {
+ FLD_DATE_STD,
+ FLD_TIME_STD,
+ STR_FILENAMEFLD,
+ STR_DBNAMEFLD,
+ STR_CHAPTERFLD,
+ STR_PAGENUMBERFLD,
+ STR_DOCSTATFLD,
+ STR_AUTHORFLD,
+ STR_SETFLD,
+ STR_GETFLD,
+ STR_FORMELFLD,
+ STR_HIDDENTXTFLD,
+ STR_SETREFFLD,
+ STR_GETREFFLD,
+ STR_DDEFLD,
+ STR_MACROFLD,
+ STR_INPUTFLD,
+ STR_HIDDENPARAFLD,
+ STR_DOCINFOFLD,
+ STR_DBFLD,
+ STR_USERFLD,
+ STR_POSTITFLD,
+ STR_TEMPLNAMEFLD,
+ STR_SEQFLD,
+ STR_DBNEXTSETFLD,
+ STR_DBNUMSETFLD,
+ STR_DBSETNUMBERFLD,
+ STR_CONDTXTFLD,
+ STR_NEXTPAGEFLD,
+ STR_PREVPAGEFLD,
+ STR_EXTUSERFLD,
+ FLD_DATE_FIX,
+ FLD_TIME_FIX,
+ STR_SETINPUTFLD,
+ STR_USRINPUTFLD,
+ STR_SETREFPAGEFLD,
+ STR_GETREFPAGEFLD,
+ STR_INTERNETFLD,
+ STR_JUMPEDITFLD,
+ STR_SCRIPTFLD,
+ STR_AUTHORITY,
+ STR_COMBINED_CHARS,
+ STR_DROPDOWN,
+ STR_CUSTOM_FIELD,
+ STR_PARAGRAPH_SIGNATURE
+ };
+
+ // insert infos for fields
+ SwFieldType::s_pFieldNames = new std::vector<OUString>;
+ SwFieldType::s_pFieldNames->reserve(SAL_N_ELEMENTS(coFieldNms));
+ for (const TranslateId & id : coFieldNms)
+ {
+ const OUString aTmp(SwResId(id));
+ SwFieldType::s_pFieldNames->push_back(MnemonicGenerator::EraseAllMnemonicChars( aTmp ));
+ }
+}
+
+bool SwFieldMgr::ChooseMacro(weld::Window* pDialogParent)
+{
+ bool bRet = false;
+
+ // choose script dialog
+ OUString aScriptURL = SfxApplication::ChooseScript(pDialogParent);
+
+ // the script selector dialog returns a valid script URL
+ if ( !aScriptURL.isEmpty() )
+ {
+ SetMacroPath( aScriptURL );
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+void SwFieldMgr::SetMacroPath(const OUString& rPath)
+{
+ m_sMacroPath = rPath;
+ m_sMacroName = rPath;
+
+ // try to set sMacroName member variable by parsing the macro path
+ // using the new URI parsing services
+
+ Reference< XComponentContext > xContext =
+ ::comphelper::getProcessComponentContext();
+
+ Reference< uri::XUriReferenceFactory >
+ xFactory = uri::UriReferenceFactory::create( xContext );
+
+ Reference< uri::XVndSunStarScriptUrl >
+ xUrl( xFactory->parse( m_sMacroPath ), UNO_QUERY );
+
+ if ( xUrl.is() )
+ {
+ m_sMacroName = xUrl->getName();
+ }
+}
+
+sal_uInt32 SwFieldMgr::GetDefaultFormat(SwFieldTypesEnum nTypeId, bool bIsText, SvNumberFormatter* pFormatter)
+{
+ SvNumFormatType nDefFormat;
+
+ switch (nTypeId)
+ {
+ case SwFieldTypesEnum::Time:
+ case SwFieldTypesEnum::Date:
+ {
+ nDefFormat = (nTypeId == SwFieldTypesEnum::Date) ? SvNumFormatType::DATE : SvNumFormatType::TIME;
+ }
+ break;
+
+ default:
+ if (bIsText)
+ {
+ nDefFormat = SvNumFormatType::TEXT;
+ }
+ else
+ {
+ nDefFormat = SvNumFormatType::ALL;
+ }
+ break;
+ }
+
+ return pFormatter->GetStandardFormat(nDefFormat, GetCurrLanguage());
+}
+
+Reference<XNumberingTypeInfo> const & SwFieldMgr::GetNumberingInfo() const
+{
+ if(!m_xNumberingInfo.is())
+ {
+ Reference<XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
+ Reference<XDefaultNumberingProvider> xDefNum = text::DefaultNumberingProvider::create(xContext);
+ const_cast<SwFieldMgr*>(this)->m_xNumberingInfo.set(xDefNum, UNO_QUERY);
+ }
+ return m_xNumberingInfo;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/fldui/fldwrap.cxx b/sw/source/uibase/fldui/fldwrap.cxx
new file mode 100644
index 0000000000..7ee3078a23
--- /dev/null
+++ b/sw/source/uibase/fldui/fldwrap.cxx
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cmdid.h>
+#include <sfx2/basedlgs.hxx>
+#include <docsh.hxx>
+#include <fldwrap.hxx>
+
+#include <swabstdlg.hxx>
+
+SFX_IMPL_CHILDWINDOW_WITHID(SwFieldDlgWrapper, FN_INSERT_FIELD)
+
+SwChildWinWrapper::SwChildWinWrapper(vcl::Window *pParentWindow, sal_uInt16 nId) :
+ SfxChildWindow(pParentWindow, nId),
+ m_aUpdateTimer("SwChildWinWrapper m_aUpdateTimer"),
+ m_pDocSh(nullptr)
+{
+ // avoid flickering of buttons:
+ m_aUpdateTimer.SetTimeout(200);
+ m_aUpdateTimer.SetInvokeHandler(LINK(this, SwChildWinWrapper, UpdateHdl));
+}
+
+IMPL_LINK_NOARG(SwChildWinWrapper, UpdateHdl, Timer *, void)
+{
+ if (GetController())
+ GetController()->Activate(); // update dialog
+}
+
+// newly initialise dialog after Doc switch
+bool SwChildWinWrapper::ReInitDlg(SwDocShell *)
+{
+ bool bRet = false;
+
+ if (m_pDocSh != GetOldDocShell())
+ {
+ m_aUpdateTimer.Stop();
+ bRet = true; // immediate Update
+ }
+ else
+ m_aUpdateTimer.Start();
+
+ return bRet;
+}
+
+SfxChildWinInfo SwFieldDlgWrapper::GetInfo() const
+{
+ SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
+ return aInfo;
+}
+
+SwFieldDlgWrapper::SwFieldDlgWrapper( vcl::Window* _pParent, sal_uInt16 nId,
+ SfxBindings* pB,
+ SfxChildWinInfo* )
+ : SwChildWinWrapper( _pParent, nId )
+{
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ m_pDlgInterface = pFact->CreateSwFieldDlg(pB, this, _pParent->GetFrameWeld());
+ SetController(m_pDlgInterface->GetController());
+ m_pDlgInterface->StartExecuteAsync(nullptr);
+}
+
+// newly initialise dialog after Doc switch
+bool SwFieldDlgWrapper::ReInitDlg(SwDocShell *pDocSh)
+{
+ bool bRet = SwChildWinWrapper::ReInitDlg(pDocSh);
+ if (bRet) // update immediately, Doc switch
+ {
+ m_pDlgInterface->ReInitDlg();
+ }
+
+ return bRet;
+}
+
+void SwFieldDlgWrapper::ShowReferencePage()
+{
+ m_pDlgInterface->ShowReferencePage();
+}
+
+SFX_IMPL_CHILDWINDOW(SwFieldDataOnlyDlgWrapper, FN_INSERT_FIELD_DATA_ONLY)
+
+SfxChildWinInfo SwFieldDataOnlyDlgWrapper::GetInfo() const
+{
+ SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
+// prevent instantiation of dialog other than by calling
+// the mail merge dialog
+ aInfo.bVisible = false;
+ return aInfo;
+}
+
+SwFieldDataOnlyDlgWrapper::SwFieldDataOnlyDlgWrapper( vcl::Window* _pParent, sal_uInt16 nId,
+ SfxBindings* pB,
+ SfxChildWinInfo* pInfo )
+ : SwChildWinWrapper( _pParent, nId )
+{
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ m_pDlgInterface = pFact->CreateSwFieldDlg(pB, this, _pParent->GetFrameWeld());
+
+ SetController(m_pDlgInterface->GetController());
+ m_pDlgInterface->ActivateDatabasePage();
+ m_pDlgInterface->StartExecuteAsync(nullptr);
+ m_pDlgInterface->Initialize( pInfo );
+}
+
+// re-init after doc activation
+bool SwFieldDataOnlyDlgWrapper::ReInitDlg(SwDocShell *pDocSh)
+{
+ bool bRet = SwChildWinWrapper::ReInitDlg(pDocSh);
+ if (bRet) // update immediately, Doc switch
+ {
+ m_pDlgInterface->ReInitDlg();
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/fldui/xfldui.cxx b/sw/source/uibase/fldui/xfldui.cxx
new file mode 100644
index 0000000000..e5532f8945
--- /dev/null
+++ b/sw/source/uibase/fldui/xfldui.cxx
@@ -0,0 +1,171 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <osl/diagnose.h>
+#include <comphelper/diagnose_ex.hxx>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <fldmgr.hxx>
+#include <dbmgr.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <swmodule.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+
+// This file contains all routines of the fldui directory, which must compile
+// with exceptions. So we can reduce the code of the other files, which don't
+// need any exception handling.
+
+// Is the database field numeric?
+// remark: in case of error true is returned
+bool SwFieldMgr::IsDBNumeric( const OUString& rDBName, const OUString& rTableQryName,
+ bool bIsTable, const OUString& rFieldName)
+{
+ bool bNumeric = true;
+
+ SwDBManager* pDBManager;
+ if (m_pWrtShell)
+ pDBManager = m_pWrtShell->GetDBManager();
+ else
+ {
+ if (SwView* pView = GetActiveView())
+ pDBManager = pView->GetWrtShell().GetDBManager();
+ else
+ return bNumeric;
+ }
+
+ Reference< XConnection> xConnection =
+ pDBManager->RegisterConnection(rDBName);
+
+ if( !xConnection.is() )
+ return bNumeric;
+
+ Reference<XColumnsSupplier> xColsSupplier;
+ if(bIsTable)
+ {
+ Reference<XTablesSupplier> xTSupplier(xConnection, UNO_QUERY);
+ if(xTSupplier.is())
+ {
+ Reference<XNameAccess> xTables = xTSupplier->getTables();
+ OSL_ENSURE(xTables->hasByName(rTableQryName), "table not available anymore?");
+ try
+ {
+ Any aTable = xTables->getByName(rTableQryName);
+ Reference<XPropertySet> xPropSet;
+ aTable >>= xPropSet;
+ xColsSupplier.set(xPropSet, UNO_QUERY);
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+ }
+ else
+ {
+ Reference<XQueriesSupplier> xQSupplier(xConnection, UNO_QUERY);
+ if(xQSupplier.is())
+ {
+ Reference<XNameAccess> xQueries = xQSupplier->getQueries();
+ OSL_ENSURE(xQueries->hasByName(rTableQryName), "table not available anymore?");
+ try
+ {
+ Any aQuery = xQueries->getByName(rTableQryName);
+ Reference<XPropertySet> xPropSet;
+ aQuery >>= xPropSet;
+ xColsSupplier.set(xPropSet, UNO_QUERY);
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+ }
+
+ if(xColsSupplier.is())
+ {
+ Reference <XNameAccess> xCols;
+ try
+ {
+ xCols = xColsSupplier->getColumns();
+ }
+ catch (const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "sw", "getColumns()");
+ }
+ if(xCols.is() && xCols->hasByName(rFieldName))
+ {
+ Any aCol = xCols->getByName(rFieldName);
+ Reference <XPropertySet> xCol;
+ aCol >>= xCol;
+ Any aType = xCol->getPropertyValue("Type");
+ sal_Int32 eDataType = 0;
+ aType >>= eDataType;
+ switch(eDataType)
+ {
+ case DataType::BIT:
+ case DataType::BOOLEAN:
+ case DataType::TINYINT:
+ case DataType::SMALLINT:
+ case DataType::INTEGER:
+ case DataType::BIGINT:
+ case DataType::FLOAT:
+ case DataType::REAL:
+ case DataType::DOUBLE:
+ case DataType::NUMERIC:
+ case DataType::DECIMAL:
+ case DataType::DATE:
+ case DataType::TIME:
+ case DataType::TIMESTAMP:
+ break;
+
+ case DataType::BINARY:
+ case DataType::VARBINARY:
+ case DataType::LONGVARBINARY:
+ case DataType::SQLNULL:
+ case DataType::OTHER:
+ case DataType::OBJECT:
+ case DataType::DISTINCT:
+ case DataType::STRUCT:
+ case DataType::ARRAY:
+ case DataType::BLOB:
+ case DataType::CLOB:
+ case DataType::REF:
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::LONGVARCHAR:
+ default:
+ bNumeric = false;
+ }
+ }
+ }
+ return bNumeric;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/frmdlg/colex.cxx b/sw/source/uibase/frmdlg/colex.cxx
new file mode 100644
index 0000000000..67cd04f79d
--- /dev/null
+++ b/sw/source/uibase/frmdlg/colex.cxx
@@ -0,0 +1,602 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cmdid.h>
+#include <hintids.hxx>
+#include <svl/eitem.hxx>
+#include <tools/fract.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/sizeitem.hxx>
+#include <svx/pageitem.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/settings.hxx>
+#include <tgrditem.hxx>
+#include <viewopt.hxx>
+#include <colex.hxx>
+#include <colmgr.hxx>
+#include <svx/unobrushitemhelper.hxx>
+
+void SwPageExample::UpdateExample( const SfxItemSet& rSet )
+{
+ if (SfxItemState::DEFAULT <= rSet.GetItemState(RES_FRAMEDIR))
+ {
+ const SvxFrameDirectionItem& rDirItem = rSet.Get(RES_FRAMEDIR);
+ m_bVertical = rDirItem.GetValue() == SvxFrameDirection::Vertical_RL_TB||
+ rDirItem.GetValue() == SvxFrameDirection::Vertical_LR_TB;
+ }
+
+ SfxItemPool* pPool = rSet.GetPool();
+ sal_uInt16 nWhich = pPool->GetWhich( SID_ATTR_PAGE );
+ if ( rSet.GetItemState( nWhich, false ) == SfxItemState::SET )
+ {
+ // alignment
+ const SvxPageItem& rPage = static_cast<const SvxPageItem&>(rSet.Get(nWhich));
+ SetUsage(rPage.GetPageUsage());
+ }
+
+ nWhich = pPool->GetWhich( SID_ATTR_PAGE_SIZE );
+
+ if ( rSet.GetItemState( nWhich, false ) == SfxItemState::SET )
+ {
+ // orientation and size from PageItem
+ const SvxSizeItem& rSize = static_cast<const SvxSizeItem&>(rSet.Get( nWhich ));
+ SetSize( rSize.GetSize() );
+ }
+ nWhich = RES_LR_SPACE;
+ if ( rSet.GetItemState( nWhich, false ) == SfxItemState::SET )
+ {
+ // set left and right border
+ const SvxLRSpaceItem& rLRSpace = static_cast<const SvxLRSpaceItem&>(rSet.Get( nWhich ));
+
+ SetLeft( rLRSpace.GetLeft() );
+ SetRight( rLRSpace.GetRight() );
+ }
+ else
+ {
+ SetLeft( 0 );
+ SetRight( 0 );
+ }
+
+ nWhich = RES_UL_SPACE;
+
+ if ( rSet.GetItemState( nWhich, false ) == SfxItemState::SET )
+ {
+ // set upper and lower border
+ const SvxULSpaceItem& rULSpace = static_cast<const SvxULSpaceItem&>(rSet.Get( nWhich ));
+
+ SetTop( rULSpace.GetUpper() );
+ SetBottom( rULSpace.GetLower() );
+ }
+ else
+ {
+ SetTop( 0 );
+ SetBottom( 0 );
+ }
+
+ // evaluate header-attributes
+ const SfxPoolItem* pItem;
+ if( SfxItemState::SET == rSet.GetItemState( pPool->GetWhich( SID_ATTR_PAGE_HEADERSET),
+ false, &pItem ) )
+ {
+ const SfxItemSet& rHeaderSet = static_cast<const SvxSetItem*>(pItem)->GetItemSet();
+ const SfxBoolItem& rHeaderOn =
+ rHeaderSet.Get( pPool->GetWhich( SID_ATTR_PAGE_ON ) );
+
+ if ( rHeaderOn.GetValue() )
+ {
+ const SvxSizeItem& rSize =
+ rHeaderSet.Get(pPool->GetWhich(SID_ATTR_PAGE_SIZE));
+
+ const SvxULSpaceItem& rUL = rHeaderSet.Get(pPool->GetWhich(SID_ATTR_ULSPACE));
+ const SvxLRSpaceItem& rLR = rHeaderSet.Get(pPool->GetWhich(SID_ATTR_LRSPACE));
+
+ SetHdHeight( rSize.GetSize().Height() - rUL.GetLower());
+ SetHdDist( rUL.GetLower() );
+ SetHdLeft( rLR.GetLeft() );
+ SetHdRight( rLR.GetRight() );
+ SetHeader( true );
+
+ if(SfxItemState::SET == rHeaderSet.GetItemState(RES_BACKGROUND))
+ {
+ // create FillAttributes from SvxBrushItem //SetHdColor(rItem.GetColor());
+ const SvxBrushItem& rItem = rHeaderSet.Get(RES_BACKGROUND);
+ SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> aTempSet(*rHeaderSet.GetPool());
+
+ setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet);
+ setHeaderFillAttributes(
+ std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(
+ aTempSet));
+ }
+ }
+ else
+ SetHeader( false );
+ }
+
+ if( SfxItemState::SET == rSet.GetItemState( pPool->GetWhich( SID_ATTR_PAGE_FOOTERSET),
+ false, &pItem ) )
+ {
+ const SfxItemSet& rFooterSet = static_cast<const SvxSetItem*>(pItem)->GetItemSet();
+ const SfxBoolItem& rFooterOn = rFooterSet.Get( SID_ATTR_PAGE_ON );
+
+ if ( rFooterOn.GetValue() )
+ {
+ const SvxSizeItem& rSize =
+ rFooterSet.Get( pPool->GetWhich( SID_ATTR_PAGE_SIZE ) );
+
+ const SvxULSpaceItem& rUL = rFooterSet.Get(pPool->GetWhich( SID_ATTR_ULSPACE ) );
+ const SvxLRSpaceItem& rLR = rFooterSet.Get(pPool->GetWhich( SID_ATTR_LRSPACE ) );
+
+ SetFtHeight( rSize.GetSize().Height() - rUL.GetUpper());
+ SetFtDist( rUL.GetUpper() );
+ SetFtLeft( rLR.GetLeft() );
+ SetFtRight( rLR.GetRight() );
+ SetFooter( true );
+
+ if( rFooterSet.GetItemState( RES_BACKGROUND ) == SfxItemState::SET )
+ {
+ // create FillAttributes from SvxBrushItem //SetFtColor(rItem.GetColor());
+ const SvxBrushItem& rItem = rFooterSet.Get(RES_BACKGROUND);
+ SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> aTempSet(*rFooterSet.GetPool());
+
+ setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet);
+ setFooterFillAttributes(
+ std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(
+ aTempSet));
+ }
+ }
+ else
+ SetFooter( false );
+ }
+
+ if(const SvxBrushItem* pBrushItem = rSet.GetItemIfSet(RES_BACKGROUND, false))
+ {
+ // create FillAttributes from SvxBrushItem
+ SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> aTempSet(*rSet.GetPool());
+
+ setSvxBrushItemAsFillAttributesToTargetSet(*pBrushItem, aTempSet);
+ setPageFillAttributes(
+ std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(
+ aTempSet));
+ }
+
+ Invalidate();
+}
+
+void SwColExample::DrawPage(vcl::RenderContext& rRenderContext, const Point& rOrg,
+ const bool bSecond, const bool bEnabled)
+{
+ SwPageExample::DrawPage(rRenderContext, rOrg, bSecond, bEnabled);
+ if (!m_pColMgr)
+ return;
+ sal_uInt16 nColumnCount = m_pColMgr->GetCount();
+ if (!nColumnCount)
+ return;
+
+ tools::Long nL = GetLeft();
+ tools::Long nR = GetRight();
+
+ if (GetUsage() == SvxPageUsage::Mirror && !bSecond)
+ {
+ // swap for mirrored
+ nL = GetRight();
+ nR = GetLeft();
+ }
+
+ rRenderContext.SetFillColor(COL_LIGHTGRAY);
+ tools::Rectangle aRect;
+ aRect.SetRight( rOrg.X() + GetSize().Width() - nR );
+ aRect.SetLeft( rOrg.X() + nL );
+ aRect.SetTop( rOrg.Y() + GetTop() + GetHdHeight() + GetHdDist() );
+ aRect.SetBottom( rOrg.Y() + GetSize().Height() - GetBottom() - GetFtHeight() - GetFtDist() );
+ rRenderContext.DrawRect(aRect);
+
+ const tools::Rectangle aDefineRect(aRect);
+ const drawinglayer::attribute::SdrAllFillAttributesHelperPtr& rFillAttributes = getPageFillAttributes();
+
+ if (!rFillAttributes || !rFillAttributes->isUsed())
+ {
+ // If there is no fill, use fallback color
+ const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
+ const Color& rFieldColor = rStyleSettings.GetFieldColor();
+
+ setPageFillAttributes(
+ std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(
+ rFieldColor));
+ }
+
+ // #97495# make sure that the automatic column width's are always equal
+ bool bAutoWidth = m_pColMgr->IsAutoWidth();
+ sal_Int32 nAutoColWidth = 0;
+ if (bAutoWidth)
+ {
+ sal_Int32 nColumnWidthSum = 0;
+ for (sal_uInt16 i = 0; i < nColumnCount; ++i)
+ nColumnWidthSum += m_pColMgr->GetColWidth( i );
+ nAutoColWidth = nColumnWidthSum / nColumnCount;
+ }
+
+ for (sal_uInt16 i = 0; i < nColumnCount; ++i)
+ {
+ if (!bAutoWidth)
+ nAutoColWidth = m_pColMgr->GetColWidth(i);
+
+ if (!m_bVertical)
+ aRect.SetRight( aRect.Left() + nAutoColWidth );
+ else
+ aRect.SetBottom( aRect.Top() + nAutoColWidth );
+
+ // use primitive draw command
+ drawFillAttributes(rRenderContext, getPageFillAttributes(), aRect, aDefineRect);
+
+ if (i < nColumnCount - 1)
+ {
+ if (!m_bVertical)
+ aRect.SetLeft( aRect.Right() + m_pColMgr->GetGutterWidth(i) );
+ else
+ aRect.SetTop( aRect.Bottom() + m_pColMgr->GetGutterWidth(i) );
+ }
+ }
+ if (!m_pColMgr->HasLine())
+ return;
+
+ Point aUp(rOrg.X() + nL, rOrg.Y() + GetTop());
+ Point aDown(rOrg.X() + nL,
+ rOrg.Y() + GetSize().Height() - GetBottom() - GetFtHeight() - GetFtDist());
+
+ if (m_pColMgr->GetLineHeightPercent() != 100)
+ {
+ tools::Long nLength = !m_bVertical ? aDown.Y() - aUp.Y() : aDown.X() - aUp.X();
+ nLength -= nLength * m_pColMgr->GetLineHeightPercent() / 100;
+ switch (m_pColMgr->GetAdjust())
+ {
+ case COLADJ_BOTTOM:
+ if (!m_bVertical)
+ aUp.AdjustY(nLength );
+ else
+ aUp.AdjustX(nLength );
+ break;
+ case COLADJ_TOP:
+ if (!m_bVertical)
+ aDown.AdjustY( -nLength );
+ else
+ aDown.AdjustX( -nLength );
+ break;
+ case COLADJ_CENTER:
+ if (!m_bVertical)
+ {
+ aUp.AdjustY(nLength / 2 );
+ aDown.AdjustY( -(nLength / 2) );
+ }
+ else
+ {
+ aUp.AdjustX(nLength / 2 );
+ aDown.AdjustX( -(nLength / 2) );
+ }
+ break;
+ default:
+ break; // prevent warning
+ }
+ }
+
+ for (sal_uInt16 i = 0; i < nColumnCount - 1; ++i)
+ {
+ int nGutter = m_pColMgr->GetGutterWidth(i);
+ int nDist = m_pColMgr->GetColWidth( i ) + nGutter;
+ nDist -= (i == 0) ? nGutter / 2 : 0;
+ if (!m_bVertical)
+ {
+ aUp.AdjustX(nDist );
+ aDown.AdjustX(nDist );
+ }
+ else
+ {
+ aUp.AdjustY(nDist );
+ aDown.AdjustY(nDist );
+ }
+
+ rRenderContext.DrawLine(aUp, aDown);
+ }
+}
+
+SwColumnOnlyExample::SwColumnOnlyExample()
+ : m_aFrameSize(SvxPaperInfo::GetPaperSize(PAPER_A4)) // DIN A4
+{
+ ::FitToActualSize(m_aCols, o3tl::narrowing<sal_uInt16>(m_aFrameSize.Width()));
+}
+
+void SwColumnOnlyExample::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/)
+{
+ rRenderContext.Push(vcl::PushFlags::MAPMODE);
+
+ Fraction aScale(m_aWinSize.Height(), m_aFrameSize.Height());
+ MapMode aMapMode(MapUnit::MapTwip);
+ aMapMode.SetScaleX(aScale);
+ aMapMode.SetScaleY(aScale);
+ rRenderContext.SetMapMode(aMapMode);
+
+ const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
+ const Color& rFieldColor = rStyleSettings.GetFieldColor();
+ const Color& rDlgColor = rStyleSettings.GetDialogColor();
+ const Color& rFieldTextColor = SwViewOption::GetCurrentViewOptions().GetFontColor();
+ Color aGrayColor(COL_LIGHTGRAY);
+ if (rFieldColor == aGrayColor)
+ aGrayColor.Invert();
+
+ Size aLogSize(rRenderContext.PixelToLogic(GetOutputSizePixel()));
+ tools::Rectangle aCompleteRect(Point(0,0), aLogSize);
+ rRenderContext.SetLineColor(rDlgColor);
+ rRenderContext.SetFillColor(rDlgColor);
+ rRenderContext.DrawRect(aCompleteRect);
+
+ rRenderContext.SetLineColor(rFieldTextColor);
+ Point aTL((aLogSize.Width() - m_aFrameSize.Width()) / 2,
+ (aLogSize.Height() - m_aFrameSize.Height()) / 2);
+ tools::Rectangle aRect(aTL, m_aFrameSize);
+
+ //draw a shadow rectangle
+ rRenderContext.SetFillColor(COL_GRAY);
+ tools::Rectangle aShadowRect(aRect);
+ aShadowRect.Move(aTL.Y(), aTL.Y());
+ rRenderContext.DrawRect(aShadowRect);
+
+ rRenderContext.SetFillColor(rFieldColor);
+ rRenderContext.DrawRect(aRect);
+
+ rRenderContext.SetFillColor(aGrayColor);
+
+ //column separator?
+ tools::Long nLength = aLogSize.Height() - 2 * aTL.Y();
+ Point aUp(aTL);
+ Point aDown(aTL.X(), nLength);
+ bool bLines = false;
+ if (m_aCols.GetLineAdj() != COLADJ_NONE)
+ {
+ bLines = true;
+
+ sal_uInt16 nPercent = m_aCols.GetLineHeight();
+ if (nPercent != 100)
+ {
+ nLength -= nLength * nPercent / 100;
+ switch(m_aCols.GetLineAdj())
+ {
+ case COLADJ_BOTTOM: aUp.AdjustY(nLength ); break;
+ case COLADJ_TOP: aDown.AdjustY( -nLength ); break;
+ case COLADJ_CENTER:
+ aUp.AdjustY(nLength / 2 );
+ aDown.AdjustY( -(nLength / 2) );
+ break;
+ default:
+ break; //prevent warning
+ }
+ }
+
+ }
+ const SwColumns& rCols = m_aCols.GetColumns();
+ sal_uInt16 nColCount = rCols.size();
+ if (nColCount)
+ {
+ rRenderContext.DrawRect(aRect);
+ rRenderContext.SetFillColor(rFieldColor);
+ tools::Rectangle aFrameRect(aTL, m_aFrameSize);
+ tools::Long nSum = aTL.X();
+ for (sal_uInt16 i = 0; i < nColCount; i++)
+ {
+ const SwColumn* pCol = &rCols[i];
+ aFrameRect.SetLeft( nSum + pCol->GetLeft() ); //nSum + pCol->GetLeft() + aTL.X();
+ nSum += pCol->GetWishWidth();
+ aFrameRect.SetRight( nSum - pCol->GetRight() );
+ rRenderContext.DrawRect(aFrameRect);
+ }
+ if (bLines)
+ {
+ nSum = aTL.X();
+ for (sal_uInt16 i = 0; i < nColCount - 1; i++)
+ {
+ nSum += rCols[i].GetWishWidth();
+ aUp.setX( nSum );
+ aDown.setX( nSum );
+ rRenderContext.DrawLine(aUp, aDown);
+ }
+ }
+ }
+ rRenderContext.Pop();
+}
+
+void SwColumnOnlyExample::SetColumns(const SwFormatCol& rCol)
+{
+ m_aCols = rCol;
+ sal_uInt16 nWishSum = m_aCols.GetWishWidth();
+ tools::Long nFrameWidth = m_aFrameSize.Width();
+ SwColumns& rCols = m_aCols.GetColumns();
+ sal_uInt16 nColCount = rCols.size();
+
+ for(sal_uInt16 i = 0; i < nColCount; i++)
+ {
+ SwColumn* pCol = &rCols[i];
+ tools::Long nWish = pCol->GetWishWidth();
+ nWish *= nFrameWidth;
+ nWish /= nWishSum;
+ pCol->SetWishWidth(o3tl::narrowing<sal_uInt16>(nWish));
+ tools::Long nLeft = pCol->GetLeft();
+ nLeft *= nFrameWidth;
+ nLeft /= nWishSum;
+ pCol->SetLeft(o3tl::narrowing<sal_uInt16>(nLeft));
+ tools::Long nRight = pCol->GetRight();
+ nRight *= nFrameWidth;
+ nRight /= nWishSum;
+ pCol->SetRight(o3tl::narrowing<sal_uInt16>(nRight));
+ }
+ // #97495# make sure that the automatic column width's are always equal
+ if(!(nColCount && m_aCols.IsOrtho()))
+ return;
+
+ sal_Int32 nColumnWidthSum = 0;
+ sal_uInt16 i;
+ for(i = 0; i < nColCount; ++i)
+ {
+ SwColumn* pCol = &rCols[i];
+ nColumnWidthSum += pCol->GetWishWidth();
+ nColumnWidthSum -= (pCol->GetRight() + pCol->GetLeft());
+ }
+ nColumnWidthSum /= nColCount;
+ for(i = 0; i < nColCount; ++i)
+ {
+ SwColumn* pCol = &rCols[i];
+ pCol->SetWishWidth( static_cast< sal_uInt16 >(nColumnWidthSum + pCol->GetRight() + pCol->GetLeft()));
+ }
+}
+
+void SwColumnOnlyExample::SetDrawingArea(weld::DrawingArea* pDrawingArea)
+{
+ weld::CustomWidgetController::SetDrawingArea(pDrawingArea);
+ OutputDevice& rRefDevice = pDrawingArea->get_ref_device();
+ Size aPrefSize(rRefDevice.LogicToPixel(Size(75, 46), MapMode(MapUnit::MapAppFont)));
+ pDrawingArea->set_size_request(aPrefSize.Width(), aPrefSize.Height());
+}
+
+void SwColumnOnlyExample::Resize()
+{
+ OutputDevice& rRefDevice = GetDrawingArea()->get_ref_device();
+ rRefDevice.Push(vcl::PushFlags::MAPMODE);
+ rRefDevice.SetMapMode(MapMode(MapUnit::MapTwip));
+ m_aWinSize = GetOutputSizePixel();
+ m_aWinSize.AdjustHeight( -4 );
+ m_aWinSize.AdjustWidth( -4 );
+ m_aWinSize = rRefDevice.PixelToLogic(m_aWinSize);
+ rRefDevice.Pop();
+ Invalidate();
+}
+
+SwPageGridExample::SwPageGridExample()
+{
+}
+
+void SwPageGridExample::DrawPage(vcl::RenderContext& rRenderContext, const Point& rOrg,
+ const bool bSecond, const bool bEnabled)
+{
+ SwPageExample::DrawPage(rRenderContext, rOrg, bSecond, bEnabled);
+
+ if (!m_pGridItem || !m_pGridItem->GetGridType())
+ return;
+
+ //paint the grid now
+ Color aLineColor = m_pGridItem->GetColor();
+ if (aLineColor == COL_AUTO)
+ {
+ aLineColor = rRenderContext.GetFillColor();
+ aLineColor.Invert();
+ }
+ rRenderContext.SetLineColor(aLineColor);
+ tools::Long nL = GetLeft();
+ tools::Long nR = GetRight();
+
+ if (GetUsage() == SvxPageUsage::Mirror && !bSecond)
+ {
+ // rotate for mirrored
+ nL = GetRight();
+ nR = GetLeft();
+ }
+
+ tools::Rectangle aRect;
+ aRect.SetRight( rOrg.X() + GetSize().Width() - nR );
+ aRect.SetLeft( rOrg.X() + nL );
+ aRect.SetTop( rOrg.Y() + GetTop() + GetHdHeight() + GetHdDist() );
+ aRect.SetBottom( rOrg.Y() + GetSize().Height() - GetBottom() - GetFtHeight() - GetFtDist() );
+
+ //increase the values to get a 'viewable' preview
+ sal_Int32 nBaseHeight = m_pGridItem->GetBaseHeight() * 3;
+ sal_Int32 nRubyHeight = m_pGridItem->GetRubyHeight() * 3;
+
+ //detect height of rectangles
+ tools::Rectangle aRubyRect(aRect.TopLeft(),
+ m_bVertical ?
+ Size(nRubyHeight, aRect.GetHeight()) :
+ Size(aRect.GetWidth(), nRubyHeight));
+ tools::Rectangle aCharRect(aRect.TopLeft(),
+ m_bVertical ?
+ Size(nBaseHeight, aRect.GetHeight()) :
+ Size(aRect.GetWidth(), nBaseHeight));
+
+ sal_Int32 nLineHeight = nBaseHeight + nRubyHeight;
+
+ //detect count of rectangles
+ sal_Int32 nLines = (m_bVertical ? aRect.GetWidth(): aRect.GetHeight()) / nLineHeight;
+ if (nLines > m_pGridItem->GetLines())
+ nLines = m_pGridItem->GetLines();
+
+ // determine start position
+ if (m_bVertical)
+ {
+ sal_Int16 nXStart = static_cast<sal_Int16>(aRect.GetWidth() / 2 - nLineHeight * nLines /2);
+ aRubyRect.Move(nXStart, 0);
+ aCharRect.Move(nXStart, 0);
+ }
+ else
+ {
+ sal_Int16 nYStart = static_cast<sal_Int16>(aRect.GetHeight() / 2 - nLineHeight * nLines /2);
+ aRubyRect.Move(0, nYStart);
+ aCharRect.Move(0, nYStart);
+ }
+
+ if (m_pGridItem->IsRubyTextBelow())
+ m_bVertical ? aRubyRect.Move(nBaseHeight, 0) : aRubyRect.Move(0, nBaseHeight);
+ else
+ m_bVertical ? aCharRect.Move(nRubyHeight, 0) : aCharRect.Move(0, nRubyHeight);
+
+ //vertical lines
+ bool bBothLines = m_pGridItem->GetGridType() == GRID_LINES_CHARS;
+ rRenderContext.SetFillColor(COL_TRANSPARENT);
+ sal_Int32 nXMove = m_bVertical ? nLineHeight : 0;
+ sal_Int32 nYMove = m_bVertical ? 0 : nLineHeight;
+ for (sal_Int32 nLine = 0; nLine < nLines; nLine++)
+ {
+ rRenderContext.DrawRect(aRubyRect);
+ rRenderContext.DrawRect(aCharRect);
+ if (bBothLines)
+ {
+ Point aStart = aCharRect.TopLeft();
+ Point aEnd = m_bVertical ? aCharRect.TopRight() : aCharRect.BottomLeft();
+ while (m_bVertical ? aStart.Y() < aRect.Bottom(): aStart.X() < aRect.Right())
+ {
+ rRenderContext.DrawLine(aStart, aEnd);
+ if (m_bVertical)
+ aStart.setY( aEnd.AdjustY(nBaseHeight ) );
+ else
+ aStart.setX( aEnd.AdjustX(nBaseHeight ) );
+ }
+ }
+ aRubyRect.Move(nXMove, nYMove);
+ aCharRect.Move(nXMove, nYMove);
+ }
+
+}
+
+void SwPageGridExample::UpdateExample( const SfxItemSet& rSet )
+{
+ m_pGridItem.reset();
+ //get the grid information
+ if (SfxItemState::DEFAULT <= rSet.GetItemState(RES_TEXTGRID))
+ m_pGridItem.reset(rSet.Get(RES_TEXTGRID).Clone());
+ SwPageExample::UpdateExample(rSet);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/frmdlg/colmgr.cxx b/sw/source/uibase/frmdlg/colmgr.cxx
new file mode 100644
index 0000000000..692a8395d6
--- /dev/null
+++ b/sw/source/uibase/frmdlg/colmgr.cxx
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <algorithm>
+
+#include <hintids.hxx>
+#include <editeng/lrspitem.hxx>
+#include <osl/diagnose.h>
+
+#include <colmgr.hxx>
+#include <fmtfsize.hxx>
+#include <swtypes.hxx>
+
+// private methods
+
+// set column width to current width
+void FitToActualSize(SwFormatCol& rCol, sal_uInt16 nWidth)
+{
+ const sal_uInt16 nCount = rCol.GetColumns().size();
+ for (sal_uInt16 i = 0; i < nCount; ++i)
+ {
+ const sal_uInt16 nTmp = rCol.CalcColWidth(i, nWidth);
+ auto& col = rCol.GetColumns()[i];
+ col.SetWishWidth(nTmp);
+ // If necessary, shrink borders (as equally as possible) to keep up the invariant that
+ // GetWishWidth() >= GetLeft() + GetRight():
+ sal_uInt32 const borders = col.GetLeft() + col.GetRight();
+ if (borders > nTmp)
+ {
+ auto const shrink = borders - nTmp;
+ auto const half = shrink / 2; // rounds down
+ if (col.GetLeft() < col.GetRight())
+ {
+ auto const shrinkLeft = std::min(sal_uInt32(col.GetLeft()), half);
+ col.SetLeft(col.GetLeft() - shrinkLeft);
+ col.SetRight(col.GetRight() - (shrink - shrinkLeft));
+ }
+ else
+ {
+ auto const shrinkRight = std::min(sal_uInt32(col.GetRight()), half);
+ col.SetLeft(col.GetLeft() - (shrink - shrinkRight));
+ col.SetRight(col.GetRight() - shrinkRight);
+ }
+ }
+ }
+ rCol.SetWishWidth(nWidth);
+}
+
+// public methods
+
+// set column quantity and Gutterwidth
+void SwColMgr::SetCount(sal_uInt16 nCount, sal_uInt16 nGutterWidth)
+{
+ m_aFormatCol.Init(nCount, nGutterWidth, m_nWidth);
+ m_aFormatCol.SetWishWidth(m_nWidth);
+ m_aFormatCol.SetGutterWidth(nGutterWidth, m_nWidth);
+}
+
+sal_uInt16 SwColMgr::GetGutterWidth(sal_uInt16 nPos) const
+{
+ sal_uInt16 nRet;
+ if (nPos == USHRT_MAX)
+ nRet = GetCount() > 1 ? m_aFormatCol.GetGutterWidth() : DEF_GUTTER_WIDTH;
+ else
+ {
+ OSL_ENSURE(nPos < GetCount() - 1, "column overindexed");
+ const SwColumns& rCols = m_aFormatCol.GetColumns();
+ nRet = rCols[nPos].GetRight() + rCols[nPos + 1].GetLeft();
+ }
+ return nRet;
+}
+
+void SwColMgr::SetGutterWidth(sal_uInt16 nGutterWidth, sal_uInt16 nPos)
+{
+ if (nPos == USHRT_MAX)
+ m_aFormatCol.SetGutterWidth(nGutterWidth, m_nWidth);
+ else
+ {
+ OSL_ENSURE(nPos < GetCount() - 1, "column overindexed");
+ SwColumns& rCols = m_aFormatCol.GetColumns();
+ sal_uInt16 nGutterWidth2 = nGutterWidth / 2;
+ rCols[nPos].SetRight(nGutterWidth2);
+ rCols[nPos + 1].SetLeft(nGutterWidth2);
+ }
+}
+
+// height separation line
+short SwColMgr::GetLineHeightPercent() const
+{
+ return static_cast<short>(m_aFormatCol.GetLineHeight());
+}
+void SwColMgr::SetLineHeightPercent(short nPercent)
+{
+ OSL_ENSURE(nPercent <= 100, "line height may be at most 100%");
+ m_aFormatCol.SetLineHeight(static_cast<sal_uInt8>(nPercent));
+}
+
+// column width
+sal_uInt16 SwColMgr::GetColWidth(sal_uInt16 nIdx) const
+{
+ OSL_ENSURE(nIdx < GetCount(), "Column array overindexed.");
+ return m_aFormatCol.CalcPrtColWidth(nIdx, m_nWidth);
+}
+
+void SwColMgr::SetColWidth(sal_uInt16 nIdx, sal_uInt16 nWd)
+{
+ OSL_ENSURE(nIdx < GetCount(), "Column array overindexed.");
+ m_aFormatCol.GetColumns()[nIdx].SetWishWidth(nWd);
+}
+
+// newly set size
+void SwColMgr::SetActualWidth(sal_uInt16 nW)
+{
+ m_nWidth = nW;
+ ::FitToActualSize(m_aFormatCol, nW);
+}
+
+// ctor
+SwColMgr::SwColMgr(const SfxItemSet& rSet)
+ : m_aFormatCol(rSet.Get(RES_COL))
+{
+ m_nWidth = o3tl::narrowing<sal_uInt16>(rSet.Get(RES_FRM_SIZE).GetWidth());
+ if (m_nWidth < MINLAY)
+ m_nWidth = USHRT_MAX;
+ const SvxLRSpaceItem& rLR = rSet.Get(RES_LR_SPACE);
+ m_nWidth = m_nWidth - o3tl::narrowing<sal_uInt16>(rLR.GetLeft());
+ m_nWidth = m_nWidth - o3tl::narrowing<sal_uInt16>(rLR.GetRight());
+ ::FitToActualSize(m_aFormatCol, m_nWidth);
+}
+
+SwColMgr::~SwColMgr() {}
+
+void SwColMgr::SetLineWidthAndColor(SvxBorderLineStyle eStyle, sal_uLong nLWidth, const Color& rCol)
+{
+ m_aFormatCol.SetLineStyle(eStyle);
+ m_aFormatCol.SetLineWidth(nLWidth);
+ m_aFormatCol.SetLineColor(rCol);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/frmdlg/frmmgr.cxx b/sw/source/uibase/frmdlg/frmmgr.cxx
new file mode 100644
index 0000000000..cdfeb267b9
--- /dev/null
+++ b/sw/source/uibase/frmdlg/frmmgr.cxx
@@ -0,0 +1,675 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cmdid.h>
+#include <hintids.hxx>
+
+#include <svl/stritem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <svx/swframevalidation.hxx>
+#include <svx/xdef.hxx>
+#include <tools/globname.hxx>
+#include <comphelper/classids.hxx>
+#include <osl/diagnose.h>
+#include <fmtclds.hxx>
+#include <utility>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <viewopt.hxx>
+#include <uitool.hxx>
+#include <frmmgr.hxx>
+#include <format.hxx>
+#include <mdiexp.hxx>
+#include <poolfmt.hxx>
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <com/sun/star/text/RelOrientation.hpp>
+#include <grfatr.hxx>
+
+using namespace ::com::sun::star;
+
+const WhichRangesContainer aFrameMgrRange(svl::Items<
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1, // 87-129
+
+ // RotGrfFlyFrame: Support here, but seems not to be
+ // added in range of m_pOwnSh->GetFlyFrameAttr result
+ // (see below). Tried to find, but could not identify
+ RES_GRFATR_ROTATION, RES_GRFATR_ROTATION, // 132
+
+ // FillAttribute support
+ XATTR_FILL_FIRST, XATTR_FILL_LAST, // 1014-1033
+
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
+ FN_SET_FRM_NAME, FN_SET_FRM_NAME
+ >);
+
+// determine frame attributes via Shell
+SwFlyFrameAttrMgr::SwFlyFrameAttrMgr( bool bNew, SwWrtShell* pSh, Frmmgr_Type nType, const SvGlobalName* pName ) :
+ m_aSet( static_cast<SwAttrPool&>(pSh->GetAttrPool()), aFrameMgrRange ),
+ m_pOwnSh( pSh ),
+ m_bAbsPos( false ),
+ m_bNewFrame( bNew ),
+ m_bIsInVertical( false ),
+ m_bIsInVerticalL2R( false )
+{
+ if ( m_bNewFrame )
+ {
+ sal_uInt16 nId;
+ switch ( nType )
+ {
+ case Frmmgr_Type::TEXT: nId = RES_POOLFRM_FRAME; break;
+ case Frmmgr_Type::OLE: nId = RES_POOLFRM_OLE; break;
+ case Frmmgr_Type::GRF: nId = RES_POOLFRM_GRAPHIC; break;
+ // set defaults:
+ default: nId=0; break;
+ }
+ m_aSet.SetParent( &m_pOwnSh->GetFormatFromPool( nId )->GetAttrSet());
+ m_aSet.Put( SwFormatFrameSize( SwFrameSize::Minimum, DFLT_WIDTH, DFLT_HEIGHT ));
+
+ SetFrameSizeFromTable();
+
+ if ( 0 != ::GetHtmlMode(pSh->GetView().GetDocShell()) )
+ m_aSet.Put( SwFormatHoriOrient( 0, text::HoriOrientation::LEFT, text::RelOrientation::PRINT_AREA ) );
+
+ if (nType == Frmmgr_Type::GRF || nType == Frmmgr_Type::OLE)
+ {
+ if (!pName || *pName != SvGlobalName( SO3_SM_CLASSID ))
+ {
+ // Default anchor for new graphics and objects is at-char, except for Math objects.
+ SwViewOption aViewOpt(*pSh->GetViewOptions());
+
+ RndStdIds eAnchorType = aViewOpt.GetDefaultAnchorType();
+
+ const SwFormatAnchor rStyleAnchor
+ = m_pOwnSh->GetFormatFromPool(nId)->GetAttrSet().GetAnchor();
+ if (rStyleAnchor.GetAnchorId() != RndStdIds::FLY_AT_PARA)
+ {
+ // The style has a custom anchor type, prefer that over the user profile
+ // default.
+ eAnchorType = rStyleAnchor.GetAnchorId();
+ }
+
+ m_aSet.Put(SwFormatAnchor(eAnchorType));
+ }
+ }
+ }
+ else if ( nType == Frmmgr_Type::NONE )
+ {
+ m_pOwnSh->GetFlyFrameAttr( m_aSet );
+ bool bRightToLeft;
+ m_bIsInVertical = m_pOwnSh->IsFrameVertical(true, bRightToLeft, m_bIsInVerticalL2R);
+ }
+ ::PrepareBoxInfo( m_aSet, *m_pOwnSh );
+}
+
+SwFlyFrameAttrMgr::SwFlyFrameAttrMgr( bool bNew, SwWrtShell* pSh, SfxItemSet aSet ) :
+ m_aSet(std::move( aSet )),
+ m_pOwnSh( pSh ),
+ m_bAbsPos( false ),
+ m_bNewFrame( bNew ),
+ m_bIsInVertical(false),
+ m_bIsInVerticalL2R(false)
+{
+ if(!bNew)
+ {
+ bool bRightToLeft;
+ m_bIsInVertical = pSh->IsFrameVertical(true, bRightToLeft, m_bIsInVerticalL2R);
+ }
+}
+
+// Initialise
+void SwFlyFrameAttrMgr::UpdateAttrMgr()
+{
+ if ( !m_bNewFrame && m_pOwnSh->IsFrameSelected() )
+ m_pOwnSh->GetFlyFrameAttr( m_aSet );
+ ::PrepareBoxInfo( m_aSet, *m_pOwnSh );
+}
+
+void SwFlyFrameAttrMgr::UpdateFlyFrame_()
+{
+ if (const SfxStringItem* pItem = m_aSet.GetItemIfSet(FN_SET_FRM_NAME, false))
+ m_pOwnSh->SetFlyName(pItem->GetValue());
+
+ m_pOwnSh->SetModified();
+
+ if ( m_bAbsPos )
+ {
+ m_pOwnSh->SetFlyPos( m_aAbsPos );
+ m_bAbsPos = false;
+ }
+}
+
+// change existing Fly-Frame
+void SwFlyFrameAttrMgr::UpdateFlyFrame()
+{
+ OSL_ENSURE( m_pOwnSh->IsFrameSelected(),
+ "no frame selected or no shell, update not possible");
+
+ if( !m_pOwnSh->IsFrameSelected() )
+ return;
+
+ //JP 6.8.2001: set never an invalid anchor into the core.
+ const SwFormatAnchor *pGItem, *pItem;
+ if( (pItem = m_aSet.GetItemIfSet( RES_ANCHOR, false )) )
+ {
+ SfxItemSetFixed<RES_ANCHOR, RES_ANCHOR> aGetSet( *m_aSet.GetPool() );
+ if( m_pOwnSh->GetFlyFrameAttr( aGetSet ) && 1 == aGetSet.Count() &&
+ (pGItem = aGetSet.GetItemIfSet( RES_ANCHOR, false ))
+ && pGItem->GetAnchorId() == pItem->GetAnchorId() )
+ m_aSet.ClearItem( RES_ANCHOR );
+ }
+
+ // return wg. BASIC
+ if( m_aSet.Count() )
+ {
+ m_pOwnSh->StartAllAction();
+ m_pOwnSh->SetFlyFrameAttr( m_aSet );
+ UpdateFlyFrame_();
+ m_pOwnSh->EndAllAction();
+ }
+}
+
+// insert frame
+void SwFlyFrameAttrMgr::InsertFlyFrame()
+{
+ m_pOwnSh->StartAllAction();
+
+ bool bRet = nullptr != m_pOwnSh->NewFlyFrame( m_aSet );
+
+ // turn on the right mode at the shell, frame got selected automatically.
+ if ( bRet )
+ {
+ UpdateFlyFrame_();
+ m_pOwnSh->EnterSelFrameMode();
+ FrameNotify(m_pOwnSh, FLY_DRAG_START);
+ }
+ m_pOwnSh->EndAllAction();
+}
+
+// Insert frames of type eAnchorType. Position and size are being set explicitly.
+// Not-allowed values of the enumeration type get corrected.
+void SwFlyFrameAttrMgr::InsertFlyFrame(RndStdIds eAnchorType,
+ const Point &rPos,
+ const Size &rSize )
+{
+ OSL_ENSURE( eAnchorType == RndStdIds::FLY_AT_PAGE ||
+ eAnchorType == RndStdIds::FLY_AT_PARA ||
+ eAnchorType == RndStdIds::FLY_AT_CHAR ||
+ eAnchorType == RndStdIds::FLY_AT_FLY ||
+ eAnchorType == RndStdIds::FLY_AS_CHAR, "invalid frame type" );
+
+ SetPos( rPos );
+
+ SetSize( rSize );
+ SetAnchor( eAnchorType );
+ InsertFlyFrame();
+}
+
+// set anchor
+void SwFlyFrameAttrMgr::SetAnchor( RndStdIds eId )
+{
+ sal_uInt16 nPhyPageNum, nVirtPageNum;
+ m_pOwnSh->GetPageNum( nPhyPageNum, nVirtPageNum );
+
+ m_aSet.Put( SwFormatAnchor( eId, RndStdIds::FLY_AT_PAGE == eId ? nPhyPageNum : 0 ) );
+ if ((RndStdIds::FLY_AT_PAGE == eId) || (RndStdIds::FLY_AT_PARA == eId) || (RndStdIds::FLY_AT_CHAR == eId)
+ || (RndStdIds::FLY_AT_FLY == eId))
+ {
+ SwFormatVertOrient aVertOrient( GetVertOrient() );
+ SwFormatHoriOrient aHoriOrient( GetHoriOrient() );
+ aHoriOrient.SetRelationOrient( text::RelOrientation::FRAME );
+ aVertOrient.SetRelationOrient( text::RelOrientation::FRAME );
+ m_aSet.Put( aVertOrient );
+ m_aSet.Put( aHoriOrient );
+ }
+}
+
+// set the attribute for columns
+void SwFlyFrameAttrMgr::SetCol( const SwFormatCol &rCol )
+{
+ m_aSet.Put( rCol );
+}
+
+// set absolute position
+void SwFlyFrameAttrMgr::SetAbsPos( const Point& rPoint )
+{
+ m_bAbsPos = true;
+ m_aAbsPos = rPoint;
+ SwFormatVertOrient aVertOrient( GetVertOrient() );
+ SwFormatHoriOrient aHoriOrient( GetHoriOrient() );
+ aHoriOrient.SetHoriOrient( text::HoriOrientation::NONE );
+ aVertOrient.SetVertOrient( text::VertOrientation::NONE );
+ m_aSet.Put( aVertOrient );
+ m_aSet.Put( aHoriOrient );
+}
+
+// check metrics for correctness
+void SwFlyFrameAttrMgr::ValidateMetrics( SvxSwFrameValidation& rVal,
+ const SwFormatAnchor* pToCharContentPos,
+ bool bOnlyPercentRefValue )
+{
+ if (!bOnlyPercentRefValue)
+ {
+ rVal.nMinHeight = MINFLY + CalcTopSpace() + CalcBottomSpace();
+ rVal.nMinWidth = MINFLY + CalcLeftSpace()+ CalcRightSpace();
+ }
+
+ SwRect aBoundRect;
+
+ // OD 18.09.2003 #i18732# - adjustment for allowing vertical position
+ // aligned to page for fly frame anchored to paragraph or to character.
+ const RndStdIds eAnchorType = rVal.nAnchorType;
+ const SwFormatFrameSize& rSize = m_aSet.Get(RES_FRM_SIZE);
+ m_pOwnSh->CalcBoundRect( aBoundRect, eAnchorType,
+ rVal.nHRelOrient,
+ rVal.nVRelOrient,
+ pToCharContentPos,
+ rVal.bFollowTextFlow,
+ rVal.bMirror, nullptr, &rVal.aPercentSize,
+ &rSize);
+
+ if (bOnlyPercentRefValue)
+ return;
+
+ // #mongolianlayout#
+ if ( m_bIsInVertical || m_bIsInVerticalL2R )
+ {
+ Point aPos(aBoundRect.Pos());
+ tools::Long nTmp = aPos.X();
+ aPos.setX( aPos.Y() );
+ aPos.setY( nTmp );
+ Size aSize(aBoundRect.SSize());
+ nTmp = aSize.Width();
+ aSize.setWidth( aSize.Height() );
+ aSize.setHeight( nTmp );
+ aBoundRect.Chg( aPos, aSize );
+ //exchange width/height to enable correct values
+ nTmp = rVal.nWidth;
+ rVal.nWidth = rVal.nHeight;
+ rVal.nHeight = nTmp;
+ }
+ if ((eAnchorType == RndStdIds::FLY_AT_PAGE) || (eAnchorType == RndStdIds::FLY_AT_FLY))
+ {
+ // MinimalPosition
+ rVal.nMinHPos = aBoundRect.Left();
+ rVal.nMinVPos = aBoundRect.Top();
+ SwTwips nH = rVal.nHPos;
+ SwTwips nV = rVal.nVPos;
+
+ if (rVal.nHPos + rVal.nWidth > aBoundRect.Right())
+ {
+ if (rVal.nHoriOrient == text::HoriOrientation::NONE)
+ {
+ rVal.nHPos -= ((rVal.nHPos + rVal.nWidth) - aBoundRect.Right());
+ nH = rVal.nHPos;
+ }
+ else
+ rVal.nWidth = aBoundRect.Right() - rVal.nHPos;
+ }
+
+ if (rVal.nHPos + rVal.nWidth > aBoundRect.Right())
+ rVal.nWidth = aBoundRect.Right() - rVal.nHPos;
+
+ if (rVal.nVPos + rVal.nHeight > aBoundRect.Bottom())
+ {
+ if (rVal.nVertOrient == text::VertOrientation::NONE)
+ {
+ rVal.nVPos -= ((rVal.nVPos + rVal.nHeight) - aBoundRect.Bottom());
+ nV = rVal.nVPos;
+ }
+ else
+ rVal.nHeight = aBoundRect.Bottom() - rVal.nVPos;
+ }
+
+ if (rVal.nVPos + rVal.nHeight > aBoundRect.Bottom())
+ rVal.nHeight = aBoundRect.Bottom() - rVal.nVPos;
+
+ if ( rVal.nVertOrient != text::VertOrientation::NONE )
+ nV = aBoundRect.Top();
+
+ if ( rVal.nHoriOrient != text::HoriOrientation::NONE )
+ nH = aBoundRect.Left();
+
+ rVal.nMaxHPos = aBoundRect.Right() - rVal.nWidth;
+ rVal.nMaxHeight = aBoundRect.Bottom() - nV;
+
+ rVal.nMaxVPos = aBoundRect.Bottom() - rVal.nHeight;
+ rVal.nMaxWidth = aBoundRect.Right() - nH;
+ }
+ // OD 12.11.2003 #i22341# - handle to character anchored objects vertical
+ // aligned at character or top of line in a special case
+ else if ((eAnchorType == RndStdIds::FLY_AT_PARA) ||
+ ((eAnchorType == RndStdIds::FLY_AT_CHAR) &&
+ (rVal.nVRelOrient != text::RelOrientation::CHAR) &&
+ (rVal.nVRelOrient != text::RelOrientation::TEXT_LINE) ) )
+ {
+ if (rVal.nHPos + rVal.nWidth > aBoundRect.Right())
+ {
+ if (rVal.nHoriOrient == text::HoriOrientation::NONE)
+ {
+ rVal.nHPos -= ((rVal.nHPos + rVal.nWidth) - aBoundRect.Right());
+ }
+ else
+ rVal.nWidth = aBoundRect.Right() - rVal.nHPos;
+ }
+
+ // OD 29.09.2003 #i17567#, #i18732# - consider following the text flow
+ // and alignment at page areas.
+ const bool bMaxVPosAtBottom = !rVal.bFollowTextFlow ||
+ rVal.nVRelOrient == text::RelOrientation::PAGE_FRAME ||
+ rVal.nVRelOrient == text::RelOrientation::PAGE_PRINT_AREA;
+ {
+ SwTwips nTmpMaxVPos = ( bMaxVPosAtBottom
+ ? aBoundRect.Bottom()
+ : aBoundRect.Height() ) -
+ rVal.nHeight;
+ if ( rVal.nVPos > nTmpMaxVPos )
+ {
+ if (rVal.nVertOrient == text::VertOrientation::NONE)
+ {
+ rVal.nVPos = nTmpMaxVPos;
+ }
+ else
+ {
+ rVal.nHeight = ( bMaxVPosAtBottom
+ ? aBoundRect.Bottom()
+ : aBoundRect.Height() ) - rVal.nVPos;
+ }
+ }
+ }
+
+ rVal.nMinHPos = aBoundRect.Left();
+ rVal.nMaxHPos = aBoundRect.Right() - rVal.nWidth;
+
+ rVal.nMinVPos = aBoundRect.Top();
+ // OD 26.09.2003 #i17567#, #i18732# - determine maximum vertical position
+ if ( bMaxVPosAtBottom )
+ {
+ rVal.nMaxVPos = aBoundRect.Bottom() - rVal.nHeight;
+ }
+ else
+ {
+ rVal.nMaxVPos = aBoundRect.Height() - rVal.nHeight;
+ }
+
+ // maximum width height
+ const SwTwips nH = ( rVal.nHoriOrient != text::HoriOrientation::NONE )
+ ? aBoundRect.Left()
+ : rVal.nHPos;
+ const SwTwips nV = ( rVal.nVertOrient != text::VertOrientation::NONE )
+ ? aBoundRect.Top()
+ : rVal.nVPos;
+ rVal.nMaxHeight = rVal.nMaxVPos + rVal.nHeight - nV;
+ rVal.nMaxWidth = rVal.nMaxHPos + rVal.nWidth - nH;
+ }
+ // OD 12.11.2003 #i22341# - special case for to character anchored objects
+ // vertical aligned at character or top of line.
+ // Note: (1) positive vertical values are positions above the top of line
+ // (2) negative vertical values are positions below the top of line
+ else if ( (eAnchorType == RndStdIds::FLY_AT_CHAR) &&
+ ( rVal.nVRelOrient == text::RelOrientation::CHAR ||
+ rVal.nVRelOrient == text::RelOrientation::TEXT_LINE ) )
+ {
+ // determine horizontal values
+ rVal.nMinHPos = aBoundRect.Left();
+
+ rVal.nMaxHPos = aBoundRect.Right() - rVal.nWidth;
+ if (rVal.nHPos + rVal.nWidth > aBoundRect.Right())
+ {
+ if (rVal.nHoriOrient == text::HoriOrientation::NONE)
+ {
+ rVal.nHPos -= ((rVal.nHPos + rVal.nWidth) - aBoundRect.Right());
+ }
+ else
+ rVal.nWidth = aBoundRect.Right() - rVal.nHPos;
+ }
+
+ const SwTwips nH = ( rVal.nHoriOrient != text::HoriOrientation::NONE )
+ ? aBoundRect.Left()
+ : rVal.nHPos;
+ rVal.nMaxWidth = rVal.nMaxHPos + rVal.nWidth - nH;
+
+ // determine vertical values
+ rVal.nMinVPos = -( aBoundRect.Bottom() - rVal.nHeight );
+ if ( rVal.nVPos < rVal.nMinVPos &&
+ rVal.nVertOrient == text::VertOrientation::NONE )
+ {
+ rVal.nVPos = rVal.nMinVPos;
+ }
+
+ rVal.nMaxVPos = -aBoundRect.Top();
+ if ( rVal.nVPos > rVal.nMaxVPos &&
+ rVal.nVertOrient == text::VertOrientation::NONE )
+ {
+ rVal.nVPos = rVal.nMaxVPos;
+ }
+
+ if ( rVal.nVertOrient == text::VertOrientation::NONE )
+ {
+ rVal.nMaxHeight = aBoundRect.Bottom() + rVal.nVPos;
+ }
+ else
+ {
+ rVal.nMaxHeight = aBoundRect.Height();
+ }
+ }
+ else if ( eAnchorType == RndStdIds::FLY_AS_CHAR )
+ {
+ rVal.nMinHPos = 0;
+ rVal.nMaxHPos = 0;
+
+ rVal.nMaxHeight = aBoundRect.Height();
+ rVal.nMaxWidth = aBoundRect.Width();
+
+ rVal.nMaxVPos = aBoundRect.Height();
+ rVal.nMinVPos = -aBoundRect.Height() + rVal.nHeight;
+ if (rVal.nMaxVPos < rVal.nMinVPos)
+ {
+ rVal.nMinVPos = rVal.nMaxVPos;
+ rVal.nMaxVPos = -aBoundRect.Height();
+ }
+ }
+ // #mongolianlayout#
+ if ( m_bIsInVertical || m_bIsInVerticalL2R )
+ {
+ //restore width/height exchange
+ tools::Long nTmp = rVal.nWidth;
+ rVal.nWidth = rVal.nHeight;
+ rVal.nHeight = nTmp;
+ }
+
+ if (rVal.nMaxWidth < rVal.nWidth)
+ rVal.nWidth = rVal.nMaxWidth;
+ if (rVal.nMaxHeight < rVal.nHeight)
+ rVal.nHeight = rVal.nMaxHeight;
+}
+
+// correction for border
+SwTwips SwFlyFrameAttrMgr::CalcTopSpace()
+{
+ const SvxShadowItem& rShadow = GetShadow();
+ const SvxBoxItem& rBox = GetBox();
+ return rShadow.CalcShadowSpace(SvxShadowItemSide::TOP ) + rBox.CalcLineSpace(SvxBoxItemLine::TOP);
+}
+
+SwTwips SwFlyFrameAttrMgr::CalcBottomSpace()
+{
+ const SvxShadowItem& rShadow = GetShadow();
+ const SvxBoxItem& rBox = GetBox();
+ return rShadow.CalcShadowSpace(SvxShadowItemSide::BOTTOM) + rBox.CalcLineSpace(SvxBoxItemLine::BOTTOM);
+}
+
+SwTwips SwFlyFrameAttrMgr::CalcLeftSpace()
+{
+ const SvxShadowItem& rShadow = GetShadow();
+ const SvxBoxItem& rBox = GetBox();
+ return rShadow.CalcShadowSpace(SvxShadowItemSide::LEFT) + rBox.CalcLineSpace(SvxBoxItemLine::LEFT);
+}
+
+SwTwips SwFlyFrameAttrMgr::CalcRightSpace()
+{
+ const SvxShadowItem& rShadow = GetShadow();
+ const SvxBoxItem& rBox = GetBox();
+ return rShadow.CalcShadowSpace(SvxShadowItemSide::RIGHT) + rBox.CalcLineSpace(SvxBoxItemLine::RIGHT);
+}
+
+// erase attribute from the set
+void SwFlyFrameAttrMgr::DelAttr( sal_uInt16 nId )
+{
+ m_aSet.ClearItem( nId );
+}
+
+void SwFlyFrameAttrMgr::SetLRSpace( tools::Long nLeft, tools::Long nRight )
+{
+ OSL_ENSURE( LONG_MAX != nLeft && LONG_MAX != nRight, "Which border to set?" );
+
+ SvxLRSpaceItem aTmp( m_aSet.Get( RES_LR_SPACE ) );
+ if( LONG_MAX != nLeft )
+ aTmp.SetLeft( sal_uInt16(nLeft) );
+ if( LONG_MAX != nRight )
+ aTmp.SetRight( sal_uInt16(nRight) );
+ m_aSet.Put( aTmp );
+}
+
+void SwFlyFrameAttrMgr::SetULSpace( tools::Long nTop, tools::Long nBottom )
+{
+ OSL_ENSURE(LONG_MAX != nTop && LONG_MAX != nBottom, "Which border to set?" );
+
+ SvxULSpaceItem aTmp( m_aSet.Get( RES_UL_SPACE ) );
+ if( LONG_MAX != nTop )
+ aTmp.SetUpper( sal_uInt16(nTop) );
+ if( LONG_MAX != nBottom )
+ aTmp.SetLower( sal_uInt16(nBottom) );
+ m_aSet.Put( aTmp );
+}
+
+void SwFlyFrameAttrMgr::SetPos( const Point& rPoint )
+{
+ SwFormatVertOrient aVertOrient( GetVertOrient() );
+ SwFormatHoriOrient aHoriOrient( GetHoriOrient() );
+
+ aHoriOrient.SetPos ( rPoint.X() );
+ aHoriOrient.SetHoriOrient( text::HoriOrientation::NONE );
+
+ aVertOrient.SetPos ( rPoint.Y() );
+ aVertOrient.SetVertOrient( text::VertOrientation::NONE );
+
+ m_aSet.Put( aVertOrient );
+ m_aSet.Put( aHoriOrient );
+}
+
+void SwFlyFrameAttrMgr::SetHorzOrientation( sal_Int16 eOrient )
+{
+ SwFormatHoriOrient aHoriOrient( GetHoriOrient() );
+ aHoriOrient.SetHoriOrient( eOrient );
+ m_aSet.Put( aHoriOrient );
+}
+
+void SwFlyFrameAttrMgr::SetVertOrientation( sal_Int16 eOrient )
+{
+ SwFormatVertOrient aVertOrient( GetVertOrient() );
+ aVertOrient.SetVertOrient( eOrient );
+ m_aSet.Put( aVertOrient );
+}
+
+void SwFlyFrameAttrMgr::SetHeightSizeType( SwFrameSize eType )
+{
+ SwFormatFrameSize aSize( GetFrameSize() );
+ aSize.SetHeightSizeType( eType );
+ m_aSet.Put( aSize );
+}
+
+void SwFlyFrameAttrMgr::SetRotation(Degree10 nOld, Degree10 nNew, const Size& rUnrotatedSize)
+{
+ // RotGrfFlyFrame: Central handling of real change of rotation here, all adaptations use this.
+ // Adaptation of pos/size may be wanted in the future. Already tried to keep last Size in
+ // UnrotatedSize in the SwRotationGrf Item, but this will lead to various problems. Also tried
+ // to use m_aSet.Put(...) as in other methods (also tried read methods for Rotation/UnrotatedSize) but
+ // somehow the needed ID (RES_GRFATR_ROTATION) is *not* in the SfxItemSet of the Frame, so for
+ // now set directly. Undo/Redo is preserved by AttributeChange
+ if(nOld != nNew)
+ {
+ m_pOwnSh->SetAttrItem(SwRotationGrf(nNew, rUnrotatedSize));
+ }
+}
+
+void SwFlyFrameAttrMgr::SetSize( const Size& rSize )
+{
+ SwFormatFrameSize aSize( GetFrameSize() );
+ aSize.SetSize(Size(std::max(rSize.Width(), tools::Long(MINFLY)), std::max(rSize.Height(), tools::Long(MINFLY))));
+ m_aSet.Put( aSize );
+}
+
+void SwFlyFrameAttrMgr::SetAttrSet(const SfxItemSet& rSet)
+{
+ m_aSet.ClearItem();
+ m_aSet.Put( rSet );
+}
+
+const SwTableFormat* SwFlyFrameAttrMgr::SingleTableSelected(SwWrtShell& rWrtShell)
+{
+ if (!rWrtShell.IsTableMode())
+ {
+ return nullptr;
+ }
+
+ // We have a table selection.
+ SwSelBoxes aBoxes;
+ GetTableSel(rWrtShell, aBoxes);
+ if (aBoxes.empty())
+ {
+ return nullptr;
+ }
+
+ auto pTableNd = const_cast<SwTableNode*>(aBoxes[0]->GetSttNd()->FindTableNode());
+ if (!pTableNd)
+ {
+ return nullptr;
+ }
+
+ SwTable& rTable = pTableNd->GetTable();
+ if (aBoxes.size() != rTable.GetTabSortBoxes().size())
+ {
+ return nullptr;
+ }
+
+ return rTable.GetFrameFormat();
+}
+
+void SwFlyFrameAttrMgr::SetFrameSizeFromTable()
+{
+ const SwTableFormat* pTableFormat = SingleTableSelected(*m_pOwnSh);
+ if (!pTableFormat)
+ {
+ return;
+ }
+
+ // The whole table is selected: default fly width should be the table width
+ // in this case.
+ m_aSet.Put(pTableFormat->GetFrameSize());
+
+ // The table can have its own border already, so an additional fly border makes no sense.
+ SvxBoxItem aBoxItem(RES_BOX);
+ m_aSet.Put(aBoxItem);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/globdoc/globdoc.cxx b/sw/source/uibase/globdoc/globdoc.cxx
new file mode 100644
index 0000000000..283b5a016a
--- /dev/null
+++ b/sw/source/uibase/globdoc/globdoc.cxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <comphelper/fileformat.h>
+#include <comphelper/classids.hxx>
+#include <osl/diagnose.h>
+#include <tools/globname.hxx>
+
+#include <swtypes.hxx>
+#include <globdoc.hxx>
+#include <strings.hrc>
+
+// Description: Register all filters
+
+
+SFX_IMPL_OBJECTFACTORY( SwGlobalDocShell, SvGlobalName(SO3_SWGLOB_CLASSID), "swriter/GlobalDocument" )
+
+SwGlobalDocShell::SwGlobalDocShell(SfxObjectCreateMode eMode ) :
+ SwDocShell(eMode)
+{
+}
+
+SwGlobalDocShell::~SwGlobalDocShell()
+{
+}
+
+void SwGlobalDocShell::FillClass( SvGlobalName * pClassName,
+ SotClipboardFormatId * pClipFormat,
+ OUString * pLongUserName,
+ sal_Int32 nVersion,
+ bool bTemplate /* = false */) const
+{
+ if (nVersion == SOFFICE_FILEFORMAT_60)
+ {
+ *pClassName = SvGlobalName( SO3_SWGLOB_CLASSID_60 );
+ *pClipFormat = SotClipboardFormatId::STARWRITERGLOB_60;
+ *pLongUserName = SwResId(STR_WRITER_GLOBALDOC_FULLTYPE);
+ OSL_ENSURE( !bTemplate, "No template for Writer Global" );
+ }
+ else if (nVersion == SOFFICE_FILEFORMAT_8)
+ {
+ *pClassName = SvGlobalName( SO3_SWGLOB_CLASSID_60 );
+ *pClipFormat = bTemplate ? SotClipboardFormatId::STARWRITERGLOB_8_TEMPLATE : SotClipboardFormatId::STARWRITERGLOB_8;
+ *pLongUserName = SwResId(STR_WRITER_GLOBALDOC_FULLTYPE);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/AccessibilityStatusBarControl.hxx b/sw/source/uibase/inc/AccessibilityStatusBarControl.hxx
new file mode 100644
index 0000000000..72940cdbce
--- /dev/null
+++ b/sw/source/uibase/inc/AccessibilityStatusBarControl.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/stbitem.hxx>
+#include <vcl/image.hxx>
+
+namespace sw
+{
+class AccessibilityStatusBarControl final : public SfxStatusBarControl
+{
+ sal_Int32 mnIssues;
+ Image maImageIssuesFound;
+ Image maImageIssuesNotFound;
+
+public:
+ SFX_DECL_STATUSBAR_CONTROL();
+
+ AccessibilityStatusBarControl(sal_uInt16 nSlotId, sal_uInt16 nId, StatusBar& rStb);
+ virtual ~AccessibilityStatusBarControl() override;
+
+ void StateChangedAtStatusBarControl(sal_uInt16 nSID, SfxItemState eState,
+ const SfxPoolItem* pState) override;
+ void Paint(const UserDrawEvent& rEvent) override;
+};
+
+} // end sw
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/DashedLine.hxx b/sw/source/uibase/inc/DashedLine.hxx
new file mode 100644
index 0000000000..f4b808ec29
--- /dev/null
+++ b/sw/source/uibase/inc/DashedLine.hxx
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DASHEDLINE_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_DASHEDLINE_HXX
+
+#include <vcl/ctrl.hxx>
+#include <viewopt.hxx>
+
+/** Class for displaying a dashed line in the Writer GUI.
+ */
+class SwDashedLine : public Control
+{
+ const Color& (SwViewOption::*m_pColorFn)() const;
+
+public:
+ SwDashedLine(vcl::Window* pParent, const Color& (SwViewOption::*pColorFn)() const);
+ virtual ~SwDashedLine() override;
+
+ virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/DateFormFieldDialog.hxx b/sw/source/uibase/inc/DateFormFieldDialog.hxx
new file mode 100644
index 0000000000..2b4573af7d
--- /dev/null
+++ b/sw/source/uibase/inc/DateFormFieldDialog.hxx
@@ -0,0 +1,54 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DATEFORMFIELDDIALOG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_DATEFORMFIELDDIALOG_HXX
+
+#include <vcl/weld.hxx>
+#include "numfmtlb.hxx"
+
+class SvNumberFormatter;
+class SwDoc;
+namespace sw::mark
+{
+class IDateFieldmark;
+}
+
+/// Dialog to specify the properties of date form field
+namespace sw
+{
+class DateFormFieldDialog final : public weld::GenericDialogController
+{
+private:
+ sw::mark::IDateFieldmark* m_pDateField;
+ SvNumberFormatter* m_pNumberFormatter;
+
+ std::unique_ptr<SwNumFormatTreeView> m_xFormatLB;
+
+ void Apply();
+ void InitControls();
+
+public:
+ DateFormFieldDialog(weld::Widget* pParent, sw::mark::IDateFieldmark* pDateField, SwDoc& rDoc);
+ virtual ~DateFormFieldDialog() override;
+
+ virtual short run() override
+ {
+ short nRet = GenericDialogController::run();
+ if (nRet == RET_OK)
+ Apply();
+ return nRet;
+ }
+};
+
+} // namespace sw
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/source/uibase/inc/DropDownFieldDialog.hxx b/sw/source/uibase/inc/DropDownFieldDialog.hxx
new file mode 100644
index 0000000000..b8b60f20c2
--- /dev/null
+++ b/sw/source/uibase/inc/DropDownFieldDialog.hxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DROPDOWNFIELDDIALOG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_DROPDOWNFIELDDIALOG_HXX
+
+#include <vcl/weld.hxx>
+
+class SwDropDownField;
+class SwField;
+class SwWrtShell;
+
+// Dialog to edit drop down field selection
+namespace sw
+{
+class DropDownFieldDialog final : public weld::GenericDialogController
+{
+ SwWrtShell &m_rSh;
+ SwDropDownField* m_pDropField;
+
+ weld::Button* m_pPressedButton;
+ std::unique_ptr<weld::TreeView> m_xListItemsLB;
+ std::unique_ptr<weld::Button> m_xOKPB;
+ std::unique_ptr<weld::Button> m_xPrevPB;
+ std::unique_ptr<weld::Button> m_xNextPB;
+ std::unique_ptr<weld::Button> m_xEditPB;
+
+ DECL_LINK(EditHdl, weld::Button&, void);
+ DECL_LINK(PrevHdl, weld::Button&, void);
+ DECL_LINK(NextHdl, weld::Button&, void);
+ void Apply();
+ DECL_LINK(DoubleClickHdl, weld::TreeView&, bool);
+public:
+ DropDownFieldDialog(weld::Widget *pParent, SwWrtShell &rSh,
+ SwField* pField, bool bPrevButton, bool bNextButton);
+ virtual ~DropDownFieldDialog() override;
+ bool PrevButtonPressed() const;
+ bool NextButtonPressed() const;
+ virtual short run() override
+ {
+ short nRet = GenericDialogController::run();
+ if (nRet == RET_OK)
+ Apply();
+ return nRet;
+ }
+};
+} //namespace sw
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/DropDownFormFieldDialog.hxx b/sw/source/uibase/inc/DropDownFormFieldDialog.hxx
new file mode 100644
index 0000000000..c6bcc98373
--- /dev/null
+++ b/sw/source/uibase/inc/DropDownFormFieldDialog.hxx
@@ -0,0 +1,65 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DROPDOWNFORMFIELDDIALOG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_DROPDOWNFORMFIELDDIALOG_HXX
+
+#include <vcl/weld.hxx>
+
+namespace sw::mark
+{
+class IFieldmark;
+}
+
+/// Dialog to specify the properties of drop-down form field
+namespace sw
+{
+class DropDownFormFieldDialog final : public weld::GenericDialogController
+{
+private:
+ mark::IFieldmark* m_pDropDownField;
+ bool m_bListHasChanged;
+
+ std::unique_ptr<weld::Entry> m_xListItemEntry;
+ std::unique_ptr<weld::Button> m_xListAddButton;
+
+ std::unique_ptr<weld::TreeView> m_xListItemsTreeView;
+
+ std::unique_ptr<weld::Button> m_xListRemoveButton;
+ std::unique_ptr<weld::Button> m_xListUpButton;
+ std::unique_ptr<weld::Button> m_xListDownButton;
+
+ DECL_LINK(ListChangedHdl, weld::TreeView&, void);
+ DECL_LINK(KeyPressedHdl, const KeyEvent&, bool);
+ DECL_LINK(EntryChangedHdl, weld::Entry&, void);
+ DECL_LINK(ButtonPushedHdl, weld::Button&, void);
+
+ void InitControls();
+ void AppendItemToList();
+ void UpdateButtons();
+ void Apply();
+
+public:
+ DropDownFormFieldDialog(weld::Widget* pParent, mark::IFieldmark* pDropDownField);
+ virtual ~DropDownFormFieldDialog() override;
+
+ virtual short run() override
+ {
+ short nRet = GenericDialogController::run();
+ if (nRet == RET_OK)
+ Apply();
+ return nRet;
+ }
+};
+
+} // namespace sw
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/source/uibase/inc/FrameControl.hxx b/sw/source/uibase/inc/FrameControl.hxx
new file mode 100644
index 0000000000..4043f834f9
--- /dev/null
+++ b/sw/source/uibase/inc/FrameControl.hxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_FRAMECONTROL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_FRAMECONTROL_HXX
+
+#include <vcl/InterimItemWindow.hxx>
+#include <vcl/virdev.hxx>
+
+#include "edtwin.hxx"
+
+class SwEditWin;
+class SwPageFrame;
+class SwFrame;
+class Point;
+
+/// Abstract interface to be implemented by writer FrameControls
+class SAL_LOPLUGIN_ANNOTATE("crosscast") ISwFrameControl
+{
+public:
+ virtual ~ISwFrameControl();
+ virtual void SetReadonly( bool bReadonly ) = 0;
+ virtual void ShowAll( bool bShow ) = 0;
+
+ /// Returns true if the point is inside the control.
+ virtual bool Contains( const Point &rDocPt ) const = 0;
+
+ virtual const SwFrame* GetFrame() = 0;
+ virtual SwEditWin* GetEditWin() = 0;
+ virtual weld::Button* GetButton() { return nullptr; };
+};
+
+class SwFrameControl final
+{
+ VclPtr<vcl::Window> mxWindow;
+ ISwFrameControl *mpIFace;
+public:
+ SwFrameControl( const VclPtr<vcl::Window> &pWindow );
+ ~SwFrameControl();
+
+ vcl::Window* GetWindow() { return mxWindow.get(); }
+ ISwFrameControl* GetIFacePtr() { return mpIFace; }
+
+ void SetReadonly( bool bReadonly ) { mpIFace->SetReadonly( bReadonly ); }
+ void ShowAll( bool bShow ) { mpIFace->ShowAll( bShow ); }
+ bool Contains( const Point &rDocPt ) const { return mpIFace->Contains( rDocPt ); }
+};
+
+/** Class sharing some MenuButton code
+ */
+class SwFrameMenuButtonBase : public InterimItemWindow, public ISwFrameControl
+{
+protected:
+ VclPtr<VirtualDevice> m_xVirDev;
+private:
+ VclPtr<SwEditWin> m_pEditWin;
+ const SwFrame* m_pFrame;
+
+protected:
+ virtual ~SwFrameMenuButtonBase() override { disposeOnce(); }
+ virtual void dispose() override;
+
+ void SetVirDevFont();
+
+public:
+ SwFrameMenuButtonBase(SwEditWin* pEditWin, const SwFrame* pFrame,
+ const OUString& rUIXMLDescription, const OUString& rID);
+
+ virtual const SwFrame* GetFrame() override { return m_pFrame; }
+ virtual SwEditWin* GetEditWin() override { return m_pEditWin; }
+ const SwPageFrame* GetPageFrame() const;
+
+ static const SwPageFrame* GetPageFrame(const SwFrame* pFrame);
+ static void SetVirDevFont(OutputDevice& rDevice);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/FrameControlsManager.hxx b/sw/source/uibase/inc/FrameControlsManager.hxx
new file mode 100644
index 0000000000..945534fcd3
--- /dev/null
+++ b/sw/source/uibase/inc/FrameControlsManager.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_FRAMECONTROLSMANAGER_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_FRAMECONTROLSMANAGER_HXX
+
+#include "FrameControl.hxx"
+
+#include <tools/gen.hxx>
+
+#include <map>
+#include <memory>
+
+class SwPageFrame;
+class SwEditWin;
+class SwContentFrame;
+class SwTextNode;
+class SwContentControl;
+
+typedef std::shared_ptr< SwFrameControl > SwFrameControlPtr;
+
+typedef std::map<const SwFrame*, SwFrameControlPtr> SwFrameControlPtrMap;
+
+/** A container for the Header/Footer, PageBreak, and Outline Content Visibility controls.
+*/
+class SwFrameControlsManager
+{
+ private:
+ VclPtr<SwEditWin> m_pEditWin;
+ std::map< FrameControlType, SwFrameControlPtrMap > m_aControls;
+
+ public:
+ SwFrameControlsManager( SwEditWin* pEditWin );
+ ~SwFrameControlsManager();
+ void dispose();
+
+ SwFrameControlPtr GetControl( FrameControlType eType, const SwFrame* pFrame );
+ void RemoveControls( const SwFrame* pFrame );
+ void RemoveControlsByType( FrameControlType eType, const SwFrame* pFrame );
+ void HideControls( FrameControlType eType );
+ void SetReadonlyControls( bool bReadonly );
+
+ // Helper methods
+ void SetHeaderFooterControl( const SwPageFrame* pPageFrame, FrameControlType eType, Point aOffset );
+ void SetPageBreakControl( const SwPageFrame* pPageFrame );
+ void SetUnfloatTableButton( const SwFlyFrame* pFlyFrame, bool bShow, Point aTopRightPixel = Point() );
+ void SetOutlineContentVisibilityButton(const SwContentFrame* pContentFrame);
+ void SetContentControlAliasButton( SwContentControl* pContentControl, Point aTopLeftPixel );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/HeaderFooterWin.hxx b/sw/source/uibase/inc/HeaderFooterWin.hxx
new file mode 100644
index 0000000000..6931e00f82
--- /dev/null
+++ b/sw/source/uibase/inc/HeaderFooterWin.hxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_HEADERFOOTERWIN_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_HEADERFOOTERWIN_HXX
+
+#include "edtwin.hxx"
+#include "DashedLine.hxx"
+#include "FrameControl.hxx"
+#include <vcl/timer.hxx>
+#include <drawinglayer/primitive2d/Primitive2DContainer.hxx>
+
+/**
+ * Button painter helper class used to paint a runtime button positioned to a writer frame.
+ * See header/footer button.
+ */
+class SwFrameButtonPainter
+{
+public:
+
+ static void PaintButton(drawinglayer::primitive2d::Primitive2DContainer& rSeq,
+ const tools::Rectangle& rRect, bool bOnTop);
+};
+
+class SwHeaderFooterWin;
+
+/** Class for the header and footer separator control window.
+
+ This control is showing the header / footer style name and provides
+ a few useful actions to the user.
+ */
+class SwHeaderFooterDashedLine final : public SwDashedLine, public ISwFrameControl
+{
+private:
+ VclPtr<SwHeaderFooterWin> m_pWin;
+ VclPtr<SwEditWin> m_pEditWin;
+ const SwFrame* m_pFrame;
+ bool m_bIsHeader;
+
+ void EnsureWin();
+
+ bool IsOnScreen();
+
+public:
+ SwHeaderFooterDashedLine(SwEditWin* pEditWin, const SwFrame *pFrame, bool bIsHeader);
+
+ virtual ~SwHeaderFooterDashedLine() override { disposeOnce(); }
+ virtual void dispose() override { m_pWin.disposeAndClear(); m_pEditWin.clear(); SwDashedLine::dispose(); }
+
+ virtual const SwFrame* GetFrame() override { return m_pFrame; }
+ virtual SwEditWin* GetEditWin() override { return m_pEditWin; }
+ virtual void ShowAll(bool bShow) override;
+ virtual bool Contains(const Point &rDocPt) const override;
+ virtual void SetReadonly(bool bReadonly) override;
+
+ void SetOffset( Point aOffset, tools::Long nXLineStart, tools::Long nXLineEnd );
+ bool IsHeader() const { return m_bIsHeader; };
+};
+
+class SwHeaderFooterWin final : public InterimItemWindow
+{
+ std::unique_ptr<weld::MenuButton> m_xMenuButton;
+ std::unique_ptr<weld::Button> m_xPushButton;
+ VclPtr<SwEditWin> m_pEditWin;
+ VclPtr<VirtualDevice> m_xVirDev;
+ const SwFrame* m_pFrame;
+ OUString m_sLabel;
+ bool m_bIsHeader;
+ bool m_bIsAppearing;
+ int m_nFadeRate;
+ Timer m_aFadeTimer;
+
+public:
+ SwHeaderFooterWin(SwEditWin *pEditWin, const SwFrame *pFrame, bool bHeader);
+ virtual ~SwHeaderFooterWin( ) override;
+ virtual void dispose() override;
+
+ void SetOffset(Point aOffset);
+ void ShowAll(bool bShow);
+ bool Contains(const Point &rDocPt) const;
+
+ bool IsEmptyHeaderFooter( ) const;
+
+ void ExecuteCommand(std::u16string_view rIdent);
+
+private:
+ DECL_LINK(FadeHandler, Timer *, void);
+ DECL_LINK(ClickHdl, weld::Button&, void);
+ DECL_LINK(SelectHdl, const OUString&, void);
+ void PaintButton();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/OutlineContentVisibilityWin.hxx b/sw/source/uibase/inc/OutlineContentVisibilityWin.hxx
new file mode 100644
index 0000000000..a03c3c1f1e
--- /dev/null
+++ b/sw/source/uibase/inc/OutlineContentVisibilityWin.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <vcl/InterimItemWindow.hxx>
+#include "edtwin.hxx"
+#include "FrameControl.hxx"
+
+enum class ButtonSymbol
+{
+ SHOW,
+ HIDE,
+ NONE
+};
+
+class SwOutlineContentVisibilityWin final : public InterimItemWindow, public ISwFrameControl
+{
+private:
+ std::unique_ptr<weld::Button> m_xShowBtn;
+ std::unique_ptr<weld::Button> m_xHideBtn;
+
+ VclPtr<SwEditWin> m_pEditWin;
+ const SwFrame* m_pFrame;
+ int m_nDelayAppearing; ///< Before we show the control, wait a few timer ticks to avoid appearing with every mouse over.
+ Timer m_aDelayTimer;
+ bool m_bDestroyed;
+ size_t m_nOutlinePos;
+
+public:
+ SwOutlineContentVisibilityWin(SwEditWin* pEditWin, const SwFrame* pFrame);
+ virtual ~SwOutlineContentVisibilityWin() override { disposeOnce(); }
+ virtual void dispose() override;
+
+ virtual void ShowAll(bool bShow) override;
+ virtual bool Contains(const Point& rDocPt) const override;
+ virtual void SetReadonly(bool /*bReadonly*/) override {}
+ virtual const SwFrame* GetFrame() override { return m_pFrame; }
+ virtual SwEditWin* GetEditWin() override { return m_pEditWin; }
+
+ void Set();
+
+ void SetSymbol(ButtonSymbol eTyle);
+ ButtonSymbol GetSymbol() const;
+
+private:
+ DECL_LINK(DelayAppearHandler, Timer*, void);
+ DECL_LINK(MousePressHdl, const MouseEvent&, bool);
+ DECL_LINK(MouseMoveHdl, const MouseEvent&, bool);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/PageBreakWin.hxx b/sw/source/uibase/inc/PageBreakWin.hxx
new file mode 100644
index 0000000000..ee494f78ba
--- /dev/null
+++ b/sw/source/uibase/inc/PageBreakWin.hxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_PAGEBREAKWIN_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_PAGEBREAKWIN_HXX
+
+#include "edtwin.hxx"
+#include "DashedLine.hxx"
+#include "FrameControl.hxx"
+#include <vcl/timer.hxx>
+#include <optional>
+
+class Menu;
+class SwPageFrame;
+
+class SwPageBreakWin;
+
+/** Class for the page break control window.
+
+ This control shows a line indicating a manual page break and a
+ button providing a few actions on that page break.
+ */
+class SwBreakDashedLine final : public SwDashedLine, public ISwFrameControl
+{
+private:
+ VclPtr<SwPageBreakWin> m_pWin;
+ VclPtr<SwEditWin> m_pEditWin;
+ std::optional<Point> m_xMousePt;
+ ::tools::Rectangle m_aBtnRect;
+ const SwFrame* m_pFrame;
+
+ SwPageBreakWin& GetOrCreateWin();
+
+public:
+ SwBreakDashedLine(SwEditWin* pEditWin, const SwFrame *pFrame);
+
+ virtual ~SwBreakDashedLine() override { disposeOnce(); }
+ virtual void dispose() override { m_pWin.disposeAndClear(); m_pEditWin.clear(); SwDashedLine::dispose(); }
+
+ virtual void MouseMove(const MouseEvent& rMEvt) override;
+
+ virtual const SwFrame* GetFrame() override { return m_pFrame; }
+ virtual SwEditWin* GetEditWin() override { return m_pEditWin; }
+ virtual void ShowAll(bool bShow) override;
+ virtual bool Contains(const Point &rDocPt) const override;
+ virtual void SetReadonly(bool bReadonly) override;
+
+ void execute(std::u16string_view rIdent);
+
+ virtual FactoryFunction GetUITestFactory() const override;
+
+ void UpdatePosition(const std::optional<Point>& xEvtPt = std::optional<Point>());
+ void DestroyWin();
+};
+
+class SwPageBreakWin final : public InterimItemWindow
+{
+ std::unique_ptr<weld::MenuButton> m_xMenuButton;
+ VclPtr<SwBreakDashedLine> m_pLine;
+ VclPtr<SwEditWin> m_pEditWin;
+ VclPtr<VirtualDevice> m_xVirDev;
+ const SwFrame* m_pFrame;
+ bool m_bIsAppearing;
+ int m_nFadeRate;
+ int m_nDelayAppearing; ///< Before we show the control, let it transparent for a few timer ticks to avoid appearing with every mouse over.
+ Timer m_aFadeTimer;
+ bool m_bDestroyed;
+
+public:
+ SwPageBreakWin(SwBreakDashedLine* pLine, SwEditWin* pEditWin, const SwFrame *pFrame);
+ virtual ~SwPageBreakWin() override;
+ virtual void dispose() override;
+
+ void Fade( bool bFadeIn );
+
+ void SetRectanglePixel(const ::tools::Rectangle& rRect);
+
+private:
+ DECL_LINK( FadeHandler, Timer *, void );
+ /// Hide the button when the menu is toggled closed, e.g by clicking outside
+ DECL_LINK(ToggleHdl, weld::Toggleable&, void);
+ DECL_LINK(SelectHdl, const OUString&, void);
+ void PaintButton();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/SidebarWindowsConsts.hxx b/sw/source/uibase/inc/SidebarWindowsConsts.hxx
new file mode 100644
index 0000000000..2e920b9907
--- /dev/null
+++ b/sw/source/uibase/inc/SidebarWindowsConsts.hxx
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SIDEBARWINDOWSCONSTS_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SIDEBARWINDOWSCONSTS_HXX
+
+#include <sal/types.h>
+
+namespace sw::sidebarwindows
+{
+const sal_Int8 ANCHORLINE_WIDTH = 1;
+
+} // end of namespace sw::sidebarwindows
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/SwSpellDialogChildWindow.hxx b/sw/source/uibase/inc/SwSpellDialogChildWindow.hxx
new file mode 100644
index 0000000000..8599256da2
--- /dev/null
+++ b/sw/source/uibase/inc/SwSpellDialogChildWindow.hxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SWSPELLDIALOGCHILDWINDOW_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SWSPELLDIALOGCHILDWINDOW_HXX
+
+#include <svx/SpellDialogChildWindow.hxx>
+#include <view.hxx>
+
+class SwWrtShell;
+struct SpellState;
+class SwSpellDialogChildWindow final
+ : public svx::SpellDialogChildWindow
+{
+ bool m_bIsGrammarCheckingOn;
+ std::unique_ptr<SpellState> m_pSpellState;
+
+ SwWrtShell* GetWrtShell_Impl();
+ void MakeTextSelection_Impl(SwWrtShell& rSh, ShellMode eSelMode);
+ bool FindNextDrawTextError_Impl(SwWrtShell& rSh);
+ bool SpellDrawText_Impl(SwWrtShell& rSh, svx::SpellPortions& rPortions);
+ void LockFocusNotification(bool bLock);
+
+ virtual svx::SpellPortions GetNextWrongSentence(bool bRecheck) override;
+ virtual void ApplyChangedSentence(const svx::SpellPortions& rChanged, bool bRecheck) override;
+ virtual void AddAutoCorrection(const OUString& rOld, const OUString& rNew, LanguageType eLanguage) override;
+ virtual bool HasAutoCorrection() override;
+ virtual bool HasGrammarChecking() override;
+ virtual bool IsGrammarChecking() override;
+ virtual void SetGrammarChecking(bool bOn) override;
+ virtual void GetFocus() override;
+ virtual void LoseFocus() override;
+
+public:
+ SwSpellDialogChildWindow (
+ vcl::Window*pParent,
+ sal_uInt16 nId,
+ SfxBindings* pBindings,
+ SfxChildWinInfo* pInfo);
+ virtual ~SwSpellDialogChildWindow() override;
+
+ SFX_DECL_CHILDWINDOW_WITHID(SwSpellDialogChildWindow);
+
+ void InvalidateSpellDialog();
+
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/SwXFilterOptions.hxx b/sw/source/uibase/inc/SwXFilterOptions.hxx
new file mode 100644
index 0000000000..2ca1aabe68
--- /dev/null
+++ b/sw/source/uibase/inc/SwXFilterOptions.hxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SWXFILTEROPTIONS_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SWXFILTEROPTIONS_HXX
+
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/beans/XPropertyAccess.hpp>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/document/XImporter.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase.hxx>
+
+namespace com::sun::star::io { class XInputStream; }
+
+class SwXFilterOptions final : public ::cppu::WeakImplHelper<
+ css::beans::XPropertyAccess,
+ css::ui::dialogs::XExecutableDialog,
+ css::document::XImporter,
+ css::document::XExporter,
+ css::lang::XInitialization,
+ css::lang::XServiceInfo >
+{
+ OUString m_sFilterOptions;
+
+ css::uno::Reference< css::io::XInputStream > m_xInputStream;
+ css::uno::Reference< css::lang::XComponent > m_xModel;
+ css::uno::Reference< css::awt::XWindow > m_xDialogParent;
+
+public:
+ SwXFilterOptions();
+ virtual ~SwXFilterOptions() override;
+
+ // XPropertyAccess
+ virtual css::uno::Sequence< css::beans::PropertyValue >
+ SAL_CALL getPropertyValues() override;
+ virtual void SAL_CALL setPropertyValues( const css::uno::Sequence<
+ css::beans::PropertyValue >& aProps ) override;
+
+ // XExecutableDialog
+ virtual void SAL_CALL setTitle( const OUString& aTitle ) override;
+ virtual sal_Int16 SAL_CALL execute() override;
+
+ // XImporter
+ virtual void SAL_CALL setTargetDocument( const css::uno::Reference<
+ css::lang::XComponent >& xDoc ) override;
+
+ // XExporter
+ virtual void SAL_CALL setSourceDocument( const css::uno::Reference<
+ css::lang::XComponent >& xDoc ) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& rArguments) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/UnfloatTableButton.hxx b/sw/source/uibase/inc/UnfloatTableButton.hxx
new file mode 100644
index 0000000000..8803b51691
--- /dev/null
+++ b/sw/source/uibase/inc/UnfloatTableButton.hxx
@@ -0,0 +1,50 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_DOCVW_UNFLOATTABLEBUTTON_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_DOCVW_UNFLOATTABLEBUTTON_HXX
+
+#include "edtwin.hxx"
+#include "FrameControl.hxx"
+
+/** Class for unfloat table button
+ *
+ * This unfloat button is used to convert a floating table into a simple writer table embedded to the text body.
+ * This unfloat operation is useful typically for documents imported from MSO file formats containing
+ * multi-page floating tables. In case of a multi-page table the text frame cuts off the table because
+ * the frame can't span across multiple pages. With unfloating we can get a multi-page table without
+ * floating properties.
+ *
+ */
+class UnfloatTableButton final : public SwFrameMenuButtonBase
+{
+ std::unique_ptr<weld::Button> m_xPushButton;
+ OUString m_sLabel;
+
+public:
+ UnfloatTableButton(SwEditWin* pEditWin, const SwFrame* pFrame);
+ virtual void dispose() override;
+ virtual ~UnfloatTableButton() override;
+
+ void SetOffset(Point aTopRightPixel);
+
+ virtual void ShowAll(bool bShow) override;
+ virtual bool Contains(const Point& rDocPt) const override;
+
+ virtual void SetReadonly(bool bReadonly) override;
+ weld::Button* GetButton() override;
+
+private:
+ DECL_LINK(ClickHdl, weld::Button&, void);
+ void PaintButton();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/source/uibase/inc/abstract.hxx b/sw/source/uibase/inc/abstract.hxx
new file mode 100644
index 0000000000..ded62f0ff5
--- /dev/null
+++ b/sw/source/uibase/inc/abstract.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/basedlgs.hxx>
+
+class SwInsertAbstractDlg final : public SfxDialogController
+{
+ std::unique_ptr<weld::SpinButton> m_xLevelNF;
+ std::unique_ptr<weld::SpinButton> m_xParaNF;
+
+public:
+ SwInsertAbstractDlg(weld::Window* pParent);
+ virtual ~SwInsertAbstractDlg() override;
+
+ sal_uInt8 GetLevel() const;
+ sal_uInt8 GetPara() const;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/addrdlg.hxx b/sw/source/uibase/inc/addrdlg.hxx
new file mode 100644
index 0000000000..66706915aa
--- /dev/null
+++ b/sw/source/uibase/inc/addrdlg.hxx
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_ADDRDLG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_ADDRDLG_HXX
+
+#include <sfx2/basedlgs.hxx>
+
+class SwAddrDlg final : public SfxSingleTabDialogController
+{
+public:
+ SwAddrDlg(weld::Window* pParent, const SfxItemSet& rSet);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/annotsh.hxx b/sw/source/uibase/inc/annotsh.hxx
new file mode 100644
index 0000000000..7c3a5fef9e
--- /dev/null
+++ b/sw/source/uibase/inc/annotsh.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_ANNOTSH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_ANNOTSH_HXX
+
+#include <sfx2/shell.hxx>
+#include <shellid.hxx>
+#include <swmodule.hxx>
+#include <unotools/caserotate.hxx>
+
+class SwView;
+class SwAnnotationShell final : public SfxShell
+{
+ SwView& m_rView;
+ RotateTransliteration m_aRotateCase;
+
+public:
+ SFX_DECL_INTERFACE(SW_ANNOTATIONSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwAnnotationShell(SwView&);
+ virtual ~SwAnnotationShell() override;
+
+ static void StateDisableItems(SfxItemSet &);
+ void Exec(SfxRequest &);
+
+ void GetState(SfxItemSet &);
+ void StateInsert(SfxItemSet &rSet);
+
+ void NoteExec(SfxRequest const &);
+ void GetNoteState(SfxItemSet &);
+
+ void ExecLingu(SfxRequest &rReq);
+ void GetLinguState(SfxItemSet &);
+
+ void ExecClpbrd(SfxRequest const &rReq);
+ void StateClpbrd(SfxItemSet &rSet);
+
+ void ExecTransliteration(SfxRequest const &);
+ void ExecRotateTransliteration(SfxRequest const &);
+
+ void ExecUndo(SfxRequest &rReq);
+ void StateUndo(SfxItemSet &rSet);
+
+ static void StateStatusLine(SfxItemSet &rSet);
+
+ void InsertSymbol(SfxRequest& rReq);
+
+ void ExecSearch(SfxRequest&);
+ void StateSearch(SfxItemSet &);
+
+ virtual SfxUndoManager*
+ GetUndoManager() override;
+
+ static SfxItemPool* GetAnnotationPool(SwView const & rV);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/ascfldlg.hxx b/sw/source/uibase/inc/ascfldlg.hxx
new file mode 100644
index 0000000000..f62e6574f2
--- /dev/null
+++ b/sw/source/uibase/inc/ascfldlg.hxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_ASCFLDLG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_ASCFLDLG_HXX
+
+#include <sfx2/basedlgs.hxx>
+#include <svx/txencbox.hxx>
+#include <svx/langbox.hxx>
+#include <tools/lineend.hxx>
+
+class SwAsciiOptions;
+class SvStream;
+class SwDocShell;
+
+class SwAsciiFilterDlg final : public SfxDialogController
+{
+ bool m_bSaveLineStatus;
+ OUString m_sExtraData;
+
+ std::unique_ptr<SvxTextEncodingBox> m_xCharSetLB;
+ std::unique_ptr<weld::Label> m_xFontFT;
+ std::unique_ptr<weld::ComboBox> m_xFontLB;
+ std::unique_ptr<weld::Label> m_xLanguageFT;
+ std::unique_ptr<SvxLanguageBox> m_xLanguageLB;
+ std::unique_ptr<weld::RadioButton> m_xCRLF_RB;
+ std::unique_ptr<weld::RadioButton> m_xCR_RB;
+ std::unique_ptr<weld::RadioButton> m_xLF_RB;
+ std::unique_ptr<weld::CheckButton> m_xIncludeBOM_CB;
+
+ DECL_LINK(CharSetSelHdl, weld::ComboBox&, void);
+ DECL_LINK(LineEndHdl, weld::Toggleable&, void);
+ void SetCRLF(LineEnd eEnd);
+ LineEnd GetCRLF() const;
+ void SetIncludeBOM(bool bIncludeBOM);
+ bool GetIncludeBOM() const;
+ void UpdateIncludeBOMSensitiveState();
+
+public:
+ // CTOR: for import - pStream is the inputstream
+ // for export - pStream must be 0
+ SwAsciiFilterDlg(weld::Window* pParent, SwDocShell& rDocSh, SvStream* pStream);
+ virtual ~SwAsciiFilterDlg() override;
+
+ void FillOptions(SwAsciiOptions& rOptions);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/autoformatpreview.hxx b/sw/source/uibase/inc/autoformatpreview.hxx
new file mode 100644
index 0000000000..e1cb91ca68
--- /dev/null
+++ b/sw/source/uibase/inc/autoformatpreview.hxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_AUTOFORMATPREVIEW_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_AUTOFORMATPREVIEW_HXX
+
+#include <com/sun/star/i18n/XBreakIterator.hpp>
+#include <sal/types.h>
+#include <svx/framelinkarray.hxx>
+#include <svl/numformat.hxx>
+#include <tools/gen.hxx>
+#include <rtl/ustring.hxx>
+#include <vcl/customweld.hxx>
+#include <vcl/font.hxx>
+
+#include "wrtsh.hxx"
+#include <tblafmt.hxx>
+
+class AutoFormatPreview final : public weld::CustomWidgetController
+{
+public:
+ AutoFormatPreview();
+
+ void NotifyChange(const SwTableAutoFormat& rNewData);
+
+ void DetectRTL(SwWrtShell const* pWrtShell);
+
+private:
+ SwTableAutoFormat maCurrentData;
+ svx::frame::Array maArray; /// Implementation to draw the frame borders.
+ bool mbFitWidth;
+ bool mbRTL;
+ Size maPreviousSize;
+ tools::Long mnLabelColumnWidth;
+ tools::Long mnDataColumnWidth1;
+ tools::Long mnDataColumnWidth2;
+ tools::Long mnRowHeight;
+ const OUString maStringJan;
+ const OUString maStringFeb;
+ const OUString maStringMar;
+ const OUString maStringNorth;
+ const OUString maStringMid;
+ const OUString maStringSouth;
+ const OUString maStringSum;
+ std::unique_ptr<SvNumberFormatter> mxNumFormat;
+
+ uno::Reference<i18n::XBreakIterator> m_xBreak;
+
+ void Init();
+ virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
+ virtual void Resize() override;
+ void CalcCellArray(bool bFitWidth);
+ void CalcLineMap();
+ void PaintCells(vcl::RenderContext& rRenderContext);
+
+ sal_uInt8 GetFormatIndex(size_t nCol, size_t nRow) const;
+
+ void DrawString(vcl::RenderContext& rRenderContext, size_t nCol, size_t nRow);
+ void DrawBackground(vcl::RenderContext& rRenderContext);
+
+ void MakeFonts(vcl::RenderContext const& rRenderContext, sal_uInt8 nIndex, vcl::Font& rFont,
+ vcl::Font& rCJKFont, vcl::Font& rCTLFont);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/barcfg.hxx b/sw/source/uibase/inc/barcfg.hxx
new file mode 100644
index 0000000000..96060ad288
--- /dev/null
+++ b/sw/source/uibase/inc/barcfg.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_BARCFG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_BARCFG_HXX
+
+#include <sfx2/toolbarids.hxx>
+#include <unotools/configitem.hxx>
+
+enum class SelectionType : sal_Int32;
+
+class SwToolbarConfigItem final : public utl::ConfigItem
+{
+ sal_Int32 m_aTbxIdArray[5];
+
+ static css::uno::Sequence<OUString> GetPropertyNames();
+
+ virtual void ImplCommit() override;
+
+public:
+ SwToolbarConfigItem(bool bWeb);
+ virtual ~SwToolbarConfigItem() override;
+
+ virtual void Notify(const css::uno::Sequence<OUString>& aPropertyNames) override;
+
+ void SetTopToolbar(SelectionType nSelType, ToolbarId eBarId);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/basesh.hxx b/sw/source/uibase/inc/basesh.hxx
new file mode 100644
index 0000000000..8937f817cb
--- /dev/null
+++ b/sw/source/uibase/inc/basesh.hxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_BASESH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_BASESH_HXX
+
+#include <shellid.hxx>
+
+#include <tools/link.hxx>
+#include <sfx2/module.hxx>
+#include <sfx2/shell.hxx>
+#include <mdiexp.hxx>
+#include <memory>
+#include <set>
+#include <vector>
+
+class SwPaM;
+class SwWrtShell;
+class SwView;
+class SfxItemSet;
+class SwCursorShell;
+
+struct DBTextStruct_Impl;
+class SW_DLLPUBLIC SwBaseShell: public SfxShell
+{
+ SwView &m_rView;
+
+ // DragMode
+ static FlyMode s_eFrameMode;
+
+ // Bug 75078 - if in GetState the async call of GetGraphic returns
+ // synch, the set the state directly into the itemset
+ SfxItemSet* m_pGetStateSet;
+
+ // Update-Timer for graphic
+ std::set<sal_uInt16> m_aGrfUpdateSlots;
+
+ DECL_DLLPRIVATE_LINK( GraphicArrivedHdl, SwCursorShell&, void );
+
+protected:
+ SwWrtShell& GetShell();
+ SwWrtShell* GetShellPtr();
+
+ SwView& GetView() { return m_rView; }
+ void SetGetStateSet( SfxItemSet* p ) { m_pGetStateSet = p; }
+ bool AddGrfUpdateSlot( sal_uInt16 nSlot ){ return m_aGrfUpdateSlots.insert( nSlot ).second; }
+
+ DECL_DLLPRIVATE_LINK( InsertDBTextHdl, void*, void );
+
+ void InsertURLButton( const OUString& rURL, const OUString& rTarget, const OUString& rText );
+ void InsertTable( SfxRequest& _rRequest );
+
+public:
+ SwBaseShell(SwView &rShell);
+ virtual ~SwBaseShell() override;
+
+ SFX_DECL_INTERFACE(SW_BASESHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ void ExecDelete(SfxRequest &);
+
+ void ExecClpbrd(SfxRequest &);
+ void StateClpbrd(SfxItemSet &);
+
+ void ExecUndo(SfxRequest &);
+ void StateUndo(SfxItemSet &);
+
+ void Execute(SfxRequest &);
+ void GetState(SfxItemSet &);
+ void StateStyle(SfxItemSet &);
+
+ void ExecuteGallery(SfxRequest&);
+ void GetGalleryState(SfxItemSet&);
+
+ void ExecDlg(SfxRequest &);
+
+ void ExecTextCtrl(SfxRequest& rReq);
+ void GetTextFontCtrlState(SfxItemSet& rSet);
+ void GetTextCtrlState(SfxItemSet& rSet);
+ void GetBorderState(SfxItemSet &rSet);
+ void GetBckColState(SfxItemSet &rSet);
+
+ void ExecBckCol(SfxRequest& rReq);
+ void SetWrapMode( sal_uInt16 nSlot );
+
+ static void StateDisableItems(SfxItemSet &);
+
+ void EditRegionDialog(SfxRequest const & rReq);
+ void InsertRegionDialog(SfxRequest& rReq);
+
+ void ExecField(SfxRequest const & rReq);
+
+ static void SetFrameMode( FlyMode eMode, SwWrtShell *pShell ); // with update!
+ static void SetFrameMode_( FlyMode eMode ) { s_eFrameMode = eMode; }
+ static FlyMode GetFrameMode() { return s_eFrameMode; }
+
+ // duplicate rOrig and rOrig's multi-selection Ring so the first element of the returned
+ // vector can be used equivalently to rOrig to affect the same selections
+ static std::shared_ptr<std::vector<std::unique_ptr<SwPaM>>> CopyPaMRing(SwPaM& rOrig);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/beziersh.hxx b/sw/source/uibase/inc/beziersh.hxx
new file mode 100644
index 0000000000..47eced7d3a
--- /dev/null
+++ b/sw/source/uibase/inc/beziersh.hxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_BEZIERSH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_BEZIERSH_HXX
+
+#include "basesh.hxx"
+
+class SwBezierShell final : public SwBaseShell
+{
+public:
+ SFX_DECL_INTERFACE(SW_BEZIERSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwBezierShell(SwView& rView);
+
+ void GetState(SfxItemSet&);
+ void Execute(SfxRequest const&);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/bmpwin.hxx b/sw/source/uibase/inc/bmpwin.hxx
new file mode 100644
index 0000000000..b05700a964
--- /dev/null
+++ b/sw/source/uibase/inc/bmpwin.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_BMPWIN_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_BMPWIN_HXX
+
+#include <vcl/customweld.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/graph.hxx>
+
+// extended page for graphics
+class BmpWindow final : public weld::CustomWidgetController
+{
+private:
+ Graphic m_aGraphic;
+ BitmapEx m_aBmp;
+
+ bool m_bHorz : 1;
+ bool m_bVert : 1;
+ bool m_bGraphic : 1;
+
+ virtual void Paint(vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle& rRect) override;
+
+ virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override;
+
+public:
+ BmpWindow();
+ virtual ~BmpWindow() override;
+ void MirrorVert(bool bMirror) { m_bVert = bMirror; Invalidate(); }
+ void MirrorHorz(bool bMirror) { m_bHorz = bMirror; Invalidate(); }
+ void SetGraphic(const Graphic& rGrf);
+ void SetBitmapEx(const BitmapEx& rGrf);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/bookctrl.hxx b/sw/source/uibase/inc/bookctrl.hxx
new file mode 100644
index 0000000000..7d6b8d4baf
--- /dev/null
+++ b/sw/source/uibase/inc/bookctrl.hxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_BOOKCTRL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_BOOKCTRL_HXX
+
+#include <sfx2/stbitem.hxx>
+
+class SwBookmarkControl final : public SfxStatusBarControl
+{
+ virtual void Command(const CommandEvent& rCEvt) override;
+
+public:
+ virtual void StateChangedAtStatusBarControl(sal_uInt16 nSID, SfxItemState eState,
+ const SfxPoolItem* pState) override;
+ virtual void Paint(const UserDrawEvent& rEvt) override;
+
+ SFX_DECL_STATUSBAR_CONTROL();
+
+ SwBookmarkControl(sal_uInt16 nSlotId, sal_uInt16 nId, StatusBar& rStb);
+ virtual ~SwBookmarkControl() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/bookmark.hxx b/sw/source/uibase/inc/bookmark.hxx
new file mode 100644
index 0000000000..8017e146d7
--- /dev/null
+++ b/sw/source/uibase/inc/bookmark.hxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/basedlgs.hxx>
+#include <vcl/weld.hxx>
+#include <IMark.hxx>
+#include "condedit.hxx"
+
+class SwWrtShell;
+class SfxRequest;
+
+class BookmarkTable
+{
+ std::unique_ptr<weld::TreeView> m_xControl;
+ std::unique_ptr<weld::TreeIter> GetRowByBookmarkName(const OUString& sName);
+public:
+ BookmarkTable(std::unique_ptr<weld::TreeView> xControl);
+ void InsertBookmark(SwWrtShell & rSh, sw::mark::IMark* pMark);
+ bool SelectByName(const OUString& sName);
+ sw::mark::IMark* GetBookmarkByName(const OUString& sName);
+ OUString GetNameProposal() const;
+
+ void unselect_all() { m_xControl->unselect_all(); }
+ bool has_focus() const { return m_xControl->has_focus(); }
+ std::unique_ptr<weld::TreeIter> get_selected() const;
+ void clear() { m_xControl->clear(); }
+ void select(const weld::TreeIter& rIter) { m_xControl->select(rIter); }
+ void remove_selection() { m_xControl->remove_selection(); }
+ OUString get_text(const weld::TreeIter& rIter) const { return m_xControl->get_text(rIter, 2); }
+ OUString get_id(const weld::TreeIter& rIter) const { return m_xControl->get_id(rIter); }
+ void set_sort_indicator(TriState eState, int nColumn = -1) { m_xControl->set_sort_indicator(eState, nColumn); }
+ void selected_foreach(const std::function<bool(weld::TreeIter&)>& func) { m_xControl->selected_foreach(func); }
+
+ void connect_changed(const Link<weld::TreeView&, void>& rLink) { m_xControl->connect_changed(rLink); }
+ void connect_row_activated(const Link<weld::TreeView&, bool>& rLink) { m_xControl->connect_row_activated(rLink); }
+ void connect_column_clicked(const Link<int, void>& rLink) { m_xControl->connect_column_clicked(rLink); }
+ void connect_editing(const Link<const weld::TreeIter&, bool>& rStartLink,
+ const Link<const weld::TreeView::iter_string&, bool>& rEndLink) { m_xControl->connect_editing(rStartLink, rEndLink); }
+ void set_column_editables(::std::vector<bool> const& rEditables) { m_xControl->set_column_editables(rEditables); }
+ void start_editing(weld::TreeIter const& rIter) { m_xControl->start_editing(rIter); }
+ void make_sorted() { m_xControl->make_sorted(); }
+ bool get_sort_order() const { return m_xControl->get_sort_order(); }
+ void set_sort_order(bool bAscending) { m_xControl->set_sort_order(bAscending); }
+ int get_sort_column() const { return m_xControl->get_sort_column(); }
+ void set_sort_column(int nColumn) { m_xControl->set_sort_column(nColumn); }
+
+ static constexpr OUString aForbiddenChars = u"/\\@*?\",#"_ustr;
+ static const char s_cSeparator;
+};
+
+class SwInsertBookmarkDlg final : public SfxDialogController
+{
+ SwWrtShell& m_rSh;
+ std::vector<std::pair<sw::mark::IMark*, OUString>> m_aTableBookmarks;
+ sal_Int32 m_nLastBookmarksCount;
+ bool m_bSorted;
+ bool m_bAreProtected;
+
+ std::unique_ptr<weld::Entry> m_xEditBox;
+ std::unique_ptr<weld::Button> m_xInsertBtn;
+ std::unique_ptr<weld::Button> m_xDeleteBtn;
+ std::unique_ptr<weld::Button> m_xGotoBtn;
+ std::unique_ptr<weld::Button> m_xEditTextBtn;
+ std::unique_ptr<weld::Button> m_xRenameBtn;
+ std::unique_ptr<weld::CheckButton> m_xHideCB;
+ std::unique_ptr<weld::Label> m_xConditionFT;
+ std::unique_ptr<ConditionEdit> m_xConditionED;
+ std::unique_ptr<BookmarkTable> m_xBookmarksBox;
+ std::unique_ptr<weld::Label> m_xForbiddenChars;
+
+ DECL_LINK(ModifyHdl, weld::Entry&, void);
+ DECL_LINK(InsertHdl, weld::Button&, void);
+ DECL_LINK(DeleteHdl, weld::Button&, void);
+ DECL_LINK(EditTextHdl, weld::Button&, void);
+ DECL_LINK(RenameHdl, weld::Button&, void);
+ DECL_LINK(GotoHdl, weld::Button&, void);
+ DECL_LINK(SelectionChangedHdl, weld::TreeView&, void);
+ DECL_LINK(DoubleClickHdl, weld::TreeView&, bool);
+ DECL_LINK(HeaderBarClick, int, void);
+ DECL_LINK(ChangeHideHdl, weld::Toggleable&, void);
+ DECL_LINK(EditingHdl, weld::TreeIter const&, bool);
+ DECL_LINK(EditedHdl, weld::TreeView::iter_string const&, bool);
+
+ // Fill table with bookmarks
+ void PopulateTable();
+ /**
+ * Check if displayed bookmarks are up-to date, if not update them.
+ * @return True if no update was needed.
+ */
+ bool ValidateBookmarks();
+ bool HaveBookmarksChanged();
+ void GotoSelectedBookmark();
+ void SelectionChanged();
+
+public:
+ SwInsertBookmarkDlg(weld::Window* pParent, SwWrtShell& rSh, OUString const* pSelected);
+ virtual ~SwInsertBookmarkDlg() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/break.hxx b/sw/source/uibase/inc/break.hxx
new file mode 100644
index 0000000000..0e39075107
--- /dev/null
+++ b/sw/source/uibase/inc/break.hxx
@@ -0,0 +1,69 @@
+
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_BREAK_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_BREAK_HXX
+
+#include <vcl/weld.hxx>
+#include <optional>
+
+class SwWrtShell;
+enum class SwLineBreakClear;
+
+class SwBreakDlg final : public weld::GenericDialogController
+{
+ std::unique_ptr<weld::RadioButton> m_xLineBtn;
+ std::unique_ptr<weld::Label> m_xLineClearText;
+ std::unique_ptr<weld::ComboBox> m_xLineClearBox;
+ std::unique_ptr<weld::RadioButton> m_xColumnBtn;
+ std::unique_ptr<weld::RadioButton> m_xPageBtn;
+ std::unique_ptr<weld::Label> m_xPageCollText;
+ std::unique_ptr<weld::ComboBox> m_xPageCollBox;
+ std::unique_ptr<weld::CheckButton> m_xPageNumBox;
+ std::unique_ptr<weld::SpinButton> m_xPageNumEdit;
+ std::unique_ptr<weld::Button> m_xOkBtn;
+
+ SwWrtShell& m_rSh;
+ OUString m_aTemplate;
+ sal_uInt16 m_nKind;
+ ::std::optional<sal_uInt16> m_oPgNum;
+ std::optional<SwLineBreakClear> m_eClear;
+
+ bool m_bHtmlMode;
+
+ DECL_LINK(ToggleHdl, weld::Toggleable&, void);
+ DECL_LINK(ChangeHdl, weld::ComboBox&, void);
+ DECL_LINK(PageNumHdl, weld::Toggleable&, void);
+ DECL_LINK(PageNumModifyHdl, weld::SpinButton&, void);
+ DECL_LINK(OkHdl, weld::Button&, void);
+
+ void CheckEnable();
+ void rememberResult();
+
+public:
+ SwBreakDlg(weld::Window* pParent, SwWrtShell& rSh);
+ const OUString& GetTemplateName() const { return m_aTemplate; }
+ sal_uInt16 GetKind() const { return m_nKind; }
+ const ::std::optional<sal_uInt16>& GetPageNumber() const { return m_oPgNum; }
+ const std::optional<SwLineBreakClear>& GetClear() const { return m_eClear; }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/caption.hxx b/sw/source/uibase/inc/caption.hxx
new file mode 100644
index 0000000000..d762091b15
--- /dev/null
+++ b/sw/source/uibase/inc/caption.hxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CAPTION_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_CAPTION_HXX
+
+#include <rtl/ustring.hxx>
+#include <tools/globname.hxx>
+#include <SwCapObjType.hxx>
+#include <swdllapi.h>
+
+class SW_DLLPUBLIC InsCaptionOpt
+{
+private:
+ bool m_bUseCaption;
+ SwCapObjType m_eObjType;
+ SvGlobalName m_aOleId;
+ OUString m_sCategory;
+ sal_uInt16 m_nNumType;
+ OUString m_sNumberSeparator;
+ OUString m_sCaption;
+ sal_uInt16 m_nPos;
+ sal_uInt16 m_nLevel;
+ OUString m_sSeparator;
+ OUString m_sCharacterStyle;
+
+ bool m_bIgnoreSeqOpts; // is not being saved
+ bool m_bCopyAttributes; // -""-
+
+public:
+ InsCaptionOpt(const SwCapObjType eType = FRAME_CAP, const SvGlobalName* pOleId = nullptr);
+
+ bool& UseCaption() { return m_bUseCaption; }
+ bool UseCaption() const { return m_bUseCaption; }
+
+ SwCapObjType GetObjType() const { return m_eObjType; }
+
+ const SvGlobalName& GetOleId() const { return m_aOleId; }
+
+ const OUString& GetCategory() const { return m_sCategory; }
+ void SetCategory(const OUString& rCat) { m_sCategory = rCat; }
+
+ sal_uInt16 GetNumType() const { return m_nNumType; }
+ void SetNumType(const sal_uInt16 nNT) { m_nNumType = nNT; }
+
+ const OUString& GetNumSeparator() const { return m_sNumberSeparator; }
+ void SetNumSeparator(const OUString& rSet) {m_sNumberSeparator = rSet;}
+
+ const OUString& GetCaption() const { return m_sCaption; }
+ void SetCaption(const OUString& rCap) { m_sCaption = rCap; }
+
+ sal_uInt16 GetPos() const { return m_nPos; }
+ void SetPos(const sal_uInt16 nP) { m_nPos = nP; }
+
+ sal_uInt16 GetLevel() const { return m_nLevel; }
+ void SetLevel(const sal_uInt16 nLvl) { m_nLevel = nLvl; }
+
+ const OUString& GetSeparator() const { return m_sSeparator; }
+ void SetSeparator(const OUString& rSep) { m_sSeparator = rSep; }
+
+ const OUString& GetCharacterStyle() const { return m_sCharacterStyle; }
+ void SetCharacterStyle(const OUString& rStyle)
+ { m_sCharacterStyle = rStyle; }
+
+ bool& IgnoreSeqOpts() { return m_bIgnoreSeqOpts; }
+ bool IgnoreSeqOpts() const { return m_bIgnoreSeqOpts; }
+
+ bool& CopyAttributes() { return m_bCopyAttributes; }
+ bool CopyAttributes() const { return m_bCopyAttributes; }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/cfgitems.hxx b/sw/source/uibase/inc/cfgitems.hxx
new file mode 100644
index 0000000000..34ffa2d24e
--- /dev/null
+++ b/sw/source/uibase/inc/cfgitems.hxx
@@ -0,0 +1,166 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CFGITEMS_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_CFGITEMS_HXX
+
+#include <svl/poolitem.hxx>
+#include <swdllapi.h>
+#include <printdata.hxx>
+
+#include <cmdid.h>
+
+class SwModule;
+#ifdef DBG_UTIL
+class SwTestTabPage;
+#endif
+class SwAddPrinterTabPage;
+class SfxPrinter;
+class SwViewShell;
+class SwViewOption;
+class SwContentOptPage;
+class SwShdwCursorOptionsTabPage;
+enum class SwFillMode;
+
+/// Item for settings dialog - document view
+class SW_DLLPUBLIC SwDocDisplayItem final : public SfxPoolItem
+{
+ friend class SwShdwCursorOptionsTabPage;
+ friend class SwModule;
+
+ bool m_bParagraphEnd :1;
+ bool m_bTab :1;
+ bool m_bSpace :1;
+ bool m_bNonbreakingSpace :1;
+ bool m_bSoftHyphen :1;
+ bool m_bCharHiddenText :1;
+ bool m_bBookmarks :1;
+ bool m_bManualBreak :1;
+ sal_Int32 m_xDefaultAnchor;
+
+public:
+ SwDocDisplayItem();
+ SwDocDisplayItem( const SwViewOption& rVOpt );
+
+ virtual SwDocDisplayItem* Clone( SfxItemPool *pPool = nullptr ) const override;
+ virtual bool operator==( const SfxPoolItem& ) const override;
+ void FillViewOptions( SwViewOption& rVOpt) const;
+};
+
+// OS 12.01.95
+// Item for settings dialog, element page
+class SW_DLLPUBLIC SwElemItem final : public SfxPoolItem
+{
+ //view
+ bool m_bVertRuler :1;
+ bool m_bVertRulerRight:1;
+ bool m_bSmoothScroll :1;
+ //visual aids
+ bool m_bCrosshair :1;
+ //display
+ bool m_bTable :1;
+ bool m_bGraphic :1;
+ bool m_bDrawing :1;
+ bool m_bNotes :1;
+ bool m_bShowInlineTooltips :1;
+ bool m_bShowOutlineContentVisibilityButton :1;
+ bool m_bTreatSubOutlineLevelsAsContent :1;
+ bool m_bShowChangesInMargin :1;
+ bool m_bFieldHiddenText :1;
+ bool m_bShowHiddenPara :1;
+
+ friend class SwContentOptPage;
+
+public:
+ SwElemItem();
+ SwElemItem(const SwViewOption& rVOpt);
+
+ virtual SwElemItem* Clone( SfxItemPool *pPool = nullptr ) const override;
+ virtual bool operator==( const SfxPoolItem& ) const override;
+
+ void FillViewOptions( SwViewOption& rVOpt) const;
+
+};
+
+// OS 12.01.95
+// Item for settings dialog - printer/add-ons
+class SW_DLLPUBLIC SwAddPrinterItem final : public SfxPoolItem, public SwPrintData
+{
+ using SwPrintData::operator ==;
+
+public:
+ SwAddPrinterItem();
+ SwAddPrinterItem( const SwPrintData& rPrtData );
+
+ virtual SwAddPrinterItem* Clone( SfxItemPool *pPool = nullptr ) const override;
+
+ virtual bool operator==( const SfxPoolItem& ) const override;
+};
+
+/// Item for settings dialog, ShadowCursorPage
+class SW_DLLPUBLIC SwShadowCursorItem final : public SfxPoolItem
+{
+ SwFillMode m_eMode;
+ bool m_bOn;
+public:
+ SwShadowCursorItem();
+ SwShadowCursorItem( const SwViewOption& rVOpt );
+
+ virtual SwShadowCursorItem* Clone( SfxItemPool *pPool = nullptr ) const override;
+ virtual bool operator==( const SfxPoolItem& ) const override;
+
+ void FillViewOptions( SwViewOption& rVOpt) const;
+
+ SwFillMode GetMode() const { return m_eMode; }
+ bool IsOn() const { return m_bOn; }
+
+ void SetMode( SwFillMode eM ) { m_eMode = eM; }
+ void SetOn( bool bFlag ) { m_bOn = bFlag; }
+};
+
+#ifdef DBG_UTIL
+
+// Item for settings dialog - test settings
+class SW_DLLPUBLIC SwTestItem final : public SfxPoolItem
+{
+ friend class SwModule;
+ friend class SwTestTabPage;
+
+ bool m_bTest1:1;
+ bool m_bTest2:1;
+ bool m_bTest3:1;
+ bool m_bTest4:1;
+ bool m_bTest5:1;
+ bool m_bTest6:1;
+ bool m_bTest7:1;
+ bool m_bTest8:1;
+ bool m_bTest9:1;
+ bool m_bTest10:1;
+
+public:
+ SwTestItem() : SfxPoolItem(FN_PARAM_SWTEST) {};
+
+ virtual SwTestItem* Clone( SfxItemPool *pPool = nullptr ) const override;
+ virtual bool operator==( const SfxPoolItem& ) const override;
+
+};
+#endif
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/changedb.hxx b/sw/source/uibase/inc/changedb.hxx
new file mode 100644
index 0000000000..f14f163dd7
--- /dev/null
+++ b/sw/source/uibase/inc/changedb.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CHANGEDB_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_CHANGEDB_HXX
+
+#include <sfx2/basedlgs.hxx>
+#include "dbtree.hxx"
+
+class SwFieldMgr;
+class SwView;
+class SwWrtShell;
+struct SwDBData;
+
+// exchange database at fields
+class SwChangeDBDlg final : public SfxDialogController
+{
+ SwWrtShell *m_pSh;
+
+ std::unique_ptr<weld::TreeView> m_xUsedDBTLB;
+ std::unique_ptr<SwDBTreeList> m_xAvailDBTLB;
+ std::unique_ptr<weld::Button> m_xAddDBPB;
+ std::unique_ptr<weld::Label> m_xDocDBNameFT;
+ std::unique_ptr<weld::Button> m_xDefineBT;
+
+ void TreeSelect();
+
+ DECL_LINK(TreeSelectHdl, weld::TreeView&, void);
+ DECL_LINK(ButtonHdl, weld::Button&, void);
+ DECL_LINK(AddDBHdl, weld::Button&, void);
+
+ void UpdateFields();
+ void FillDBPopup();
+ std::unique_ptr<weld::TreeIter> Insert(std::u16string_view rDBName);
+ void ShowDBName(const SwDBData& rDBData);
+
+public:
+ SwChangeDBDlg(SwView const & rVw);
+ virtual short run() override;
+ virtual ~SwChangeDBDlg() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/chartins.hxx b/sw/source/uibase/inc/chartins.hxx
new file mode 100644
index 0000000000..dcac7be0b0
--- /dev/null
+++ b/sw/source/uibase/inc/chartins.hxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CHARTINS_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_CHARTINS_HXX
+
+#include <tools/gen.hxx>
+#include <tools/link.hxx>
+#include <com/sun/star/ui/dialogs/DialogClosedEvent.hpp>
+
+namespace vcl { class Window; }
+
+Point SwGetChartDialogPos( const vcl::Window *pParentWin, const Size& rDialogSize, const tools::Rectangle& rLogicChart );
+
+class SwInsertChart
+{
+public:
+ SwInsertChart( const Link<css::ui::dialogs::DialogClosedEvent*,void>& rLink );
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_CHARTINS_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/chldwrap.hxx b/sw/source/uibase/inc/chldwrap.hxx
new file mode 100644
index 0000000000..7253d7702f
--- /dev/null
+++ b/sw/source/uibase/inc/chldwrap.hxx
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CHLDWRAP_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_CHLDWRAP_HXX
+
+#include <sfx2/childwin.hxx>
+#include <vcl/timer.hxx>
+
+class SwDocShell;
+
+class SAL_DLLPUBLIC_RTTI SwChildWinWrapper : public SfxChildWindow
+{
+ Timer m_aUpdateTimer;
+ SwDocShell* m_pDocSh;
+
+ DECL_DLLPRIVATE_LINK( UpdateHdl, Timer*, void );
+
+ // Implementation in fldtdlg.cxx
+protected:
+ SwChildWinWrapper(vcl::Window *pParentWindow, sal_uInt16 nId);
+
+public:
+ virtual bool ReInitDlg(SwDocShell *pDocSh);
+
+ SwDocShell* GetOldDocShell() { return m_pDocSh; }
+ void SetOldDocShell(SwDocShell *pDcSh) { m_pDocSh = pDcSh; }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/chrdlg.hxx b/sw/source/uibase/inc/chrdlg.hxx
new file mode 100644
index 0000000000..cf37a9496a
--- /dev/null
+++ b/sw/source/uibase/inc/chrdlg.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CHRDLG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_CHRDLG_HXX
+
+#include <sfx2/tabdlg.hxx>
+#include "chrdlgmodes.hxx"
+#include <svl/macitem.hxx>
+#include <optional>
+
+class SwView;
+
+class SwCharDlg final : public SfxTabDialogController
+{
+ SwView& m_rView;
+ SwCharDlgMode m_nDialogMode;
+
+public:
+ SwCharDlg(weld::Window* pParent, SwView& pVw, const SfxItemSet& rCoreSet,
+ SwCharDlgMode nDialogMode, const OUString* pFormatStr);
+
+ virtual ~SwCharDlg() override;
+
+ virtual void PageCreated(const OUString& rId, SfxTabPage &rPage) override;
+};
+
+class SwCharURLPage final : public SfxTabPage
+{
+ std::optional<SvxMacroTableDtor> m_oINetMacroTable;
+ bool m_bModified;
+
+ std::unique_ptr<weld::Entry> m_xURLED;
+ std::unique_ptr<weld::Label> m_xTextFT;
+ std::unique_ptr<weld::Entry> m_xTextED;
+ std::unique_ptr<weld::Entry> m_xNameED;
+ std::unique_ptr<weld::ComboBox> m_xTargetFrameLB;
+ std::unique_ptr<weld::Button> m_xURLPB;
+ std::unique_ptr<weld::Button> m_xEventPB;
+ std::unique_ptr<weld::ComboBox> m_xVisitedLB;
+ std::unique_ptr<weld::ComboBox> m_xNotVisitedLB;
+ std::unique_ptr<weld::Widget> m_xCharStyleContainer;
+
+ DECL_LINK(InsertFileHdl, weld::Button&, void);
+ DECL_LINK(EventHdl, weld::Button&, void);
+
+public:
+ SwCharURLPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+
+ virtual ~SwCharURLPage() override;
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet);
+
+ virtual bool FillItemSet( SfxItemSet* rSet ) override;
+ virtual void Reset( const SfxItemSet* rSet ) override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/chrdlgmodes.hxx b/sw/source/uibase/inc/chrdlgmodes.hxx
new file mode 100644
index 0000000000..cddb6a9c29
--- /dev/null
+++ b/sw/source/uibase/inc/chrdlgmodes.hxx
@@ -0,0 +1,20 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CHRDLGMODES_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_CHRDLGMODES_HXX
+
+// DialogModes for SwCharDlg
+enum class SwCharDlgMode {
+ Std, Draw, Env, Ann
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_CHRDLGMODES_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/cnttab.hxx b/sw/source/uibase/inc/cnttab.hxx
new file mode 100644
index 0000000000..e95cc5c62b
--- /dev/null
+++ b/sw/source/uibase/inc/cnttab.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CNTTAB_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_CNTTAB_HXX
+
+#include <sal/types.h>
+
+#include <toxe.hxx>
+
+#define TOX_PAGE_SELECT 1
+#define TOX_PAGE_ENTRY 2
+#define TOX_PAGE_STYLES 3
+
+#define TO_CONTENT 1
+#define TO_INDEX 2
+#define TO_ILLUSTRATION 4
+#define TO_TABLE 8
+#define TO_USER 16
+#define TO_OBJECT 32
+#define TO_AUTHORITIES 64
+#define TO_BIBLIOGRAPHY 128
+
+struct CurTOXType
+{
+ TOXTypes eType;
+ sal_uInt16 nIndex; //for TOX_USER only
+
+ bool operator==(const CurTOXType& rCmp) const
+ {
+ return eType == rCmp.eType && nIndex == rCmp.nIndex;
+ }
+ sal_uInt16 GetFlatIndex() const;
+
+ CurTOXType () : eType (TOX_INDEX), nIndex (0) {};
+
+ CurTOXType (TOXTypes t) : eType (t), nIndex (0) {};
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/colex.hxx b/sw/source/uibase/inc/colex.hxx
new file mode 100644
index 0000000000..2abe442982
--- /dev/null
+++ b/sw/source/uibase/inc/colex.hxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_COLEX_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_COLEX_HXX
+
+#include <svx/pagectrl.hxx>
+#include <editeng/paperinf.hxx>
+#include <swdllapi.h>
+#include <tgrditem.hxx>
+#include <fmtclds.hxx>
+
+class SwColMgr;
+class SfxItemSet;
+
+class SW_DLLPUBLIC SwPageExample : public SvxPageWindow
+{
+protected:
+ bool m_bVertical;
+public:
+ SwPageExample()
+ : m_bVertical(false)
+ {
+ SetSize(SvxPaperInfo::GetPaperSize(PAPER_A4));
+ }
+
+ void UpdateExample( const SfxItemSet& rSet );
+};
+
+class SW_DLLPUBLIC SwPageGridExample final : public SwPageExample
+{
+ std::unique_ptr<SwTextGridItem> m_pGridItem;
+
+ virtual void DrawPage(vcl::RenderContext& rRenderContext,
+ const Point& rPoint,
+ const bool bSecond,
+ const bool bEnabled) override;
+public:
+ SwPageGridExample();
+
+ void UpdateExample( const SfxItemSet& rSet );
+};
+
+
+class SW_DLLPUBLIC SwColExample final : public SwPageExample
+{
+ SwColMgr* m_pColMgr;
+
+ using SwPageExample::UpdateExample;
+
+ virtual void DrawPage(vcl::RenderContext& rRenderContext,
+ const Point& rPoint,
+ const bool bSecond,
+ const bool bEnabled) override;
+
+public:
+ SwColExample()
+ : m_pColMgr(nullptr)
+ {
+ }
+
+ void UpdateExample( const SfxItemSet& rSet, SwColMgr* pMgr )
+ {
+ m_pColMgr = pMgr;
+ SwPageExample::UpdateExample(rSet);
+ }
+};
+
+class SW_DLLPUBLIC SwColumnOnlyExample final : public weld::CustomWidgetController
+{
+private:
+ Size m_aWinSize;
+
+ Size m_aFrameSize;
+ SwFormatCol m_aCols;
+
+ virtual void Resize() override;
+ virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
+
+public:
+ SwColumnOnlyExample();
+
+ void SetColumns(const SwFormatCol& rCol);
+
+ virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override;
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_COLEX_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/colmgr.hxx b/sw/source/uibase/inc/colmgr.hxx
new file mode 100644
index 0000000000..3a4f43ef6f
--- /dev/null
+++ b/sw/source/uibase/inc/colmgr.hxx
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_COLMGR_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_COLMGR_HXX
+
+#include <swdllapi.h>
+#include <fmtclds.hxx>
+
+#include <climits>
+
+SW_DLLPUBLIC void FitToActualSize(SwFormatCol& rCol, sal_uInt16 nWidth);
+
+class SW_DLLPUBLIC SwColMgr
+{
+public:
+ // lActWidth is passed directly from the page dialogs edits
+ SwColMgr(const SfxItemSet &rSet);
+ ~SwColMgr();
+
+ inline sal_uInt16 GetCount() const;
+ void SetCount(sal_uInt16 nCount, sal_uInt16 nGutterWidth);
+ sal_uInt16 GetGutterWidth(sal_uInt16 nPos = USHRT_MAX) const;
+ void SetGutterWidth(sal_uInt16 nWidth, sal_uInt16 nPos = USHRT_MAX);
+
+ sal_uInt16 GetColWidth(sal_uInt16 nIdx) const;
+ void SetColWidth(sal_uInt16 nIdx, sal_uInt16 nWidth);
+
+ inline bool IsAutoWidth() const;
+ void SetAutoWidth(bool bOn, sal_uInt16 lGutterWidth = 0);
+
+ inline bool HasLine() const;
+ inline void SetNoLine();
+
+ void SetLineWidthAndColor(SvxBorderLineStyle eStyle, sal_uLong nWidth, const Color& rCol);
+ inline SvxBorderLineStyle GetLineStyle() const;
+ inline sal_uLong GetLineWidth() const;
+ inline const Color& GetLineColor() const;
+
+ inline SwColLineAdj GetAdjust() const;
+ inline void SetAdjust(SwColLineAdj);
+
+ short GetLineHeightPercent() const;
+ void SetLineHeightPercent(short nPercent);
+
+ inline void NoCols();
+
+ const SwFormatCol& GetColumns() const { return m_aFormatCol; }
+
+ void SetActualWidth(sal_uInt16 nW);
+ sal_uInt16 GetActualSize() const { return m_nWidth; }
+
+private:
+ SwFormatCol m_aFormatCol;
+ sal_uInt16 m_nWidth;
+};
+
+inline sal_uInt16 SwColMgr::GetCount() const
+{
+ return m_aFormatCol.GetNumCols();
+}
+
+inline SvxBorderLineStyle SwColMgr::GetLineStyle() const
+{
+ return m_aFormatCol.GetLineStyle();
+}
+inline sal_uLong SwColMgr::GetLineWidth() const
+{
+ return m_aFormatCol.GetLineWidth();
+}
+
+inline const Color& SwColMgr::GetLineColor() const
+{
+ return m_aFormatCol.GetLineColor();
+}
+
+inline SwColLineAdj SwColMgr::GetAdjust() const
+{
+ return m_aFormatCol.GetLineAdj();
+}
+
+inline void SwColMgr::SetAdjust(SwColLineAdj eAdj)
+{
+ m_aFormatCol.SetLineAdj(eAdj);
+}
+inline bool SwColMgr::IsAutoWidth() const
+{
+ return m_aFormatCol.IsOrtho();
+}
+inline void SwColMgr::SetAutoWidth(bool bOn, sal_uInt16 nGutterWidth)
+{
+ m_aFormatCol.SetOrtho(bOn, nGutterWidth, m_nWidth);
+}
+
+inline void SwColMgr::NoCols()
+{
+ m_aFormatCol.GetColumns().clear();
+}
+inline bool SwColMgr::HasLine() const
+{
+ return GetAdjust() != COLADJ_NONE;
+}
+
+inline void SwColMgr::SetNoLine()
+{
+ SetAdjust(COLADJ_NONE);
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/column.hxx b/sw/source/uibase/inc/column.hxx
new file mode 100644
index 0000000000..d45331cddf
--- /dev/null
+++ b/sw/source/uibase/inc/column.hxx
@@ -0,0 +1,203 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <svtools/ctrlbox.hxx>
+#include <svtools/valueset.hxx>
+#include <sfx2/basedlgs.hxx>
+#include <sfx2/tabdlg.hxx>
+#include <svx/colorbox.hxx>
+#include <svx/frmdirlbox.hxx>
+#include <map>
+#include "colex.hxx"
+#include "prcntfld.hxx"
+
+const int nMaxCols = 99;
+class SwColMgr;
+class SwWrtShell;
+class SwColumnPage;
+
+class SwColumnDlg final : public SfxDialogController
+{
+ SwWrtShell& m_rWrtShell;
+ std::unique_ptr<SwColumnPage> m_xTabPage;
+ std::unique_ptr<SfxItemSet> m_pPageSet;
+ std::unique_ptr<SfxItemSet> m_pSectionSet;
+ std::unique_ptr<SfxItemSet> m_pSelectionSet;
+ SfxItemSet* m_pFrameSet;
+
+ tools::Long m_nOldSelection;
+ tools::Long m_nSelectionWidth;
+ tools::Long m_nPageWidth;
+
+ bool m_bPageChanged : 1;
+ bool m_bSectionChanged : 1;
+ bool m_bSelSectionChanged : 1;
+ bool m_bFrameChanged : 1;
+
+ std::unique_ptr<weld::Container> m_xContentArea;
+ std::unique_ptr<weld::Button> m_xOkButton;
+
+ DECL_LINK(ObjectListBoxHdl, weld::ComboBox&, void);
+ DECL_LINK(OkHdl, weld::Button&, void);
+ void ObjectHdl(const weld::ComboBox*);
+ SfxItemSet* EvalCurrentSelection(void);
+
+public:
+ SwColumnDlg(weld::Window* pParent, SwWrtShell& rSh);
+ virtual ~SwColumnDlg() override;
+};
+
+class ColumnValueSet final : public ValueSet
+{
+public:
+ ColumnValueSet()
+ : ValueSet(nullptr)
+ {
+ }
+ virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override
+ {
+ ValueSet::SetDrawingArea(pDrawingArea);
+ SetStyle(WB_TABSTOP | WB_ITEMBORDER | WB_DOUBLEBORDER);
+ }
+ virtual void UserDraw(const UserDrawEvent& rUDEvt) override;
+ virtual void StyleUpdated() override;
+};
+
+// column dialog now as TabPage
+class SwColumnPage final : public SfxTabPage
+{
+ std::unique_ptr<SwColMgr> m_xColMgr;
+
+ sal_uInt16 m_nFirstVis;
+ sal_uInt16 m_nCols;
+ tools::Long m_nColWidth[nMaxCols];
+ tools::Long m_nColDist[nMaxCols];
+ SwPercentField* m_pModifiedField;
+
+ std::map<weld::MetricSpinButton*, SwPercentField*> m_aPercentFieldsMap;
+
+ bool m_bFormat;
+ bool m_bFrame;
+ bool m_bHtmlMode;
+ bool m_bLockUpdate;
+
+ ColumnValueSet m_aDefaultVS;
+ SwColExample m_aPgeExampleWN;
+ SwColumnOnlyExample m_aFrameExampleWN;
+
+ std::unique_ptr<weld::SpinButton> m_xCLNrEdt;
+ std::unique_ptr<weld::CheckButton> m_xBalanceColsCB;
+ std::unique_ptr<weld::Button> m_xBtnBack;
+ std::unique_ptr<weld::Label> m_xLbl1;
+ std::unique_ptr<weld::Label> m_xLbl2;
+ std::unique_ptr<weld::Label> m_xLbl3;
+ std::unique_ptr<weld::Button> m_xBtnNext;
+ std::unique_ptr<weld::CheckButton> m_xAutoWidthBox;
+ std::unique_ptr<weld::Label> m_xLineTypeLbl;
+ std::unique_ptr<weld::Label> m_xLineWidthLbl;
+ std::unique_ptr<weld::MetricSpinButton> m_xLineWidthEdit;
+ std::unique_ptr<weld::Label> m_xLineColorLbl;
+ std::unique_ptr<weld::Label> m_xLineHeightLbl;
+ std::unique_ptr<weld::MetricSpinButton> m_xLineHeightEdit;
+ std::unique_ptr<weld::Label> m_xLinePosLbl;
+ std::unique_ptr<weld::ComboBox> m_xLinePosDLB;
+ std::unique_ptr<weld::Label> m_xTextDirectionFT;
+ std::unique_ptr<svx::FrameDirectionListBox> m_xTextDirectionLB;
+ std::unique_ptr<ColorListBox> m_xLineColorDLB;
+ std::unique_ptr<SvtLineListBox> m_xLineTypeDLB;
+ std::unique_ptr<SwPercentField> m_xEd1;
+ std::unique_ptr<SwPercentField> m_xEd2;
+ std::unique_ptr<SwPercentField> m_xEd3;
+ std::unique_ptr<SwPercentField> m_xDistEd1;
+ std::unique_ptr<SwPercentField> m_xDistEd2;
+ std::unique_ptr<weld::CustomWeld> m_xDefaultVS;
+ // Example
+ std::unique_ptr<weld::CustomWeld> m_xPgeExampleWN;
+ std::unique_ptr<weld::CustomWeld> m_xFrameExampleWN;
+
+ std::unique_ptr<weld::Label> m_xApplyToFT;
+ std::unique_ptr<weld::ComboBox> m_xApplyToLB;
+
+ // Handler
+ DECL_LINK(ColModify, weld::SpinButton&, void);
+ void ColModify(bool bForceColReset);
+ DECL_LINK(GapModify, weld::MetricSpinButton&, void);
+ DECL_LINK(EdModify, weld::MetricSpinButton&, void);
+ DECL_LINK(AutoWidthHdl, weld::Toggleable&, void );
+ DECL_LINK(SetDefaultsHdl, ValueSet *, void);
+
+ DECL_LINK(Up, weld::Button&, void);
+ DECL_LINK(Down, weld::Button&, void);
+ DECL_LINK(UpdateColMgr, weld::MetricSpinButton&, void);
+ DECL_LINK(UpdateColMgrListBox, weld::ComboBox&, void);
+ DECL_LINK(UpdateColMgrLineBox, SvtLineListBox&, void);
+ DECL_LINK(UpdateColMgrColorBox, ColorListBox&, void);
+ void Timeout();
+
+ void Update(const weld::MetricSpinButton* pInteractiveField);
+ void UpdateCols();
+ void Init();
+ void ResetColWidth();
+ void SetLabels( sal_uInt16 nVis );
+
+ virtual void ActivatePage(const SfxItemSet& rSet) override;
+ virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override;
+
+ void connectPercentField(SwPercentField &rWrap);
+
+ bool isLineNotNone() const;
+
+ static const WhichRangesContainer s_aPageRg;
+
+public:
+ SwColumnPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet);
+ virtual ~SwColumnPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet);
+ static WhichRangesContainer GetRanges() { return s_aPageRg; }
+
+ virtual bool FillItemSet(SfxItemSet *rSet) override;
+ virtual void Reset(const SfxItemSet *rSet) override;
+
+ void SetFrameMode(bool bMod);
+ void SetPageWidth(tools::Long nPageWidth);
+
+ void SetFormatUsed(bool bFormatUsed)
+ {
+ m_bFormat = bFormatUsed;
+ }
+
+ void ShowBalance(bool bShow)
+ {
+ m_xBalanceColsCB->set_visible(bShow);
+ }
+
+ void SetInSection(bool bSet);
+
+ void ActivateColumnControl()
+ {
+ m_xCLNrEdt->grab_focus();
+ }
+
+ weld::Label* GetApplyLabel() { return m_xApplyToFT.get(); }
+ weld::ComboBox* GetApplyComboBox() { return m_xApplyToLB.get(); }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/conarc.hxx b/sw/source/uibase/inc/conarc.hxx
new file mode 100644
index 0000000000..eb65042f31
--- /dev/null
+++ b/sw/source/uibase/inc/conarc.hxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CONARC_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_CONARC_HXX
+
+#include "drawbase.hxx"
+
+// draw rectangle
+class ConstArc final : public SwDrawBase
+{
+ Point m_aStartPoint;
+ sal_uInt16 m_nButtonUpCount;
+
+public:
+ ConstArc(SwWrtShell* pSh, SwEditWin* pWin, SwView* pView);
+
+ // Mouse- & Key-Events
+ virtual bool MouseButtonUp(const MouseEvent& rMEvt) override;
+ virtual bool MouseButtonDown(const MouseEvent& rMEvt) override;
+
+ virtual void Activate(const sal_uInt16 nSlotId) override; // activate function
+ virtual void Deactivate() override;
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_CONARC_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/concustomshape.hxx b/sw/source/uibase/inc/concustomshape.hxx
new file mode 100644
index 0000000000..cc2358ceee
--- /dev/null
+++ b/sw/source/uibase/inc/concustomshape.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CONCUSTOMSHAPE_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_CONCUSTOMSHAPE_HXX
+
+#include <rtl/ustring.hxx>
+#include "drawbase.hxx"
+
+class SdrObject;
+class SfxRequest;
+
+// draw rectangle
+class ConstCustomShape final : public SwDrawBase
+{
+
+ OUString m_aCustomShape;
+
+ void SetAttributes( SdrObject* pObj );
+
+ public:
+
+ ConstCustomShape( SwWrtShell* pSh, SwEditWin* pWin, SwView* pView, SfxRequest const & rReq );
+
+ // Mouse- & Key-Events
+ virtual bool MouseButtonDown(const MouseEvent& rMEvt) override;
+
+ virtual void Activate(const sal_uInt16 nSlotId) override; // activate function
+
+ const OUString& GetShapeType() const;
+ static OUString GetShapeTypeFromRequest( SfxRequest const & rReq );
+
+ virtual void CreateDefaultObject() override;
+ virtual void CreateDefaultObjectAtPosWithSize(Point aPos, Size aSize) override;
+
+ // #i33136#
+ virtual bool doConstructOrthogonal() const override;
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_CONCUSTOMSHAPE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/condedit.hxx b/sw/source/uibase/inc/condedit.hxx
new file mode 100644
index 0000000000..fddf1f00dd
--- /dev/null
+++ b/sw/source/uibase/inc/condedit.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CONDEDIT_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_CONDEDIT_HXX
+
+#include <vcl/transfer.hxx>
+#include <vcl/weld.hxx>
+#include <swdllapi.h>
+
+class ConditionEdit;
+
+class SW_DLLPUBLIC ConditionEditDropTarget final : public DropTargetHelper
+{
+private:
+ ConditionEdit& m_rEdit;
+
+ SAL_DLLPRIVATE virtual sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt) override;
+ SAL_DLLPRIVATE virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt) override;
+
+public:
+ ConditionEditDropTarget(ConditionEdit& rEdit);
+};
+
+class SW_DLLPUBLIC ConditionEdit
+{
+ std::unique_ptr<weld::Entry> m_xControl;
+ ConditionEditDropTarget m_aDropTargetHelper;
+ bool m_bBrackets, m_bEnableDrop;
+
+public:
+ ConditionEdit(std::unique_ptr<weld::Entry> xControl);
+
+ OUString get_text() const { return m_xControl->get_text(); }
+ void set_text(const OUString& rText) { m_xControl->set_text(rText); }
+ void set_visible(bool bVisible) { m_xControl->set_visible(bVisible); }
+ void set_accessible_name(const OUString& rName) { m_xControl->set_accessible_name(rName); }
+ void save_value() { m_xControl->save_value(); }
+ bool get_value_changed_from_saved() const { return m_xControl->get_value_changed_from_saved(); }
+ void set_sensitive(bool bSensitive) { m_xControl->set_sensitive(bSensitive); }
+ void connect_changed(const Link<weld::Entry&, void>& rLink)
+ {
+ m_xControl->connect_changed(rLink);
+ }
+ void replace_selection(const OUString& rText) { m_xControl->replace_selection(rText); }
+ void hide() { m_xControl->hide(); }
+ weld::Entry& get_widget() { return *m_xControl; }
+
+ OUString get_buildable_name() const { return m_xControl->get_buildable_name(); }
+ void set_buildable_name(const OUString& rId) { m_xControl->set_buildable_name(rId); }
+
+ void ShowBrackets(bool bShow) { m_bBrackets = bShow; }
+ bool GetBrackets() const { return m_bBrackets; }
+ void SetDropEnable(bool bFlag) { m_bEnableDrop = bFlag; }
+ bool GetDropEnable() const { return m_bEnableDrop; }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/conform.hxx b/sw/source/uibase/inc/conform.hxx
new file mode 100644
index 0000000000..e0585f2622
--- /dev/null
+++ b/sw/source/uibase/inc/conform.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "drawbase.hxx"
+#include <svx/svdobjkind.hxx>
+
+class ConstFormControl final : public SwDrawBase
+{
+private:
+ SdrObjKind m_eObjKind;
+
+public:
+ ConstFormControl(SwWrtShell* pSh, SwEditWin* pWin, SwView* pView, SdrObjKind eObjKind);
+
+ // Mouse- & Key-Events
+ virtual bool MouseButtonDown(const MouseEvent& rMEvt) override;
+
+ virtual void Activate(const sal_uInt16 nSlotId) override; // activate function
+ virtual void CreateDefaultObject() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/conpoly.hxx b/sw/source/uibase/inc/conpoly.hxx
new file mode 100644
index 0000000000..377eb685b6
--- /dev/null
+++ b/sw/source/uibase/inc/conpoly.hxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CONPOLY_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_CONPOLY_HXX
+
+#include "drawbase.hxx"
+
+// base class for all functions
+class ConstPolygon final : public SwDrawBase
+{
+public:
+ ConstPolygon(SwWrtShell* pSh, SwEditWin* pWin, SwView* pView);
+
+ // Mouse- & Key-Events
+ virtual bool MouseButtonUp(const MouseEvent& rMEvt) override;
+
+ virtual void Activate(const sal_uInt16 nSlotId) override; // activate function
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_CONPOLY_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/conrect.hxx b/sw/source/uibase/inc/conrect.hxx
new file mode 100644
index 0000000000..bc290f8e84
--- /dev/null
+++ b/sw/source/uibase/inc/conrect.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CONRECT_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_CONRECT_HXX
+
+#include "drawbase.hxx"
+
+// draw rectangle
+class ConstRectangle final : public SwDrawBase
+{
+ bool m_bMarquee;
+ bool m_bCapVertical;
+
+ bool mbVertical;
+
+ public:
+ ConstRectangle(SwWrtShell* pSh, SwEditWin* pWin, SwView* pView);
+
+ // Mouse- & Key-Events
+ virtual bool MouseButtonUp(const MouseEvent& rMEvt) override;
+ virtual bool MouseButtonDown(const MouseEvent& rMEvt) override;
+
+ virtual void Activate(const sal_uInt16 nSlotId) override; // activate function
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_CONRECT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/content.hxx b/sw/source/uibase/inc/content.hxx
new file mode 100644
index 0000000000..c6698f4b03
--- /dev/null
+++ b/sw/source/uibase/inc/content.hxx
@@ -0,0 +1,228 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CONTENT_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_CONTENT_HXX
+#include <memory>
+#include "swcont.hxx"
+
+#include <ndarr.hxx>
+#include <tools/long.hxx>
+#include <utility>
+
+class SwWrtShell;
+class SwContentArr;
+class SwContentType;
+class SwFormatField;
+class SwTextINetFormat;
+class SwTOXBase;
+class SwRangeRedline;
+class SwTextFootnote;
+
+// helper classes
+
+class SwOutlineContent final : public SwContent
+{
+ SwOutlineNodes::size_type m_nOutlinePos;
+ sal_uInt8 m_nOutlineLevel;
+ bool m_bIsMoveable;
+ public:
+ SwOutlineContent( const SwContentType* pCnt,
+ const OUString& rName,
+ SwOutlineNodes::size_type nArrPos,
+ sal_uInt8 nLevel,
+ bool bMove,
+ double nYPos) :
+ SwContent(pCnt, rName, nYPos),
+ m_nOutlinePos(nArrPos), m_nOutlineLevel(nLevel), m_bIsMoveable(bMove) {}
+
+ SwOutlineNodes::size_type GetOutlinePos() const {return m_nOutlinePos;}
+ sal_uInt8 GetOutlineLevel() const {return m_nOutlineLevel;}
+ bool IsMoveable() const {return m_bIsMoveable;};
+};
+
+class SwRegionContent final : public SwContent
+{
+
+ sal_uInt8 m_nRegionLevel;
+ const SwSectionFormat* m_pSectionFormat;
+
+ public:
+ SwRegionContent( const SwContentType* pCnt,
+ const OUString& rName,
+ sal_uInt8 nLevel,
+ tools::Long nYPos,
+ const SwSectionFormat* pSectionFormat) :
+ SwContent(pCnt, rName, nYPos),
+ m_nRegionLevel(nLevel), m_pSectionFormat(pSectionFormat){}
+ sal_uInt8 GetRegionLevel() const {return m_nRegionLevel;}
+ const SwSectionFormat* GetSectionFormat() const {return m_pSectionFormat;}
+
+ bool IsProtect() const override;
+};
+
+class SwURLFieldContent final : public SwContent
+{
+ OUString m_sURL;
+ const SwTextINetFormat* m_pINetAttr;
+
+public:
+ SwURLFieldContent( const SwContentType* pCnt,
+ const OUString& rName,
+ OUString aURL,
+ const SwTextINetFormat* pAttr,
+ tools::Long nYPos )
+ : SwContent( pCnt, rName, nYPos ), m_sURL(std::move( aURL )), m_pINetAttr( pAttr )
+ {}
+
+ virtual bool IsProtect() const override;
+ const OUString& GetURL() const { return m_sURL; }
+ const SwTextINetFormat* GetINetAttr() const { return m_pINetAttr; }
+};
+
+class SwTextFieldContent final : public SwContent
+{
+ const SwFormatField* m_pFormatField;
+public:
+ SwTextFieldContent(const SwContentType* pCnt,
+ const OUString& rName,
+ const SwFormatField* pFormatField,
+ tools::Long nYPos)
+ : SwContent(pCnt, rName, nYPos),
+ m_pFormatField(pFormatField)
+ {}
+
+ const SwFormatField* GetFormatField() const {return m_pFormatField;}
+ virtual bool IsProtect() const override;
+};
+
+class SwTextFootnoteContent final : public SwContent
+{
+ const SwTextFootnote* m_pTextFootnote;
+public:
+ SwTextFootnoteContent(const SwContentType* pCnt,
+ const OUString& rName,
+ const SwTextFootnote* pTextFootnote,
+ tools::Long nYPos)
+ : SwContent(pCnt, rName, nYPos),
+ m_pTextFootnote(pTextFootnote)
+ {}
+
+ const SwTextFootnote* GetTextFootnote() const {return m_pTextFootnote;}
+};
+
+class SwPostItContent final : public SwContent
+{
+ const SwFormatField* m_pField;
+public:
+ SwPostItContent( const SwContentType* pCnt,
+ const OUString& rName,
+ const SwFormatField* pFormatField,
+ tools::Long nYPos )
+ : SwContent(pCnt, rName, nYPos)
+ , m_pField(pFormatField)
+ {}
+
+ const SwFormatField* GetPostIt() const { return m_pField; }
+ virtual bool IsProtect() const override;
+};
+
+class SwGraphicContent final : public SwContent
+{
+ OUString m_sLink;
+public:
+ SwGraphicContent(const SwContentType* pCnt, const OUString& rName, OUString aLink, tools::Long nYPos)
+ : SwContent( pCnt, rName, nYPos ), m_sLink(std::move( aLink ))
+ {}
+ virtual ~SwGraphicContent() override;
+
+ const OUString& GetLink() const {return m_sLink;}
+};
+
+class SwTOXBaseContent final : public SwContent
+{
+ const SwTOXBase* m_pBase;
+public:
+ SwTOXBaseContent(const SwContentType* pCnt, const OUString& rName, tools::Long nYPos, const SwTOXBase& rBase)
+ : SwContent( pCnt, rName, nYPos ), m_pBase(&rBase)
+ {}
+ virtual ~SwTOXBaseContent() override;
+
+ const SwTOXBase* GetTOXBase() const {return m_pBase;}
+};
+
+/**
+ * Content type, knows it's contents and the WrtShell.
+ *
+ * The class ContentType contains information to one type of content.
+ * MemberArray is only populated if the content is requested by
+ * GetMember. It is reloaded after Invalidate() only if the content
+ * should be read again.
+*/
+class SwContentType final : public SwTypeNumber
+{
+ SwWrtShell* m_pWrtShell;
+ std::unique_ptr<SwContentArr>
+ m_pMember; // array for content
+ OUString m_sContentTypeName; // name of content type
+ OUString m_sSingleContentTypeName; // name of content type, singular
+ OUString m_sTypeToken; // attachment for URL
+ size_t m_nMemberCount; // content count
+ ContentTypeId m_nContentType; // content type's Id
+ sal_uInt8 m_nOutlineLevel;
+ bool m_bDataValid : 1;
+ bool m_bEdit: 1; // can this type be edited?
+ bool m_bDelete: 1; // can this type be deleted?
+
+ bool m_bAlphabeticSort = false;
+
+ static OUString RemoveNewline(const OUString&);
+public:
+ SwContentType(SwWrtShell* pParent, ContentTypeId nType, sal_uInt8 nLevel );
+ virtual ~SwContentType() override;
+
+ /** Fill the List of contents */
+ void FillMemberList(bool* pbContentChanged = nullptr);
+ size_t GetMemberCount() const
+ {return m_nMemberCount;};
+ ContentTypeId GetType() const {return m_nContentType;}
+
+ /** Deliver content, for that if necessary fill the list */
+ const SwContent* GetMember(size_t nIndex);
+ const OUString& GetName() const {return m_sContentTypeName;}
+ const OUString& GetSingleName() const {return m_sSingleContentTypeName;}
+ const OUString& GetTypeToken() const{return m_sTypeToken;}
+
+ void SetOutlineLevel(sal_uInt8 nNew)
+ {
+ m_nOutlineLevel = nNew;
+ Invalidate();
+ }
+
+ bool IsAlphabeticSort() const {return m_bAlphabeticSort;}
+ void SetAlphabeticSort(bool bAlphabetic) {m_bAlphabeticSort = bAlphabetic;}
+
+ void Invalidate(); // only nMemberCount is read again
+
+ bool IsEditable() const {return m_bEdit;}
+ bool IsDeletable() const {return m_bDelete;}
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/contentcontrolaliasbutton.hxx b/sw/source/uibase/inc/contentcontrolaliasbutton.hxx
new file mode 100644
index 0000000000..818a4415b9
--- /dev/null
+++ b/sw/source/uibase/inc/contentcontrolaliasbutton.hxx
@@ -0,0 +1,42 @@
+/* -*- 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 "FrameControl.hxx"
+
+class SwEditWin;
+class SwContentControl;
+
+/// In case the content control has an alias/title, this widget shows it above the top left corner
+/// of the content control till the cursor is inside the content control.
+class SwContentControlAliasButton final : public SwFrameMenuButtonBase
+{
+ std::unique_ptr<weld::Button> m_xPushButton;
+ OUString m_sLabel;
+ bool m_bReadOnly = false;
+
+public:
+ SwContentControlAliasButton(SwEditWin* pEditWin, SwContentControl* pContentControl);
+ ~SwContentControlAliasButton() override;
+
+ bool Contains(const Point& rDocPt) const override;
+ void SetReadonly(bool bReadonly) override;
+ void ShowAll(bool bShow) override;
+ void dispose() override;
+
+ void SetContentControl(SwContentControl* pContentControl);
+ void SetOffset(Point aTopLeftPixel);
+
+private:
+ DECL_LINK(ClickHdl, weld::Button&, void);
+ void PaintButton();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/contentcontroldlg.hxx b/sw/source/uibase/inc/contentcontroldlg.hxx
new file mode 100644
index 0000000000..8fbc57d9ad
--- /dev/null
+++ b/sw/source/uibase/inc/contentcontroldlg.hxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/basedlgs.hxx>
+#include <vcl/abstdlg.hxx>
+#include <vcl/weld.hxx>
+
+class SwWrtShell;
+class SwContentControl;
+class SwContentControlListItem;
+class SwNumFormatTreeView;
+
+/**
+ * The content control dialog allows editing the properties of the content control under the
+ * cursor.
+ */
+class SwContentControlDlg final : public SfxDialogController
+{
+ SwWrtShell& m_rWrtShell;
+ std::shared_ptr<SwContentControl> m_pContentControl;
+ std::vector<SwContentControlListItem> m_aSavedListItems;
+
+ std::unique_ptr<weld::CheckButton> m_xShowingPlaceHolderCB;
+ std::unique_ptr<weld::Entry> m_xAlias;
+ std::unique_ptr<weld::Entry> m_xTag;
+ std::unique_ptr<weld::SpinButton> m_xId;
+ std::unique_ptr<weld::SpinButton> m_xTabIndex;
+ std::unique_ptr<weld::Frame> m_xCheckboxFrame;
+ std::unique_ptr<weld::Entry> m_xCheckedState;
+ std::unique_ptr<weld::Button> m_xCheckedStateBtn;
+ std::unique_ptr<weld::Entry> m_xUncheckedState;
+ std::unique_ptr<weld::Button> m_xUncheckedStateBtn;
+ std::unique_ptr<weld::Frame> m_xListItemsFrame;
+ std::unique_ptr<weld::TreeView> m_xListItems;
+ std::unique_ptr<weld::Box> m_xListItemButtons;
+ std::unique_ptr<weld::Button> m_xInsertBtn;
+ std::unique_ptr<weld::Button> m_xRenameBtn;
+ std::unique_ptr<weld::Button> m_xDeleteBtn;
+ std::unique_ptr<weld::Button> m_xMoveUpBtn;
+ std::unique_ptr<weld::Button> m_xMoveDownBtn;
+ std::unique_ptr<weld::Frame> m_xDateFrame;
+ std::unique_ptr<SwNumFormatTreeView> m_xDateFormat;
+
+ std::unique_ptr<weld::Button> m_xOk;
+
+ VclPtr<VclAbstractDialog> m_xListItemDialog;
+
+ DECL_LINK(InsertHdl, weld::Button&, void);
+ DECL_LINK(RenameHdl, weld::Button&, void);
+ DECL_LINK(DeleteHdl, weld::Button&, void);
+ DECL_LINK(MoveUpHdl, weld::Button&, void);
+ DECL_LINK(MoveDownHdl, weld::Button&, void);
+ DECL_LINK(SelectionChangedHdl, weld::TreeView&, void);
+ DECL_LINK(OkHdl, weld::Button&, void);
+ DECL_LINK(SelectCharHdl, weld::Button&, void);
+
+public:
+ SwContentControlDlg(weld::Window* pParent, SwWrtShell& rSh);
+ virtual ~SwContentControlDlg() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/contentcontrollistitemdlg.hxx b/sw/source/uibase/inc/contentcontrollistitemdlg.hxx
new file mode 100644
index 0000000000..2367de4847
--- /dev/null
+++ b/sw/source/uibase/inc/contentcontrollistitemdlg.hxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+
+class SwContentControlListItem;
+
+/// Edits the properties of a sing list item in a (drop-down) content control.
+class SwContentControlListItemDlg final : public weld::GenericDialogController
+{
+ SwContentControlListItem& m_rItem;
+
+ std::unique_ptr<weld::Entry> m_xDisplayNameED;
+ std::unique_ptr<weld::Entry> m_xValueED;
+ std::unique_ptr<weld::Button> m_xOk;
+
+ DECL_LINK(OkHdl, weld::Button&, void);
+
+public:
+ SwContentControlListItemDlg(weld::Widget* pParent, SwContentControlListItem& rItem);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/conttree.hxx b/sw/source/uibase/inc/conttree.hxx
new file mode 100644
index 0000000000..b693a7da97
--- /dev/null
+++ b/sw/source/uibase/inc/conttree.hxx
@@ -0,0 +1,423 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CONTTREE_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_CONTTREE_HXX
+
+#include <svl/lstner.hxx>
+#include <vcl/timer.hxx>
+#include <vcl/transfer.hxx>
+#include <vcl/weld.hxx>
+#include <ndarr.hxx>
+#include "swcont.hxx"
+
+#include <map>
+#include <memory>
+
+#include <o3tl/enumarray.hxx>
+#include <o3tl/typed_flags_set.hxx>
+
+#include <svx/sdr/overlay/overlayobject.hxx>
+#include <editsh.hxx>
+#include <edglbldc.hxx>
+
+class SwWrtShell;
+class SwContentType;
+class SwNavigationPI;
+class SwNavigationConfig;
+class Menu;
+class ToolBox;
+class SwGlblDocContents;
+class SfxObjectShell;
+class SdrObject;
+
+enum class EditEntryMode
+{
+ EDIT = 0,
+ UPD_IDX = 1,
+ RMV_IDX = 2,
+ UNPROTECT_TABLE = 3,
+ DELETE = 4,
+ RENAME = 5,
+};
+
+// Flags for PopupMenu-enable/disable
+enum class MenuEnableFlags {
+ NONE = 0x0000,
+ InsertIdx = 0x0001,
+ InsertFile = 0x0002,
+ InsertText = 0x0004,
+ Edit = 0x0008,
+ Delete = 0x0010,
+ Update = 0x0020,
+ UpdateSel = 0x0040,
+ EditLink = 0x0080
+};
+namespace o3tl {
+ template<> struct typed_flags<MenuEnableFlags> : is_typed_flags<MenuEnableFlags, 0x00ff> {};
+}
+
+class SwContentTree;
+
+class SwContentTreeDropTarget final : public DropTargetHelper
+{
+private:
+ SwContentTree& m_rTreeView;
+
+ virtual sal_Int8 AcceptDrop( const AcceptDropEvent& rEvt ) override;
+ virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt ) override;
+
+public:
+ SwContentTreeDropTarget(SwContentTree& rTreeView);
+};
+
+/** TreeListBox for content indicator */
+class SwContentTree final : public SfxListener
+{
+ std::unique_ptr<weld::TreeView> m_xTreeView;
+ SwContentTreeDropTarget m_aDropTargetHelper;
+ SwNavigationPI* m_pDialog;
+ OUString m_sSpace;
+ AutoTimer m_aUpdTimer;
+ AutoTimer m_aOverlayObjectDelayTimer;
+
+ o3tl::enumarray<ContentTypeId,std::unique_ptr<SwContentType>> m_aActiveContentArr;
+ o3tl::enumarray<ContentTypeId,std::unique_ptr<SwContentType>> m_aHiddenContentArr;
+ OUString m_aContextStrings[CONTEXT_COUNT + 1];
+ OUString m_sInvisible;
+ OUString m_sSelectedItem; // last selected item (only bookmarks yet)
+
+ SwWrtShell* m_pHiddenShell; // dropped Doc
+ SwWrtShell* m_pActiveShell; // the active or a const. open view
+ SwNavigationConfig* m_pConfig;
+
+ // these maps store the expand state of nodes with children
+ std::map< void*, bool > mOutLineNodeMap;
+ std::map<const void*, bool> m_aRegionNodeExpandMap;
+ std::map<const void*, bool> m_aPostItNodeExpandMap;
+
+ sal_Int32 m_nActiveBlock; // used to restore content types expand state
+ sal_Int32 m_nHiddenBlock;
+ size_t m_nEntryCount;
+ ContentTypeId m_nRootType; // content type that is currently displayed in the tree
+ ContentTypeId m_nLastSelType;
+ sal_uInt8 m_nOutlineLevel;
+
+ sal_uInt8 m_nOutlineTracking = 1; // 1 default, 2 focus, 3 off
+ o3tl::enumarray<ContentTypeId, bool> mTrackContentType;
+
+ SwOutlineNodes::size_type m_nLastGotoContentWasOutlinePos = SwOutlineNodes::npos;
+
+ enum class State { ACTIVE, CONSTANT, HIDDEN } m_eState;
+
+ bool m_bIsRoot :1;
+ bool m_bIsIdleClear :1;
+ bool m_bIsLastReadOnly :1;
+ bool m_bIsOutlineMoveable :1;
+ bool m_bViewHasChanged :1;
+
+ // outline root mode drag & drop
+ std::vector<std::unique_ptr<weld::TreeIter>> m_aDndOutlinesSelected;
+
+ bool m_bDocHasChanged = true;
+ bool m_bIgnoreDocChange = false; // used to prevent tracking update
+
+ ImplSVEvent* m_nRowActivateEventId = nullptr;
+ bool m_bSelectTo = false;
+
+ std::unique_ptr<weld::TreeIter> m_xOverlayCompareEntry;
+ std::unique_ptr<sdr::overlay::OverlayObject> m_xOverlayObject;
+
+ void OverlayObject(std::vector<basegfx::B2DRange>&& aRanges = {});
+
+ void BringEntryToAttention(const weld::TreeIter& rEntry);
+ void BringFramesToAttention(const std::vector<const SwFrameFormat*>& rFrameFormats);
+ void BringBookmarksToAttention(const std::vector<OUString>& rNames);
+ void BringURLFieldsToAttention(const SwGetINetAttrs& rINetAttrsArr);
+ void BringReferencesToAttention(std::vector<const SwTextAttr*>& rTextAttrsArr);
+ void BringPostItFieldsToAttention(std::vector<const SwTextAttr*>& rTextAttrsArr);
+ void BringDrawingObjectsToAttention(std::vector<const SdrObject*>& rDrawingObjectsArr);
+ void BringTextFieldsToAttention(std::vector<const SwTextAttr*>& rTextAttrsArr);
+ void BringFootnotesToAttention(std::vector<const SwTextAttr*>& rTextAttrsArr);
+ void BringTypesWithFlowFramesToAttention(const std::vector<const SwNode*>& rNodes,
+ const bool bIncludeTopMargin = true);
+
+ /**
+ * Before any data will be deleted, the last active entry has to be found.
+ * After this the UserData will be deleted
+ */
+ void FindActiveTypeAndRemoveUserData();
+
+ void InsertContent(const weld::TreeIter& rParent);
+
+ void insert(const weld::TreeIter* pParent, const OUString& rStr, const OUString& rId,
+ bool bChildrenOnDemand, weld::TreeIter* pRet);
+
+ void remove(const weld::TreeIter& rIter);
+
+ SwNavigationPI* GetParentWindow();
+
+ bool FillTransferData( TransferDataContainer& rTransfer,
+ sal_Int8& rDragMode );
+
+ /** Check if the displayed content is valid. */
+ bool HasContentChanged();
+
+ size_t GetAbsPos(const weld::TreeIter& rIter);
+
+ void EditEntry(const weld::TreeIter& rEntry, EditEntryMode nMode);
+
+ void GotoContent(const SwContent* pCnt);
+
+ void ExecuteContextMenuAction(const OUString& rSelectedPopupEntry);
+
+ void DeleteOutlineSelections();
+ void CopyOutlineSelections();
+
+ size_t GetEntryCount() const;
+
+ size_t GetChildCount(const weld::TreeIter& rParent) const;
+
+ std::unique_ptr<weld::TreeIter> GetEntryAtAbsPos(size_t nAbsPos) const;
+
+ void Expand(const weld::TreeIter& rParent, std::vector<std::unique_ptr<weld::TreeIter>>* pNodesToExpand);
+
+ void MoveOutline(SwOutlineNodes::size_type nTargetPos);
+
+ void UpdateLastSelType();
+
+ /** Expand - Remember the state for content types */
+ DECL_LINK(ExpandHdl, const weld::TreeIter&, bool);
+ /** Collapse - Remember the state for content types. */
+ DECL_LINK(CollapseHdl, const weld::TreeIter&, bool);
+ DECL_LINK(ContentDoubleClickHdl, weld::TreeView&, bool);
+ DECL_LINK(AsyncContentDoubleClickHdl, void*, void);
+ DECL_LINK(SelectHdl, weld::TreeView&, void);
+ DECL_LINK(FocusInHdl, weld::Widget&, void);
+ DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
+ DECL_LINK(CommandHdl, const CommandEvent&, bool);
+ DECL_LINK(QueryTooltipHdl, const weld::TreeIter&, OUString);
+ DECL_LINK(DragBeginHdl, bool&, bool);
+ DECL_LINK(TimerUpdate, Timer *, void);
+ DECL_LINK(OverlayObjectDelayTimerHdl, Timer *, void);
+ DECL_LINK(MouseMoveHdl, const MouseEvent&, bool);
+ DECL_LINK(MousePressHdl, const MouseEvent&, bool);
+
+public:
+ SwContentTree(std::unique_ptr<weld::TreeView> xTreeView, SwNavigationPI* pDialog);
+ ~SwContentTree();
+ SdrObject* GetDrawingObjectsByContent(const SwContent *pCnt);
+
+ /** Switch the display to Root */
+ void ToggleToRoot();
+ void SetRootType(ContentTypeId nType);
+
+ /** Show the file */
+ void Display( bool bActiveView );
+ /** In the clear the content types have to be deleted, also. */
+ void clear();
+
+ /** After a file is dropped on the Navigator, the new shell will be set */
+ void SetHiddenShell(SwWrtShell* pSh);
+ void ShowHiddenShell();
+ void ShowActualView();
+
+ /** Document change - set new Shell */
+ void SetActiveShell(SwWrtShell* pSh);
+
+ /** Set an open view as active. */
+ void SetConstantShell(SwWrtShell* pSh);
+
+ SwWrtShell* GetWrtShell()
+ { return State::HIDDEN == m_eState ? m_pHiddenShell : m_pActiveShell; }
+
+ bool IsInDrag() const;
+ bool HasHeadings() const;
+
+ sal_uInt8 GetOutlineLevel()const {return m_nOutlineLevel;}
+ void SetOutlineLevel(sal_uInt8 nSet);
+
+ void SetOutlineTracking(sal_uInt8 nSet);
+ void SetContentTypeTracking(ContentTypeId eCntTypeId, bool bSet);
+
+ /** Execute commands of the Navigator */
+ void ExecCommand(std::u16string_view rCmd, bool bModifier);
+
+ void ShowTree();
+ void HideTree();
+
+ bool IsConstantView() const { return State::CONSTANT == m_eState; }
+ bool IsActiveView() const { return State::ACTIVE == m_eState; }
+ bool IsHiddenView() const { return State::HIDDEN == m_eState; }
+
+ const SwWrtShell* GetActiveWrtShell() const {return m_pActiveShell;}
+ SwWrtShell* GetHiddenWrtShell() {return m_pHiddenShell;}
+
+ void Select();
+
+ void UpdateTracking();
+ void SelectOutlinesWithSelection();
+ void SelectContentType(std::u16string_view rContentTypeName);
+
+ // return true if it has any children
+ bool RequestingChildren(const weld::TreeIter& rParent);
+
+ void ExpandAllHeadings();
+
+ virtual void Notify(SfxBroadcaster& rBC, SfxHint const& rHint) override;
+
+ sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt);
+ sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt);
+
+ bool IsDropFormatSupported(SotClipboardFormatId nFormat)
+ {
+ return m_aDropTargetHelper.IsDropFormatSupported(nFormat);
+ }
+
+ void set_accessible_name(const OUString& rName)
+ {
+ m_xTreeView->set_accessible_name(rName);
+ }
+
+ void grab_focus()
+ {
+ m_xTreeView->grab_focus();
+ }
+
+ void set_selection_mode(SelectionMode eMode)
+ {
+ m_xTreeView->set_selection_mode(eMode);
+ }
+
+ weld::TreeView& get_widget()
+ {
+ return *m_xTreeView;
+ }
+};
+
+namespace sfx2 { class DocumentInserter; }
+namespace sfx2 { class FileDialogHelper; }
+
+class SwGlobalTree;
+
+class SwGlobalTreeDropTarget final : public DropTargetHelper
+{
+private:
+ SwGlobalTree& m_rTreeView;
+
+ virtual sal_Int8 AcceptDrop( const AcceptDropEvent& rEvt ) override;
+ virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt ) override;
+
+public:
+ SwGlobalTreeDropTarget(SwGlobalTree& rTreeView);
+};
+
+class SwGlobalTree final : public SfxListener
+{
+private:
+ std::unique_ptr<weld::TreeView> m_xTreeView;
+ SwGlobalTreeDropTarget m_aDropTargetHelper;
+ SwNavigationPI* m_pDialog;
+ AutoTimer m_aUpdateTimer;
+ OUString m_aContextStrings[GLOBAL_CONTEXT_COUNT];
+
+ SwWrtShell* m_pActiveShell;
+ std::unique_ptr<SwGlblDocContents> m_pSwGlblDocContents; // array with sorted content
+
+ std::optional<SwGlblDocContent> m_oDocContent;
+ std::unique_ptr<sfx2::DocumentInserter> m_pDocInserter;
+
+ static const SfxObjectShell* s_pShowShell;
+
+ void InsertRegion( const SwGlblDocContent* _pContent,
+ const css::uno::Sequence< OUString >& _rFiles );
+
+ DECL_LINK( DialogClosedHdl, sfx2::FileDialogHelper*, void );
+
+ void Select();
+
+ DECL_LINK(Timeout, Timer*, void);
+ DECL_LINK(DoubleClickHdl, weld::TreeView&, bool);
+ DECL_LINK(SelectHdl, weld::TreeView&, void);
+ DECL_LINK(FocusInHdl, weld::Widget&, void);
+ DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
+ DECL_LINK(CommandHdl, const CommandEvent&, bool);
+ DECL_LINK(QueryTooltipHdl, const weld::TreeIter&, OUString);
+
+ SwNavigationPI* GetParentWindow();
+
+ void OpenDoc(const SwGlblDocContent*);
+ void GotoContent(const SwGlblDocContent*);
+ MenuEnableFlags GetEnableFlags() const;
+
+ static void SetShowShell(const SfxObjectShell*pSet) {s_pShowShell = pSet;}
+ DECL_STATIC_LINK(SwGlobalTree, ShowFrameHdl, void*, void);
+
+public:
+ SwGlobalTree(std::unique_ptr<weld::TreeView> xTreeView, SwNavigationPI* pDialog);
+ ~SwGlobalTree();
+
+ bool get_visible() const { return m_xTreeView->get_visible(); }
+
+ void set_accessible_name(const OUString& rName)
+ {
+ m_xTreeView->set_accessible_name(rName);
+ }
+
+ void grab_focus()
+ {
+ m_xTreeView->grab_focus();
+ }
+
+ void set_selection_mode(SelectionMode eMode)
+ {
+ m_xTreeView->set_selection_mode(eMode);
+ }
+
+ weld::TreeView& get_widget()
+ {
+ return *m_xTreeView;
+ }
+
+ void MoveSelectionTo(const weld::TreeIter* pDropTarget);
+
+ void TbxMenuHdl(std::u16string_view rCommand, weld::Menu& rMenu);
+ void InsertRegion( const SwGlblDocContent* pCont,
+ const OUString* pFileName = nullptr );
+ void EditContent(const SwGlblDocContent* pCont );
+
+ void ShowTree();
+ void HideTree();
+
+ void ExecCommand(std::u16string_view rCmd);
+
+ void Display(bool bOnlyUpdateUserData = false);
+
+ bool Update(bool bHard);
+
+ void ExecuteContextMenuAction(std::u16string_view rSelectedPopupEntry);
+
+ const SwWrtShell* GetActiveWrtShell() const {return m_pActiveShell;}
+
+ virtual void Notify(SfxBroadcaster& rBC, SfxHint const& rHint) override;
+ void UpdateTracking();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/convert.hxx b/sw/source/uibase/inc/convert.hxx
new file mode 100644
index 0000000000..c780bd2d24
--- /dev/null
+++ b/sw/source/uibase/inc/convert.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CONVERT_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_CONVERT_HXX
+
+#include <sfx2/basedlgs.hxx>
+#include <tblafmt.hxx>
+
+class VclContainer;
+class SwTableAutoFormat;
+class SwView;
+class SwWrtShell;
+struct SwInsertTableOptions;
+
+class SwConvertTableDlg final : public SfxDialogController
+{
+ std::unique_ptr<weld::RadioButton> m_xTabBtn;
+ std::unique_ptr<weld::RadioButton> m_xSemiBtn;
+ std::unique_ptr<weld::RadioButton> m_xParaBtn;
+ std::unique_ptr<weld::RadioButton> m_xOtherBtn;
+ std::unique_ptr<weld::Entry> m_xOtherEd;
+ std::unique_ptr<weld::CheckButton> m_xKeepColumn;
+
+ std::unique_ptr<weld::Container> m_xOptions;
+
+ std::unique_ptr<weld::CheckButton> m_xHeaderCB;
+ std::unique_ptr<weld::CheckButton> m_xRepeatHeaderCB;
+
+ std::unique_ptr<weld::Container> m_xRepeatRows;
+ std::unique_ptr<weld::SpinButton> m_xRepeatHeaderNF;
+
+ std::unique_ptr<weld::CheckButton> m_xDontSplitCB;
+ std::unique_ptr<weld::Button> m_xAutoFormatBtn;
+
+ std::unique_ptr<SwTableAutoFormat> mxTAutoFormat;
+ SwWrtShell* m_pShell;
+
+ DECL_LINK(AutoFormatHdl, weld::Button&, void);
+ DECL_LINK(BtnHdl, weld::Toggleable&, void);
+ DECL_LINK(CheckBoxHdl, weld::Toggleable&, void);
+ DECL_LINK(RepeatHeaderCheckBoxHdl, weld::Toggleable&, void);
+
+public:
+ SwConvertTableDlg(SwView& rView, bool bToTable);
+
+ void GetValues(sal_Unicode& rDelim, SwInsertTableOptions& rInsTableOpts,
+ SwTableAutoFormat const*& prTAFormat);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/cption.hxx b/sw/source/uibase/inc/cption.hxx
new file mode 100644
index 0000000000..4d28b71668
--- /dev/null
+++ b/sw/source/uibase/inc/cption.hxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CPTION_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_CPTION_HXX
+
+#include <sfx2/basedlgs.hxx>
+
+#include <com/sun/star/container/XNameAccess.hpp>
+
+#include "wrtsh.hxx"
+#include "optload.hxx"
+
+class SwFieldMgr;
+class SwView;
+
+class SwCaptionDialog final : public SfxDialogController
+{
+ OUString m_sNone;
+ TextFilterAutoConvert m_aTextFilter;
+ SwView& m_rView; // search per active, avoid View
+ std::unique_ptr<SwFieldMgr> m_pMgr; // pointer to save the include
+
+ OUString m_sCharacterStyle;
+ bool m_bCopyAttributes;
+ bool m_bOrderNumberingFirst; //#i61007# order of captions
+
+ css::uno::Reference<css::container::XNameAccess> m_xNameAccess;
+
+ SwCaptionPreview m_aPreview;
+ std::unique_ptr<weld::Entry> m_xTextEdit;
+ std::unique_ptr<weld::ComboBox> m_xCategoryBox;
+ std::unique_ptr<weld::Label> m_xFormatText;
+ std::unique_ptr<weld::ComboBox> m_xFormatBox;
+ //#i61007# order of captions
+ std::unique_ptr<weld::Label> m_xNumberingSeparatorFT;
+ std::unique_ptr<weld::Entry> m_xNumberingSeparatorED;
+ std::unique_ptr<weld::Label> m_xSepText;
+ std::unique_ptr<weld::Entry> m_xSepEdit;
+ std::unique_ptr<weld::ComboBox> m_xPosBox;
+ std::unique_ptr<weld::Button> m_xOKButton;
+ std::unique_ptr<weld::Button> m_xAutoCaptionButton;
+ std::unique_ptr<weld::Button> m_xOptionButton;
+ std::unique_ptr<weld::CustomWeld> m_xPreview;
+
+ DECL_LINK(SelectListBoxHdl, weld::ComboBox&, void);
+ DECL_LINK(ModifyEntryHdl, weld::Entry&, void);
+ DECL_LINK(ModifyComboHdl, weld::ComboBox&, void);
+ DECL_LINK(OptionHdl, weld::Button&, void);
+ DECL_LINK(CaptionHdl, weld::Button&, void);
+ DECL_LINK(OKHdl, weld::Button&, void);
+
+ void Apply();
+
+ void ModifyHdl();
+ void DrawSample();
+ void ApplyCaptionOrder(); //#i61007# order of captions
+
+ static OUString s_aSepTextSave; // Save caption separator text
+public:
+ SwCaptionDialog(weld::Window* pParent, SwView& rV);
+ virtual short run() override;
+ virtual ~SwCaptionDialog() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/dbconfig.hxx b/sw/source/uibase/inc/dbconfig.hxx
new file mode 100644
index 0000000000..66ebfc2b90
--- /dev/null
+++ b/sw/source/uibase/inc/dbconfig.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DBCONFIG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_DBCONFIG_HXX
+
+#include <unotools/configitem.hxx>
+#include <swdllapi.h>
+
+struct SwDBData;
+
+class SW_DLLPUBLIC SwDBConfig final : public utl::ConfigItem
+{
+private:
+ SAL_DLLPRIVATE static const css::uno::Sequence<OUString>& GetPropertyNames();
+ virtual void ImplCommit() override;
+
+ std::unique_ptr<SwDBData> m_pAdrImpl;
+ std::unique_ptr<SwDBData> m_pBibImpl;
+
+public:
+ SwDBConfig();
+ virtual ~SwDBConfig() override;
+
+ void Load();
+ const SwDBData& GetAddressSource();
+ const SwDBData& GetBibliographySource();
+ virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/dbinsdlg.hxx b/sw/source/uibase/inc/dbinsdlg.hxx
new file mode 100644
index 0000000000..035bf49c61
--- /dev/null
+++ b/sw/source/uibase/inc/dbinsdlg.hxx
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DBINSDLG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_DBINSDLG_HXX
+
+#include <utility>
+#include <vcl/weld.hxx>
+#include <sfx2/basedlgs.hxx>
+#include <unotools/configitem.hxx>
+#include "numfmtlb.hxx"
+#include <swdbdata.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Sequence.h>
+#include <o3tl/sorted_vector.hxx>
+
+#include <memory>
+#include <vector>
+
+namespace com::sun::star{
+ namespace sdbcx{
+ class XColumnsSupplier;
+ }
+ namespace sdbc{
+ class XDataSource;
+ class XConnection;
+ class XResultSet;
+ }
+}
+
+class SwTableAutoFormat;
+class SwView;
+class SfxItemSet;
+class SwTableRep;
+struct DB_Column;
+
+typedef std::vector<std::unique_ptr<DB_Column>> DB_Columns;
+
+struct SwInsDBColumn
+{
+ OUString sColumn, sUsrNumFormat;
+ sal_Int32 nDBNumFormat;
+ sal_uInt32 nUsrNumFormat;
+ LanguageType eUsrNumFormatLng;
+ bool bHasFormat : 1;
+ bool bIsDBFormat : 1;
+
+ SwInsDBColumn( OUString aStr )
+ : sColumn(std::move( aStr )),
+ nDBNumFormat( 0 ),
+ nUsrNumFormat( 0 ),
+ eUsrNumFormatLng( LANGUAGE_SYSTEM ),
+ bHasFormat(false),
+ bIsDBFormat(true)
+ {}
+
+ bool operator<( const SwInsDBColumn& rCmp ) const;
+};
+
+class SwInsDBColumns : public o3tl::sorted_vector<std::unique_ptr<SwInsDBColumn>, o3tl::less_uniqueptr_to<SwInsDBColumn> >
+{
+};
+
+class SwInsertDBColAutoPilot final : public SfxDialogController, public utl::ConfigItem
+{
+ SwInsDBColumns m_aDBColumns;
+ const SwDBData m_aDBData;
+
+ OUString m_sNoTmpl;
+
+ SwView* m_pView;
+ std::unique_ptr<SwTableAutoFormat> m_xTAutoFormat;
+
+ std::unique_ptr<SfxItemSet> m_pTableSet;
+ std::unique_ptr<SwTableRep> m_pRep;
+ sal_Int32 m_nGBFormatLen;
+
+ std::unique_ptr<weld::RadioButton> m_xRbAsTable;
+ std::unique_ptr<weld::RadioButton> m_xRbAsField;
+ std::unique_ptr<weld::RadioButton> m_xRbAsText;
+
+ std::unique_ptr<weld::Frame> m_xHeadFrame;
+
+ std::unique_ptr<weld::TreeView> m_xLbTableDbColumn;
+ std::unique_ptr<weld::TreeView> m_xLbTextDbColumn;
+
+ std::unique_ptr<weld::Frame> m_xFormatFrame;
+ std::unique_ptr<weld::RadioButton> m_xRbDbFormatFromDb;
+ std::unique_ptr<weld::RadioButton> m_xRbDbFormatFromUsr;
+ std::unique_ptr<NumFormatListBox> m_xLbDbFormatFromUsr;
+
+ // Page Text/Field
+ std::unique_ptr<weld::Button> m_xIbDbcolToEdit;
+ std::unique_ptr<weld::TextView> m_xEdDbText;
+ std::unique_ptr<weld::Label> m_xFtDbParaColl;
+ std::unique_ptr<weld::ComboBox> m_xLbDbParaColl;
+
+ // Page Table
+ std::unique_ptr<weld::Button> m_xIbDbcolAllTo;
+ std::unique_ptr<weld::Button> m_xIbDbcolOneTo;
+ std::unique_ptr<weld::Button> m_xIbDbcolOneFrom;
+ std::unique_ptr<weld::Button> m_xIbDbcolAllFrom;
+ std::unique_ptr<weld::Label> m_xFtTableCol;
+ std::unique_ptr<weld::TreeView> m_xLbTableCol;
+ std::unique_ptr<weld::CheckButton> m_xCbTableHeadon;
+ std::unique_ptr<weld::RadioButton> m_xRbHeadlColnms;
+ std::unique_ptr<weld::RadioButton> m_xRbHeadlEmpty;
+ std::unique_ptr<weld::Button> m_xPbTableFormat;
+ std::unique_ptr<weld::Button> m_xPbTableAutofmt;
+
+ DECL_LINK( PageHdl, weld::Toggleable&, void );
+ DECL_LINK( AutoFormatHdl, weld::Button&, void );
+ DECL_LINK( TableFormatHdl, weld::Button&, void );
+ DECL_LINK( DBFormatHdl, weld::Toggleable&, void );
+ DECL_LINK( TableToFromHdl, weld::Button&, void );
+ DECL_LINK( TVSelectHdl, weld::TreeView&, void );
+ DECL_LINK( CBSelectHdl, weld::ComboBox&, void );
+ DECL_LINK( DblClickHdl, weld::TreeView&, bool );
+ DECL_LINK( HeaderHdl, weld::Toggleable&, void );
+
+ bool SplitTextToColArr( const OUString& rText, DB_Columns& rColArr, bool bInsField );
+ virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+ virtual void ImplCommit() override;
+ void Load();
+
+ // set the tables - properties
+ void SetTabSet();
+
+public:
+ SwInsertDBColAutoPilot( SwView& rView,
+ css::uno::Reference< css::sdbc::XDataSource> const & rxSource,
+ css::uno::Reference<css::sdbcx::XColumnsSupplier> const & xColSupp,
+ SwDBData aData );
+
+ virtual ~SwInsertDBColAutoPilot() override;
+
+ void DataToDoc( const css::uno::Sequence< css::uno::Any >& rSelection,
+ css::uno::Reference< css::sdbc::XDataSource> const & rxSource,
+ css::uno::Reference< css::sdbc::XConnection> const & xConnection,
+ css::uno::Reference< css::sdbc::XResultSet > const & xResultSet);
+
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/dbtree.hxx b/sw/source/uibase/inc/dbtree.hxx
new file mode 100644
index 0000000000..c6806cdfed
--- /dev/null
+++ b/sw/source/uibase/inc/dbtree.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DBTREE_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_DBTREE_HXX
+
+#include <memory>
+#include <vcl/weld.hxx>
+
+#include <swdllapi.h>
+
+class SwDBTreeList_Impl;
+class SwWrtShell;
+
+class SW_DLLPUBLIC SwDBTreeList
+{
+ bool m_bInitialized;
+ bool m_bShowColumns;
+
+ rtl::Reference<SwDBTreeList_Impl> m_pImpl;
+ std::unique_ptr<weld::TreeView> m_xTreeView;
+ std::unique_ptr<weld::TreeIter> m_xScratchIter;
+
+ DECL_DLLPRIVATE_LINK(RequestingChildrenHdl, const weld::TreeIter&, bool);
+ SAL_DLLPRIVATE void InitTreeList();
+
+public:
+ SwDBTreeList(std::unique_ptr<weld::TreeView> xTreeView);
+ ~SwDBTreeList();
+
+ OUString GetDBName(OUString& rTableName, OUString& rColumnName, sal_Bool* pbIsTable = nullptr);
+
+ void Select( std::u16string_view rDBName, std::u16string_view rTableName,
+ std::u16string_view rColumnName );
+
+ void ShowColumns(bool bShowCol);
+
+ void SetWrtShell(SwWrtShell& rSh);
+
+ void AddDataSource(const OUString& rSource);
+
+ void connect_changed(const Link<weld::TreeView&, void>& rLink) { m_xTreeView->connect_changed(rLink); }
+ void connect_row_activated(const Link<weld::TreeView&, bool>& rLink) { m_xTreeView->connect_row_activated(rLink); }
+ std::unique_ptr<weld::TreeIter> make_iterator(const weld::TreeIter* pOrig = nullptr) const { return m_xTreeView->make_iterator(pOrig); }
+ bool get_selected(weld::TreeIter* pIter) const { return m_xTreeView->get_selected(pIter); }
+ bool iter_parent(weld::TreeIter& rIter) const { return m_xTreeView->iter_parent(rIter); }
+ int get_iter_depth(const weld::TreeIter& rIter) const { return m_xTreeView->get_iter_depth(rIter); }
+ void set_size_request(int nWidth, int nHeight) { m_xTreeView->set_size_request(nWidth, nHeight); }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/dbui.hxx b/sw/source/uibase/inc/dbui.hxx
new file mode 100644
index 0000000000..19b12dd43c
--- /dev/null
+++ b/sw/source/uibase/inc/dbui.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DBUI_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_DBUI_HXX
+
+#include <vcl/weld.hxx>
+
+#include <swdllapi.h>
+
+class PrintMonitor final : public weld::GenericDialogController
+{
+public:
+ std::unique_ptr<weld::Label> m_xPrinter;
+ std::unique_ptr<weld::Label> m_xPrintInfo;
+
+ PrintMonitor(weld::Window* pParent);
+ virtual ~PrintMonitor() override;
+};
+
+class SW_DLLPUBLIC SaveMonitor final : public weld::GenericDialogController
+{
+public:
+ std::unique_ptr<weld::Label> m_xDocName;
+ std::unique_ptr<weld::Label> m_xPrinter;
+ std::unique_ptr<weld::Label> m_xPrintInfo;
+
+ SaveMonitor(weld::Window* pParent);
+ virtual ~SaveMonitor() override;
+};
+
+class CreateMonitor final : public weld::GenericDialogController
+{
+public:
+ CreateMonitor(weld::Window* pParent);
+ virtual ~CreateMonitor() override;
+
+ void SetTotalCount(sal_Int32 nTotal);
+ void SetCurrentPosition(sal_Int32 nCurrent);
+
+private:
+ void UpdateCountingText();
+
+private:
+ OUString m_sCountingPattern;
+ sal_Int32 m_nTotalCount;
+ sal_Int32 m_nCurrentPosition;
+
+ std::unique_ptr<weld::Label> m_xCounting;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/docfnote.hxx b/sw/source/uibase/inc/docfnote.hxx
new file mode 100644
index 0000000000..8bc5d1851d
--- /dev/null
+++ b/sw/source/uibase/inc/docfnote.hxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DOCFNOTE_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_DOCFNOTE_HXX
+
+#include <sfx2/tabdlg.hxx>
+
+class SwWrtShell;
+
+class SwFootNoteOptionDlg final : public SfxTabDialogController
+{
+ SwWrtShell& m_rSh;
+
+ virtual void PageCreated(const OUString& rId, SfxTabPage& rPage) override;
+
+ DECL_LINK(OkHdl, weld::Button&, void);
+
+public:
+ SwFootNoteOptionDlg(weld::Window* pParent, SwWrtShell& rSh);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/docstdlg.hxx b/sw/source/uibase/inc/docstdlg.hxx
new file mode 100644
index 0000000000..3642b9fd71
--- /dev/null
+++ b/sw/source/uibase/inc/docstdlg.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DOCSTDLG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_DOCSTDLG_HXX
+
+#include <sfx2/tabdlg.hxx>
+#include <docstat.hxx>
+
+// DocInfo now as page
+class SwDocStatPage final : public SfxTabPage
+{
+public:
+ SwDocStatPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet);
+ virtual ~SwDocStatPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet);
+
+private:
+ virtual bool FillItemSet( SfxItemSet *rSet) override;
+ virtual void Reset (const SfxItemSet *rSet) override;
+
+ DECL_LINK(UpdateHdl, weld::Button&, void);
+
+ std::unique_ptr<weld::Label> m_xPageNo;
+ std::unique_ptr<weld::Label> m_xTableNo;
+ std::unique_ptr<weld::Label> m_xGrfNo;
+ std::unique_ptr<weld::Label> m_xOLENo;
+ std::unique_ptr<weld::Label> m_xParaNo;
+ std::unique_ptr<weld::Label> m_xWordNo;
+ std::unique_ptr<weld::Label> m_xCharNo;
+ std::unique_ptr<weld::Label> m_xCharExclSpacesNo;
+ std::unique_ptr<weld::Label> m_xLineLbl;
+ std::unique_ptr<weld::Label> m_xLineNo;
+ std::unique_ptr<weld::Button> m_xUpdatePB;
+
+ SwDocStat m_aDocStat;
+
+ void Update();
+
+ void SetData(const SwDocStat &rStat);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/drawbase.hxx b/sw/source/uibase/inc/drawbase.hxx
new file mode 100644
index 0000000000..ccc045ced3
--- /dev/null
+++ b/sw/source/uibase/inc/drawbase.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DRAWBASE_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_DRAWBASE_HXX
+
+#include <tools/gen.hxx>
+#include <vcl/vclptr.hxx>
+
+class SwView;
+class SwWrtShell;
+class SwEditWin;
+class KeyEvent;
+class MouseEvent;
+
+// base class for all functions
+class SwDrawBase
+{
+protected:
+ SwView* m_pView;
+ SwWrtShell* m_pSh;
+ VclPtr<SwEditWin> m_pWin;
+ Point m_aStartPos; // position of BeginCreate
+ sal_uInt16 m_nSlotId;
+ bool m_bCreateObj :1;
+ bool m_bInsForm :1;
+
+ Point GetDefaultCenterPos() const;
+public:
+ SwDrawBase(SwWrtShell *pSh, SwEditWin* pWin, SwView* pView);
+ virtual ~SwDrawBase();
+
+ void SetDrawPointer();
+ void EnterSelectMode(const MouseEvent& rMEvt);
+ bool IsInsertForm() const { return m_bInsForm; }
+ bool IsCreateObj() const { return m_bCreateObj; }
+
+ // mouse- & key events; return value=true: event was edited
+ bool MouseMove(const MouseEvent& rMEvt);
+ virtual bool MouseButtonUp(const MouseEvent& rMEvt);
+ virtual bool MouseButtonDown(const MouseEvent& rMEvt);
+
+ void BreakCreate();
+ void SetSlotId(sal_uInt16 nSlot) {m_nSlotId = nSlot;}
+ sal_uInt16 GetSlotId() const { return m_nSlotId;}
+
+ virtual void Activate(const sal_uInt16 nSlotId); // activate function
+ virtual void Deactivate(); // deactivate function
+
+ virtual void CreateDefaultObject();
+ virtual void CreateDefaultObjectAtPosWithSize(Point aPos, Size aSize);
+
+ // #i33136#
+ virtual bool doConstructOrthogonal() const;
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_DRAWBASE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/drawsh.hxx b/sw/source/uibase/inc/drawsh.hxx
new file mode 100644
index 0000000000..ca164e95eb
--- /dev/null
+++ b/sw/source/uibase/inc/drawsh.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DRAWSH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_DRAWSH_HXX
+
+#include "drwbassh.hxx"
+
+#include <svx/svdobj.hxx>
+
+class SwDrawBaseShell;
+
+class SwDrawShell final : public SwDrawBaseShell
+{
+public:
+ SFX_DECL_INTERFACE(SW_DRAWSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwDrawShell(SwView &rView);
+
+ void Execute(SfxRequest &);
+ void GetState(SfxItemSet &);
+ void ExecDrawDlg(SfxRequest& rReq);
+ void ExecDrawAttrArgs(SfxRequest const & rReq);
+ void GetDrawAttrState(SfxItemSet &rSet);
+
+ void ExecFormText(SfxRequest const & rReq);
+ void GetFormTextState(SfxItemSet& rSet);
+
+ // #i123922# added helper methods to handle applying graphic data to draw objects
+ SdrObject* IsSingleFillableNonOLESelected();
+ void InsertPictureFromFile(SdrObject& rObject);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/drformsh.hxx b/sw/source/uibase/inc/drformsh.hxx
new file mode 100644
index 0000000000..9c8602d149
--- /dev/null
+++ b/sw/source/uibase/inc/drformsh.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DRFORMSH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_DRFORMSH_HXX
+
+#include "drwbassh.hxx"
+
+class SwDrawBaseShell;
+
+class SwDrawFormShell: public SwDrawBaseShell
+{
+public:
+ SFX_DECL_INTERFACE(SW_DRAWFORMSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwDrawFormShell(SwView &rView);
+ virtual ~SwDrawFormShell() override;
+
+ void Execute(SfxRequest const &);
+ void GetState(SfxItemSet &);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/drpcps.hxx b/sw/source/uibase/inc/drpcps.hxx
new file mode 100644
index 0000000000..afc7c64822
--- /dev/null
+++ b/sw/source/uibase/inc/drpcps.hxx
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DRPCPS_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_DRPCPS_HXX
+
+#include <com/sun/star/i18n/XBreakIterator.hpp>
+#include <editeng/svxfont.hxx>
+#include <sfx2/basedlgs.hxx>
+#include <sfx2/tabdlg.hxx>
+#include <vcl/customweld.hxx>
+#include <vcl/print.hxx>
+
+class SwWrtShell;
+
+/// Dedicated drop caps dialog, opened by the .uno:FormatDropcap UNO command, which is not in the
+/// default menus.
+class SwDropCapsDlg final : public SfxSingleTabDialogController
+{
+public:
+ SwDropCapsDlg(weld::Window *pParent, const SfxItemSet &rSet);
+};
+
+class SwDropCapsPage;
+
+class SwDropCapsPict final : public weld::CustomWidgetController
+{
+ SwDropCapsPage* mpPage;
+ OUString maText;
+ OUString maScriptText;
+ Color maBackColor;
+ Color maTextLineColor;
+ sal_uInt8 mnLines;
+ tools::Long mnTotLineH;
+ tools::Long mnLineH;
+ tools::Long mnTextH;
+ sal_uInt16 mnDistance;
+ VclPtr<Printer> mpPrinter;
+ bool mbDelPrinter;
+ /// The ScriptInfo structure holds information on where we change from one
+ /// script to another.
+ struct ScriptInfo
+ {
+ sal_uLong textWidth; ///< Physical width of this segment.
+ sal_uInt16 scriptType; ///< Script type (e.g. Latin, Asian, Complex)
+ sal_Int32 changePos; ///< Character position where the script changes.
+ ScriptInfo(sal_uInt16 scrptType, sal_Int32 position)
+ : textWidth(0), scriptType(scrptType), changePos(position) {}
+ };
+ std::vector<ScriptInfo> maScriptChanges;
+ SvxFont maFont;
+ SvxFont maCJKFont;
+ SvxFont maCTLFont;
+ Size maTextSize;
+ css::uno::Reference< css::i18n::XBreakIterator > m_xBreak;
+
+ virtual void Paint(vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle &rRect) override;
+ void CheckScript();
+ Size CalcTextSize();
+ inline void InitPrinter();
+ void InitPrinter_();
+ static void GetFontSettings( vcl::Font& _rFont, sal_uInt16 _nWhich );
+ void GetFirstScriptSegment(sal_Int32 &start, sal_Int32 &end, sal_uInt16 &scriptType);
+ bool GetNextScriptSegment(size_t &nIdx, sal_Int32 &start, sal_Int32 &end, sal_uInt16 &scriptType);
+
+public:
+
+ SwDropCapsPict()
+ : mpPage(nullptr)
+ , mnLines(0)
+ , mnTotLineH(0)
+ , mnLineH(0)
+ , mnTextH(0)
+ , mnDistance(0)
+ , mpPrinter(nullptr)
+ , mbDelPrinter(false)
+ {}
+
+ void SetDropCapsPage(SwDropCapsPage* pPage) { mpPage = pPage; }
+
+ virtual ~SwDropCapsPict() override;
+
+ void UpdatePaintSettings(); // also invalidates control!
+
+ virtual void Resize() override;
+
+ virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override;
+
+ void SetText( const OUString& rT );
+ void SetLines( sal_uInt8 nL );
+ void SetDistance( sal_uInt16 nD );
+ void SetValues( const OUString& rText, sal_uInt8 nLines, sal_uInt16 nDistance );
+
+ void DrawPrev(vcl::RenderContext& rRenderContext, const Point& rPt);
+};
+
+class SwDropCapsPage final : public SfxTabPage
+{
+friend class SwDropCapsPict;
+ SwDropCapsPict m_aPict;
+
+ bool m_bModified;
+ bool m_bFormat;
+ bool m_bHtmlMode;
+
+ std::unique_ptr<weld::CheckButton> m_xDropCapsBox;
+ std::unique_ptr<weld::CheckButton> m_xWholeWordCB;
+ std::unique_ptr<weld::Label> m_xSwitchText;
+ std::unique_ptr<weld::SpinButton> m_xDropCapsField;
+ std::unique_ptr<weld::Label> m_xLinesText;
+ std::unique_ptr<weld::SpinButton> m_xLinesField;
+ std::unique_ptr<weld::Label> m_xDistanceText;
+ std::unique_ptr<weld::MetricSpinButton> m_xDistanceField;
+ std::unique_ptr<weld::Label> m_xTextText;
+ std::unique_ptr<weld::Entry> m_xTextEdit;
+ std::unique_ptr<weld::Label> m_xTemplateText;
+ std::unique_ptr<weld::ComboBox> m_xTemplateBox;
+ std::unique_ptr<weld::CustomWeld> m_xPict;
+
+ virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override;
+ void FillSet( SfxItemSet &rSet );
+
+ void ModifyEntry(const weld::Entry& rEdit);
+
+ DECL_LINK(ClickHdl, weld::Toggleable&, void);
+ DECL_LINK(MetricValueChangedHdl, weld::MetricSpinButton&, void);
+ DECL_LINK(ValueChangedHdl, weld::SpinButton&, void);
+ DECL_LINK(ModifyHdl, weld::Entry&, void);
+ DECL_LINK(SelectHdl, weld::ComboBox&, void);
+ DECL_LINK(WholeWordHdl, weld::Toggleable&, void);
+
+ static const WhichRangesContainer s_aPageRg;
+
+public:
+ SwDropCapsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet);
+ virtual ~SwDropCapsPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet);
+ static WhichRangesContainer GetRanges() { return s_aPageRg; }
+
+
+ virtual bool FillItemSet( SfxItemSet *rSet) override;
+ virtual void Reset (const SfxItemSet *rSet) override;
+
+ void SetFormat(bool bSet){m_bFormat = bSet;}
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/drwbassh.hxx b/sw/source/uibase/inc/drwbassh.hxx
new file mode 100644
index 0000000000..e75576dec2
--- /dev/null
+++ b/sw/source/uibase/inc/drwbassh.hxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DRWBASSH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_DRWBASSH_HXX
+
+#include "basesh.hxx"
+
+class SwView;
+class SfxItemSet;
+class SwDrawBase;
+class AbstractSvxObjectNameDialog;
+struct SvxSwFrameValidation;
+
+class SwDrawBaseShell: public SwBaseShell
+{
+ DECL_LINK( CheckGroupShapeNameHdl, AbstractSvxObjectNameDialog&, bool );
+ DECL_LINK(ValidatePosition, SvxSwFrameValidation&, void );
+public:
+ SwDrawBaseShell(SwView &rShell);
+ virtual ~SwDrawBaseShell() override;
+
+ SFX_DECL_INTERFACE(SW_DRAWBASESHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ void Execute(SfxRequest const &);
+ void GetState(SfxItemSet &);
+ void GetDrawAttrStateForIFBX( SfxItemSet& rSet );
+ void DisableState(SfxItemSet &rSet);
+ bool Disable(SfxItemSet& rSet, sal_uInt16 nWhich = 0);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/drwtxtsh.hxx b/sw/source/uibase/inc/drwtxtsh.hxx
new file mode 100644
index 0000000000..8c3f4da5d0
--- /dev/null
+++ b/sw/source/uibase/inc/drwtxtsh.hxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DRWTXTSH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_DRWTXTSH_HXX
+
+#include <sfx2/shell.hxx>
+#include <shellid.hxx>
+#include <unotools/caserotate.hxx>
+
+class SdrView;
+class SwView;
+class SwWrtShell;
+
+/// SfxShell subclass that is used while interacting with the editeng-based text of a shape.
+class SwDrawTextShell final : public SfxShell
+{
+ SwView &m_rView;
+ RotateTransliteration m_aRotateCase;
+
+ SdrView *m_pSdrView;
+
+ void SetAttrToMarked(const SfxItemSet& rAttr);
+ void InsertSymbol(SfxRequest& rReq);
+ bool IsTextEdit() const;
+
+public:
+ SFX_DECL_INTERFACE(SW_DRWTXTSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwView &GetView() { return m_rView; }
+ SwWrtShell &GetShell();
+
+ SwDrawTextShell(SwView &rView);
+ virtual ~SwDrawTextShell() override;
+
+ virtual SfxUndoManager*
+ GetUndoManager() override;
+
+ static void StateDisableItems(SfxItemSet &);
+
+ void Execute(SfxRequest &);
+ void ExecDraw(SfxRequest &);
+ void GetStatePropPanelAttr(SfxItemSet &);
+ void GetState(SfxItemSet &);
+ void GetDrawTextCtrlState(SfxItemSet&);
+
+ void ExecFontWork(SfxRequest const & rReq);
+ void StateFontWork(SfxItemSet& rSet);
+ void ExecFormText(SfxRequest const & rReq);
+ void GetFormTextState(SfxItemSet& rSet);
+ void ExecDrawLingu(SfxRequest const &rReq);
+ void ExecUndo(SfxRequest &rReq);
+ void StateUndo(SfxItemSet &rSet);
+ void ExecClpbrd(SfxRequest const &rReq);
+ void StateClpbrd(SfxItemSet &rSet);
+ void StateInsert(SfxItemSet &rSet);
+ void ExecTransliteration(SfxRequest const &);
+ void ExecRotateTransliteration(SfxRequest const &);
+
+ void Init();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/dselect.hxx b/sw/source/uibase/inc/dselect.hxx
new file mode 100644
index 0000000000..4f53feb310
--- /dev/null
+++ b/sw/source/uibase/inc/dselect.hxx
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DSELECT_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_DSELECT_HXX
+
+#include "drawbase.hxx"
+
+// draw rectangle
+class DrawSelection final : public SwDrawBase
+{
+public:
+ DrawSelection(SwWrtShell* pSh, SwEditWin* pWin, SwView* pView);
+
+ virtual void Activate(const sal_uInt16 nSlotId) override; // activate function
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_DSELECT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/edtdd.hxx b/sw/source/uibase/inc/edtdd.hxx
new file mode 100644
index 0000000000..4416bc73cc
--- /dev/null
+++ b/sw/source/uibase/inc/edtdd.hxx
@@ -0,0 +1,19 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_EDTDD_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_EDTDD_HXX
+
+#include <sal/config.h>
+
+extern bool g_bExecuteDrag;
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/source/uibase/inc/edtwin.hxx b/sw/source/uibase/inc/edtwin.hxx
new file mode 100644
index 0000000000..714e6bcc3b
--- /dev/null
+++ b/sw/source/uibase/inc/edtwin.hxx
@@ -0,0 +1,306 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_EDTWIN_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_EDTWIN_HXX
+
+#include <o3tl/deleter.hxx>
+#include <sot/exchange.hxx>
+#include <svx/svdobj.hxx>
+#include <tools/link.hxx>
+#include <vcl/timer.hxx>
+#include <vcl/DocWindow.hxx>
+#include <vcl/transfer.hxx>
+#include <swevent.hxx>
+#include <swtypes.hxx>
+
+class SwWrtShell;
+class SwView;
+class SwRect;
+class SwViewShell;
+class SwAnchorMarker;
+class SdrObject;
+class SwShadowCursor;
+class DataChangedEvent;
+class SvxAutoCorrCfg;
+class SvxAutoCorrect;
+class SwPaM;
+struct SwApplyTemplate;
+struct QuickHelpData;
+class SdrDropMarkerOverlay;
+class SwFrameControlsManager;
+enum class SdrHitKind;
+class SwTextFrame;
+
+// input window
+
+/** Window class for the Writer edit area, this is the one handling mouse
+ and keyboard events and doing the final painting of the document from
+ the buffered layout.
+
+ To translate the pixel positions from the buffer OutputDevice to the real
+ pixel positions, use the PixelToLogic methods of this class.
+ */
+class SW_DLLPUBLIC SwEditWin final : public vcl::DocWindow,
+ public DropTargetHelper, public DragSourceHelper
+{
+ static QuickHelpData* s_pQuickHlpData;
+
+ static tools::Long s_nDDStartPosX;
+ static tools::Long s_nDDStartPosY;
+
+ Color m_aWaterCanTextColor; // text color; for the watering can
+ Color m_aWaterCanTextBackColor; // text background; for the watering can
+
+ /*
+ * timer and handler for scrolling on when the mousepointer
+ * stops outside of EditWin during a drag-operation.
+ * The selection is increased towards the mouse position
+ * regularly.
+ */
+ AutoTimer m_aTimer;
+ // timer for ANY-KeyInput question without a following KeyInputEvent
+ Timer m_aKeyInputFlushTimer;
+
+ OUString m_aInBuffer;
+ LanguageType m_eBufferLanguage;
+ Point m_aStartPos;
+ Point m_aMovePos;
+ Point m_aRszMvHdlPt;
+ Timer m_aTemplateTimer;
+
+ // type/object where the mouse pointer is
+ SwCallMouseEvent m_aSaveCallEvent;
+
+ std::unique_ptr<SwApplyTemplate> m_pApplyTempl;
+ std::unique_ptr<SwAnchorMarker> m_pAnchorMarker; // for relocating the anchor
+
+ std::unique_ptr<SdrDropMarkerOverlay> m_pUserMarker;
+ SdrObject *m_pUserMarkerObj;
+ std::unique_ptr<SwShadowCursor, o3tl::default_delete<SwShadowCursor>> m_pShadCursor;
+ sal_Int16 m_eOrient;
+ std::optional<Point> m_xRowColumnSelectionStart; // save position where table row/column selection has been started
+
+ SwView &m_rView;
+
+ SdrHitKind m_aActHitType; // current mouse pointer
+
+ SotClipboardFormatId m_nDropFormat; // format from the last QueryDrop
+ sal_uInt8 m_nDropAction; // action from the last QueryDrop
+ SotExchangeDest m_nDropDestination; // destination from the last QueryDrop
+
+ sal_uInt16 m_eBezierMode;
+ sal_uInt16 m_nInsFrameColCount; // column number for interactive frame
+ SdrObjKind m_eDrawMode;
+ bool m_bMBPressed : 1,
+ m_bInsDraw : 1,
+ m_bInsFrame : 1,
+ m_bIsInMove : 1,
+ m_bIsInDrag : 1, // don't execute StartExecuteDrag twice
+ m_bOldIdle : 1, // to stop to idle
+ m_bOldIdleSet : 1, // during QeueryDrop
+ m_bChainMode : 1, // connect frames
+ m_bWasShdwCursor : 1, // ShadowCursor was on in MouseButtonDown
+ m_bLockInput : 1, // lock while calc panel is active
+ m_bIsRowDrag : 1, //selection of rows is used, in combination with m_pRowColumnSelectionStart
+ /** #i42732# display status of font size/name depending on either the input language or the
+ selection position depending on what has changed lately
+ */
+ m_bUseInputLanguage: 1,
+ m_bObjectSelect : 1;
+
+ sal_uInt16 m_nKS_NUMDOWN_Count; // #i23725#
+ sal_uInt16 m_nKS_NUMINDENTINC_Count;
+
+ std::unique_ptr<SwFrameControlsManager> m_pFrameControlsManager;
+
+ SwTextFrame* m_pSavedOutlineFrame = nullptr;
+
+ void LeaveArea(const Point &);
+ void JustifyAreaTimer();
+ inline void EnterArea();
+
+ void ResetMouseButtonDownFlags();
+
+ void ChangeFly( sal_uInt8 nDir, bool bWeb );
+ void ChangeDrawing( sal_uInt8 nDir );
+
+ bool EnterDrawMode(const MouseEvent& rMEvt, const Point& aDocPos);
+ bool RulerColumnDrag( const MouseEvent& rMEvt, bool bVerticalMode);
+
+ // helper function for D&D
+ void DropCleanup();
+ void CleanupDropUserMarker();
+ SotExchangeDest GetDropDestination( const Point& rPixPnt,
+ SdrObject ** ppObj = nullptr );
+ //select the object/cursor at the mouse position of the context menu request
+ void SelectMenuPosition(SwWrtShell& rSh, const Point& rMousePos );
+
+ /*
+ * handler for scrolling on when the mousepointer
+ * stops outside of EditWin during a drag-operation.
+ * The selection is regularly increased towards the mouse
+ * position.
+ */
+ DECL_DLLPRIVATE_LINK( TimerHandler, Timer *, void );
+ void StartDDTimer();
+ void StopDDTimer(SwWrtShell *, const Point &);
+ DECL_DLLPRIVATE_LINK( DDHandler, Timer *, void );
+
+ // timer for ANY-KeyInut question without a following KeyInputEvent
+ DECL_DLLPRIVATE_LINK( KeyInputFlushHandler, Timer *, void );
+
+ // timer for ApplyTemplates via mouse (in disguise Drag&Drop)
+ DECL_DLLPRIVATE_LINK( TemplateTimerHdl, Timer *, void );
+
+ void MoveCursor( SwWrtShell &rSh, const Point& rDocPos,
+ const bool bOnlyText, bool bLockView );
+
+ virtual void DataChanged( const DataChangedEvent& ) override;
+ virtual void PrePaint(vcl::RenderContext& rRenderContext) override;
+ virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
+
+ virtual void GetFocus() override;
+ virtual void LoseFocus() override;
+
+ bool changeMousePointer(Point const & rDocPoint);
+
+ virtual void MouseMove(const MouseEvent& rMEvt) override;
+ virtual void MouseButtonDown(const MouseEvent& rMEvt) override;
+ virtual void MouseButtonUp(const MouseEvent& rMEvt) override;
+ virtual void RequestHelp(const HelpEvent& rEvt) override;
+
+ // Drag & Drop Interface
+ virtual sal_Int8 AcceptDrop( const AcceptDropEvent& rEvt ) override;
+ virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt ) override;
+ virtual void StartDrag( sal_Int8 nAction, const Point& rPosPixel ) override;
+
+ virtual OUString GetSurroundingText() const override;
+ virtual Selection GetSurroundingTextSelection() const override;
+ virtual bool DeleteSurroundingText(const Selection& rSelection) override;
+
+ void ShowAutoCorrectQuickHelp(const OUString& rWord, SvxAutoCorrect& rACorr);
+ bool ShowAutoText(const std::vector<OUString>& rChunkCandidates);
+
+ /// Returns true if in header/footer area, or in the header/footer control.
+ bool IsInHeaderFooter( const Point &rDocPt, FrameControlType &rControl ) const;
+
+ bool IsOverHeaderFooterFly( const Point& rDocPos, FrameControlType& rControl, bool& bOverFly, bool& bPageAnchored ) const;
+
+public:
+ virtual void KeyInput(const KeyEvent &rKEvt) override;
+ void UpdatePointer(const Point &, sal_uInt16 nButtons = 0);
+
+ bool IsDrawSelMode() const;
+ bool IsDrawAction() const { return m_bInsDraw; }
+ void SetDrawAction(bool bFlag) { m_bInsDraw = bFlag; }
+
+ void SetObjectSelect( bool bVal ) { m_bObjectSelect = bVal; }
+ bool IsObjectSelect() const { return m_bObjectSelect; }
+
+ SdrObjKind GetSdrDrawMode() const { return m_eDrawMode; }
+ void SetSdrDrawMode( SdrObjKind eSdrObjectKind ) { m_eDrawMode = eSdrObjectKind; SetObjectSelect( false ); }
+ void StdDrawMode( SdrObjKind eSdrObjectKind, bool bObjSelect );
+
+ bool IsFrameAction() const { return m_bInsFrame; }
+ sal_uInt16 GetBezierMode() const { return m_eBezierMode; }
+ void SetBezierMode(sal_uInt16 eBezMode) { m_eBezierMode = eBezMode; }
+ void EnterDrawTextMode(const Point& aDocPos); // turn on DrawTextEditMode
+ void InsFrame(sal_uInt16 nCols);
+ void StopInsFrame();
+ sal_uInt16 GetFrameColCount() const {return m_nInsFrameColCount;} // column number for interactive frame
+
+ void SetChainMode( bool bOn );
+ bool IsChainMode() const { return m_bChainMode; }
+
+ void FlushInBuffer();
+ static bool IsInputSequenceCheckingRequired( const OUString &rText, const SwPaM& rCursor );
+
+ void SetApplyTemplate(const SwApplyTemplate &);
+ SwApplyTemplate* GetApplyTemplate() const { return m_pApplyTempl.get(); }
+
+ void StartExecuteDrag();
+ void DragFinished();
+
+ void SetWaterCanTextColor(const Color& rCol ) { m_aWaterCanTextColor = rCol; }
+
+ void SetWaterCanTextBackColor(const Color& rCol ) { m_aWaterCanTextBackColor = rCol; }
+
+ void LockKeyInput(bool bSet){m_bLockInput = bSet;}
+
+ const SwView &GetView() const { return m_rView; }
+ SwView &GetView() { return m_rView; }
+
+ virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessible() override;
+
+ static tools::Long GetDDStartPosX() { return s_nDDStartPosX; }
+ static tools::Long GetDDStartPosY() { return s_nDDStartPosY; }
+
+ static void InitStaticData();
+ static void FinitStaticData();
+
+ //#i3370# remove quick help to prevent saving of autocorrection suggestions
+ void StopQuickHelp();
+
+ // #i42921# - add parameter <bVerticalMode>
+ bool RulerMarginDrag( const MouseEvent& rMEvt,
+ const bool bVerticalMode );
+
+ /** #i42732# display status of font size/name depending on either the input
+ language or the selection position depending on what has changed lately
+ */
+ void SetUseInputLanguage( bool bNew );
+ bool IsUseInputLanguage() const { return m_bUseInputLanguage; }
+
+ /** fdo#55546 cut very long tooltips to 2/3 of the width of the screen
+ via center ellipsis
+ */
+ OUString ClipLongToolTip(const OUString& rText);
+
+ SwFrameControlsManager& GetFrameControlsManager();
+
+ SwEditWin(vcl::Window *pParent, SwView &);
+ virtual ~SwEditWin() override;
+ virtual void dispose() override;
+
+ virtual void Command( const CommandEvent& rCEvt ) override;
+
+ /// @see Window::LogicInvalidate().
+ void LogicInvalidate(const tools::Rectangle* pRectangle) override;
+ /// Allows adjusting the point or mark of the selection to a document coordinate.
+ void SetCursorTwipPosition(const Point& rPosition, bool bPoint, bool bClearMark);
+ /// Allows starting or ending a graphic move or resize action.
+ void SetGraphicTwipPosition(bool bStart, const Point& rPosition);
+
+ const SwTextFrame* GetSavedOutlineFrame() const { return m_pSavedOutlineFrame; }
+ void SetSavedOutlineFrame(SwTextFrame* pFrame) { m_pSavedOutlineFrame = pFrame; }
+ // bSubs set true, sets all sub level outline content to same visibility as nOutlinePos.
+ // It is only applicable when not treating sub outline levels as content.
+ void ToggleOutlineContentVisibility(const size_t nOutlinePos, const bool bSubs);
+
+ virtual FactoryFunction GetUITestFactory() const override;
+};
+
+extern bool g_bModePushed;
+extern bool g_bFrameDrag;
+extern bool g_bDDTimerStarted;
+extern bool g_bDDINetAttr;
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/envimg.hxx b/sw/source/uibase/inc/envimg.hxx
new file mode 100644
index 0000000000..15c2560b9b
--- /dev/null
+++ b/sw/source/uibase/inc/envimg.hxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_ENVIMG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_ENVIMG_HXX
+
+#include <svl/poolitem.hxx>
+#include <unotools/configitem.hxx>
+#include <swdllapi.h>
+
+SW_DLLPUBLIC OUString MakeSender();
+
+enum SwEnvAlign
+{
+ ENV_HOR_LEFT = 0,
+ ENV_HOR_CNTR,
+ ENV_HOR_RGHT,
+ ENV_VER_LEFT,
+ ENV_VER_CNTR,
+ ENV_VER_RGHT
+};
+
+class SW_DLLPUBLIC SwEnvItem final : public SfxPoolItem
+{
+public:
+
+ OUString m_aAddrText; // text for receiver
+ bool m_bSend; // sender?
+ OUString m_aSendText; // text for sender
+ sal_Int32 m_nAddrFromLeft; // left gap for receiver (twips)
+ sal_Int32 m_nAddrFromTop; // upper gap for receiver (twips)
+ sal_Int32 m_nSendFromLeft; // left gap for sender (twips)
+ sal_Int32 m_nSendFromTop; // upper gap for sender (twips)
+ sal_Int32 m_nWidth; // envelope's width (twips)
+ sal_Int32 m_nHeight; // envelope's height (twips)
+ SwEnvAlign m_eAlign; // alignment at indent
+ bool m_bPrintFromAbove; // print from above?
+ sal_Int32 m_nShiftRight; // shift to right (twips)
+ sal_Int32 m_nShiftDown; // shift down (twips)
+
+ SwEnvItem();
+
+ static SfxPoolItem* CreateDefault();
+ SwEnvItem& operator =(const SwEnvItem& rItem);
+ SwEnvItem(SwEnvItem const &) = default; // SfxPoolItem copy function dichotomy
+
+ virtual bool operator ==(const SfxPoolItem& rItem) const override;
+
+ virtual SwEnvItem* Clone(SfxItemPool* = nullptr) const override;
+ virtual bool QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId = 0 ) const override;
+ virtual bool PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId ) override;
+};
+
+class SwEnvCfgItem final : public utl::ConfigItem
+{
+private:
+ SwEnvItem m_aEnvItem;
+
+ static css::uno::Sequence<OUString> GetPropertyNames();
+
+ virtual void ImplCommit() override;
+
+public:
+ SwEnvCfgItem();
+ virtual ~SwEnvCfgItem() override;
+
+ SwEnvItem& GetItem() {return m_aEnvItem;}
+
+ virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/envlop.hxx b/sw/source/uibase/inc/envlop.hxx
new file mode 100644
index 0000000000..302184f83b
--- /dev/null
+++ b/sw/source/uibase/inc/envlop.hxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_ENVLOP_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_ENVLOP_HXX
+
+#include <sfx2/tabdlg.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/customweld.hxx>
+#include "envimg.hxx"
+
+#define GetFieldVal(rField) (rField).Denormalize((rField).GetValue(FieldUnit::TWIP))
+#define SetFieldVal(rField, lValue) (rField).SetValue((rField).Normalize(lValue), FieldUnit::TWIP)
+
+inline int getfieldval(const weld::MetricSpinButton& rField)
+{
+ return rField.denormalize(rField.get_value(FieldUnit::TWIP));
+}
+
+inline void setfieldval(weld::MetricSpinButton& rField, int lValue)
+{
+ rField.set_value(rField.normalize(lValue), FieldUnit::TWIP);
+}
+
+class SwEnvDlg;
+class SwEnvPage;
+class SwEnvFormatPage;
+class SwWrtShell;
+class Printer;
+
+class SwEnvPreview final : public weld::CustomWidgetController
+{
+private:
+ SwEnvDlg* m_pDialog;
+
+ virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
+ virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override;
+
+public:
+ SwEnvPreview();
+ void SetDialog(SwEnvDlg* pDialog) { m_pDialog = pDialog; }
+};
+
+class SwEnvDlg final : public SfxTabDialogController
+{
+ friend class SwEnvPage;
+ friend class SwEnvFormatPage;
+ friend class SwEnvPrtPage;
+ friend class SwEnvPreview;
+
+ SwEnvItem m_aEnvItem;
+ SwWrtShell* m_pSh;
+ VclPtr<Printer> m_pPrinter;
+ std::unique_ptr<SfxItemSet> m_pAddresseeSet;
+ std::unique_ptr<SfxItemSet> m_pSenderSet;
+
+ std::unique_ptr<weld::Button> m_xModify;
+
+ virtual void PageCreated(const OUString& rId, SfxTabPage& rPage) override;
+ virtual short Ok() override;
+
+public:
+ SwEnvDlg(weld::Window* pParent, const SfxItemSet& rSet, SwWrtShell* pWrtSh, Printer* pPrt,
+ bool bInsert);
+ virtual ~SwEnvDlg() override;
+};
+
+class SwEnvPage final : public SfxTabPage
+{
+ SwEnvDlg* m_pDialog;
+ SwWrtShell* m_pSh;
+ OUString m_sActDBName;
+
+ SwEnvPreview m_aPreview;
+ std::unique_ptr<weld::TextView> m_xAddrEdit;
+ std::unique_ptr<weld::ComboBox> m_xDatabaseLB;
+ std::unique_ptr<weld::ComboBox> m_xTableLB;
+ std::unique_ptr<weld::ComboBox> m_xDBFieldLB;
+ std::unique_ptr<weld::Button> m_xInsertBT;
+ std::unique_ptr<weld::CheckButton> m_xSenderBox;
+ std::unique_ptr<weld::TextView> m_xSenderEdit;
+ std::unique_ptr<weld::CustomWeld> m_xPreview;
+
+ DECL_LINK(DatabaseHdl, weld::ComboBox&, void);
+ DECL_LINK(FieldHdl, weld::Button&, void);
+ DECL_LINK(SenderHdl, weld::Toggleable&, void);
+
+ void InitDatabaseBox();
+
+ SwEnvDlg* GetParentSwEnvDlg() { return m_pDialog; }
+
+public:
+ SwEnvPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ void Init(SwEnvDlg* pDialog);
+ virtual ~SwEnvPage() override;
+
+ static std::unique_ptr<SfxTabPage>
+ Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet);
+
+ virtual void ActivatePage(const SfxItemSet& rSet) override;
+ virtual DeactivateRC DeactivatePage(SfxItemSet* pSet) override;
+ void FillItem(SwEnvItem& rItem);
+ virtual bool FillItemSet(SfxItemSet* rSet) override;
+ virtual void Reset(const SfxItemSet* rSet) override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/fldedt.hxx b/sw/source/uibase/inc/fldedt.hxx
new file mode 100644
index 0000000000..7692e12561
--- /dev/null
+++ b/sw/source/uibase/inc/fldedt.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_FLDEDT_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_FLDEDT_HXX
+
+#include <fldbas.hxx>
+
+#include <sfx2/basedlgs.hxx>
+
+class SwView;
+class SwWrtShell;
+class SwFieldMgr;
+
+class SwFieldEditDlg final : public SfxSingleTabDialogController
+{
+ SwWrtShell* m_pSh;
+ std::unique_ptr<weld::Button> m_xPrevBT;
+ std::unique_ptr<weld::Button> m_xNextBT;
+ std::unique_ptr<weld::Button> m_xAddressBT;
+
+ DECL_LINK(AddressHdl, weld::Button&, void);
+ DECL_LINK(NextPrevHdl, weld::Button&, void);
+
+ void Init();
+ SfxTabPage* CreatePage(sal_uInt16 nGroup);
+
+ void EnsureSelection(SwField *pCurField, SwFieldMgr &rMgr);
+public:
+
+ SwFieldEditDlg(SwView const & rVw);
+ virtual ~SwFieldEditDlg() override;
+
+ DECL_LINK(OKHdl, weld::Button&, void);
+
+ virtual short run() override;
+
+ void EnableInsert(bool bEnable);
+ void InsertHdl();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/fldmgr.hxx b/sw/source/uibase/inc/fldmgr.hxx
new file mode 100644
index 0000000000..48d4500513
--- /dev/null
+++ b/sw/source/uibase/inc/fldmgr.hxx
@@ -0,0 +1,203 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_FLDMGR_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_FLDMGR_HXX
+
+#include <fldbas.hxx>
+#include <pam.hxx>
+#include <swdllapi.h>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Any.h>
+#include <memory>
+#include <optional>
+#include <utility>
+#include <vector>
+
+namespace com::sun::star{
+ namespace container{
+ class XNameAccess;
+ }
+ namespace text{
+ class XNumberingTypeInfo;
+ }
+}
+
+class SwWrtShell;
+class SwField;
+class SwFieldType;
+class SwPaM;
+class SbModule;
+class SvxMacroItem;
+class SvNumberFormatter;
+namespace weld { class Widget; class Window; }
+enum class SwFieldIds : sal_uInt16;
+
+// the groups of fields
+enum SwFieldGroups
+{
+ GRP_DOC,
+ GRP_FKT,
+ GRP_REF,
+ GRP_REG,
+ GRP_DB,
+ GRP_VAR
+};
+
+struct SwFieldGroupRgn
+{
+ sal_uInt16 nStart;
+ sal_uInt16 nEnd;
+};
+
+// the field manager handles the insertation of fields
+// with command strings
+struct SwInsertField_Data
+{
+ SwFieldTypesEnum m_nTypeId;
+ sal_uInt16 m_nSubType;
+ const OUString m_sPar1;
+ const OUString m_sPar2;
+ sal_uInt32 m_nFormatId;
+ SwWrtShell* m_pSh;
+ sal_Unicode m_cSeparator;
+ bool m_bIsAutomaticLanguage;
+ css::uno::Any m_aDBDataSource;
+ css::uno::Any m_aDBConnection;
+ css::uno::Any m_aDBColumn;
+ weld::Widget* m_pParent; // parent widget used for SwWrtShell::StartInputFieldDlg()
+ /// Marks the PostIt field's annotation start/end if it differs from the cursor selection.
+ std::optional<SwPaM> m_oAnnotationRange;
+
+ SwInsertField_Data(SwFieldTypesEnum nType, sal_uInt16 nSub, OUString aPar1, OUString aPar2,
+ sal_uInt32 nFormatId, SwWrtShell* pShell = nullptr, sal_Unicode cSep = ' ', bool bIsAutoLanguage = true) :
+ m_nTypeId(nType),
+ m_nSubType(nSub),
+ m_sPar1(std::move(aPar1)),
+ m_sPar2(std::move(aPar2)),
+ m_nFormatId(nFormatId),
+ m_pSh(pShell),
+ m_cSeparator(cSep),
+ m_bIsAutomaticLanguage(bIsAutoLanguage),
+ m_pParent(nullptr) {}
+};
+
+class SW_DLLPUBLIC SwFieldMgr
+{
+private:
+ SwField* m_pCurField;
+ SwWrtShell* m_pWrtShell; // can be ZERO too!
+ OUString m_aCurPar1;
+ OUString m_aCurPar2;
+ OUString m_sCurFrame;
+
+ OUString m_sMacroPath;
+ OUString m_sMacroName;
+
+ bool m_bEvalExp;
+
+ SAL_DLLPRIVATE LanguageType GetCurrLanguage() const;
+
+ css::uno::Reference<css::text::XNumberingTypeInfo> m_xNumberingInfo;
+ SAL_DLLPRIVATE css::uno::Reference<css::text::XNumberingTypeInfo> const & GetNumberingInfo()const;
+
+public:
+ explicit SwFieldMgr(SwWrtShell* pSh = nullptr);
+ ~SwFieldMgr();
+
+ void SetWrtShell( SwWrtShell* pShell )
+ { m_pWrtShell = pShell; }
+
+ // insert field using TypeID (TYP_ ...)
+ bool InsertField( SwInsertField_Data& rData );
+
+ // change the current field directly
+ void UpdateCurField(sal_uInt32 nFormat,
+ const OUString& rPar1,
+ const OUString& rPar2,
+ std::unique_ptr<SwField> _pField = nullptr);
+
+ const OUString& GetCurFieldPar1() const { return m_aCurPar1; }
+ const OUString& GetCurFieldPar2() const { return m_aCurPar2; }
+
+ // determine a field
+ SwField* GetCurField();
+
+ void InsertFieldType(SwFieldType const & rType);
+
+ bool ChooseMacro(weld::Window* pDialogParent);
+ void SetMacroPath(const OUString& rPath);
+ const OUString& GetMacroPath() const { return m_sMacroPath; }
+ const OUString& GetMacroName() const { return m_sMacroName; }
+
+ // previous and next of the same type
+ bool GoNextPrev( bool bNext = true, SwFieldType* pTyp = nullptr );
+ bool GoNext() { return GoNextPrev(); }
+ bool GoPrev() { return GoNextPrev( false ); }
+
+ bool IsDBNumeric(const OUString& rDBName, const OUString& rTableQryName,
+ bool bIsTable, const OUString& rFieldName);
+
+ // organise RefMark with names
+ bool CanInsertRefMark( std::u16string_view rStr );
+
+ // access to field types via ResId
+ size_t GetFieldTypeCount() const;
+ SwFieldType* GetFieldType(SwFieldIds nResId, size_t nField = 0) const;
+ SwFieldType* GetFieldType(SwFieldIds nResId, const OUString& rName) const;
+
+ void RemoveFieldType(SwFieldIds nResId, const OUString& rName);
+
+ // access via TypeId from the dialog
+ // Ids for a range of fields
+ static const SwFieldGroupRgn& GetGroupRange(bool bHtmlMode, sal_uInt16 nGrpId);
+ static sal_uInt16 GetGroup(SwFieldTypesEnum nTypeId, sal_uInt16 nSubType);
+
+ // the current field's TypeId
+ SwFieldTypesEnum GetCurTypeId() const;
+
+ // TypeId for a concrete position in the list
+ static SwFieldTypesEnum GetTypeId(sal_uInt16 nPos);
+ // name of the type in the list of fields
+ static const OUString & GetTypeStr(sal_uInt16 nPos);
+
+ // Pos in the list of fields
+ static sal_uInt16 GetPos(SwFieldTypesEnum nTypeId);
+
+ // subtypes to a type
+ void GetSubTypes(SwFieldTypesEnum nId, std::vector<OUString>& rToFill);
+
+ // format to a type
+ sal_uInt16 GetFormatCount(SwFieldTypesEnum nTypeId, bool bHtmlMode) const;
+ OUString GetFormatStr(SwFieldTypesEnum nTypeId, sal_uInt32 nFormatId) const;
+ sal_uInt16 GetFormatId(SwFieldTypesEnum nTypeId, sal_uInt32 nFormatId) const;
+ sal_uInt32 GetDefaultFormat(SwFieldTypesEnum nTypeId, bool bIsText, SvNumberFormatter* pFormatter);
+
+ // turn off evaluation of expression fields for insertation
+ // of many expression fields (see labels)
+
+ inline void SetEvalExpFields(bool bEval);
+ void EvalExpFields(SwWrtShell* pSh);
+};
+
+inline void SwFieldMgr::SetEvalExpFields(bool bEval)
+ { m_bEvalExp = bEval; }
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/fldtdlg.hxx b/sw/source/uibase/inc/fldtdlg.hxx
new file mode 100644
index 0000000000..0db155b3d5
--- /dev/null
+++ b/sw/source/uibase/inc/fldtdlg.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_FLDTDLG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_FLDTDLG_HXX
+
+#include <sal/config.h>
+
+#include <string_view>
+#include <memory>
+#include <sfx2/tabdlg.hxx>
+
+class SfxBindings;
+class SfxTabPage;
+class SwChildWinWrapper;
+struct SfxChildWinInfo;
+
+class SwFieldDlg final : public SfxTabDialogController
+{
+ SwChildWinWrapper* m_pChildWin;
+ SfxBindings* m_pBindings;
+ bool m_bHtmlMode;
+ bool m_bDataBaseMode;
+ bool m_bClosing;
+ std::unique_ptr<SfxItemSet> mxInputItemSet;
+
+ virtual SfxItemSet* CreateInputItemSet(const OUString& rId) override;
+ virtual void PageCreated(const OUString& rId, SfxTabPage& rPage) override;
+
+ void ReInitTabPage(std::u16string_view rPageId,
+ bool bOnlyActivate = false);
+
+public:
+ SwFieldDlg(SfxBindings* pB, SwChildWinWrapper* pCW, weld::Window *pParent);
+ virtual ~SwFieldDlg() override;
+
+ DECL_LINK(OKHdl, weld::Button&, void);
+ DECL_LINK(CancelHdl, weld::Button&, void);
+
+ void Initialize(SfxChildWinInfo const *pInfo);
+ void ReInitDlg();
+ void EnableInsert(bool bEnable);
+ void InsertHdl();
+ void ActivateDatabasePage();
+ void ShowReferencePage();
+ virtual void Close() override;
+ virtual void EndDialog(int nResponse) override;
+ virtual void Activate() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/fldwrap.hxx b/sw/source/uibase/inc/fldwrap.hxx
new file mode 100644
index 0000000000..b696d30611
--- /dev/null
+++ b/sw/source/uibase/inc/fldwrap.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_FLDWRAP_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_FLDWRAP_HXX
+
+#include <vcl/vclptr.hxx>
+
+#include <swabstdlg.hxx>
+
+#include "chldwrap.hxx"
+class AbstractSwFieldDlg;
+
+class SwFieldDlgWrapper final : public SwChildWinWrapper
+{
+ ScopedVclPtr<AbstractSwFieldDlg> m_pDlgInterface;
+public:
+ SwFieldDlgWrapper(vcl::Window* pParent, sal_uInt16 nId,
+ SfxBindings* pBindings, SfxChildWinInfo* pInfo);
+
+ SFX_DECL_CHILDWINDOW_WITHID(SwFieldDlgWrapper);
+
+ virtual bool ReInitDlg(SwDocShell *pDocSh) override;
+ void ShowReferencePage();
+};
+
+// field dialog only showing database page to support mail merge
+class SwFieldDataOnlyDlgWrapper final : public SwChildWinWrapper
+{
+ ScopedVclPtr<AbstractSwFieldDlg> m_pDlgInterface;
+public:
+ SwFieldDataOnlyDlgWrapper(vcl::Window* pParent, sal_uInt16 nId,
+ SfxBindings* pBindings, SfxChildWinInfo* pInfo);
+
+ SFX_DECL_CHILDWINDOW(SwFieldDataOnlyDlgWrapper);
+
+ virtual bool ReInitDlg(SwDocShell *pDocSh) override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/fontcfg.hxx b/sw/source/uibase/inc/fontcfg.hxx
new file mode 100644
index 0000000000..786b06d869
--- /dev/null
+++ b/sw/source/uibase/inc/fontcfg.hxx
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_FONTCFG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_FONTCFG_HXX
+
+#include <rtl/ustring.hxx>
+#include <unotools/configitem.hxx>
+#include <i18nlangtag/lang.h>
+#include <swdllapi.h>
+
+#define FONT_STANDARD 0
+#define FONT_OUTLINE 1
+#define FONT_LIST 2
+#define FONT_CAPTION 3
+#define FONT_INDEX 4
+#define FONT_STANDARD_CJK 5
+#define FONT_OUTLINE_CJK 6
+#define FONT_LIST_CJK 7
+#define FONT_CAPTION_CJK 8
+#define FONT_INDEX_CJK 9
+#define FONT_STANDARD_CTL 10
+#define FONT_OUTLINE_CTL 11
+#define FONT_LIST_CTL 12
+#define FONT_CAPTION_CTL 13
+#define FONT_INDEX_CTL 14
+#define DEF_FONT_COUNT 15
+
+#define FONT_PER_GROUP 5
+
+#define FONT_GROUP_DEFAULT 0
+#define FONT_GROUP_CJK 1
+#define FONT_GROUP_CTL 2
+
+//pt-size of fonts
+#define FONTSIZE_DEFAULT 240
+#define FONTSIZE_KOREAN_DEFAULT 200
+#define FONTSIZE_CJK_DEFAULT 210
+#define FONTSIZE_OUTLINE 280
+
+class SW_DLLPUBLIC SwStdFontConfig final : public utl::ConfigItem
+{
+ OUString m_sDefaultFonts[DEF_FONT_COUNT];
+ sal_Int32 m_nDefaultFontHeight[DEF_FONT_COUNT];
+
+ SAL_DLLPRIVATE static css::uno::Sequence<OUString> const & GetPropertyNames();
+
+ void ChangeString(sal_uInt16 nFontType, const OUString& rSet)
+ {
+ if(m_sDefaultFonts[nFontType] != rSet)
+ {
+ SetModified();
+ m_sDefaultFonts[nFontType] = rSet;
+ }
+ }
+
+ void ChangeInt( sal_uInt16 nFontType, sal_Int32 nHeight );
+
+ virtual void ImplCommit() override;
+
+public:
+ SwStdFontConfig();
+ virtual ~SwStdFontConfig() override;
+
+ virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+
+ const OUString& GetFontStandard(sal_uInt8 nFontGroup) const {return m_sDefaultFonts[FONT_STANDARD + FONT_PER_GROUP * nFontGroup];}
+ const OUString& GetFontOutline(sal_uInt8 nFontGroup) const {return m_sDefaultFonts[FONT_OUTLINE + FONT_PER_GROUP * nFontGroup];}
+ const OUString& GetFontList (sal_uInt8 nFontGroup) const {return m_sDefaultFonts[FONT_LIST + FONT_PER_GROUP * nFontGroup];}
+ const OUString& GetFontCaption(sal_uInt8 nFontGroup) const {return m_sDefaultFonts[FONT_CAPTION + FONT_PER_GROUP * nFontGroup];}
+ const OUString& GetFontIndex (sal_uInt8 nFontGroup) const {return m_sDefaultFonts[FONT_INDEX + FONT_PER_GROUP * nFontGroup];}
+
+ const OUString& GetFontFor(sal_uInt16 nFontType) const {return m_sDefaultFonts[nFontType];}
+ bool IsFontDefault(sal_uInt16 nFontType) const;
+
+ void SetFontStandard(const OUString& rSet, sal_uInt8 nFontGroup)
+ {ChangeString(FONT_STANDARD + FONT_PER_GROUP * nFontGroup, rSet);}
+
+ void SetFontOutline(const OUString& rSet, sal_uInt8 nFontGroup)
+ { ChangeString(FONT_OUTLINE + FONT_PER_GROUP * nFontGroup, rSet);}
+ void SetFontList (const OUString& rSet, sal_uInt8 nFontGroup)
+ { ChangeString(FONT_LIST + FONT_PER_GROUP * nFontGroup, rSet);}
+ void SetFontCaption(const OUString& rSet, sal_uInt8 nFontGroup)
+ { ChangeString(FONT_CAPTION + FONT_PER_GROUP * nFontGroup, rSet);}
+ void SetFontIndex (const OUString& rSet, sal_uInt8 nFontGroup)
+ { ChangeString(FONT_INDEX + FONT_PER_GROUP * nFontGroup, rSet);}
+
+ void SetFontHeight( sal_Int32 nHeight, sal_uInt8 nFont, sal_uInt8 nScriptType )
+ { ChangeInt(nFont + FONT_PER_GROUP * nScriptType, nHeight);}
+
+ sal_Int32 GetFontHeight( sal_uInt8 nFont, sal_uInt8 nScriptType, LanguageType eLang );
+
+ static OUString GetDefaultFor(sal_uInt16 nFontType, LanguageType eLang);
+ static sal_Int32 GetDefaultHeightFor(sal_uInt16 nFontType, LanguageType eLang);
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/formatclipboard.hxx b/sw/source/uibase/inc/formatclipboard.hxx
new file mode 100644
index 0000000000..e83267bd70
--- /dev/null
+++ b/sw/source/uibase/inc/formatclipboard.hxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_FORMATCLIPBOARD_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_FORMATCLIPBOARD_HXX
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include "wrtsh.hxx"
+#include <svl/itemset.hxx>
+#include <svl/style.hxx>
+
+/** This class acts as data container and execution class for the format paintbrush feature in writer.
+*/
+
+class SwFormatClipboard
+{
+public:
+ SwFormatClipboard();
+
+ /**
+ * Test if the object contains text or paragraph attribute
+ */
+ bool HasContent() const;
+ bool HasContentForThisType(SelectionType nSelectionType) const;
+ static bool CanCopyThisType(SelectionType nSelectionType);
+
+ /**
+ * Store/Backup the text and paragraph attribute of the current selection.
+ *
+ * @param bPersistentCopy
+ * input parameter - specify if the Paste function will erase the current object.
+ */
+ void Copy(SwWrtShell& rWrtShell, SfxItemPool& rPool, bool bPersistentCopy);
+
+ /**
+ * Paste the stored text and paragraph attributes on the current selection and current paragraph.
+ *
+ * @param bNoCharacterFormats
+ * Do not paste the character formats.
+ *
+ * @param bNoParagraphFormats
+ * Do not paste the paragraph formats.
+ */
+ void Paste(SwWrtShell& rWrtShell, SfxStyleSheetBasePool* pPool, bool bNoCharacterFormats,
+ bool bNoParagraphFormats);
+
+ /**
+ * Clear the currently stored text and paragraph attributes.
+ */
+ void Erase();
+
+private:
+ SelectionType m_nSelectionType;
+
+ /** automatic/named character attribute set */
+ std::unique_ptr<SfxItemSet> m_pItemSet_TextAttr;
+ /** automatic/named paragraph attribute set
+ * (it can be character attribute applied to the paragraph) */
+ std::unique_ptr<SfxItemSet> m_pItemSet_ParAttr;
+
+ /** table attribute set */
+ std::unique_ptr<SfxItemSet> m_pTableItemSet;
+
+ /** name of the character format (if it exist) */
+ OUString m_aCharStyle;
+ /** name of the paragraph format (if it exist) */
+ OUString m_aParaStyle;
+ //no frame style because it contains position information
+
+ /** specify if the Paste function have to clear the current object */
+ bool m_bPersistentCopy;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/frmdlg.hxx b/sw/source/uibase/inc/frmdlg.hxx
new file mode 100644
index 0000000000..425bed5fcb
--- /dev/null
+++ b/sw/source/uibase/inc/frmdlg.hxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_FRMDLG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_FRMDLG_HXX
+
+#include <sfx2/tabdlg.hxx>
+#include <sfx2/viewfrm.hxx>
+
+class SwWrtShell;
+
+// frame dialog
+class SwFrameDlg final : public SfxTabDialogController
+{
+ bool m_bFormat;
+ bool m_bNew;
+ const SfxItemSet& m_rSet;
+ OUString m_sDlgType;
+ SwWrtShell* m_pWrtShell;
+
+ virtual void PageCreated(const OUString& rId, SfxTabPage &rPage) override;
+
+public:
+ SwFrameDlg(const SfxViewFrame& rFrame, weld::Window* pParent,
+ const SfxItemSet& rCoreSet,
+ bool bNewFrame,
+ const OUString& sResType,
+ bool bFormat,
+ const OUString& sDefPage = {},
+ const OUString* pFormatStr = nullptr);
+
+ virtual ~SwFrameDlg() override;
+
+ SwWrtShell* GetWrtShell() { return m_pWrtShell; }
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_FRMDLG_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/frmmgr.hxx b/sw/source/uibase/inc/frmmgr.hxx
new file mode 100644
index 0000000000..70e66d9bf1
--- /dev/null
+++ b/sw/source/uibase/inc/frmmgr.hxx
@@ -0,0 +1,177 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_FRMMGR_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_FRMMGR_HXX
+
+#include <swtypes.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <tools/gen.hxx>
+#include <fmtfsize.hxx>
+#include <fmtornt.hxx>
+#include <fmtanchr.hxx>
+#include <swdllapi.h>
+
+class SwWrtShell;
+struct SvxSwFrameValidation;
+struct SwPosition;
+
+class SwFormatCol;
+class SvGlobalName;
+
+constexpr SwTwips DFLT_WIDTH = o3tl::toTwips(20, o3tl::Length::mm);
+constexpr SwTwips DFLT_HEIGHT = o3tl::toTwips(5, o3tl::Length::mm);
+
+enum class Frmmgr_Type
+{
+ NONE = 0x00,
+ TEXT = 0x01,
+ GRF = 0x02,
+ OLE = 0x04,
+ ENVELP = 0x10
+};
+
+class SW_DLLPUBLIC SwFlyFrameAttrMgr
+{
+ SfxItemSet m_aSet;
+ Point m_aAbsPos;
+ SwWrtShell* m_pOwnSh;
+
+ bool m_bAbsPos,
+ m_bNewFrame;
+ bool m_bIsInVertical;
+ // #mongolianlayout#
+ bool m_bIsInVerticalL2R;
+
+ // internal calculation for borders
+ SAL_DLLPRIVATE SwTwips CalcTopSpace();
+ SAL_DLLPRIVATE SwTwips CalcBottomSpace();
+ SAL_DLLPRIVATE SwTwips CalcLeftSpace();
+ SAL_DLLPRIVATE SwTwips CalcRightSpace();
+
+ SAL_DLLPRIVATE void UpdateFlyFrame_(); // post-treatment after insert or update
+
+public:
+ SwFlyFrameAttrMgr( bool bNew, SwWrtShell* pSh, Frmmgr_Type nType, const SvGlobalName* pName );
+
+ //CopyCtor for dialogs to check the metrics
+ SwFlyFrameAttrMgr( bool bNew, SwWrtShell *pSh, SfxItemSet aSet );
+
+ void SetAnchor(RndStdIds eId);
+ inline RndStdIds GetAnchor() const;
+
+ void SetHorzOrientation(sal_Int16 eOrient);
+ void SetVertOrientation(sal_Int16 eOrient);
+
+ // absolute position
+ void SetAbsPos(const Point& rLPoint);
+
+ // anchor's relative position
+ void SetPos(const Point& rLPoint);
+ inline Point GetPos() const;
+
+ // size
+ void SetSize(const Size& rLSize);
+ inline const Size& GetSize() const;
+
+ void SetHeightSizeType(SwFrameSize eType);
+
+ // rotation
+ void SetRotation(Degree10 nOld, Degree10 nNew, const Size& rUnrotatedSize);
+
+ // space to content
+ void SetLRSpace( tools::Long nLeft,
+ tools::Long nRight );
+ void SetULSpace( tools::Long nTop,
+ tools::Long nBottom );
+
+ void SetCol( const SwFormatCol &rCol);
+
+ // change and query attributes
+ void UpdateAttrMgr();
+ void UpdateFlyFrame();
+
+ // create new frame
+ void InsertFlyFrame();
+ void InsertFlyFrame(RndStdIds eAnchorType,
+ const Point &rPos,
+ const Size &rSize);
+
+ // check and change metrics
+ void ValidateMetrics(SvxSwFrameValidation& rVal,
+ const SwFormatAnchor* pToCharContentPos,
+ bool bOnlyPercentRefValue = false);
+
+ void DelAttr(sal_uInt16 nId);
+
+ // reach out the set
+ const SfxItemSet &GetAttrSet() const { return m_aSet; }
+ SfxItemSet &GetAttrSet() { return m_aSet; }
+ void SetAttrSet(const SfxItemSet& rSet);
+ void SetFrameSizeFromTable();
+ /// Checks if we have a table selection and that covers exactly 1 full table.
+ static const SwTableFormat* SingleTableSelected(SwWrtShell& rWrtShell);
+
+ inline const SwFormatVertOrient &GetVertOrient() const;
+ inline const SwFormatHoriOrient &GetHoriOrient() const;
+ inline const SvxShadowItem &GetShadow() const;
+ inline const SvxBoxItem &GetBox() const;
+ inline const SwFormatFrameSize &GetFrameSize() const;
+
+ tools::Long CalcWidthBorder() { return CalcLeftSpace()+CalcRightSpace(); }
+ tools::Long CalcHeightBorder() { return CalcTopSpace()+CalcBottomSpace(); }
+};
+
+inline const Size& SwFlyFrameAttrMgr::GetSize() const
+{
+ return m_aSet.Get(RES_FRM_SIZE).GetSize();
+}
+
+inline const SwFormatVertOrient &SwFlyFrameAttrMgr::GetVertOrient() const
+{
+ return m_aSet.Get(RES_VERT_ORIENT);
+}
+inline const SwFormatHoriOrient &SwFlyFrameAttrMgr::GetHoriOrient() const
+{
+ return m_aSet.Get(RES_HORI_ORIENT);
+}
+inline const SwFormatFrameSize& SwFlyFrameAttrMgr::GetFrameSize() const
+{
+ return m_aSet.Get(RES_FRM_SIZE);
+}
+inline const SvxShadowItem &SwFlyFrameAttrMgr::GetShadow() const
+{
+ return m_aSet.Get(RES_SHADOW);
+}
+inline const SvxBoxItem &SwFlyFrameAttrMgr::GetBox() const
+{
+ return m_aSet.Get(RES_BOX);
+}
+inline Point SwFlyFrameAttrMgr::GetPos() const
+{
+ return Point( GetHoriOrient().GetPos(), GetVertOrient().GetPos() );
+}
+inline RndStdIds SwFlyFrameAttrMgr::GetAnchor() const
+{
+ return m_aSet.Get(RES_ANCHOR).GetAnchorId();
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/frmpage.hxx b/sw/source/uibase/inc/frmpage.hxx
new file mode 100644
index 0000000000..6f05ca1d65
--- /dev/null
+++ b/sw/source/uibase/inc/frmpage.hxx
@@ -0,0 +1,330 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_FRMPAGE_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_FRMPAGE_HXX
+
+#include <sfx2/tabdlg.hxx>
+#include <svx/dialcontrol.hxx>
+#include <svx/frmdirlbox.hxx>
+#include <svx/swframeexample.hxx>
+#include <swtypes.hxx>
+#include "bmpwin.hxx"
+#include "prcntfld.hxx"
+
+namespace sfx2{class FileDialogHelper;}
+class SwWrtShell;
+struct FrameMap;
+// OD 12.11.2003 #i22341#
+struct SwPosition;
+
+/// This is the Position & Size tab page of the Insert -> Frame -> Frame dialog.
+class SwFramePage final : public SfxTabPage
+{
+ bool m_bAtHorzPosModified;
+ bool m_bAtVertPosModified;
+
+ bool m_bFormat;
+ bool m_bNew;
+ bool m_bNoModifyHdl;
+ bool m_bIsVerticalFrame; //current frame is in vertical environment - strings are exchanged
+ // #mongolianlayout#
+ bool m_bIsVerticalL2R;
+ bool m_bIsInRightToLeft; // current frame is in right-to-left environment - strings are exchanged
+ bool m_bHtmlMode;
+ sal_uInt16 m_nHtmlMode;
+ OUString m_sDlgType;
+ Size m_aGrfSize;
+ SwTwips m_nUpperBorder;
+ SwTwips m_nLowerBorder;
+ double m_fWidthHeightRatio; //width-to-height ratio to support the KeepRatio button
+
+ // OD 12.11.2003 #i22341# - keep content position of character for
+ // to character anchored objects.
+ const SwFormatAnchor* mpToCharContentPos;
+
+ // old alignment
+ sal_Int16 m_nOldH;
+ sal_Int16 m_nOldHRel;
+ sal_Int16 m_nOldV;
+ sal_Int16 m_nOldVRel;
+
+ FrameMap const * m_pVMap;
+ FrameMap const * m_pHMap;
+
+ bool m_bAllowVertPositioning;
+ bool m_bIsMathOLE;
+ bool m_bIsMathBaselineAlignment;
+
+ SwFrameExample m_aExampleWN;
+
+ // size
+ std::unique_ptr<weld::Label> m_xWidthFT;
+ std::unique_ptr<weld::Label> m_xWidthAutoFT;
+ std::unique_ptr<weld::CheckButton> m_xRelWidthCB;
+ std::unique_ptr<weld::ComboBox> m_xRelWidthRelationLB;
+ std::unique_ptr<weld::CheckButton> m_xAutoWidthCB;
+
+ std::unique_ptr<weld::Label> m_xHeightFT;
+ std::unique_ptr<weld::Label> m_xHeightAutoFT;
+ std::unique_ptr<weld::CheckButton> m_xRelHeightCB;
+ std::unique_ptr<weld::ComboBox> m_xRelHeightRelationLB;
+ std::unique_ptr<weld::CheckButton> m_xAutoHeightCB;
+
+ std::unique_ptr<weld::CheckButton> m_xFixedRatioCB;
+ std::unique_ptr<weld::Button> m_xRealSizeBT;
+
+ // anchor
+ std::unique_ptr<weld::Widget> m_xAnchorFrame;
+ std::unique_ptr<weld::RadioButton> m_xAnchorAtPageRB;
+ std::unique_ptr<weld::RadioButton> m_xAnchorAtParaRB;
+ std::unique_ptr<weld::RadioButton> m_xAnchorAtCharRB;
+ std::unique_ptr<weld::RadioButton> m_xAnchorAsCharRB;
+ std::unique_ptr<weld::RadioButton> m_xAnchorAtFrameRB;
+
+ // position
+ std::unique_ptr<weld::Label> m_xHorizontalFT;
+ std::unique_ptr<weld::ComboBox> m_xHorizontalDLB;
+ std::unique_ptr<weld::Label> m_xAtHorzPosFT;
+ std::unique_ptr<weld::MetricSpinButton> m_xAtHorzPosED;
+ std::unique_ptr<weld::Label> m_xHoriRelationFT;
+ std::unique_ptr<weld::ComboBox> m_xHoriRelationLB;
+
+ std::unique_ptr<weld::CheckButton> m_xMirrorPagesCB;
+
+ std::unique_ptr<weld::Label> m_xVerticalFT;
+ std::unique_ptr<weld::ComboBox> m_xVerticalDLB;
+ std::unique_ptr<weld::Label> m_xAtVertPosFT;
+ std::unique_ptr<weld::MetricSpinButton> m_xAtVertPosED;
+ std::unique_ptr<weld::Label> m_xVertRelationFT;
+ std::unique_ptr<weld::ComboBox> m_xVertRelationLB;
+ // #i18732# - check box for new option 'FollowTextFlow'
+ std::unique_ptr<weld::CheckButton> m_xFollowTextFlowCB;
+ std::unique_ptr<weld::CheckButton> m_xFlySplitCB;
+
+ // example
+ std::unique_ptr<weld::CustomWeld> m_xExampleWN;
+
+ std::unique_ptr<SwPercentField> m_xWidthED;
+ std::unique_ptr<SwPercentField> m_xHeightED;
+
+ virtual void ActivatePage(const SfxItemSet& rSet) override;
+ virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override;
+
+ DECL_LINK(RangeModifyClickHdl, weld::Toggleable&, void);
+ void RangeModifyHdl();
+ DECL_LINK(AnchorTypeHdl, weld::Toggleable&, void);
+ DECL_LINK(PosHdl, weld::ComboBox&, void);
+ DECL_LINK(RelHdl, weld::ComboBox&, void);
+ void InitPos(RndStdIds eId, sal_Int16 nH, sal_Int16 nHRel,
+ sal_Int16 nV, sal_Int16 nVRel,
+ tools::Long nX, tools::Long nY);
+
+ DECL_LINK(RealSizeHdl, weld::Button&, void);
+ DECL_LINK(RelSizeClickHdl, weld::Toggleable&, void);
+ DECL_LINK(MirrorHdl, weld::Toggleable&, void);
+
+ DECL_LINK(AutoWidthClickHdl, weld::Toggleable&, void);
+ DECL_LINK(AutoHeightClickHdl, weld::Toggleable&, void);
+
+ // update example
+ void UpdateExample();
+ DECL_LINK(ModifyHdl, weld::MetricSpinButton&, void);
+
+ void Init(const SfxItemSet& rSet);
+ // OD 12.11.2003 #i22341# - adjustment to handle maps, that are ambiguous
+ // in the alignment.
+ sal_Int32 FillPosLB( const FrameMap* _pMap,
+ const sal_Int16 _nAlign,
+ const sal_Int16 _nRel,
+ weld::ComboBox& _rLB );
+ // OD 14.11.2003 #i22341# - adjustment to handle maps, that are ambiguous
+ // in their string entries.
+ void FillRelLB( const FrameMap* _pMap,
+ const sal_uInt16 _nLBSelPos,
+ const sal_Int16 _nAlign,
+ const sal_Int16 _nRel,
+ weld::ComboBox& _rLB,
+ weld::Label& _rFT );
+ static sal_Int32 GetMapPos(const FrameMap *pMap, const weld::ComboBox& rAlignLB);
+ static sal_Int16 GetAlignment(FrameMap const *pMap, sal_Int32 nMapPos, const weld::ComboBox& rRelationLB);
+ static sal_Int16 GetRelation(const weld::ComboBox& rRelationLB);
+ RndStdIds GetAnchor() const;
+
+ void setOptimalFrameWidth();
+ void setOptimalRelWidth();
+
+ void EnableGraficMode(); // hides auto check boxes and re-org controls for "Real Size" button
+
+ SwWrtShell *getFrameDlgParentShell();
+
+ static const WhichRangesContainer s_aPageRg;
+
+public:
+ SwFramePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet);
+ virtual ~SwFramePage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet);
+ static WhichRangesContainer GetRanges() { return s_aPageRg; }
+
+ virtual bool FillItemSet(SfxItemSet *rSet) override;
+ virtual void Reset(const SfxItemSet *rSet) override;
+
+ void SetNewFrame(bool bNewFrame) { m_bNew = bNewFrame; }
+ void SetFormatUsed(bool bFormat);
+ void SetFrameType(const OUString &rType) { m_sDlgType = rType; }
+ bool IsInGraficMode() const { return m_sDlgType == "PictureDialog" || m_sDlgType == "ObjectDialog"; }
+ void EnableVerticalPositioning( bool bEnable );
+};
+
+/// Tabpage providing the functionality behind Format -> Image -> Properties and then the Rotation
+/// tabpage.
+class SwGrfExtPage final : public SfxTabPage
+{
+ OUString m_aFilterName;
+ OUString m_aGrfName, m_aNewGrfName;
+
+ std::unique_ptr<::sfx2::FileDialogHelper> m_xGrfDlg;
+
+ bool m_bHtmlMode;
+
+ // mirror
+ BmpWindow m_aBmpWin;
+ std::unique_ptr<weld::Widget> m_xMirror;
+ std::unique_ptr<weld::CheckButton> m_xMirrorVertBox;
+ std::unique_ptr<weld::CheckButton> m_xMirrorHorzBox;
+ std::unique_ptr<weld::RadioButton> m_xAllPagesRB;
+ std::unique_ptr<weld::RadioButton> m_xLeftPagesRB;
+ std::unique_ptr<weld::RadioButton> m_xRightPagesRB;
+
+ std::unique_ptr<weld::Entry> m_xConnectED;
+ std::unique_ptr<weld::Button> m_xBrowseBT;
+ std::unique_ptr<weld::Frame> m_xLinkFrame;
+
+ // RotGrfFlyFrame: Need Angle and RotateControls now
+ std::unique_ptr<weld::Frame> m_xFlAngle;
+ std::unique_ptr<weld::MetricSpinButton> m_xNfAngle;
+ std::unique_ptr<svx::DialControl> m_xCtlAngle;
+ std::unique_ptr<weld::CustomWeld> m_xCtlAngleWin;
+ std::unique_ptr<weld::CustomWeld> m_xBmpWin;
+
+ // tdf#138843 add place holder for the graphic type
+ std::unique_ptr<weld::Label> m_xLabelGraphicType;
+
+ // handler for mirroring
+ DECL_LINK(MirrorHdl, weld::Toggleable&, void);
+ DECL_LINK(BrowseHdl, weld::Button&, void);
+
+ virtual void ActivatePage(const SfxItemSet& rSet) override;
+
+public:
+ SwGrfExtPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet);
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet);
+ virtual ~SwGrfExtPage() override;
+
+ virtual bool FillItemSet(SfxItemSet *rSet) override;
+ virtual void Reset(const SfxItemSet *rSet) override;
+ virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override;
+};
+
+class SwFrameURLPage final : public SfxTabPage
+{
+ // hyperlink
+ std::unique_ptr<weld::Entry> m_xURLED;
+ std::unique_ptr<weld::Button> m_xSearchPB;
+ std::unique_ptr<weld::Entry> m_xNameED;
+ std::unique_ptr<weld::ComboBox> m_xFrameCB;
+
+ // image map
+ std::unique_ptr<weld::CheckButton> m_xServerCB;
+ std::unique_ptr<weld::CheckButton> m_xClientCB;
+
+ DECL_LINK(InsertFileHdl, weld::Button&, void);
+
+public:
+ SwFrameURLPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet);
+ virtual ~SwFrameURLPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet);
+
+ virtual bool FillItemSet(SfxItemSet *rSet) override;
+ virtual void Reset(const SfxItemSet *rSet) override;
+};
+
+class SwFrameAddPage final : public SfxTabPage
+{
+ SwWrtShell* m_pWrtSh;
+
+ OUString m_sDlgType;
+ bool m_bHtmlMode;
+ bool m_bFormat;
+ bool m_bNew;
+
+ std::unique_ptr<weld::Widget> m_xNameFrame;
+ std::unique_ptr<weld::Label> m_xNameFT;
+ std::unique_ptr<weld::Entry> m_xNameED;
+ std::unique_ptr<weld::Label> m_xAltNameFT;
+ std::unique_ptr<weld::Entry> m_xAltNameED;
+ std::unique_ptr<weld::Label> m_xDescriptionFT;
+ std::unique_ptr<weld::TextView> m_xDescriptionED;
+ std::unique_ptr<weld::CheckButton> m_xDecorativeCB;
+ std::unique_ptr<weld::Widget> m_xSequenceFrame;
+ std::unique_ptr<weld::ComboBox> m_xPrevLB;
+ std::unique_ptr<weld::ComboBox> m_xNextLB;
+
+ std::unique_ptr<weld::Widget> m_xProtectFrame;
+ std::unique_ptr<weld::CheckButton> m_xProtectContentCB;
+ std::unique_ptr<weld::CheckButton> m_xProtectFrameCB;
+ std::unique_ptr<weld::CheckButton> m_xProtectSizeCB;
+
+ std::unique_ptr<weld::Widget> m_xContentAlignFrame;
+ std::unique_ptr<weld::ComboBox> m_xVertAlignLB;
+
+ std::unique_ptr<weld::Widget> m_xPropertiesFrame;
+ std::unique_ptr<weld::CheckButton> m_xEditInReadonlyCB;
+ std::unique_ptr<weld::CheckButton> m_xPrintFrameCB;
+ std::unique_ptr<weld::Label> m_xTextFlowFT;
+ std::unique_ptr<svx::FrameDirectionListBox> m_xTextFlowLB;
+
+ DECL_LINK(EditModifyHdl, weld::Entry&, void);
+ DECL_LINK(DecorativeHdl, weld::Toggleable&, void);
+ DECL_LINK(ChainModifyHdl, weld::ComboBox&, void);
+
+ static const WhichRangesContainer s_aAddPgRg;
+
+public:
+ SwFrameAddPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet);
+ virtual ~SwFrameAddPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet);
+ static WhichRangesContainer GetRanges() { return s_aAddPgRg; }
+
+ virtual bool FillItemSet(SfxItemSet *rSet) override;
+ virtual void Reset(const SfxItemSet *rSet) override;
+
+ void SetFormatUsed(bool bFormat);
+ void SetFrameType(const OUString &rType) { m_sDlgType = rType; }
+ void SetNewFrame(bool bNewFrame) { m_bNew = bNewFrame; }
+ void SetShell(SwWrtShell* pSh) { m_pWrtSh = pSh; }
+
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_FRMPAGE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/frmsh.hxx b/sw/source/uibase/inc/frmsh.hxx
new file mode 100644
index 0000000000..3bb36497bf
--- /dev/null
+++ b/sw/source/uibase/inc/frmsh.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_FRMSH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_FRMSH_HXX
+
+#include "basesh.hxx"
+
+class SwFrameShell: public SwBaseShell
+{
+public:
+ SFX_DECL_INTERFACE(SW_FRAMESHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwFrameShell(SwView &rView);
+ virtual ~SwFrameShell() override;
+
+ void Execute(SfxRequest &);
+ void ExecMove(SfxRequest& rReq);
+ void ExecField(const SfxRequest& rReq);
+ void GetState(SfxItemSet &);
+ void ExecFrameStyle(SfxRequest const & rReq);
+ void GetLineStyleState(SfxItemSet &rSet);
+ void StateInsert(SfxItemSet &rSet);
+
+ void GetDrawAttrStateTextFrame(SfxItemSet &rSet);
+ void ExecDrawAttrArgsTextFrame(SfxRequest const & rReq);
+
+ void ExecDrawDlgTextFrame(SfxRequest const & rReq);
+ void DisableStateTextFrame(SfxItemSet &rSet);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/globals.h b/sw/source/uibase/inc/globals.h
new file mode 100644
index 0000000000..8617d791c5
--- /dev/null
+++ b/sw/source/uibase/inc/globals.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_GLOBALS_H
+#define INCLUDED_SW_SOURCE_UIBASE_INC_GLOBALS_H
+
+enum SwChangeState
+{
+ STATE_OFF = 0,
+ STATE_ON = 1,
+ STATE_TOGGLE = 2
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/glosbib.hxx b/sw/source/uibase/inc/glosbib.hxx
new file mode 100644
index 0000000000..1df058d0a7
--- /dev/null
+++ b/sw/source/uibase/inc/glosbib.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_GLOSBIB_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_GLOSBIB_HXX
+
+#include <sfx2/basedlgs.hxx>
+#include <rtl/ustring.hxx>
+#include <vcl/weld.hxx>
+
+#include <vector>
+
+class SwGlossaryHdl;
+
+struct GlosBibUserData
+{
+ OUString sPath;
+ OUString sGroupName;
+ OUString sGroupTitle;
+};
+
+class SwGlossaryGroupDlg final : public SfxDialogController
+{
+ std::vector<OUString> m_RemovedArr;
+ std::vector<OUString> m_InsertedArr;
+ std::vector<OUString> m_RenamedArr;
+
+ weld::Window* m_pParent;
+ SwGlossaryHdl* m_pGlosHdl;
+
+ OUString m_sCreatedGroup;
+
+ std::unique_ptr<weld::Entry> m_xNameED;
+ std::unique_ptr<weld::ComboBox> m_xPathLB;
+ std::unique_ptr<weld::TreeView> m_xGroupTLB;
+
+ std::unique_ptr<weld::Button> m_xNewPB;
+ std::unique_ptr<weld::Button> m_xDelPB;
+ std::unique_ptr<weld::Button> m_xRenamePB;
+
+ bool IsDeleteAllowed(const OUString& rGroup);
+
+ void Apply();
+ DECL_LINK(SelectHdl, weld::TreeView&, void);
+ DECL_LINK(NewHdl, weld::Button&, void);
+ DECL_LINK(DeleteHdl, weld::Button&, void);
+ DECL_LINK(ModifyHdl, weld::Entry&, void);
+ DECL_LINK(ModifyListBoxHdl, weld::ComboBox&, void);
+ DECL_LINK(RenameHdl, weld::Button&, void);
+ DECL_STATIC_LINK(SwGlossaryGroupDlg, EditInsertTextHdl, OUString&, bool);
+ DECL_LINK(EntrySizeAllocHdl, const Size&, void);
+
+public:
+ SwGlossaryGroupDlg(weld::Window* pParent, std::vector<OUString> const& rPathArr,
+ SwGlossaryHdl* pGlosHdl);
+ virtual short run() override;
+ virtual ~SwGlossaryGroupDlg() override;
+
+ const OUString& GetCreatedGroupName() const { return m_sCreatedGroup; }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/glosdoc.hxx b/sw/source/uibase/inc/glosdoc.hxx
new file mode 100644
index 0000000000..f879dc1c7b
--- /dev/null
+++ b/sw/source/uibase/inc/glosdoc.hxx
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_GLOSDOC_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_GLOSDOC_HXX
+
+#include <rtl/ustring.hxx>
+#include <unotools/weakref.hxx>
+#include <com/sun/star/text/XAutoTextGroup.hpp>
+
+class SwTextBlocks;
+class SwDocShell;
+
+#ifndef SW_DECL_SWDOCSHELL_DEFINED
+#define SW_DECL_SWDOCSHELL_DEFINED
+#include <tools/ref.hxx>
+typedef tools::SvRef<SwDocShell> SwDocShellRef;
+#endif
+#include <cppuhelper/weakref.hxx>
+
+#include <vector>
+#include <swdllapi.h>
+
+class SwXAutoTextEntry;
+class SwXAutoTextGroup;
+
+typedef std::vector< unotools::WeakReference< SwXAutoTextGroup > > UnoAutoTextGroups;
+typedef std::vector< unotools::WeakReference< SwXAutoTextEntry > > UnoAutoTextEntries;
+
+#define GLOS_DELIM u'*'
+
+class SW_DLLPUBLIC SwGlossaries
+{
+ UnoAutoTextGroups m_aGlossaryGroups;
+ UnoAutoTextEntries m_aGlossaryEntries;
+
+ OUString m_aPath;
+ std::vector<OUString> m_aInvalidPaths;
+ std::vector<OUString> m_PathArr;
+ std::vector<OUString> m_GlosArr;
+ bool m_bError;
+
+ SAL_DLLPRIVATE std::unique_ptr<SwTextBlocks> GetGlosDoc(const OUString &rName, bool bCreate = true) const;
+ SAL_DLLPRIVATE std::vector<OUString> & GetNameList();
+
+ // implementation in unoatxt.cxx
+ SAL_DLLPRIVATE void RemoveFileFromList( const OUString& rGroup );
+ SAL_DLLPRIVATE void InvalidateUNOOjects();
+
+public:
+ SwGlossaries();
+ ~SwGlossaries();
+
+ /** returns the cached AutoTextGroup (if any) for the given group name
+ The group is created if it does not yet exist
+
+ @precond
+ If <arg>_bCreate</arg> is <TRUE/>, the SolarMutex must be locked when calling into this method.
+
+ @param _rGroupName
+ the name of the glossaries group
+ */
+ css::uno::Reference< css::text::XAutoTextGroup >
+ GetAutoTextGroup(
+ std::u16string_view _rGroupName
+ );
+
+ /** returns the cached AutoTextEntry (if any) for the given group/with the given name
+ The entry is created if it does not yet exist
+
+ @precond
+ If <arg>_bCreate</arg> is <TRUE/>, the SolarMutex must be locked when calling into this method.
+
+ @param _rGroupAccessName
+ the name to access the group
+ @param _rGroupName
+ the name of the glossaries group, as to be passed to the entry
+ @param _rEntryName
+ the name of the auto text entry
+ */
+ css::uno::Reference< css::text::XAutoTextEntry >
+ GetAutoTextEntry(
+ const OUString& _rCompleteGroupName,
+ const OUString& _rGroupName,
+ const OUString& _rEntryName
+ );
+
+ size_t GetGroupCnt();
+ OUString const & GetGroupName(size_t);
+ OUString GetGroupTitle( const OUString& rGroupName );
+
+ bool FindGroupName(OUString& rGroup);
+
+ std::unique_ptr<SwTextBlocks>
+ GetGroupDoc(const OUString &rName,
+ bool bCreate = false);
+ static OUString GetDefName();
+ static OUString GetExtension();
+
+ OUString GetCompleteGroupName( std::u16string_view GroupName );
+
+ bool NewGroupDoc(OUString &rGroupName, const OUString& rTitle);
+ bool RenameGroupDoc(const OUString& sOldGroup, OUString& sNewGroup, const OUString& rNewTitle);
+ bool DelGroupDoc(std::u16string_view);
+ SwDocShellRef EditGroupDoc(const OUString &rGrpName, const OUString& rShortName, bool bShow = true );
+ void UpdateGlosPath(bool bFull);
+ void ShowError();
+ bool IsGlosPathErr() const { return m_bError; }
+ std::vector<OUString> const& GetPathArray() const { return m_PathArr; }
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_GLOSDOC_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/gloshdl.hxx b/sw/source/uibase/inc/gloshdl.hxx
new file mode 100644
index 0000000000..c7f0187000
--- /dev/null
+++ b/sw/source/uibase/inc/gloshdl.hxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_GLOSHDL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_GLOSHDL_HXX
+
+#include <memory>
+#include <rtl/ustring.hxx>
+#include <vcl/weld.hxx>
+
+#include <swdllapi.h>
+
+class SwWrtShell;
+class SwTextBlocks;
+class SvxMacro;
+class SwGlossaries;
+class SfxViewFrame;
+
+class SW_DLLPUBLIC SwGlossaryHdl
+{
+
+ SwGlossaries& m_rStatGlossaries;
+ OUString m_aCurGrp;
+ SfxViewFrame& m_rViewFrame;
+ SwWrtShell* m_pWrtShell;
+ std::unique_ptr<SwTextBlocks>
+ m_pCurGrp;
+
+ SAL_DLLPRIVATE bool Expand(weld::Window* pParent, const OUString& rShortName,
+ SwGlossaries* pGlossaries,
+ std::unique_ptr<SwTextBlocks> pGlossary );
+
+public:
+ void GlossaryDlg();
+
+ size_t GetGroupCnt() const;
+ OUString GetGroupName( size_t, OUString* pTitle );
+ void NewGroup(OUString & rGroupName, const OUString& rTitle);
+ bool DelGroup(const OUString &);
+ void RenameGroup(const OUString& rOld, OUString& rNew, const OUString& rNewTitle);
+ void SetCurGroup(const OUString &aGrp, bool bApi = false, bool bAlwaysCreateNew = false);
+
+ sal_uInt16 GetGlossaryCnt() const;
+ OUString GetGlossaryName(sal_uInt16);
+ OUString GetGlossaryShortName(std::u16string_view aName);
+ OUString GetGlossaryShortName(sal_uInt16);
+
+ bool Rename( const OUString& rOldShortName, const OUString& rNewShortName,
+ const OUString& rNewName);
+ bool CopyOrMove( const OUString& rSourceGroupName, OUString& rSourceShortName,
+ const OUString& rDestGroupName, const OUString& rLongName, bool bMove );
+ bool HasShortName(const OUString &rShortName) const;
+ // when NewGlossary is called from Basic then the previously set group should
+ // be newly created if applicable.
+ bool NewGlossary(const OUString &rName, const OUString &rShortName,
+ bool bApiCall = false, bool bNoAttr = false );
+ bool DelGlossary(const OUString&);
+ bool CopyToClipboard(SwWrtShell& rSh, const OUString& rShortName);
+
+ bool ExpandGlossary(weld::Window* pParent);
+ bool InsertGlossary(const OUString &rName);
+
+ void SetMacros(const OUString& rName,
+ const SvxMacro* pStart,
+ const SvxMacro* pEnd,
+ SwTextBlocks *pGlossary = nullptr );
+ void GetMacros(const OUString& rShortName,
+ SvxMacro& rStart,
+ SvxMacro& rEnd,
+ SwTextBlocks* pGlossary = nullptr );
+
+ bool IsReadOnly( const OUString* = nullptr ) const;
+ bool IsOld() const;
+
+ bool FindGroupName(OUString& rGroup); // find group without path index
+
+ bool ImportGlossaries( const OUString& rName );
+
+ SwGlossaryHdl(SfxViewFrame& rViewFrame, SwWrtShell*);
+ ~SwGlossaryHdl();
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_GLOSHDL_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/gloslst.hxx b/sw/source/uibase/inc/gloslst.hxx
new file mode 100644
index 0000000000..65e09f5cf1
--- /dev/null
+++ b/sw/source/uibase/inc/gloslst.hxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_GLOSLST_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_GLOSLST_HXX
+
+#include <rtl/ustring.hxx>
+#include <tools/datetime.hxx>
+#include <vcl/timer.hxx>
+
+#include <vector>
+
+class SwGlossaries;
+
+struct AutoTextGroup
+{
+ sal_uInt16 nCount;
+ OUString sName;
+ OUString sTitle;
+ OUString sLongNames; // by 0x0A separated long names
+ OUString sShortNames; // by 0x0A separated short names
+ DateTime aDateModified;
+
+ AutoTextGroup()
+ : nCount(0)
+ , aDateModified(DateTime::EMPTY)
+ {
+ }
+};
+
+class SwGlossaryList final : public AutoTimer
+{
+ std::vector<std::unique_ptr<AutoTextGroup>> m_aGroupArr;
+ OUString m_sPath;
+ bool m_bFilled;
+
+ AutoTextGroup* FindGroup(std::u16string_view rGroupName);
+ static void FillGroup(AutoTextGroup* pGroup, SwGlossaries* pGloss);
+
+public:
+ SwGlossaryList();
+ virtual ~SwGlossaryList() override;
+
+ void HasLongName(const std::vector<OUString>& rBeginCandidates,
+ std::vector<std::pair<OUString, sal_uInt16>>& rLongNames);
+ bool GetShortName(std::u16string_view rLongName,
+ OUString& rShortName, OUString& rGroupName );
+
+ size_t GetGroupCount();
+ OUString GetGroupName(size_t nPos);
+ OUString GetGroupTitle(size_t nPos);
+
+ sal_uInt16 GetBlockCount(size_t nGroup);
+ OUString GetBlockLongName(size_t nGroup, sal_uInt16 nBlock);
+ OUString GetBlockShortName(size_t nGroup, sal_uInt16 nBlock);
+
+ void Update();
+
+ virtual void Invoke() override;
+
+ void ClearGroups();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/glossary.hxx b/sw/source/uibase/inc/glossary.hxx
new file mode 100644
index 0000000000..b93925f344
--- /dev/null
+++ b/sw/source/uibase/inc/glossary.hxx
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_GLOSSARY_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_GLOSSARY_HXX
+
+#include <vcl/customweld.hxx>
+#include <vcl/textfilter.hxx>
+#include <vcl/weld.hxx>
+
+#include <com/sun/star/text/XAutoTextContainer2.hpp>
+
+#include <rtl/ustring.hxx>
+#include <sfx2/basedlgs.hxx>
+
+struct GroupUserData;
+class SwGlossaryHdl;
+class SwNewGlosNameDlg;
+class SwWrtShell;
+class SfxViewFrame;
+class PopupMenu;
+class Menu;
+class SwOneExampleFrame;
+
+const short RET_EDIT = 100;
+
+class SwGlossaryDropTarget;
+
+class SwGlossaryDlg final : public SfxDialogController
+{
+ friend class SwNewGlosNameDlg;
+
+ OUString const m_sReadonlyPath;
+
+ css::uno::Reference< css::text::XAutoTextContainer2 > m_xAutoText;
+
+ SwGlossaryHdl* m_pGlossaryHdl;
+
+ OUString m_sResumeGroup;
+ OUString m_sResumeShortName;
+ bool m_bResume;
+
+ const bool m_bSelection : 1;
+ bool m_bReadOnly : 1;
+ bool m_bIsOld : 1;
+ bool m_bIsDocReadOnly:1;
+
+ SwWrtShell* m_pShell;
+
+ std::vector<std::unique_ptr<GroupUserData>> m_xGroupData;
+
+ std::unique_ptr<weld::CheckButton> m_xInsertTipCB;
+ std::unique_ptr<weld::Entry> m_xNameED;
+ std::unique_ptr<weld::Label> m_xShortNameLbl;
+ TextFilter m_aNoSpaceFilter;
+ std::unique_ptr<weld::Entry> m_xShortNameEdit;
+ std::unique_ptr<weld::TreeView> m_xCategoryBox;
+ std::unique_ptr<weld::CheckButton> m_xFileRelCB;
+ std::unique_ptr<weld::CheckButton> m_xNetRelCB;
+ std::unique_ptr<weld::Button> m_xInsertBtn;
+ std::unique_ptr<weld::MenuButton> m_xEditBtn;
+ std::unique_ptr<weld::Button> m_xBibBtn;
+ std::unique_ptr<weld::Button> m_xPathBtn;
+ std::unique_ptr<SwOneExampleFrame> m_xExampleFrame;
+ std::unique_ptr<weld::CustomWeld> m_xExampleFrameWin;
+ std::unique_ptr<SwGlossaryDropTarget> m_xDropTarget;
+
+ void EnableShortName(bool bOn = true);
+ void ShowPreview();
+
+ DECL_LINK( NameModify, weld::Entry&, void );
+ DECL_LINK( NameDoubleClick, weld::TreeView&, bool );
+ DECL_LINK( GrpSelect, weld::TreeView&, void );
+ DECL_LINK( MenuHdl, const OUString&, void );
+ DECL_LINK( EnableHdl, weld::Toggleable&, void );
+ DECL_LINK( BibHdl, weld::Button&, void );
+ DECL_LINK( InsertHdl, weld::Button&, void );
+ DECL_LINK( PathHdl, weld::Button&, void );
+ DECL_LINK( CheckBoxHdl, weld::Toggleable&, void );
+ DECL_LINK( PreviewLoadedHdl, SwOneExampleFrame&, void );
+ DECL_LINK( KeyInputHdl, const KeyEvent&, bool );
+ DECL_LINK( TextFilterHdl, OUString&, bool );
+
+ void Apply();
+ void Init();
+ std::unique_ptr<weld::TreeIter> DoesBlockExist(std::u16string_view sBlock, std::u16string_view rShort);
+ void ShowAutoText(const OUString& rGroup, const OUString& rShortName);
+ void ResumeShowAutoText();
+
+ bool GetResumeData(OUString& rGroup, OUString& rShortName)
+ {rGroup = m_sResumeGroup; rShortName = m_sResumeShortName; return m_bResume;}
+ void SetResumeData(const OUString& rGroup, const OUString& rShortName)
+ {m_sResumeGroup = rGroup; m_sResumeShortName = rShortName; m_bResume = true;}
+
+ void DeleteEntry();
+public:
+ SwGlossaryDlg(const SfxViewFrame& rViewFrame, SwGlossaryHdl* pGlosHdl, SwWrtShell *pWrtShell);
+ virtual short run() override;
+ virtual ~SwGlossaryDlg() override;
+ OUString GetCurrGrpName() const;
+ OUString GetCurrShortName() const
+ {
+ return m_xShortNameEdit->get_text();
+ }
+ static OUString GetCurrGroup();
+ static void SetActGroup(const OUString& rNewGroup);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/glshell.hxx b/sw/source/uibase/inc/glshell.hxx
new file mode 100644
index 0000000000..0b13b76812
--- /dev/null
+++ b/sw/source/uibase/inc/glshell.hxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_GLSHELL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_GLSHELL_HXX
+#include <wdocsh.hxx>
+
+class SwGlosDocShell final : public SwDocShell
+{
+ OUString m_aLongName;
+ OUString m_aShortName;
+ OUString m_aGroupName;
+
+ virtual bool Save() override;
+
+public:
+ SFX_DECL_INTERFACE(SW_GLOSDOCSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwGlosDocShell( bool bNewShow);
+ virtual ~SwGlosDocShell() override;
+
+ void Execute( SfxRequest& );
+ void GetState( SfxItemSet& );
+ void SetLongName( const OUString& rLongName )
+ { m_aLongName = rLongName; }
+ void SetShortName( const OUString& rShortName )
+ { m_aShortName = rShortName; }
+ void SetGroupName( const OUString& rGroupName )
+ { m_aGroupName = rGroupName; }
+};
+
+class SwWebGlosDocShell final : public SwWebDocShell
+{
+ OUString m_aLongName;
+ OUString m_aShortName;
+ OUString m_aGroupName;
+
+ virtual bool Save() override;
+
+public:
+ SFX_DECL_INTERFACE(SW_WEBGLOSDOCSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwWebGlosDocShell();
+ virtual ~SwWebGlosDocShell() override;
+
+ void Execute( SfxRequest& );
+ void GetState( SfxItemSet& );
+ void SetLongName( const OUString& rLongName )
+ { m_aLongName = rLongName; }
+ void SetShortName( const OUString& rShortName )
+ { m_aShortName = rShortName; }
+ void SetGroupName( const OUString& rGroupName )
+ { m_aGroupName = rGroupName; }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/grfsh.hxx b/sw/source/uibase/inc/grfsh.hxx
new file mode 100644
index 0000000000..c5de732025
--- /dev/null
+++ b/sw/source/uibase/inc/grfsh.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_GRFSH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_GRFSH_HXX
+
+#include <memory>
+#include <vector>
+
+#include "basesh.hxx"
+#include <shellid.hxx>
+
+#include <sfx2/shell.hxx>
+
+class SwGrfShell : public SwBaseShell
+{
+ class SwExternalToolEdit;
+ std::vector<std::unique_ptr<SwExternalToolEdit>> m_ExternalEdits;
+
+public:
+ SFX_DECL_INTERFACE(SW_GRFSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ void Execute(SfxRequest& rRequest);
+ void ExecAttr(SfxRequest const& rRequest);
+ void GetAttrState(SfxItemSet& rRequest);
+
+ void ExecuteRotation(SfxRequest const& rRequest);
+ void GetAttrStateForRotation(SfxItemSet& rRequest);
+
+ SwGrfShell(SwView& rView);
+ virtual ~SwGrfShell() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/hyp.hxx b/sw/source/uibase/inc/hyp.hxx
new file mode 100644
index 0000000000..bbe8208f9f
--- /dev/null
+++ b/sw/source/uibase/inc/hyp.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_HYP_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_HYP_HXX
+
+#include <editeng/splwrap.hxx>
+#include <com/sun/star/linguistic2/XHyphenator.hpp>
+#include <swdllapi.h>
+
+class SwView;
+
+class SW_DLLPUBLIC SwHyphWrapper final : public SvxSpellWrapper {
+private:
+ SwView* m_pView;
+ sal_uInt16 m_nPageCount; // page count for progress view
+ sal_uInt16 m_nPageStart; // 1st checked page
+ bool m_bInSelection : 1; // separating selected text
+ bool m_bAutomatic : 1; // insert separators without further inquiry
+ bool m_bInfoBox : 1; // display info-box when ending
+
+ virtual void SpellStart( SvxSpellArea eSpell ) override;
+ virtual void SpellContinue() override;
+ virtual void SpellEnd( ) override;
+ virtual bool SpellMore() override;
+ virtual void InsertHyphen( const sal_Int32 nPos ) override; // insert hyphen
+
+public:
+ SwHyphWrapper( SwView* pVw,
+ css::uno::Reference< css::linguistic2::XHyphenator > const &rxHyph,
+ bool bStart, bool bOther, bool bSelect );
+ virtual ~SwHyphWrapper() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/idxmrk.hxx b/sw/source/uibase/inc/idxmrk.hxx
new file mode 100644
index 0000000000..37dfa76c1b
--- /dev/null
+++ b/sw/source/uibase/inc/idxmrk.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_IDXMRK_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_IDXMRK_HXX
+
+#include <sfx2/childwin.hxx>
+
+#include <swabstdlg.hxx>
+
+class SwWrtShell;
+
+class SwInsertIdxMarkWrapper final : public SfxChildWindow
+{
+ ScopedVclPtr<AbstractMarkFloatDlg> m_xAbstDlg;
+
+public:
+ SwInsertIdxMarkWrapper(vcl::Window *pParentWindow,
+ sal_uInt16 nId,
+ SfxBindings* pBindings,
+ SfxChildWinInfo* pInfo);
+
+ SFX_DECL_CHILDWINDOW_WITHID(SwInsertIdxMarkWrapper);
+
+ void ReInitDlg(SwWrtShell& rWrtShell);
+};
+
+class SwInsertAuthMarkWrapper final : public SfxChildWindow
+{
+ ScopedVclPtr<AbstractMarkFloatDlg> m_xAbstDlg;
+
+public:
+ SwInsertAuthMarkWrapper(vcl::Window *pParentWindow,
+ sal_uInt16 nId,
+ SfxBindings* pBindings,
+ SfxChildWinInfo* pInfo);
+
+ SFX_DECL_CHILDWINDOW_WITHID(SwInsertAuthMarkWrapper);
+
+ void ReInitDlg(SwWrtShell& rWrtShell);
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_IDXMRK_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/imaildsplistener.hxx b/sw/source/uibase/inc/imaildsplistener.hxx
new file mode 100644
index 0000000000..8852a88009
--- /dev/null
+++ b/sw/source/uibase/inc/imaildsplistener.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_IMAILDSPLISTENER_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_IMAILDSPLISTENER_HXX
+
+#include <com/sun/star/mail/XMailMessage.hpp>
+#include <salhelper/simplereferenceobject.hxx>
+#include <rtl/ref.hxx>
+
+class MailDispatcher;
+
+/**
+ MailDispatcher listener interface.
+ Clients may implement and register instances of the
+ mail dispatcher interface in order to get notifications
+ about the MailDispatcher status.
+
+ @see MailDispatcher
+*/
+class IMailDispatcherListener : public salhelper::SimpleReferenceObject
+{
+public:
+ /**
+ Called when there are no more mail messages
+ to deliver.
+ */
+ virtual void idle() = 0;
+
+ /**
+ Called for every mail message that has been
+ successfully delivered.
+ */
+ virtual void mailDelivered(css::uno::Reference< css::mail::XMailMessage> xMailMessage) = 0;
+
+ /**
+ Called for every mail message whose delivery
+ failed.
+ */
+ virtual void mailDeliveryError(::rtl::Reference<MailDispatcher> xMailDispatcher, css::uno::Reference< css::mail::XMailMessage> xMailMessage, const OUString& sErrorMessage) = 0;
+};
+
+#endif // INCLUDED_IMAILDISPATCHERLISTENER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/initui.hxx b/sw/source/uibase/inc/initui.hxx
new file mode 100644
index 0000000000..a74f7b3932
--- /dev/null
+++ b/sw/source/uibase/inc/initui.hxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_INITUI_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_INITUI_HXX
+
+#include <swdllapi.h>
+#include <rtl/ustring.hxx>
+
+SW_DLLPUBLIC const OUString& GetCurrGlosGroup();
+SW_DLLPUBLIC void SetCurrGlosGroup(const OUString& sStr);
+
+// provides textblock management
+class SwGlossaries;
+SW_DLLPUBLIC SwGlossaries* GetGlossaries();
+
+class SwGlossaryList;
+
+bool HasGlossaryList();
+SwGlossaryList* GetGlossaryList();
+
+extern void InitUI();
+extern void FinitUI();
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/inpdlg.hxx b/sw/source/uibase/inc/inpdlg.hxx
new file mode 100644
index 0000000000..26ffc960d5
--- /dev/null
+++ b/sw/source/uibase/inc/inpdlg.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_INPDLG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_INPDLG_HXX
+
+#include <vcl/weld.hxx>
+
+class SwInputField;
+class SwSetExpField;
+class SwUserFieldType;
+class SwField;
+class SwWrtShell;
+class SwFieldMgr;
+
+// insert fields
+class SwFieldInputDlg final : public weld::GenericDialogController
+{
+ void Apply();
+
+ SwWrtShell& m_rSh;
+ SwInputField* m_pInpField;
+ SwSetExpField* m_pSetField;
+ SwUserFieldType* m_pUsrType;
+
+ weld::Button* m_pPressedButton;
+ std::unique_ptr<weld::Entry> m_xLabelED;
+ std::unique_ptr<weld::TextView> m_xEditED;
+ std::unique_ptr<weld::Button> m_xPrevBT;
+ std::unique_ptr<weld::Button> m_xNextBT;
+ std::unique_ptr<weld::Button> m_xOKBT;
+
+ DECL_LINK(NextHdl, weld::Button&, void);
+ DECL_LINK(PrevHdl, weld::Button&, void);
+
+public:
+ SwFieldInputDlg(weld::Widget *pParent, SwWrtShell &rSh,
+ SwField* pField, bool bPrevButton, bool bNextButton);
+ virtual short run() override
+ {
+ short nRet = GenericDialogController::run();
+ if (nRet == RET_OK)
+ Apply();
+ return nRet;
+ }
+ virtual ~SwFieldInputDlg() override;
+ bool PrevButtonPressed() const;
+ bool NextButtonPressed() const;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/inputwin.hxx b/sw/source/uibase/inc/inputwin.hxx
new file mode 100644
index 0000000000..05d181a886
--- /dev/null
+++ b/sw/source/uibase/inc/inputwin.hxx
@@ -0,0 +1,211 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_INPUTWIN_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_INPUTWIN_HXX
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <vcl/InterimItemWindow.hxx>
+#include <vcl/toolbox.hxx>
+
+#include <sfx2/childwin.hxx>
+
+class SwFieldMgr;
+class SwWrtShell;
+class SwView;
+class SfxDispatcher;
+
+class InputEdit final : public InterimItemWindow
+{
+private:
+ std::unique_ptr<weld::Entry> m_xWidget;
+
+ DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
+ DECL_LINK(ActivateHdl, weld::Entry&, bool);
+public:
+ InputEdit(vcl::Window* pParent)
+ : InterimItemWindow(pParent, "modules/swriter/ui/inputeditbox.ui", "InputEditBox")
+ , m_xWidget(m_xBuilder->weld_entry("entry"))
+ {
+ InitControlBase(m_xWidget.get());
+
+ m_xWidget->connect_key_press(LINK(this, InputEdit, KeyInputHdl));
+ m_xWidget->connect_activate(LINK(this, InputEdit, ActivateHdl));
+ SetSizePixel(m_xWidget->get_preferred_size());
+ }
+
+ void UpdateRange(std::u16string_view rSel, const OUString& rTableName);
+
+ virtual void dispose() override
+ {
+ m_xWidget.reset();
+ InterimItemWindow::dispose();
+ }
+
+ void set_text(const OUString& rText)
+ {
+ m_xWidget->set_text(rText);
+ }
+
+ OUString get_text() const
+ {
+ return m_xWidget->get_text();
+ }
+
+ void set_accessible_name(const OUString& rName)
+ {
+ m_xWidget->set_accessible_name(rName);
+ }
+
+ void replace_selection(const OUString& rText)
+ {
+ int nStartPos, nEndPos;
+ m_xWidget->get_selection_bounds(nStartPos, nEndPos);
+ if (nStartPos > nEndPos)
+ std::swap(nStartPos, nEndPos);
+
+ m_xWidget->replace_selection(rText);
+
+ nStartPos = nStartPos + rText.getLength();
+ m_xWidget->select_region(nStartPos, nStartPos);
+ }
+
+ void select_region(int nStartPos, int nEndPos)
+ {
+ m_xWidget->select_region(nStartPos, nEndPos);
+ }
+
+ void connect_changed(const Link<weld::Entry&, void>& rLink)
+ {
+ m_xWidget->connect_changed(rLink);
+ }
+
+ virtual ~InputEdit() override
+ {
+ disposeOnce();
+ }
+};
+
+
+class PosEdit final : public InterimItemWindow
+{
+private:
+ std::unique_ptr<weld::Entry> m_xWidget;
+
+ DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
+public:
+ PosEdit(vcl::Window* pParent)
+ : InterimItemWindow(pParent, "modules/swriter/ui/poseditbox.ui", "PosEditBox")
+ , m_xWidget(m_xBuilder->weld_entry("entry"))
+ {
+ InitControlBase(m_xWidget.get());
+
+ m_xWidget->connect_key_press(LINK(this, PosEdit, KeyInputHdl));
+ SetSizePixel(m_xWidget->get_preferred_size());
+ }
+
+ virtual void dispose() override
+ {
+ m_xWidget.reset();
+ InterimItemWindow::dispose();
+ }
+
+ void set_text(const OUString& rText)
+ {
+ m_xWidget->set_text(rText);
+ }
+
+ void set_accessible_name(const OUString& rName)
+ {
+ m_xWidget->set_accessible_name(rName);
+ }
+
+ virtual ~PosEdit() override
+ {
+ disposeOnce();
+ }
+};
+
+class SwInputWindow final : public ToolBox
+{
+friend class InputEdit;
+
+ VclPtr<PosEdit> mxPos;
+ VclPtr<InputEdit> mxEdit;
+ std::unique_ptr<SwFieldMgr> m_pMgr;
+ SwWrtShell* m_pWrtShell;
+ SwView* m_pView;
+ OUString m_aCurrentTableName, m_sOldFormula;
+
+ bool m_bFirst : 1; // initialisations at first call
+ bool m_bIsTable : 1;
+ bool m_bDelSel : 1;
+ bool m_bDoesUndo : 1;
+ bool m_bResetUndo : 1;
+ bool m_bCallUndo : 1;
+
+ void CleanupUglyHackWithUndo();
+
+ void DelBoxContent();
+ DECL_LINK(ModifyHdl, weld::Entry&, void);
+
+ using Window::IsActive;
+
+ virtual void Resize() override;
+ virtual void Click() override;
+ void MenuHdl(std::u16string_view command);
+ DECL_LINK( DropdownClickHdl, ToolBox*, void );
+ void ApplyFormula();
+ void CancelFormula();
+
+public:
+ SwInputWindow(vcl::Window* pParent, SfxDispatcher const * pDispatcher);
+ virtual ~SwInputWindow() override;
+ virtual void dispose() override;
+
+ void ShowWin();
+
+ DECL_LINK( SelTableCellsNotify, SwWrtShell&, void );
+
+ void SetFormula( const OUString& rFormula );
+ const SwView* GetView() const{return m_pView;}
+};
+
+class SwInputChild final : public SfxChildWindow
+{
+ SfxDispatcher* m_pDispatch;
+public:
+ SwInputChild( vcl::Window* ,
+ sal_uInt16 nId,
+ SfxBindings const *,
+ SfxChildWinInfo* );
+ virtual ~SwInputChild() override;
+ SFX_DECL_CHILDWINDOW_WITHID( SwInputChild );
+ void SetFormula( const OUString& rFormula )
+ { static_cast<SwInputWindow*>(GetWindow())->SetFormula( rFormula ); }
+ const SwView* GetView() const
+ { return static_cast<SwInputWindow*>(GetWindow())->GetView();}
+
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/insfnote.hxx b/sw/source/uibase/inc/insfnote.hxx
new file mode 100644
index 0000000000..396e874046
--- /dev/null
+++ b/sw/source/uibase/inc/insfnote.hxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_INSFNOTE_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_INSFNOTE_HXX
+
+#include <vcl/weld.hxx>
+
+class SwWrtShell;
+
+class VclFrame;
+
+class SwInsFootNoteDlg final : public weld::GenericDialogController
+{
+ SwWrtShell &m_rSh;
+
+ // everything for the character(s)
+ OUString m_aFontName;
+ rtl_TextEncoding m_eCharSet;
+ bool m_bExtCharAvailable;
+ bool m_bEdit;
+
+ std::unique_ptr<weld::Widget> m_xNumberFrame;
+ std::unique_ptr<weld::RadioButton> m_xNumberAutoBtn;
+ std::unique_ptr<weld::RadioButton> m_xNumberCharBtn;
+ std::unique_ptr<weld::Entry> m_xNumberCharEdit;
+ std::unique_ptr<weld::Button> m_xNumberExtChar;
+
+ // everything for the selection footnote/endnote
+ std::unique_ptr<weld::RadioButton> m_xFootnoteBtn;
+ std::unique_ptr<weld::RadioButton> m_xEndNoteBtn;
+
+ std::unique_ptr<weld::Button> m_xOkBtn;
+ std::unique_ptr<weld::Button> m_xPrevBT;
+ std::unique_ptr<weld::Button> m_xNextBT;
+
+ DECL_LINK(NumberToggleHdl, weld::Toggleable&, void);
+ DECL_LINK(NumberEditHdl, weld::Entry&, void);
+ DECL_LINK(NumberExtCharHdl, weld::Button&, void);
+ DECL_LINK(NextPrevHdl, weld::Button&, void);
+
+ void Apply();
+
+ void Init();
+
+public:
+ SwInsFootNoteDlg(weld::Window * pParent, SwWrtShell &rSh, bool bEd);
+ virtual ~SwInsFootNoteDlg() COVERITY_NOEXCEPT_FALSE override;
+
+ const OUString& GetFontName() const { return m_aFontName; }
+ bool IsEndNote() const { return m_xEndNoteBtn->get_active(); }
+ OUString GetStr() const
+ {
+ if (m_xNumberCharBtn->get_active())
+ return m_xNumberCharEdit->get_text();
+ return OUString();
+ }
+ virtual short run() override
+ {
+ short nRet = GenericDialogController::run();
+ if (nRet == RET_OK)
+ Apply();
+ return nRet;
+ }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/instable.hxx b/sw/source/uibase/inc/instable.hxx
new file mode 100644
index 0000000000..be20b64daf
--- /dev/null
+++ b/sw/source/uibase/inc/instable.hxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_INSTABLE_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_INSTABLE_HXX
+
+#include <sfx2/basedlgs.hxx>
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+#include <tools/link.hxx>
+#include <vcl/textfilter.hxx>
+
+#include "wrtsh.hxx"
+#include "autoformatpreview.hxx"
+#include <view.hxx>
+#include <tblafmt.hxx>
+#include <itabenum.hxx>
+#include <memory>
+
+class SwInsTableDlg final : public SfxDialogController
+{
+ TextFilter m_aTextFilter;
+
+ SwWrtShell* m_pShell;
+ std::unique_ptr<SwTableAutoFormatTable> m_xTableTable;
+ std::unique_ptr<SwTableAutoFormat> m_xTAutoFormat;
+
+ sal_uInt8 m_lbIndex;
+ sal_uInt8 m_tbIndex;
+ sal_uInt8 minTableIndexInLb;
+ sal_uInt8 maxTableIndexInLb;
+ sal_Int64 m_nEnteredValRepeatHeaderNF;
+
+ AutoFormatPreview m_aWndPreview;
+
+ std::unique_ptr<weld::Entry> m_xNameEdit;
+ std::unique_ptr<weld::Label> m_xWarning;
+ std::unique_ptr<weld::SpinButton> m_xColSpinButton;
+ std::unique_ptr<weld::SpinButton> m_xRowSpinButton;
+ std::unique_ptr<weld::CheckButton> m_xHeaderCB;
+ std::unique_ptr<weld::CheckButton> m_xRepeatHeaderCB;
+ std::unique_ptr<weld::SpinButton> m_xRepeatHeaderNF;
+ std::unique_ptr<weld::Widget> m_xRepeatGroup;
+ std::unique_ptr<weld::CheckButton> m_xDontSplitCB;
+ std::unique_ptr<weld::Button> m_xInsertBtn;
+ std::unique_ptr<weld::TreeView> m_xLbFormat;
+ std::unique_ptr<weld::CustomWeld> m_xWndPreview;
+ std::unique_ptr<weld::Frame> m_xStyleFrame;
+
+ // Returns 255 if mapping is not possible.
+ // This means there cannot be more than 255 autotable style.
+ sal_uInt8 lbIndexToTableIndex(const sal_uInt8 listboxIndex);
+ void InitAutoTableFormat();
+
+ DECL_LINK(TextFilterHdl, OUString&, bool);
+ DECL_LINK(SelFormatHdl, weld::TreeView&, void);
+ DECL_LINK(ModifyName, weld::Entry&, void);
+ DECL_LINK(ModifyRowCol, weld::Entry&, void);
+ DECL_LINK(OKHdl, weld::Button&, void);
+ DECL_LINK(CheckBoxHdl, weld::Toggleable&, void);
+ DECL_LINK(RepeatHeaderCheckBoxHdl, weld::Toggleable&, void);
+ DECL_LINK(ModifyRepeatHeaderNF_Hdl, weld::SpinButton&, void);
+
+public:
+ SwInsTableDlg(SwView& rView);
+
+ void GetValues(OUString& rName, sal_uInt16& rRow, sal_uInt16& rCol,
+ SwInsertTableOptions& rInsTableOpts, OUString& rTableAutoFormatName,
+ std::unique_ptr<SwTableAutoFormat>& prTAFormat);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/javaedit.hxx b/sw/source/uibase/inc/javaedit.hxx
new file mode 100644
index 0000000000..0b4ca37cab
--- /dev/null
+++ b/sw/source/uibase/inc/javaedit.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+
+class SwWrtShell;
+class SwFieldMgr;
+class SwScriptField;
+
+namespace sfx2 { class FileDialogHelper; }
+
+class SwJavaEditDialog final : public weld::GenericDialogController
+{
+private:
+ OUString m_aText;
+ OUString m_aType;
+
+ bool m_bNew;
+ bool m_bIsUrl;
+
+ SwScriptField* m_pField;
+ std::unique_ptr<SwFieldMgr> m_pMgr;
+ SwWrtShell* m_pSh;
+ std::unique_ptr<sfx2::FileDialogHelper> m_pFileDlg;
+
+ std::unique_ptr<weld::Entry> m_xTypeED;
+ std::unique_ptr<weld::RadioButton> m_xUrlRB;
+ std::unique_ptr<weld::RadioButton> m_xEditRB;
+ std::unique_ptr<weld::Button> m_xUrlPB;
+ std::unique_ptr<weld::Entry> m_xUrlED;
+ std::unique_ptr<weld::TextView> m_xEditED;
+ std::unique_ptr<weld::Button> m_xOKBtn;
+ std::unique_ptr<weld::Button> m_xPrevBtn;
+ std::unique_ptr<weld::Button> m_xNextBtn;
+
+ DECL_LINK(OKHdl, weld::Button&, void);
+ DECL_LINK(PrevHdl, weld::Button&, void);
+ DECL_LINK(NextHdl, weld::Button&, void);
+ DECL_LINK(RadioButtonHdl, weld::Toggleable&, void);
+ DECL_LINK(InsertFileHdl, weld::Button&, void);
+ DECL_LINK(DlgClosedHdl, sfx2::FileDialogHelper *, void);
+
+ void UpdateFromRadioButtons();
+ void CheckTravel();
+ void SetField();
+
+public:
+ SwJavaEditDialog(weld::Window* pParent, SwWrtShell* pWrtSh);
+ virtual ~SwJavaEditDialog() override;
+
+ const OUString& GetScriptText() const { return m_aText; }
+
+ const OUString& GetScriptType() const { return m_aType; }
+
+ bool IsUrl() const { return m_bIsUrl; }
+ bool IsNew() const { return m_bNew; }
+ bool IsUpdate() const;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/label.hxx b/sw/source/uibase/inc/label.hxx
new file mode 100644
index 0000000000..825767726b
--- /dev/null
+++ b/sw/source/uibase/inc/label.hxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_LABEL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_LABEL_HXX
+
+#include <sfx2/tabdlg.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include "labelcfg.hxx"
+#include <vector>
+
+class SwLabItem;
+class SwLabPrtPage;
+class SwDBManager;
+class Printer;
+
+class SwLabDlg final : public SfxTabDialogController
+{
+ SwLabelConfig m_aLabelsCfg;
+ SwDBManager* m_pDBManager;
+ SwLabPrtPage* m_pPrtPage;
+
+ std::vector<sal_uInt16> m_aTypeIds;
+ std::vector<OUString> m_aMakes;
+
+ std::unique_ptr<SwLabRecs> m_pRecs;
+ OUString m_aLstGroup;
+ OUString m_sBusinessCardDlg;
+ bool m_bLabel;
+ void ReplaceGroup_( const OUString &rMake );
+
+ virtual void PageCreated(const OUString& rId, SfxTabPage &rPage) override;
+public:
+
+ SwLabDlg(weld::Window* pParent, const SfxItemSet& rSet,
+ SwDBManager* pDBManager, bool bLabel);
+ virtual ~SwLabDlg() override;
+
+ SwLabRec* GetRecord(std::u16string_view rRecName, bool bCont);
+ void GetLabItem(SwLabItem &rItem);
+
+ SwLabRecs &Recs() { return *m_pRecs; }
+ const SwLabRecs &Recs() const { return *m_pRecs; }
+
+ std::vector<sal_uInt16> &TypeIds() { return m_aTypeIds; }
+ const std::vector<sal_uInt16> &TypeIds() const { return m_aTypeIds; }
+
+ std::vector<OUString> &Makes() { return m_aMakes; }
+ const std::vector<OUString> &Makes() const { return m_aMakes; }
+
+ Printer *GetPrt();
+ void ReplaceGroup( const OUString &rMake )
+ {
+ if ( rMake != m_aLstGroup )
+ ReplaceGroup_( rMake );
+ }
+
+ void UpdateGroup( const OUString &rMake ) {ReplaceGroup_( rMake );}
+ static void UpdateFieldInformation(css::uno::Reference< css::frame::XModel> const & xModel,
+ const SwLabItem& rItem);
+ const OUString& GetBusinessCardStr() const {return m_sBusinessCardDlg;}
+
+ SwLabelConfig& GetLabelsConfig() {return m_aLabelsCfg;}
+
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/labelcfg.hxx b/sw/source/uibase/inc/labelcfg.hxx
new file mode 100644
index 0000000000..2a88d59021
--- /dev/null
+++ b/sw/source/uibase/inc/labelcfg.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_LABELCFG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_LABELCFG_HXX
+
+#include <unotools/configitem.hxx>
+#include <swdllapi.h>
+#include "labrec.hxx"
+
+#include <map>
+#include <vector>
+
+struct SwLabelMeasure
+{
+ OUString m_aMeasure; // string contains the label dimensions
+ bool m_bPredefined; // used to distinguish predefined from user-defined labels
+};
+
+class SW_DLLPUBLIC SwLabelConfig final : public utl::ConfigItem
+{
+private:
+ std::vector<OUString> m_aManufacturers;
+ std::map< OUString, std::map<OUString, SwLabelMeasure> > m_aLabels;
+
+ virtual void ImplCommit() override;
+
+public:
+ SwLabelConfig();
+ virtual ~SwLabelConfig() override;
+
+ virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+
+ void FillLabels(const OUString& rManufacturer, SwLabRecs& rLabArr);
+ const std::vector<OUString>& GetManufacturers() const {return m_aManufacturers;}
+
+ bool HasLabel(const OUString& rManufacturer, const OUString& rType);
+ bool IsPredefinedLabel(const OUString& rManufacturer, const OUString& rType)
+ { return m_aLabels[rManufacturer][rType].m_bPredefined; };
+ void SaveLabel(const OUString& rManufacturer, const OUString& rType,
+ const SwLabRec& rRec);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/labimg.hxx b/sw/source/uibase/inc/labimg.hxx
new file mode 100644
index 0000000000..5e5c428bd7
--- /dev/null
+++ b/sw/source/uibase/inc/labimg.hxx
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_LABIMG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_LABIMG_HXX
+
+#include <svl/poolitem.hxx>
+#include <unotools/configitem.hxx>
+#include <swdllapi.h>
+
+class SwLabCfgItem;
+
+class SW_DLLPUBLIC SwLabItem final : public SfxPoolItem
+{
+
+public:
+
+ SwLabItem();
+
+ SwLabItem& operator =(const SwLabItem& rItem);
+ SwLabItem(SwLabItem const &) = default; // SfxPoolItem copy function dichotomy
+
+ virtual bool operator ==(const SfxPoolItem& rItem) const override;
+
+ virtual SwLabItem* Clone(SfxItemPool* = nullptr) const override;
+
+ OUString m_aLstMake; // remember last selection
+ OUString m_aLstType;
+ OUString m_sDBName; // used database
+
+ OUString m_aWriting; // label
+ OUString m_aMake; // label mark
+ OUString m_aType; // label type
+ sal_Int32 m_lHDist; // horizontal distance (user)
+ sal_Int32 m_lVDist; // vertical distance (user)
+ sal_Int32 m_lWidth; // width (user)
+ sal_Int32 m_lHeight; // height (user)
+ sal_Int32 m_lLeft; // left border (user)
+ sal_Int32 m_lUpper; // upper border (user)
+ sal_Int32 m_nCols; // number of columns (user)
+ sal_Int32 m_nRows; // number of rows (user)
+ sal_Int32 m_nCol; // column for single print
+ sal_Int32 m_nRow; // row for single print
+ sal_Int32 m_lPHeight; // paper height
+ sal_Int32 m_lPWidth; // paper width
+ bool m_bAddr;// address as label?
+ bool m_bCont;// continuous paper?
+ bool m_bPage;// whole page or single labels?
+ bool m_bSynchron;// synchronise all labels
+
+ //parts of the business card
+ OUString m_aPrivFirstName;
+ OUString m_aPrivName;
+ OUString m_aPrivShortCut;
+ OUString m_aPrivFirstName2;
+ OUString m_aPrivName2;
+ OUString m_aPrivShortCut2;
+ OUString m_aPrivStreet;
+ OUString m_aPrivZip;
+ OUString m_aPrivCity;
+ OUString m_aPrivCountry;
+ OUString m_aPrivState;
+ OUString m_aPrivTitle;
+ OUString m_aPrivProfession;
+ OUString m_aPrivPhone;
+ OUString m_aPrivMobile;
+ OUString m_aPrivFax;
+ OUString m_aPrivWWW;
+ OUString m_aPrivMail;
+ OUString m_aCompCompany;
+ OUString m_aCompCompanyExt;
+ OUString m_aCompSlogan;
+ OUString m_aCompStreet;
+ OUString m_aCompZip;
+ OUString m_aCompCity;
+ OUString m_aCompCountry;
+ OUString m_aCompState;
+ OUString m_aCompPosition;
+ OUString m_aCompPhone;
+ OUString m_aCompMobile;
+ OUString m_aCompFax;
+ OUString m_aCompWWW;
+ OUString m_aCompMail;
+
+ OUString m_sGlossaryGroup;
+ OUString m_sGlossaryBlockName;
+};
+
+class SwLabCfgItem final : public utl::ConfigItem
+{
+private:
+ SwLabItem m_aItem;
+ bool m_bIsLabel;
+
+ css::uno::Sequence<OUString> GetPropertyNames() const;
+
+ virtual void ImplCommit() override;
+
+public:
+ SwLabCfgItem(bool bLabel);
+
+ SwLabItem& GetItem() {return m_aItem;}
+
+ virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/labimp.hxx b/sw/source/uibase/inc/labimp.hxx
new file mode 100644
index 0000000000..e8db8aab11
--- /dev/null
+++ b/sw/source/uibase/inc/labimp.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_LABIMP_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_LABIMP_HXX
+
+#include <vcl/weld.hxx>
+
+inline int getfldval(const weld::MetricSpinButton& rField)
+{
+ return rField.denormalize(rField.get_value(FieldUnit::TWIP));
+}
+
+inline void setfldval(weld::MetricSpinButton& rField, int lValue)
+{
+ rField.set_value(rField.normalize(lValue), FieldUnit::TWIP);
+}
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_LABIMP_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/labrec.hxx b/sw/source/uibase/inc/labrec.hxx
new file mode 100644
index 0000000000..feb7fdf65a
--- /dev/null
+++ b/sw/source/uibase/inc/labrec.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_LABREC_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_LABREC_HXX
+
+#include <rtl/ustring.hxx>
+#include <tools/long.hxx>
+
+#include <memory>
+#include <vector>
+
+
+class SwLabItem;
+
+class SwLabRec
+{
+public:
+ SwLabRec(): m_nHDist(0), m_nVDist(0), m_nWidth(0), m_nHeight(0), m_nLeft(0), m_nUpper(0), m_nPWidth(0), m_nPHeight(0), m_nCols(0), m_nRows(0), m_bCont(false) {}
+
+ void SetFromItem( const SwLabItem& rItem );
+ void FillItem( SwLabItem& rItem ) const;
+
+ OUString m_aMake;
+ OUString m_aType;
+ tools::Long m_nHDist;
+ tools::Long m_nVDist;
+ tools::Long m_nWidth;
+ tools::Long m_nHeight;
+ tools::Long m_nLeft;
+ tools::Long m_nUpper;
+ tools::Long m_nPWidth;
+ tools::Long m_nPHeight;
+ sal_Int32 m_nCols;
+ sal_Int32 m_nRows;
+ bool m_bCont;
+};
+
+typedef std::vector<std::unique_ptr<SwLabRec>> SwLabRecs;
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/langhelper.hxx b/sw/source/uibase/inc/langhelper.hxx
new file mode 100644
index 0000000000..e9e12f1d38
--- /dev/null
+++ b/sw/source/uibase/inc/langhelper.hxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_LANGHELPER_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_LANGHELPER_HXX
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+#include <i18nlangtag/lang.h>
+
+class SwWrtShell;
+class SwView;
+class EditEngine;
+class EditView;
+class OutlinerView;
+class SfxItemSet;
+class SfxRequest;
+struct ESelection;
+enum class SvtScriptType : sal_uInt8;
+
+namespace SwLangHelper
+{
+ extern void GetLanguageStatus( OutlinerView* pOLV, SfxItemSet& rSet );
+ extern bool SetLanguageStatus( OutlinerView* pOLV, SfxRequest &rReq, SwView const &rView, SwWrtShell &rSh );
+
+ extern void SetLanguage( SwWrtShell &rWrtSh, std::u16string_view rLangText, bool bIsForSelection, SfxItemSet &rCoreSet );
+ extern void SetLanguage( SwWrtShell &rWrtSh, OutlinerView const * pOLV, const ESelection& rSelection, std::u16string_view rLangText, bool bIsForSelection, SfxItemSet &rCoreSet );
+ extern void SetLanguage_None( SwWrtShell &rWrtSh, bool bIsForSelection, SfxItemSet &rCoreSet );
+ extern void SetLanguage_None( SwWrtShell &rWrtSh, OutlinerView const * pOLV, const ESelection& rSelection, bool bIsForSelection, SfxItemSet &rCoreSet );
+ extern void ResetLanguages( SwWrtShell &rWrtSh, OutlinerView const * pOLV = nullptr );
+
+ // document
+ extern void SelectCurrentPara( SwWrtShell &rWrtSh );
+ // EditView
+ extern void SelectPara( EditView &rEditView, const ESelection &rCurSel );
+
+ extern OUString GetTextForLanguageGuessing(EditEngine const * rEditEngine, const ESelection& rDocSelection);
+ extern OUString GetTextForLanguageGuessing(SwWrtShell const &rSh);
+
+ extern LanguageType GetLanguage( SfxItemSet const & aSet, TypedWhichId<SvxLanguageItem> nLangWhichId );
+ extern LanguageType GetLanguage( SwWrtShell &rSh, TypedWhichId<SvxLanguageItem> nLangWhichId );
+
+ extern LanguageType GetCurrentLanguage( SfxItemSet const & aSet, SvtScriptType nScriptType );
+ extern LanguageType GetCurrentLanguage( SwWrtShell &rSh );
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/linenum.hxx b/sw/source/uibase/inc/linenum.hxx
new file mode 100644
index 0000000000..eaed161296
--- /dev/null
+++ b/sw/source/uibase/inc/linenum.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_LINENUM_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_LINENUM_HXX
+
+#include <sfx2/basedlgs.hxx>
+#include "numberingtypelistbox.hxx"
+
+class SwView;
+class SwWrtShell;
+
+class SwLineNumberingDlg final : public SfxDialogController
+{
+private:
+ SwWrtShell* m_pSh;
+ std::unique_ptr<weld::Widget> m_xBodyContent;
+ std::unique_ptr<weld::Widget> m_xDivIntervalFT;
+ std::unique_ptr<weld::SpinButton> m_xDivIntervalNF;
+ std::unique_ptr<weld::Widget> m_xDivRowsFT;
+ std::unique_ptr<weld::SpinButton> m_xNumIntervalNF;
+ std::unique_ptr<weld::ComboBox> m_xCharStyleLB;
+ std::unique_ptr<SwNumberingTypeListBox> m_xFormatLB;
+ std::unique_ptr<weld::ComboBox> m_xPosLB;
+ std::unique_ptr<weld::MetricSpinButton> m_xOffsetMF;
+ std::unique_ptr<weld::Entry> m_xDivisorED;
+ std::unique_ptr<weld::CheckButton> m_xCountEmptyLinesCB;
+ std::unique_ptr<weld::CheckButton> m_xCountFrameLinesCB;
+ std::unique_ptr<weld::CheckButton> m_xRestartEachPageCB;
+ std::unique_ptr<weld::CheckButton> m_xNumberingOnCB;
+ std::unique_ptr<weld::CheckButton> m_xNumberingOnFooterHeader;
+ std::unique_ptr<weld::Button> m_xOKButton;
+ std::unique_ptr<weld::Widget> m_xNumIntervalFT;
+ std::unique_ptr<weld::Widget> m_xNumRowsFT;
+ DECL_LINK(OKHdl, weld::Button&, void);
+ DECL_LINK(LineOnOffHdl, weld::Toggleable&, void);
+ DECL_LINK(ModifyHdl, weld::Entry&, void);
+
+public:
+ SwLineNumberingDlg(const SwView& rVw);
+ virtual ~SwLineNumberingDlg() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/listsh.hxx b/sw/source/uibase/inc/listsh.hxx
new file mode 100644
index 0000000000..83bc9b321c
--- /dev/null
+++ b/sw/source/uibase/inc/listsh.hxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_LISTSH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_LISTSH_HXX
+
+#include "basesh.hxx"
+
+class SwListShell : public SwBaseShell
+{
+public:
+ SFX_DECL_INTERFACE(SW_LISTSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwListShell(SwView& rView);
+
+ void Execute(SfxRequest&);
+ void GetState(SfxItemSet&);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/macassgn.hxx b/sw/source/uibase/inc/macassgn.hxx
new file mode 100644
index 0000000000..4311e91075
--- /dev/null
+++ b/sw/source/uibase/inc/macassgn.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_MACASSGN_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_MACASSGN_HXX
+
+#include <sfx2/evntconf.hxx>
+#include <vcl/weld.hxx>
+#include <svl/macitem.hxx>
+#include <optional>
+
+class SwWrtShell;
+
+enum DlgEventType
+{
+ MACASSGN_AUTOTEXT,
+ MACASSGN_GRAPHIC,
+ MACASSGN_OLE,
+ MACASSGN_FRMURL,
+ MACASSGN_INETFMT,
+ MACASSGN_ALLFRM
+};
+
+class SwMacroAssignDlg
+{
+public:
+ static SfxEventNamesItem AddEvents(DlgEventType eType);
+ static bool INetFormatDlg(weld::Window* pParent, SwWrtShell& rSh,
+ std::optional<SvxMacroTableDtor>& rpINetItem);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/mailconfigpage.hxx b/sw/source/uibase/inc/mailconfigpage.hxx
new file mode 100644
index 0000000000..138739c2c4
--- /dev/null
+++ b/sw/source/uibase/inc/mailconfigpage.hxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_MAILCONFIGPAGE_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_MAILCONFIGPAGE_HXX
+
+#include <sfx2/tabdlg.hxx>
+#include <sfx2/basedlgs.hxx>
+
+class SwTestAccountSettingsDialog;
+class SwMailMergeConfigItem;
+
+class SwMailConfigPage final : public SfxTabPage
+{
+ friend class SwTestAccountSettingsDialog;
+
+ std::unique_ptr<SwMailMergeConfigItem> m_pConfigItem;
+
+ std::unique_ptr<weld::Entry> m_xDisplayNameED;
+ std::unique_ptr<weld::Widget> m_xDisplayNameImg;
+ std::unique_ptr<weld::Entry> m_xAddressED;
+ std::unique_ptr<weld::Widget> m_xAddressImg;
+ std::unique_ptr<weld::CheckButton> m_xReplyToCB;
+ std::unique_ptr<weld::Widget> m_xReplyToCBImg;
+ std::unique_ptr<weld::Label> m_xReplyToFT;
+ std::unique_ptr<weld::Entry> m_xReplyToED;
+ std::unique_ptr<weld::Widget> m_xReplyToImg;
+ std::unique_ptr<weld::Entry> m_xServerED;
+ std::unique_ptr<weld::Widget> m_xServerImg;
+ std::unique_ptr<weld::SpinButton> m_xPortNF;
+ std::unique_ptr<weld::Widget> m_xPortImg;
+ std::unique_ptr<weld::CheckButton> m_xSecureCB;
+ std::unique_ptr<weld::Widget> m_xSecureImg;
+ std::unique_ptr<weld::Button> m_xServerAuthenticationPB;
+ std::unique_ptr<weld::Button> m_xTestPB;
+
+ DECL_LINK(ReplyToHdl, weld::Toggleable&, void);
+ DECL_LINK(AuthenticationHdl, weld::Button&, void);
+ DECL_LINK(TestHdl, weld::Button&, void);
+ DECL_LINK(SecureHdl, weld::Toggleable&, void);
+
+public:
+ SwMailConfigPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~SwMailConfigPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet);
+
+ virtual OUString GetAllStrings() override;
+
+ virtual bool FillItemSet( SfxItemSet* rSet ) override;
+ virtual void Reset( const SfxItemSet* rSet ) override;
+};
+
+class SwMailConfigDlg final : public SfxSingleTabDialogController
+{
+public:
+ SwMailConfigDlg(weld::Window* pParent, const SfxItemSet& rSet);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/maildispatcher.hxx b/sw/source/uibase/inc/maildispatcher.hxx
new file mode 100644
index 0000000000..e0cdd3a751
--- /dev/null
+++ b/sw/source/uibase/inc/maildispatcher.hxx
@@ -0,0 +1,156 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_MAILDISPATCHER_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_MAILDISPATCHER_HXX
+
+#include <com/sun/star/mail/XSmtpService.hpp>
+#include <com/sun/star/mail/XMailMessage.hpp>
+#include <osl/thread.hxx>
+#include <osl/conditn.hxx>
+#include <rtl/ref.hxx>
+#include <salhelper/simplereferenceobject.hxx>
+
+#include <list>
+#include <vector>
+
+#include <swdllapi.h>
+
+class IMailDispatcherListener;
+
+/**
+ A MailDispatcher should be used for sending a bunch a mail messages
+ asynchronously. Usually a client enqueues a number of mail messages
+ and then calls start to begin sending them. An instance of this class
+ must not be shared among different client threads. Instead each client
+ thread should create an own instance of this class.
+*/
+class SW_DLLPUBLIC MailDispatcher final : public salhelper::SimpleReferenceObject,
+ private ::osl::Thread
+{
+public:
+ // bringing operator new/delete into scope
+ using osl::Thread::operator new;
+ using osl::Thread::operator delete;
+ using osl::Thread::join;
+
+ /**
+ @param xSmtpService
+ [in] a reference to a mail server. A user must be
+ connected to the mail server otherwise errors occur
+ during the delivery of mail messages.
+
+ @throws css::uno::RuntimeException
+ on errors during construction of an instance of this class.
+ */
+ MailDispatcher(css::uno::Reference<css::mail::XSmtpService> xMailService);
+
+ /**
+ Shutdown the mail dispatcher. Every mail messages
+ not yet sent will be discarded.
+ */
+ virtual ~MailDispatcher() override;
+
+ /**
+ Enqueue a mail message for delivery. A client must
+ start the mail dispatcher in order to send the
+ enqueued mail messages.
+
+ @param xMailMessage
+ [in] a mail message that should be send.
+ */
+ void enqueueMailMessage(css::uno::Reference<css::mail::XMailMessage> const& xMailMessage);
+ /**
+ Dequeues a mail message.
+ This enables the caller to remove attachments when sending mails is to be cancelled.
+ */
+ css::uno::Reference<css::mail::XMailMessage> dequeueMailMessage();
+
+ /**
+ Start sending mail messages asynchronously. A client may register
+ a listener for mail dispatcher events. For every mail message sent
+ the notification will be sent. While handling such notification a
+ client may enqueue new mail messages. If there are no more mail
+ messages to send a respective notification is sent and the mail
+ dispatcher waits for more mail messages.
+
+ @precond not isStarted()
+ */
+ void start();
+
+ /**
+ Stop sending mail messages.
+
+ @precond isStarted()
+ */
+ void stop();
+
+ /**
+ Request shutdown of the mail dispatcher thread.
+ NOTE: You must call this method before you release
+ your last reference to this class otherwise the
+ mail dispatcher thread will never end.
+ */
+ void shutdown();
+
+ /**
+ Check whether the mail dispatcher is started or not.
+
+ @return
+ <TRUE/> if the sending thread is running.
+ */
+ bool isStarted() const { return m_bActive; }
+
+ /** returns if the thread is still running
+ */
+ using osl::Thread::isRunning;
+
+ /**
+ * returns if shutdown has already been called
+ */
+ bool isShutdownRequested() const { return m_bShutdownRequested; }
+
+ /**
+ * Register a listener for mail dispatcher events
+ */
+ void addListener(::rtl::Reference<IMailDispatcherListener> const& listener);
+
+private:
+ virtual void SAL_CALL run() override;
+ virtual void SAL_CALL onTerminated() override;
+
+ std::vector<::rtl::Reference<IMailDispatcherListener>> cloneListener();
+ void sendMailMessageNotifyListener(css::uno::Reference<css::mail::XMailMessage> const& message);
+
+ css::uno::Reference<css::mail::XSmtpService> m_xMailserver;
+ std::list<css::uno::Reference<css::mail::XMailMessage>> m_aXMessageList;
+ std::vector<::rtl::Reference<IMailDispatcherListener>> m_aListenerVector;
+ ::osl::Mutex m_aMessageContainerMutex;
+ ::osl::Mutex m_aListenerContainerMutex;
+ ::osl::Mutex m_aThreadStatusMutex;
+ ::osl::Condition m_aRunCondition;
+ ::osl::Condition m_aWakeupCondition;
+ ::rtl::Reference<MailDispatcher> m_xSelfReference;
+ bool m_bActive;
+ bool m_bShutdownRequested;
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_MAILDISPATCHER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/mailmergehelper.hxx b/sw/source/uibase/inc/mailmergehelper.hxx
new file mode 100644
index 0000000000..2497c8833e
--- /dev/null
+++ b/sw/source/uibase/inc/mailmergehelper.hxx
@@ -0,0 +1,273 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_MAILMERGEHELPER_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_MAILMERGEHELPER_HXX
+
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/mail/XAuthenticator.hpp>
+#include <com/sun/star/mail/XConnectionListener.hpp>
+#include <com/sun/star/uno/XCurrentContext.hpp>
+#include <com/sun/star/mail/XMailMessage.hpp>
+#include <com/sun/star/datatransfer/XTransferable.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/compbase.hxx>
+#include <utility>
+#include <vcl/customweld.hxx>
+#include <vcl/weld.hxx>
+#include <rtl/ustring.hxx>
+#include <swdllapi.h>
+
+class SwMailMergeConfigItem;
+
+namespace com::sun::star::mail {
+ class XMailService;
+ class XSmtpService;
+}
+
+namespace SwMailMergeHelper
+{
+ SW_DLLPUBLIC OUString CallSaveAsDialog(weld::Window* pParent, OUString& rFilter);
+ SW_DLLPUBLIC bool CheckMailAddress(std::u16string_view aMailAddress);
+ SW_DLLPUBLIC css::uno::Reference<css::mail::XSmtpService> ConnectToSmtpServer(
+ SwMailMergeConfigItem const & rConfigItem,
+ css::uno::Reference<css::mail::XMailService>& xInMailService,
+ const OUString& rInMailServerPassword,
+ const OUString& rOutMailServerPassword,
+ weld::Window* pDialogParentWindow = nullptr);
+}
+
+struct SwAddressPreview_Impl;
+
+// Preview window used to show the possible selection of address blocks
+// and also the resulting address filled with database data
+class SW_DLLPUBLIC SwAddressPreview final : public weld::CustomWidgetController
+{
+ std::unique_ptr<SwAddressPreview_Impl> m_pImpl;
+ std::unique_ptr<weld::ScrolledWindow> m_xVScrollBar;
+ Link<LinkParamNone*,void> m_aSelectHdl;
+
+ void DrawText_Impl(vcl::RenderContext& rRenderContext, std::u16string_view rAddress,
+ const Point& rTopLeft, const Size& rSize, bool bIsSelected);
+
+ virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) override;
+ virtual bool MouseButtonDown( const MouseEvent& rMEvt ) override;
+ virtual bool KeyInput( const KeyEvent& rKEvt ) override;
+ void UpdateScrollBar();
+
+ DECL_DLLPRIVATE_LINK(ScrollHdl, weld::ScrolledWindow&,void);
+
+public:
+ SwAddressPreview(std::unique_ptr<weld::ScrolledWindow> xParent);
+ virtual ~SwAddressPreview() override;
+
+ /** The address string is a list of address elements separated by spaces
+ and breaks. The addresses fit into the given layout. If more addresses then
+ rows/columns should be used a scrollbar will be added.
+
+ AddAddress appends the new address to the already added ones.
+ Initially the first added address will be selected
+ */
+ void AddAddress(const OUString& rAddress);
+ // for preview mode - replaces the currently used address by the given one
+ void SetAddress(const OUString& rAddress);
+ // removes all addresses
+ void Clear();
+
+ // returns the selected address
+ sal_uInt16 GetSelectedAddress() const;
+ void SelectAddress(sal_uInt16 nSelect);
+ void ReplaceSelectedAddress(const OUString&);
+ void RemoveSelectedAddress();
+
+ // set the number of rows and columns of addresses
+ void SetLayout(sal_uInt16 nRows, sal_uInt16 nColumns);
+ void EnableScrollBar();
+
+ // fill the actual data into a string (address block or greeting)
+ static OUString FillData(const OUString& rAddress, SwMailMergeConfigItem const & rConfigItem,
+ const css::uno::Sequence<OUString>* pAssignments = nullptr);
+
+ void SetSelectHdl (const Link<LinkParamNone*,void>& rLink) { m_aSelectHdl = rLink; }
+};
+
+
+// iterate over an address block or a greeting line the iterator returns the
+// parts either as pure string or as column
+struct SwMergeAddressItem
+{
+ OUString sText;
+ bool bIsColumn;
+ bool bIsReturn;
+
+ SwMergeAddressItem()
+ : bIsColumn(false)
+ , bIsReturn(false)
+ {}
+};
+
+class SW_DLLPUBLIC SwAddressIterator
+{
+ OUString m_sAddress;
+public:
+ SwAddressIterator(OUString aAddress) :
+ m_sAddress(std::move(aAddress))
+ {}
+
+ SwMergeAddressItem Next();
+ bool HasMore() const { return !m_sAddress.isEmpty(); }
+};
+
+class SW_DLLPUBLIC SwAuthenticator final :
+ public cppu::WeakImplHelper<css::mail::XAuthenticator>
+{
+ OUString m_aUserName;
+ OUString m_aPassword;
+ weld::Window* m_pParentWindow;
+public:
+ SwAuthenticator()
+ : m_pParentWindow(nullptr)
+ {}
+ SwAuthenticator(OUString username, OUString password, weld::Window* pParent)
+ : m_aUserName(std::move(username))
+ , m_aPassword(std::move(password))
+ , m_pParentWindow(pParent)
+ {}
+ virtual ~SwAuthenticator() override;
+
+ virtual OUString SAL_CALL getUserName() override;
+ virtual OUString SAL_CALL getPassword() override;
+
+};
+
+class SW_DLLPUBLIC SwConnectionContext final : public cppu::WeakImplHelper<css::uno::XCurrentContext>
+{
+ OUString m_sMailServer;
+ sal_Int16 m_nPort;
+ OUString m_sConnectionType;
+
+public:
+ SwConnectionContext(OUString aMailServer, sal_Int16 nPort, OUString aConnectionType);
+ virtual ~SwConnectionContext() override;
+
+ virtual css::uno::Any SAL_CALL getValueByName(const OUString& Name) override;
+};
+
+class SW_DLLPUBLIC SwConnectionListener final :
+ public comphelper::WeakComponentImplHelper<css::mail::XConnectionListener>
+{
+ using comphelper::WeakComponentImplHelperBase::disposing;
+
+public:
+ virtual ~SwConnectionListener() override;
+
+ virtual void SAL_CALL connected(const css::lang::EventObject& aEvent) override;
+
+ virtual void SAL_CALL disconnected(const css::lang::EventObject& aEvent) override;
+
+ virtual void SAL_CALL disposing(const css::lang::EventObject& aEvent) override;
+};
+
+class SW_DLLPUBLIC SwMailTransferable final :
+ public comphelper::WeakComponentImplHelper<css::datatransfer::XTransferable, css::beans::XPropertySet>
+{
+ OUString m_aMimeType;
+ OUString m_sBody;
+ OUString m_aURL;
+ OUString m_aName;
+ bool m_bIsBody;
+
+ public:
+ SwMailTransferable(OUString aURL, OUString aName, OUString aMimeType);
+ SwMailTransferable(OUString aBody, OUString aMimeType);
+ virtual ~SwMailTransferable() override;
+ virtual css::uno::Any SAL_CALL getTransferData(const css::datatransfer::DataFlavor& aFlavor) override;
+
+ virtual css::uno::Sequence<css::datatransfer::DataFlavor> SAL_CALL getTransferDataFlavors() override;
+ virtual sal_Bool SAL_CALL isDataFlavorSupported(const css::datatransfer::DataFlavor& aFlavor) override;
+
+ //XPropertySet
+ virtual css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual void SAL_CALL setPropertyValue(const OUString& aPropertyName, const css::uno::Any& aValue) override;
+
+ virtual css::uno::Any SAL_CALL getPropertyValue(const OUString& PropertyName) override;
+ virtual void SAL_CALL addPropertyChangeListener(const OUString& aPropertyName,
+ const css::uno::Reference<css::beans::XPropertyChangeListener>& xListener) override;
+ virtual void SAL_CALL removePropertyChangeListener(const OUString& aPropertyName,
+ const css::uno::Reference<css::beans::XPropertyChangeListener >& aListener) override;
+ virtual void SAL_CALL addVetoableChangeListener(const OUString& PropertyName,
+ const css::uno::Reference<css::beans::XVetoableChangeListener>& aListener) override;
+ virtual void SAL_CALL removeVetoableChangeListener(const OUString& PropertyName,
+ const css::uno::Reference<css::beans::XVetoableChangeListener>& aListener) override;
+
+};
+
+class SW_DLLPUBLIC SwMailMessage final :
+ public comphelper::WeakComponentImplHelper<css::mail::XMailMessage>
+{
+ OUString m_sSenderName;
+ OUString m_sSenderAddress;
+ OUString m_sReplyToAddress;
+ OUString m_sSubject;
+
+ css::uno::Reference<css::datatransfer::XTransferable> m_xBody;
+// css::mail::MailMessageBody m_aBody;
+
+ css::uno::Sequence<OUString> m_aRecipients;
+ css::uno::Sequence<OUString> m_aCcRecipients;
+ css::uno::Sequence<OUString> m_aBccRecipients;
+// css::uno::Sequence<css::mail::MailAttachmentDescriptor> m_aAttachments;
+ css::uno::Sequence<css::mail::MailAttachment> m_aAttachments;
+public:
+ SwMailMessage();
+ virtual ~SwMailMessage() override;
+
+ // attributes
+ virtual OUString SAL_CALL getSenderName() override;
+ virtual OUString SAL_CALL getSenderAddress() override;
+ virtual OUString SAL_CALL getReplyToAddress() override;
+ virtual void SAL_CALL setReplyToAddress( const OUString& _replytoaddress ) override;
+ virtual OUString SAL_CALL getSubject() override;
+ virtual void SAL_CALL setSubject(const OUString& _subject) override;
+
+ virtual css::uno::Reference<css::datatransfer::XTransferable> SAL_CALL getBody() override;
+ virtual void SAL_CALL setBody(const css::uno::Reference<css::datatransfer::XTransferable>& _body) override;
+
+ // methods
+ virtual void SAL_CALL addRecipient( const OUString& sRecipientAddress ) override;
+ virtual void SAL_CALL addCcRecipient( const OUString& sRecipientAddress ) override;
+ virtual void SAL_CALL addBccRecipient( const OUString& sRecipientAddress ) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getRecipients() override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getCcRecipients() override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getBccRecipients() override;
+ virtual void SAL_CALL addAttachment(const css::mail::MailAttachment& aMailAttachment) override;
+ virtual css::uno::Sequence<css::mail::MailAttachment> SAL_CALL getAttachments() override;
+ void SetSenderName(const OUString& rSenderName)
+ {
+ m_sSenderName = rSenderName;
+ }
+ void SetSenderAddress(const OUString& rSenderAddress)
+ {
+ m_sSenderAddress = rSenderAddress;
+ }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/mailmergewizard.hxx b/sw/source/uibase/inc/mailmergewizard.hxx
new file mode 100644
index 0000000000..f011718f64
--- /dev/null
+++ b/sw/source/uibase/inc/mailmergewizard.hxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_MAILMERGEWIZARD_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_MAILMERGEWIZARD_HXX
+
+#include <vcl/roadmapwizard.hxx>
+#include <rtl/ustring.hxx>
+
+class SwView;
+class SwMailMergeConfigItem;
+
+using vcl::WizardTypes::WizardState;
+
+#define MM_DOCUMENTSELECTPAGE 0
+#define MM_OUTPUTTYPETPAGE 1
+#define MM_ADDRESSBLOCKPAGE 2
+#define MM_GREETINGSPAGE 3
+#define MM_LAYOUTPAGE 4
+
+class SwMailMergeWizard final : public ::vcl::RoadmapWizardMachine
+{
+ SwView* m_pSwView;
+ OUString m_sDocumentURL;
+ bool m_bDocumentLoad;
+
+ std::shared_ptr<SwMailMergeConfigItem> m_xConfigItem;
+
+ OUString m_sStarting;
+ OUString m_sDocumentType;
+ OUString m_sAddressBlock;
+ OUString m_sAddressList;
+ OUString m_sGreetingsLine;
+ OUString m_sLayout;
+
+ sal_uInt16 m_nRestartPage;
+
+ using vcl::WizardMachine::skipUntil;
+
+ virtual std::unique_ptr<BuilderPage> createPage( WizardState _nState ) override;
+ virtual void enterState( WizardState _nState ) override;
+
+ virtual OUString getStateDisplayName( WizardState _nState ) const override;
+
+public:
+ SwMailMergeWizard(SwView& rView, std::shared_ptr<SwMailMergeConfigItem> xConfigItem);
+ virtual ~SwMailMergeWizard() override;
+
+ SwView* GetSwView() {return m_pSwView;}
+ SwMailMergeConfigItem& GetConfigItem() { return *m_xConfigItem;}
+
+ void SetReloadDocument(const OUString& rURL) {m_sDocumentURL = rURL;}
+ const OUString& GetReloadDocument() const {return m_sDocumentURL;}
+
+ //next step requires loading of document
+ void SetDocumentLoad(bool bSet) {m_bDocumentLoad = bSet;}
+
+ void UpdateRoadmap();
+
+ sal_uInt16 GetRestartPage() const {return m_nRestartPage;}
+ void SetRestartPage(sal_uInt16 nPage) { m_nRestartPage = nPage;}
+
+ bool skipUntil( sal_uInt16 nPage)
+ {return ::vcl::RoadmapWizardMachine::skipUntil(WizardState(nPage));}
+
+ virtual short run() override;
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/mailmrge.hxx b/sw/source/uibase/inc/mailmrge.hxx
new file mode 100644
index 0000000000..7875617853
--- /dev/null
+++ b/sw/source/uibase/inc/mailmrge.hxx
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_MAILMRGE_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_MAILMRGE_HXX
+
+#include <memory>
+#include <sfx2/basedlgs.hxx>
+
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/uno/Reference.h>
+
+#include <dbmgr.hxx>
+
+class SwWrtShell;
+class SwModuleOptions;
+class SwXSelChgLstnr_Impl;
+struct SwMailMergeDlg_Impl;
+namespace com::sun::star{
+ namespace frame{
+ class XFrame2;
+ }
+ namespace sdbc{
+ class XResultSet;
+ class XConnection;
+ }
+}
+
+class SwMailMergeDlg final : public SfxDialogController
+{
+ friend class SwXSelChgLstnr_Impl;
+
+ std::unique_ptr<SwMailMergeDlg_Impl> m_pImpl;
+
+ SwWrtShell& m_rSh;
+ SwModuleOptions* m_pModOpt;
+
+ DBManagerOptions m_nMergeType;
+ css::uno::Sequence< css::uno::Any > m_aSelection;
+ css::uno::Reference< css::frame::XFrame2 > m_xFrame;
+
+ OUString m_sSaveFilter;
+ OUString m_sFilename;
+
+ std::unique_ptr<weld::Container> m_xBeamerWin;
+
+ std::unique_ptr<weld::RadioButton> m_xAllRB;
+ std::unique_ptr<weld::RadioButton> m_xMarkedRB;
+ std::unique_ptr<weld::RadioButton> m_xFromRB;
+ std::unique_ptr<weld::SpinButton> m_xFromNF;
+ std::unique_ptr<weld::SpinButton> m_xToNF;
+
+ std::unique_ptr<weld::RadioButton> m_xPrinterRB;
+ std::unique_ptr<weld::RadioButton> m_xMailingRB;
+ std::unique_ptr<weld::RadioButton> m_xFileRB;
+
+ std::unique_ptr<weld::CheckButton> m_xSingleJobsCB;
+ std::unique_ptr<weld::CheckButton> m_xPasswordCB;
+
+ std::unique_ptr<weld::Label> m_xSaveMergedDocumentFT;
+ std::unique_ptr<weld::RadioButton> m_xSaveSingleDocRB;
+ std::unique_ptr<weld::RadioButton> m_xSaveIndividualRB;
+
+ std::unique_ptr<weld::CheckButton> m_xGenerateFromDataBaseCB;
+
+ std::unique_ptr<weld::Label> m_xColumnFT;
+ std::unique_ptr<weld::ComboBox> m_xColumnLB;
+ std::unique_ptr<weld::Label> m_xPasswordFT;
+ std::unique_ptr<weld::ComboBox> m_xPasswordLB;
+ std::unique_ptr<weld::Label> m_xPathFT;
+ std::unique_ptr<weld::Entry> m_xPathED;
+ std::unique_ptr<weld::Button> m_xPathPB;
+ std::unique_ptr<weld::Label> m_xFilterFT;
+ std::unique_ptr<weld::ComboBox> m_xFilterLB;
+
+ std::unique_ptr<weld::ComboBox> m_xAddressFieldLB;
+ std::unique_ptr<weld::Label> m_xSubjectFT;
+ std::unique_ptr<weld::Entry> m_xSubjectED;
+ std::unique_ptr<weld::Label> m_xFormatFT;
+ std::unique_ptr<weld::Label> m_xAttachFT;
+ std::unique_ptr<weld::Entry> m_xAttachED;
+ std::unique_ptr<weld::Button> m_xAttachPB;
+ std::unique_ptr<weld::CheckButton> m_xFormatHtmlCB;
+ std::unique_ptr<weld::CheckButton> m_xFormatRtfCB;
+ std::unique_ptr<weld::CheckButton> m_xFormatSwCB;
+
+ std::unique_ptr<weld::Button> m_xOkBTN;
+
+ DECL_LINK( ButtonHdl, weld::Button&, void );
+ DECL_LINK( InsertPathHdl, weld::Button&, void );
+ DECL_LINK( OutputTypeHdl, weld::Toggleable&, void );
+ DECL_LINK( FilenameHdl, weld::Toggleable&, void );
+ DECL_LINK( ModifyHdl, weld::SpinButton&, void );
+ DECL_LINK( SaveTypeHdl, weld::Toggleable&, void );
+ DECL_LINK( FileFormatHdl, weld::ComboBox&, void );
+
+ bool ExecQryShell();
+ bool AskUserFilename() const;
+ OUString GetURLfromPath() const;
+
+public:
+ SwMailMergeDlg(weld::Window* pParent, SwWrtShell& rSh,
+ const OUString& rSourceName,
+ const OUString& rTableName,
+ sal_Int32 nCommandType,
+ const css::uno::Reference< css::sdbc::XConnection>& xConnection,
+ css::uno::Sequence< css::uno::Any > const * pSelection);
+ virtual ~SwMailMergeDlg() override;
+
+ DBManagerOptions GetMergeType() const { return m_nMergeType; }
+
+ bool IsSaveSingleDoc() const { return m_xSaveSingleDocRB->get_active(); }
+ bool IsGenerateFromDataBase() const { return m_xGenerateFromDataBaseCB->get_active(); }
+ bool IsFileEncryptedFromDataBase() const { return m_xPasswordCB->get_active(); }
+ OUString GetColumnName() const { return m_xColumnLB->get_active_text(); }
+ OUString GetPasswordColumnName() const { return m_xPasswordLB->get_active_text(); }
+ OUString GetTargetURL() const;
+
+ const OUString& GetSaveFilter() const {return m_sSaveFilter;}
+ const css::uno::Sequence< css::uno::Any >& GetSelection() const { return m_aSelection; }
+ css::uno::Reference< css::sdbc::XResultSet> GetResultSet() const;
+
+};
+
+class SwMailMergeCreateFromDlg final : public weld::GenericDialogController
+{
+ std::unique_ptr<weld::RadioButton> m_xThisDocRB;
+public:
+ SwMailMergeCreateFromDlg(weld::Window* pParent);
+ virtual ~SwMailMergeCreateFromDlg() override;
+ bool IsThisDocument() const
+ {
+ return m_xThisDocRB->get_active();
+ }
+};
+
+class SwMailMergeFieldConnectionsDlg final : public weld::GenericDialogController
+{
+ std::unique_ptr<weld::RadioButton> m_xUseExistingRB;
+public:
+ SwMailMergeFieldConnectionsDlg(weld::Window* pParent);
+ virtual ~SwMailMergeFieldConnectionsDlg() override;
+
+ bool IsUseExistingConnections() const
+ {
+ return m_xUseExistingRB->get_active();
+ }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/mediash.hxx b/sw/source/uibase/inc/mediash.hxx
new file mode 100644
index 0000000000..da13c88b53
--- /dev/null
+++ b/sw/source/uibase/inc/mediash.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_MEDIASH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_MEDIASH_HXX
+
+#include <sfx2/module.hxx>
+#include <sfx2/shell.hxx>
+
+#include "basesh.hxx"
+#include <shellid.hxx>
+
+class SwMediaShell final : public SwBaseShell
+{
+public:
+ SFX_DECL_INTERFACE(SW_MEDIASHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ void ExecMedia(SfxRequest const&);
+ void GetMediaState(SfxItemSet&);
+
+ SwMediaShell(SwView& rView);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/mergetbl.hxx b/sw/source/uibase/inc/mergetbl.hxx
new file mode 100644
index 0000000000..5b4ef970ef
--- /dev/null
+++ b/sw/source/uibase/inc/mergetbl.hxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_MERGETBL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_MERGETBL_HXX
+
+#include <vcl/weld.hxx>
+
+class SwMergeTableDlg final : public weld::GenericDialogController
+{
+ bool& m_rMergePrev;
+
+ std::unique_ptr<weld::RadioButton> m_xMergePrevRB;
+
+private:
+ void Apply();
+
+public:
+ SwMergeTableDlg(weld::Window* pParent, bool& rWithPrev);
+ virtual short run() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/mmconfigitem.hxx b/sw/source/uibase/inc/mmconfigitem.hxx
new file mode 100644
index 0000000000..d1296dfe46
--- /dev/null
+++ b/sw/source/uibase/inc/mmconfigitem.hxx
@@ -0,0 +1,259 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_MMCONFIGITEM_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_MMCONFIGITEM_HXX
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/view/XSelectionChangeListener.hpp>
+#include <memory>
+#include <set>
+#include <vector>
+#include <swdbdata.hxx>
+#include <swdllapi.h>
+#include "sharedconnection.hxx"
+
+namespace com::sun::star{
+ namespace sdbc{
+ class XDataSource;
+ class XResultSet;
+ }
+ namespace sdbcx{
+ class XColumnsSupplier;
+ }
+}
+
+class SwMailMergeConfigItem_Impl;
+class SwView;
+namespace sw::mark { class IMark; }
+
+struct SwDocMergeInfo
+{
+ sw::mark::IMark* startPageInTarget;
+ sal_Int32 nDBRow;
+};
+
+class SW_DLLPUBLIC SwMailMergeConfigItem
+{
+ std::unique_ptr<SwMailMergeConfigItem_Impl> m_pImpl;
+ //session information - not stored in configuration
+ bool m_bAddressInserted;
+ bool m_bGreetingInserted;
+ sal_Int32 m_nGreetingMoves;
+ sal_uInt32 m_nBegin;
+ sal_uInt32 m_nEnd;
+ std::set<sal_Int32> m_aExcludedRecords;
+ css::uno::Reference<css::view::XSelectionChangeListener> m_xDBChangedListener;
+
+ OUString m_sSelectedPrinter;
+
+ SwView* m_pSourceView;
+ SwView* m_pTargetView;
+public:
+ SwMailMergeConfigItem();
+ ~SwMailMergeConfigItem();
+
+ enum Gender
+ {
+ FEMALE,
+ MALE,
+ NEUTRAL
+ };
+
+ void Commit();
+
+ const std::vector<std::pair<OUString, int>>& GetDefaultAddressHeaders() const;
+
+ void SetCurrentConnection(
+ css::uno::Reference< css::sdbc::XDataSource> const & xSource,
+ const SharedConnection& rConnection,
+ css::uno::Reference< css::sdbcx::XColumnsSupplier> const & xColumnsSupplier,
+ const SwDBData& rDBData);
+
+ css::uno::Reference< css::sdbc::XDataSource> const & GetSource() const;
+
+ SharedConnection const & GetConnection() const;
+
+ css::uno::Reference< css::sdbcx::XColumnsSupplier> const & GetColumnsSupplier();
+
+ css::uno::Reference< css::sdbc::XResultSet> const & GetResultSet() const;
+
+ void DisposeResultSet();
+
+ OUString& GetFilter() const;
+ void SetFilter(OUString const &);
+
+ void SetCurrentDBData( const SwDBData& rDBData);
+ const SwDBData& GetCurrentDBData() const;
+
+ // move absolute, nTarget == -1 -> goto last record
+ sal_Int32 MoveResultSet(sal_Int32 nTarget);
+ sal_Int32 GetResultSetPosition()const;
+ bool IsResultSetFirstLast(bool& bIsFirst, bool& bIsLast);
+
+ bool IsRecordIncluded(sal_uInt32 nRecord) const;
+ bool IsRecordExcluded(sal_uInt32 nRecord) const;
+ void ExcludeRecord(sal_Int32 nRecord, bool bExclude);
+ css::uno::Sequence< css::uno::Any> GetSelection() const;
+
+ const css::uno::Sequence<OUString>& GetSavedDocuments() const;
+
+ bool IsOutputToLetter()const;
+ void SetOutputToLetter(bool bSet);
+
+ bool IsAddressBlock()const;
+ void SetAddressBlock(bool bSet);
+
+ bool IsHideEmptyParagraphs() const;
+ void SetHideEmptyParagraphs(bool bSet);
+
+ css::uno::Sequence<OUString> GetAddressBlocks() const;
+ void SetAddressBlocks(const css::uno::Sequence< OUString>& rBlocks);
+
+ void SetCurrentAddressBlockIndex( sal_Int32 nSet );
+ sal_Int32 GetCurrentAddressBlockIndex() const;
+
+ bool IsIncludeCountry() const;
+ OUString& GetExcludeCountry() const;
+ void SetCountrySettings(bool bSet, const OUString& sCountry);
+
+ bool IsIndividualGreeting(bool bInEMail) const;
+ void SetIndividualGreeting(bool bSet, bool bInEMail);
+
+ bool IsGreetingLine(bool bInEMail) const;
+ void SetGreetingLine(bool bSet, bool bInEMail);
+
+ css::uno::Sequence<OUString> GetGreetings(Gender eType) const;
+ void SetGreetings(Gender eType, const css::uno::Sequence< OUString>& rBlocks);
+
+ sal_Int32 GetCurrentGreeting(Gender eType) const;
+ void SetCurrentGreeting(Gender eType, sal_Int32 nIndex);
+
+ //the content of the gender column that marks it as female
+ const OUString& GetFemaleGenderValue() const;
+ void SetFemaleGenderValue(const OUString& rValue);
+
+ //returns the assignment in the order of the default headers (GetDefaultAddressHeaders())
+ css::uno::Sequence<OUString> GetColumnAssignment( const SwDBData& rDBData ) const;
+ void SetColumnAssignment(
+ const SwDBData& rDBData,
+ const css::uno::Sequence< OUString>& );
+
+ bool IsAddressFieldsAssigned() const;
+ bool IsGreetingFieldsAssigned() const;
+
+ //e-Mail settings:
+ OUString const & GetMailDisplayName() const;
+ void SetMailDisplayName(const OUString& rName);
+
+ OUString const & GetMailAddress() const;
+ void SetMailAddress(const OUString& rAddress);
+
+ bool IsMailReplyTo() const;
+ void SetMailReplyTo(bool bSet);
+
+ OUString const & GetMailReplyTo() const;
+ void SetMailReplyTo(const OUString& rReplyTo);
+
+ OUString const & GetMailServer() const;
+ void SetMailServer(const OUString& rAddress);
+
+ sal_Int16 GetMailPort() const;
+ void SetMailPort(sal_Int16 nSet);
+
+ bool IsSecureConnection() const;
+ void SetSecureConnection(bool bSet);
+
+ bool IsAuthentication() const;
+ void SetAuthentication(bool bSet);
+
+ OUString const & GetMailUserName() const;
+ void SetMailUserName(const OUString& rName);
+
+ OUString const & GetMailPassword() const;
+ void SetMailPassword(const OUString& rPassword);
+
+ bool IsSMTPAfterPOP() const;
+ void SetSMTPAfterPOP(bool bSet);
+
+ OUString const & GetInServerName() const;
+ void SetInServerName(const OUString& rServer);
+
+ sal_Int16 GetInServerPort() const;
+ void SetInServerPort(sal_Int16 nSet);
+
+ bool IsInServerPOP() const;
+ void SetInServerPOP(bool bSet);
+
+ OUString const & GetInServerUserName() const;
+ void SetInServerUserName(const OUString& rName);
+
+ OUString const & GetInServerPassword() const;
+ void SetInServerPassword(const OUString& rPassword);
+
+ //session information
+ bool IsAddressInserted() const { return m_bAddressInserted; }
+ void SetAddressInserted()
+ {
+ m_bAddressInserted = true;
+ }
+
+ bool IsGreetingInserted() const
+ { return m_bGreetingInserted; }
+ void SetGreetingInserted()
+ { m_bGreetingInserted = true; }
+
+ void SetBeginEnd(sal_uInt32 nBegin, sal_uInt32 nEnd)
+ { m_nBegin = nBegin; m_nEnd = nEnd; }
+
+ // counts the moves in the layout page
+ void MoveGreeting( sal_Int32 nMove) { m_nGreetingMoves += nMove;}
+ sal_Int32 GetGreetingMoves() const { return m_nGreetingMoves;}
+
+ // new source document - reset some flags
+ void DocumentReloaded();
+
+ bool IsMailAvailable() const;
+
+ // notify a completed merge, provide the appropriate e-Mail address if available
+ void AddMergedDocument(SwDocMergeInfo const & rInfo);
+ //returns the page and database cursor information of each merged document
+ SwDocMergeInfo& GetDocumentMergeInfo(sal_uInt32 nDocument);
+ sal_uInt32 GetMergedDocumentCount();
+
+ const OUString& GetSelectedPrinter() const
+ { return m_sSelectedPrinter; }
+ void SetSelectedPrinter(const OUString& rSet)
+ { m_sSelectedPrinter = rSet; }
+
+ SwView* GetTargetView();
+ void SetTargetView(SwView* pView);
+
+ SwView* GetSourceView();
+ void SetSourceView(SwView* pView);
+
+ //helper methods
+ OUString GetAssignedColumn(sal_uInt32 nColumn) const;
+ void stopDBChangeListening();
+ void updateCurrentDBDataFromDocument();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/multmrk.hxx b/sw/source/uibase/inc/multmrk.hxx
new file mode 100644
index 0000000000..7e2fead650
--- /dev/null
+++ b/sw/source/uibase/inc/multmrk.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_MULTMRK_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_MULTMRK_HXX
+
+#include <vcl/weld.hxx>
+
+class SwTOXMgr;
+
+// insert mark for index entry
+class SwMultiTOXMarkDlg final : public weld::GenericDialogController
+{
+ DECL_LINK(SelectHdl, weld::TreeView&, void);
+ SwTOXMgr& m_rMgr;
+ sal_uInt16 m_nPos;
+
+ std::unique_ptr<weld::Label> m_xTextFT;
+ std::unique_ptr<weld::TreeView> m_xTOXLB;
+
+public:
+ SwMultiTOXMarkDlg(weld::Window* pParent, SwTOXMgr& rTOXMgr);
+ virtual ~SwMultiTOXMarkDlg() override;
+ virtual short run() override;
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_MULTMRK_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/navicfg.hxx b/sw/source/uibase/inc/navicfg.hxx
new file mode 100644
index 0000000000..b39614f9f6
--- /dev/null
+++ b/sw/source/uibase/inc/navicfg.hxx
@@ -0,0 +1,144 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_NAVICFG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_NAVICFG_HXX
+
+#include <unotools/configitem.hxx>
+#include <o3tl/enumarray.hxx>
+#include "swcont.hxx"
+
+class SwNavigationConfig final : public utl::ConfigItem
+{
+ ContentTypeId m_nRootType; //RootType
+ sal_Int32 m_nSelectedPos; //SelectedPosition
+ sal_Int32 m_nOutlineLevel; //OutlineLevel
+ RegionMode m_nRegionMode; //InsertMode
+ sal_Int32 m_nActiveBlock; //ActiveBlock//Expand/CollapsState
+ bool m_bIsSmall; //ShowListBox
+ bool m_bIsGlobalActive; //GlobalDocMode// global view for GlobalDoc valid?
+ sal_Int32 m_nOutlineTracking;
+ bool m_bIsNavigateOnSelect;
+
+ o3tl::enumarray<ContentTypeId, bool> mContentTypeTrack;
+
+ sal_Int32 m_nSortAlphabeticallyBlock = 0; // persists content type alphabetical sort setting
+
+ static css::uno::Sequence<OUString> GetPropertyNames();
+
+ virtual void ImplCommit() override;
+
+public:
+ SwNavigationConfig();
+ virtual ~SwNavigationConfig() override;
+
+ void Load();
+ virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+
+ ContentTypeId GetRootType()const {return m_nRootType;}
+ void SetRootType(ContentTypeId nSet){
+ if(m_nRootType != nSet)
+ {
+ SetModified();
+ m_nRootType = nSet;
+ }
+ }
+
+ sal_Int32 GetOutlineLevel()const {return m_nOutlineLevel;}
+ void SetOutlineLevel(sal_Int32 nSet){
+ if(m_nOutlineLevel != nSet)
+ {
+ SetModified();
+ m_nOutlineLevel = nSet;
+ }
+ }
+
+ RegionMode GetRegionMode()const {return m_nRegionMode;}
+ void SetRegionMode(RegionMode nSet){
+ if(m_nRegionMode != nSet)
+ {
+ SetModified();
+ m_nRegionMode = nSet;
+ }
+ }
+
+ sal_Int32 GetActiveBlock()const {return m_nActiveBlock;}
+ void SetActiveBlock(sal_Int32 nSet){
+ if(m_nActiveBlock != nSet)
+ {
+ SetModified();
+ m_nActiveBlock = nSet;
+ }
+ }
+
+ bool IsSmall() const {return m_bIsSmall;}
+ void SetSmall(bool bSet){
+ if(m_bIsSmall != bSet)
+ {
+ SetModified();
+ m_bIsSmall = bSet;
+ }
+ }
+
+ bool IsGlobalActive() const {return m_bIsGlobalActive;}
+ void SetGlobalActive(bool bSet){
+ if(m_bIsGlobalActive != bSet)
+ {
+ SetModified();
+ m_bIsGlobalActive = bSet;
+ }
+ }
+
+ sal_Int32 GetOutlineTracking()const {return m_nOutlineTracking;}
+ void SetOutlineTracking(sal_Int32 nSet){
+ if(m_nOutlineTracking != nSet)
+ {
+ SetModified();
+ m_nOutlineTracking = nSet;
+ }
+ }
+
+ bool IsContentTypeTrack(ContentTypeId eCntTypeId)
+ {
+ return mContentTypeTrack[eCntTypeId];
+ }
+ void SetContentTypeTrack(ContentTypeId eCntTypeId, const bool bSet)
+ {
+ if (mContentTypeTrack[eCntTypeId] != bSet)
+ {
+ SetModified();
+ mContentTypeTrack[eCntTypeId] = bSet;
+ }
+ }
+
+ bool IsNavigateOnSelect() const {return m_bIsNavigateOnSelect;}
+
+ sal_Int32 GetSortAlphabeticallyBlock() const {return m_nSortAlphabeticallyBlock;}
+ void SetSortAlphabeticallyBlock(sal_Int32 nSet)
+ {
+ if(m_nSortAlphabeticallyBlock != nSet)
+ {
+ SetModified();
+ m_nSortAlphabeticallyBlock = nSet;
+ }
+ }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/navicont.hxx b/sw/source/uibase/inc/navicont.hxx
new file mode 100644
index 0000000000..604c1c982c
--- /dev/null
+++ b/sw/source/uibase/inc/navicont.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_NAVICONT_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_NAVICONT_HXX
+
+#include <rtl/ustring.hxx>
+#include <tools/long.hxx>
+
+class SwDocShell;
+class TransferDataContainer;
+class TransferableDataHelper;
+enum class RegionMode;
+
+/*
+ navigator bookmark for distinct identification in Sw
+*/
+
+class NaviContentBookmark
+{
+ OUString m_aUrl; // URL including jump mark
+ OUString m_aDescription; // description
+ tools::Long m_nDocSh; // address of DocShell
+ RegionMode m_nDefaultDrag; // description contains defaultDragType
+
+public:
+ NaviContentBookmark();
+ NaviContentBookmark( OUString aUrl, OUString aDesc,
+ RegionMode nDragType, const SwDocShell* );
+
+ const OUString& GetURL() const { return m_aUrl; }
+ const OUString& GetDescription() const { return m_aDescription; }
+ RegionMode GetDefaultDragType() const { return m_nDefaultDrag; }
+ void Copy( TransferDataContainer& rData ) const;
+ bool Paste( const TransferableDataHelper& rData, const OUString& rsDesc );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/navipi.hxx b/sw/source/uibase/inc/navipi.hxx
new file mode 100644
index 0000000000..f87474ab7c
--- /dev/null
+++ b/sw/source/uibase/inc/navipi.hxx
@@ -0,0 +1,180 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_NAVIPI_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_NAVIPI_HXX
+
+#include <vcl/idle.hxx>
+#include <svl/lstner.hxx>
+#include <vcl/transfer.hxx>
+#include <sfx2/childwin.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/sidebar/ControllerItem.hxx>
+#include <sfx2/navigat.hxx>
+#include <sfx2/weldutils.hxx>
+#include <sfx2/sidebar/PanelLayout.hxx>
+#include "conttree.hxx"
+#include <ndarr.hxx>
+#include <memory>
+#include <optional>
+
+class SwWrtShell;
+class SfxBindings;
+class SwNavigationConfig;
+class SwView;
+enum class RegionMode;
+class SpinField;
+
+class SwNavigationPI final : public PanelLayout
+ , public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface
+ , public SfxListener
+{
+ friend class SwNavigatorWin;
+ friend class SwContentTree;
+ friend class SwGlobalTree;
+
+ ::sfx2::sidebar::ControllerItem m_aDocFullName;
+ ::sfx2::sidebar::ControllerItem m_aPageStats;
+
+ std::unique_ptr<weld::Toolbar> m_xContent1ToolBox;
+ std::unique_ptr<weld::Toolbar> m_xContent2ToolBox;
+ std::unique_ptr<weld::Toolbar> m_xContent3ToolBox;
+ std::unique_ptr<weld::Toolbar> m_xContent4ToolBox;
+ std::unique_ptr<weld::Toolbar> m_xContent5ToolBox;
+ std::unique_ptr<weld::Toolbar> m_xContent6ToolBox;
+ std::unique_ptr<ToolbarUnoDispatcher> m_xContent2Dispatch;
+ std::unique_ptr<ToolbarUnoDispatcher> m_xContent3Dispatch;
+ std::unique_ptr<weld::Menu> m_xHeadingsMenu;
+ std::unique_ptr<weld::Menu> m_xDragModeMenu;
+ std::unique_ptr<weld::Menu> m_xUpdateMenu;
+ std::unique_ptr<weld::Menu> m_xInsertMenu;
+ std::unique_ptr<weld::Toolbar> m_xGlobalToolBox;
+ std::unique_ptr<weld::SpinButton> m_xEdit;
+ std::unique_ptr<weld::Widget> m_xContentBox;
+ std::unique_ptr<SwContentTree> m_xContentTree;
+ std::unique_ptr<weld::Widget> m_xGlobalBox;
+ std::unique_ptr<SwGlobalTree> m_xGlobalTree;
+ std::unique_ptr<weld::ComboBox> m_xDocListBox;
+ Idle m_aPageChgIdle;
+ OUString m_sContentFileName;
+ OUString m_aStatusArr[4];
+
+ VclPtr<SfxNavigator> m_xNavigatorDlg;
+
+ std::optional<SfxObjectShellLock> m_oObjectShell;
+ SwView *m_pContentView;
+ SwWrtShell *m_pContentWrtShell;
+ SwView *m_pActContView;
+ SwView *m_pCreateView;
+
+ SwNavigationConfig *m_pConfig;
+ SfxBindings &m_rBindings;
+
+ RegionMode m_nRegionMode; // 0 - URL, 1 - region with link 2 - region without link
+ Size m_aExpandedSize;
+
+ bool m_bIsZoomedIn : 1;
+ bool m_bGlobalMode : 1;
+
+ weld::ComboBox* m_pNavigateByComboBox;
+
+ bool IsZoomedIn() const {return m_bIsZoomedIn;}
+ void ZoomOut();
+ void ZoomIn();
+
+ void FillBox();
+
+ DECL_LINK( DocListBoxSelectHdl, weld::ComboBox&, void );
+ DECL_LINK( ToolBoxSelectHdl, const OUString&, void );
+ DECL_LINK( ToolBoxClickHdl, const OUString&, void );
+ DECL_LINK( ToolBox5DropdownClickHdl, const OUString&, void );
+ DECL_LINK( ToolBox6DropdownClickHdl, const OUString&, void );
+ DECL_LINK( DoneLink, SfxPoolItem const *, void );
+ DECL_LINK( DropModeMenuSelectHdl, const OUString&, void );
+ DECL_LINK( HeadingsMenuSelectHdl, const OUString&, void );
+ DECL_LINK( GlobalMenuSelectHdl, const OUString&, void );
+ DECL_LINK( ChangePageHdl, Timer*, void );
+ DECL_LINK( PageEditModifyHdl, weld::SpinButton&, void );
+ DECL_LINK( EditActionHdl, weld::Entry&, bool );
+ DECL_LINK( SetFocusChildHdl, weld::Container&, void );
+ DECL_LINK( NavigateByComboBoxSelectHdl, weld::ComboBox&, void );
+ DECL_LINK( PageModifiedHdl, weld::Entry&, void );
+
+ bool EditAction();
+ void UsePage();
+
+ void UpdateInitShow();
+
+ // release ObjectShellLock early enough for app end
+ virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
+
+ void ToggleTree();
+ void SetGlobalMode(bool bSet) {m_bGlobalMode = bSet;}
+
+ void UpdateNavigateBy();
+
+public:
+
+ static std::unique_ptr<PanelLayout> Create(weld::Widget* pParent,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame,
+ SfxBindings* pBindings);
+ SwNavigationPI(weld::Widget* pParent,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame,
+ SfxBindings* _pBindings, SfxNavigator* pNavigatorDlg);
+ virtual ~SwNavigationPI() override;
+
+ void UpdateListBox();
+ void MoveOutline(SwOutlineNodes::size_type nSource, SwOutlineNodes::size_type nTarget);
+
+ virtual void NotifyItemUpdate(const sal_uInt16 nSId,
+ const SfxItemState eState,
+ const SfxPoolItem* pState) override;
+
+ virtual void GetControlState(const sal_uInt16 /*nSId*/,
+ boost::property_tree::ptree& /*rState*/) override {};
+
+ static OUString CreateDropFileName( const TransferableDataHelper& rData );
+ static OUString CleanEntry(const OUString& rEntry);
+
+ RegionMode GetRegionDropMode() const {return m_nRegionMode;}
+ void SetRegionDropMode(RegionMode nNewMode);
+
+ sal_Int8 AcceptDrop();
+ sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt );
+
+ bool IsGlobalDoc() const;
+ bool IsGlobalMode() const {return m_bGlobalMode;}
+
+ SwView* GetCreateView() const;
+
+ virtual weld::Window* GetFrameWeld() const override;
+
+ void SelectNavigateByContentType(const OUString& rContentTypeName);
+};
+
+class SwNavigatorWrapper final : public SfxNavigatorWrapper
+{
+public:
+ SwNavigatorWrapper(vcl::Window *pParent, sal_uInt16 nId,
+ SfxBindings* pBindings, SfxChildWinInfo* pInfo);
+ SFX_DECL_CHILDWINDOW(SwNavigatorWrapper);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/navmgr.hxx b/sw/source/uibase/inc/navmgr.hxx
new file mode 100644
index 0000000000..858b990fd1
--- /dev/null
+++ b/sw/source/uibase/inc/navmgr.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_NAVMGR_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_NAVMGR_HXX
+
+#include <vector>
+
+#include <unocrsr.hxx>
+
+class SwWrtShell;
+struct SwPosition;
+class SwUnoCursor;
+
+class SwNavigationMgr final : public SfxListener
+{
+private:
+ /*
+ * List of entries in the navigation history
+ * Entries are SwUnoCursor because these gets corrected automatically
+ * when nodes are deleted.
+ *
+ * The navigation history behaves as a stack, to which items are added when we jump to a new position
+ * (e.g. click a link, or double click an entry from the navigator).
+ * Every use of the back/forward buttons results in moving the stack pointer within the navigation history
+ */
+ typedef std::vector< sw::UnoCursorPointer > Stack_t;
+ Stack_t m_entries;
+ Stack_t::size_type m_nCurrent; /* Current position within the navigation history */
+ SwWrtShell & m_rMyShell; /* The active shell within which the navigation occurs */
+
+ void GotoSwPosition(const SwPosition &rPos);
+
+public:
+ /* Constructor that initializes the shell to the current shell */
+ SwNavigationMgr( SwWrtShell & rShell );
+ ~SwNavigationMgr() override;
+ /* Can we go back in the history ? */
+ bool backEnabled() ;
+ /* Can we go forward in the history ? */
+ bool forwardEnabled();
+ /* The method that is called when we click the back button */
+ void goBack() ;
+ /* The method that is called when we click the forward button */
+ void goForward() ;
+ /* The method that adds the position pPos to the navigation history */
+ bool addEntry(const SwPosition& rPos);
+ /* to get notified if our cursors self-destruct */
+ virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override;
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/navsh.hxx b/sw/source/uibase/inc/navsh.hxx
new file mode 100644
index 0000000000..3ee72ff9fe
--- /dev/null
+++ b/sw/source/uibase/inc/navsh.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_NAVSH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_NAVSH_HXX
+
+#include <sfx2/module.hxx>
+#include <sfx2/shell.hxx>
+
+#include "basesh.hxx"
+#include <shellid.hxx>
+
+class SwNavigationShell final : public SwBaseShell
+{
+public:
+ SFX_DECL_INTERFACE(SW_NAVIGATIONSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwNavigationShell(SwView& rView);
+
+ void GetState(SfxItemSet&);
+ void Execute(SfxRequest const&);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/num.hxx b/sw/source/uibase/inc/num.hxx
new file mode 100644
index 0000000000..9dfa2bf9ea
--- /dev/null
+++ b/sw/source/uibase/inc/num.hxx
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_NUM_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_NUM_HXX
+
+#include <sfx2/tabdlg.hxx>
+#include "numprevw.hxx"
+#include <numrule.hxx>
+
+class SwWrtShell;
+class SvxBrushItem;
+class SwOutlineTabDialog;
+
+class SwNumPositionTabPage final : public SfxTabPage
+{
+ std::unique_ptr<SwNumRule> m_pActNum;
+ SwNumRule* m_pSaveNum;
+ SwWrtShell* m_pWrtSh;
+
+ SwOutlineTabDialog* m_pOutlineDlg;
+ sal_uInt16 m_nActNumLvl;
+
+ bool m_bModified : 1;
+ bool m_bPreset : 1;
+ bool m_bInInintControl : 1; // work around modify-error; should be resolved from 391 on
+ bool m_bLabelAlignmentPosAndSpaceModeActive;
+
+ NumberingPreview m_aPreviewWIN;
+
+ std::unique_ptr<weld::TreeView> m_xLevelLB;
+ std::unique_ptr<weld::Widget> m_xPositionFrame;
+
+ // former set of controls shown for numbering rules containing list level
+ // attributes in SvxNumberFormat::SvxNumPositionAndSpaceMode == LABEL_WIDTH_AND_POSITION
+ std::unique_ptr<weld::Label> m_xDistBorderFT;
+ std::unique_ptr<weld::MetricSpinButton> m_xDistBorderMF;
+ std::unique_ptr<weld::CheckButton> m_xRelativeCB;
+ std::unique_ptr<weld::Label> m_xIndentFT;
+ std::unique_ptr<weld::MetricSpinButton> m_xIndentMF;
+ std::unique_ptr<weld::Label> m_xDistNumFT;
+ std::unique_ptr<weld::MetricSpinButton> m_xDistNumMF;
+ std::unique_ptr<weld::Label> m_xAlignFT;
+ std::unique_ptr<weld::ComboBox> m_xAlignLB;
+
+ // new set of controls shown for numbering rules containing list level
+ // attributes in SvxNumberFormat::SvxNumPositionAndSpaceMode == LABEL_ALIGNMENT
+ std::unique_ptr<weld::Label> m_xLabelFollowedByFT;
+ std::unique_ptr<weld::ComboBox> m_xLabelFollowedByLB;
+ std::unique_ptr<weld::Label> m_xListtabFT;
+ std::unique_ptr<weld::MetricSpinButton> m_xListtabMF;
+ std::unique_ptr<weld::Label> m_xAlign2FT;
+ std::unique_ptr<weld::ComboBox> m_xAlign2LB;
+ std::unique_ptr<weld::Label> m_xAlignedAtFT;
+ std::unique_ptr<weld::MetricSpinButton> m_xAlignedAtMF;
+ std::unique_ptr<weld::Label> m_xIndentAtFT;
+ std::unique_ptr<weld::MetricSpinButton> m_xIndentAtMF;
+ std::unique_ptr<weld::Button> m_xStandardPB;
+ std::unique_ptr<weld::CustomWeld> m_xPreviewWIN;
+
+
+ void InitControls();
+
+ DECL_LINK(LevelHdl, weld::TreeView&, void);
+ DECL_LINK(EditModifyHdl, weld::ComboBox&, void);
+ DECL_LINK(DistanceHdl, weld::MetricSpinButton&, void);
+ DECL_LINK(RelativeHdl, weld::Toggleable&, void);
+ DECL_LINK(StandardHdl, weld::Button&, void);
+
+ void InitPosAndSpaceMode();
+ void ShowControlsDependingOnPosAndSpaceMode();
+
+ DECL_LINK(LabelFollowedByHdl_Impl, weld::ComboBox&, void);
+ DECL_LINK(ListtabPosHdl_Impl, weld::MetricSpinButton&, void);
+ DECL_LINK(AlignAtHdl_Impl, weld::MetricSpinButton&, void);
+ DECL_LINK(IndentAtHdl_Impl, weld::MetricSpinButton&, void);
+
+public:
+
+ SwNumPositionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~SwNumPositionTabPage() override;
+
+ virtual void ActivatePage(const SfxItemSet& rSet) override;
+ virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override;
+ virtual bool FillItemSet( SfxItemSet* rSet ) override;
+ virtual void Reset( const SfxItemSet* rSet ) override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet);
+
+ void SetOutlineTabDialog(SwOutlineTabDialog* pDlg){m_pOutlineDlg = pDlg;}
+ void SetWrtShell(SwWrtShell* pSh);
+#ifdef DBG_UTIL
+ void SetModified();
+#else
+ void SetModified()
+ {
+ m_bModified = true;
+ m_aPreviewWIN.SetLevel(m_nActNumLvl);
+ m_aPreviewWIN.Invalidate();
+ }
+#endif
+};
+
+class SwSvxNumBulletTabDialog final : public SfxTabDialogController
+{
+ SwWrtShell& m_rWrtSh;
+
+ virtual short Ok() override;
+ virtual void PageCreated(const OUString& rPageId, SfxTabPage& rPage) override;
+ DECL_LINK(RemoveNumberingHdl, weld::Button&, void);
+
+ std::unique_ptr<weld::ComboBox> m_xDummyCombo;
+
+public:
+ SwSvxNumBulletTabDialog(weld::Window* pParent,
+ const SfxItemSet& rSwItemSet,
+ SwWrtShell &);
+ virtual ~SwSvxNumBulletTabDialog() override;
+};
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_NUM_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/numberingtypelistbox.hxx b/sw/source/uibase/inc/numberingtypelistbox.hxx
new file mode 100644
index 0000000000..b264dcf8cf
--- /dev/null
+++ b/sw/source/uibase/inc/numberingtypelistbox.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_NUMBERINGTYPELISTBOX_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_NUMBERINGTYPELISTBOX_HXX
+
+#include <memory>
+#include <vcl/weld.hxx>
+#include <swdllapi.h>
+#include <o3tl/typed_flags_set.hxx>
+#include <editeng/svxenum.hxx>
+
+enum class SwInsertNumTypes
+{
+ NoNumbering = 0x01,
+ Extended = 0x02
+};
+
+namespace o3tl {
+ template<> struct typed_flags<SwInsertNumTypes> : is_typed_flags<SwInsertNumTypes, 0x03> {};
+};
+
+struct SwNumberingTypeListBox_Impl;
+
+class SW_DLLPUBLIC SwNumberingTypeListBox
+{
+ std::unique_ptr<weld::ComboBox> m_xWidget;
+ std::unique_ptr<SwNumberingTypeListBox_Impl> m_xImpl;
+
+public:
+ SwNumberingTypeListBox(std::unique_ptr<weld::ComboBox> pWidget);
+ ~SwNumberingTypeListBox();
+
+ void connect_changed(const Link<weld::ComboBox&, void>& rLink) { m_xWidget->connect_changed(rLink); }
+
+ void Reload(SwInsertNumTypes nTypeFlags);
+ SvxNumType GetSelectedNumberingType() const;
+ bool SelectNumberingType(SvxNumType nType);
+ void SetNoSelection() { m_xWidget->set_active(-1); }
+ void set_sensitive(bool bEnable) { m_xWidget->set_sensitive(bEnable); }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/numfmtlb.hxx b/sw/source/uibase/inc/numfmtlb.hxx
new file mode 100644
index 0000000000..95f527a6f2
--- /dev/null
+++ b/sw/source/uibase/inc/numfmtlb.hxx
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_NUMFMTLB_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_NUMFMTLB_HXX
+
+#include <vcl/weld.hxx>
+#include <svl/zforlist.hxx>
+#include <swdllapi.h>
+
+class SwView;
+
+class SW_DLLPUBLIC SwNumFormatBase
+{
+ sal_Int32 m_nStdEntry;
+ sal_uInt32 m_nDefFormat;
+ SvNumFormatType m_nCurrFormatType;
+ LanguageType m_eCurLanguage;
+ bool m_bOneArea;
+ bool mbCurrFormatTypeNeedsInit;
+ bool m_bShowLanguageControl; //determine whether the language control has
+ //to be shown in the number format dialog
+ bool m_bUseAutomaticLanguage;//determine whether language is automatically assigned
+public:
+ SwNumFormatBase();
+
+ void SetAutomaticLanguage(bool bSet) { m_bUseAutomaticLanguage = bSet; }
+ bool IsAutomaticLanguage()const { return m_bUseAutomaticLanguage; }
+ SvNumFormatType GetFormatType() const { return m_nCurrFormatType; }
+ LanguageType GetCurLanguage() const { return m_eCurLanguage;}
+ void SetLanguage(LanguageType eSet) { m_eCurLanguage = eSet; }
+ void SetShowLanguageControl(bool bSet) { m_bShowLanguageControl = bSet; }
+ SAL_DLLPRIVATE static double GetDefValue(const SvNumFormatType nFormatType);
+ void SetOneArea(bool bOnlyOne) { m_bOneArea = bOnlyOne; }
+
+ void SetFormatType(const SvNumFormatType nFormatType);
+ void SetDefFormat(const sal_uInt32 nDefFormat);
+ virtual sal_uInt32 GetFormat() const = 0;
+
+ virtual void Init();
+ void CallSelectHdl();
+
+ virtual void clear();
+ virtual int get_count() const = 0;
+ virtual int get_active() const = 0;
+ virtual OUString get_id(int nPos) const = 0;
+ virtual OUString get_text(int nPos) const = 0;
+ virtual weld::Widget& get_widget() const = 0;
+ virtual void append(const OUString& rId, const OUString& rText) = 0;
+ virtual void append_text(const OUString& rText) = 0;
+ virtual void insert_text(int nPos, const OUString& rText) = 0;
+ virtual void set_active(int nPos) = 0;
+ virtual void set_id(int nPos, const OUString& rId) = 0;
+ virtual ~SwNumFormatBase() {}
+};
+
+class SW_DLLPUBLIC NumFormatListBox final : public SwNumFormatBase
+{
+ std::unique_ptr<weld::ComboBox> mxControl;
+
+ DECL_DLLPRIVATE_LINK( SelectHdl, weld::ComboBox&, void );
+
+ virtual void Init() override;
+
+public:
+ NumFormatListBox(std::unique_ptr<weld::ComboBox> xControl);
+
+ virtual sal_uInt32 GetFormat() const override;
+
+ virtual void clear() override;
+ virtual int get_count() const override { return mxControl->get_count(); }
+ virtual int get_active() const override { return mxControl->get_active(); }
+ virtual OUString get_id(int nPos) const override { return mxControl->get_id(nPos); }
+ virtual OUString get_text(int nPos) const override { return mxControl->get_text(nPos); }
+ virtual weld::Widget& get_widget() const override { return *mxControl; }
+ virtual void append(const OUString& rId, const OUString& rText) override { mxControl->append(rId, rText); }
+ virtual void append_text(const OUString& rText) override { mxControl->append_text(rText); }
+ virtual void insert_text(int nPos, const OUString& rText) override { mxControl->insert_text(nPos, rText); }
+ virtual void set_active(int nPos) override { mxControl->set_active(nPos); }
+ virtual void set_id(int nPos, const OUString& rId) override { mxControl->set_id(nPos, rId); }
+ void show() { mxControl->show(); }
+ void hide() { mxControl->hide(); }
+
+ void set_sensitive(bool bSensitive) { mxControl->set_sensitive(bSensitive); }
+ void connect_changed(const Link<weld::ComboBox&, void>& rLink) { mxControl->connect_changed(rLink); }
+ OUString get_buildable_name() const { return mxControl->get_buildable_name(); }
+ void set_buildable_name(const OUString& rId){ mxControl->set_buildable_name(rId); }
+};
+
+class SW_DLLPUBLIC SwNumFormatTreeView final : public SwNumFormatBase
+{
+ std::unique_ptr<weld::TreeView> mxControl;
+
+ DECL_DLLPRIVATE_LINK( SelectHdl, weld::TreeView&, void );
+
+ virtual void Init() override;
+
+public:
+ SwNumFormatTreeView(std::unique_ptr<weld::TreeView> xControl);
+
+ virtual sal_uInt32 GetFormat() const override;
+
+ virtual void clear() override;
+ virtual int get_count() const override { return mxControl->n_children(); }
+ virtual int get_active() const override { return mxControl->get_selected_index(); }
+ virtual OUString get_id(int nPos) const override { return mxControl->get_id(nPos); }
+ virtual OUString get_text(int nPos) const override { return mxControl->get_text(nPos); }
+ virtual weld::Widget& get_widget() const override { return *mxControl; }
+ virtual void append(const OUString& rId, const OUString& rText) override { mxControl->append(rId, rText); }
+ virtual void append_text(const OUString& rText) override { mxControl->append_text(rText); }
+ virtual void insert_text(int nPos, const OUString& rText) override { mxControl->insert_text(nPos, rText); }
+ virtual void set_active(int nPos) override { mxControl->select(nPos); }
+ virtual void set_id(int nPos, const OUString& rId) override { mxControl->set_id(nPos, rId); }
+ OUString get_selected_text() const { return mxControl->get_selected_text(); }
+ bool get_visible() const { return mxControl->get_visible(); }
+ int get_selected_index() const { return mxControl->get_selected_index(); }
+ void set_visible(bool bVisible) { mxControl->set_visible(bVisible); }
+ void select(int nPos) { mxControl->select(nPos); }
+ void connect_row_activated(const Link<weld::TreeView&, bool>& rLink) { mxControl->connect_row_activated(rLink); }
+ OUString get_buildable_name() const { return mxControl->get_buildable_name(); }
+ void set_buildable_name(const OUString& rId){ mxControl->set_buildable_name(rId); }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/numpara.hxx b/sw/source/uibase/inc/numpara.hxx
new file mode 100644
index 0000000000..f6da0b9f71
--- /dev/null
+++ b/sw/source/uibase/inc/numpara.hxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_NUMPARA_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_NUMPARA_HXX
+
+#include <sfx2/tabdlg.hxx>
+#include <svl/style.hxx>
+
+// with this TabPage numbering settings at the paragraph / paragraph style
+// are performed.
+class SwParagraphNumTabPage final : public SfxTabPage
+{
+ // #outlinelevel#
+ const OUString msOutlineNumbering;
+
+ bool m_bModified : 1;
+ bool m_bCurNumrule : 1;
+
+ std::unique_ptr<weld::Widget> m_xOutlineStartBX;
+ std::unique_ptr<weld::ComboBox> m_xOutlineLvLB;
+ std::unique_ptr<weld::Widget> m_xNumberStyleBX;
+ std::unique_ptr<weld::ComboBox> m_xNumberStyleLB;
+ std::unique_ptr<weld::Button> m_xEditNumStyleBtn;
+
+ std::unique_ptr<weld::Widget> m_xListLvBX;
+ std::unique_ptr<weld::ComboBox> m_xListLvLB;
+
+ std::unique_ptr<weld::CheckButton> m_xNewStartCB;
+ std::unique_ptr<weld::Widget> m_xNewStartBX;
+ std::unique_ptr<weld::CheckButton> m_xNewStartNumberCB;
+ std::unique_ptr<weld::SpinButton> m_xNewStartNF;
+
+ std::unique_ptr<weld::Widget> m_xCountParaFram;
+ std::unique_ptr<weld::CheckButton> m_xCountParaCB;
+ std::unique_ptr<weld::CheckButton> m_xRestartParaCountCB;
+
+ std::unique_ptr<weld::Widget> m_xRestartBX;
+ std::unique_ptr<weld::SpinButton> m_xRestartNF;
+
+ DECL_LINK(NewStartHdl_Impl, weld::Toggleable&, void);
+ DECL_LINK(StyleHdl_Impl, weld::ComboBox&,void);
+ DECL_LINK(LineCountHdl_Impl, weld::Toggleable&, void);
+ DECL_LINK(EditNumStyleHdl_Impl, weld::Button&, void);
+ DECL_LINK(EditNumStyleSelectHdl_Impl, weld::ComboBox&, void);
+
+ static const WhichRangesContainer s_aPageRg;
+
+ void ExecuteEditNumStyle_Impl(sal_uInt16 nId, const OUString& rStr,
+ SfxStyleFamily nFamily);
+
+public:
+ SwParagraphNumTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet );
+ virtual ~SwParagraphNumTabPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rSet );
+ static WhichRangesContainer GetRanges() { return s_aPageRg; }
+
+ virtual bool FillItemSet( SfxItemSet* rSet ) override;
+ virtual void Reset( const SfxItemSet* rSet ) override;
+ virtual void ChangesApplied() override;
+
+ void EnableNewStart();
+ void DisableOutline();
+ void DisableNumbering();
+
+ weld::ComboBox& GetStyleBox() {return *m_xNumberStyleLB;};
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/numprevw.hxx b/sw/source/uibase/inc/numprevw.hxx
new file mode 100644
index 0000000000..2f858be6fd
--- /dev/null
+++ b/sw/source/uibase/inc/numprevw.hxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_NUMPREVW_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_NUMPREVW_HXX
+
+#include <vcl/customweld.hxx>
+
+class SwNumRule;
+namespace rtl { class OUString; }
+
+class NumberingPreview final : public weld::CustomWidgetController
+{
+ const SwNumRule* m_pActNum;
+ vcl::Font m_aStdFont;
+ tools::Long m_nPageWidth;
+ const OUString* m_pOutlineNames;
+ bool m_bPosition;
+ sal_uInt16 m_nActLevel;
+
+private:
+ virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
+
+public:
+ NumberingPreview()
+ : m_pActNum(nullptr)
+ , m_nPageWidth(0)
+ , m_pOutlineNames(nullptr)
+ , m_bPosition(false)
+ , m_nActLevel(USHRT_MAX)
+ {
+ }
+
+ void SetNumRule(const SwNumRule* pNum)
+ {
+ m_pActNum = pNum;
+ Invalidate();
+ }
+
+ void SetPageWidth(tools::Long nPgWidth)
+ {m_nPageWidth = nPgWidth;}
+ void SetOutlineNames(const OUString* pNames)
+ {m_pOutlineNames = pNames;}
+ void SetPositionMode()
+ { m_bPosition = true;}
+ void SetLevel(sal_uInt16 nSet) {m_nActLevel = nSet;}
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/olesh.hxx b/sw/source/uibase/inc/olesh.hxx
new file mode 100644
index 0000000000..a5c9eb28d0
--- /dev/null
+++ b/sw/source/uibase/inc/olesh.hxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_OLESH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_OLESH_HXX
+
+#include "frmsh.hxx"
+
+class SwOleShell : public SwFrameShell
+{
+public:
+ SFX_DECL_INTERFACE(SW_OLESHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+protected:
+ virtual void Activate(bool bMDI) override;
+ virtual void Deactivate(bool bMDI) override;
+
+public:
+ SwOleShell(SwView& rView);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/olmenu.hxx b/sw/source/uibase/inc/olmenu.hxx
new file mode 100644
index 0000000000..a071b6b5cf
--- /dev/null
+++ b/sw/source/uibase/inc/olmenu.hxx
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/linguistic2/XDictionary.hpp>
+#include <com/sun/star/linguistic2/XSpellAlternatives.hpp>
+#include <com/sun/star/linguistic2/ProofreadingResult.hpp>
+#include <com/sun/star/uno/Sequence.h>
+
+#include <rtl/ustring.hxx>
+#include <toolkit/awt/vclxmenu.hxx>
+#include <vcl/builder.hxx>
+#include <vcl/menu.hxx>
+
+#include <map>
+#include <vector>
+
+#include <swdllapi.h>
+
+//! Don't change these values. You may break context menu modifying extensions!
+#define MN_IGNORE_SELECTION 201
+#define MN_SHORT_COMMENT 208
+#define MN_EXPLANATION_LINK 209
+
+// id range for dictionaries sub menu
+#define MN_DICTIONARIES_START 300
+#define MN_DICTIONARIES_END (MN_DICTIONARIES_START + 99)
+
+// id range for suggestions from spell and grammar checker
+#define MN_SUGGESTION_START 500
+#define MN_SUGGESTION_END (MN_SUGGESTION_START + MN_MAX_NUM_LANG)
+
+// id range for auto correction sub menu entries
+#define MN_AUTOCORR_START 700
+#define MN_AUTOCORR_END (MN_AUTOCORR_START + MN_MAX_NUM_LANG)
+
+// max number of language entries sub menus
+#define MN_MAX_NUM_LANG 99
+
+#define MN_NONE_OFFSET (MN_MAX_NUM_LANG + 1)
+#define MN_RESET_OFFSET (MN_MAX_NUM_LANG + 2)
+#define MN_MORE_OFFSET (MN_MAX_NUM_LANG + 3)
+
+// id range for 'set language for selection' sub menu entries
+#define MN_SET_LANGUAGE_SELECTION_START 900
+#define MN_SET_LANGUAGE_SELECTION_END (MN_SET_LANGUAGE_SELECTION_START + MN_MAX_NUM_LANG)
+#define MN_SET_SELECTION_NONE (MN_SET_LANGUAGE_SELECTION_START + MN_NONE_OFFSET)
+#define MN_SET_SELECTION_RESET (MN_SET_LANGUAGE_SELECTION_START + MN_RESET_OFFSET)
+#define MN_SET_SELECTION_MORE (MN_SET_LANGUAGE_SELECTION_START + MN_MORE_OFFSET)
+
+// id range for 'set language for paragraph' sub menu entries
+#define MN_SET_LANGUAGE_PARAGRAPH_START 1100
+#define MN_SET_LANGUAGE_PARAGRAPH_END (MN_SET_LANGUAGE_PARAGRAPH_START + MN_MAX_NUM_LANG)
+#define MN_SET_PARA_NONE (MN_SET_LANGUAGE_PARAGRAPH_START + MN_NONE_OFFSET)
+#define MN_SET_PARA_RESET (MN_SET_LANGUAGE_PARAGRAPH_START + MN_RESET_OFFSET)
+#define MN_SET_PARA_MORE (MN_SET_LANGUAGE_PARAGRAPH_START + MN_MORE_OFFSET)
+
+class SwWrtShell;
+
+class SW_DLLPUBLIC SwSpellPopup
+{
+ VclBuilder m_aBuilder;
+ VclPtr<PopupMenu> m_xPopupMenu;
+ sal_uInt16 m_nIgnoreWordId;
+ sal_uInt16 m_nAddMenuId;
+ sal_uInt16 m_nAddId;
+ sal_uInt16 m_nSpellDialogId;
+ sal_uInt16 m_nCorrectMenuId;
+ sal_uInt16 m_nCorrectDialogId;
+ sal_uInt16 m_nLangSelectionMenuId;
+ sal_uInt16 m_nLangParaMenuId;
+ sal_uInt16 m_nRedlineAcceptId;
+ sal_uInt16 m_nRedlineRejectId;
+ sal_uInt16 m_nRedlineNextId;
+ sal_uInt16 m_nRedlinePrevId;
+ SwWrtShell* m_pSh;
+ css::uno::Sequence< css::uno::Reference< css::linguistic2::XDictionary > > m_aDics;
+ css::uno::Reference< css::linguistic2::XSpellAlternatives > m_xSpellAlt;
+
+ OUString m_sExplanationLink;
+
+ LanguageType m_nCheckedLanguage;
+
+ std::map< sal_Int16, OUString > m_aLangTable_Text;
+ std::map< sal_Int16, OUString > m_aLangTable_Paragraph;
+
+ OUString m_aDicNameSingle;
+ bool m_bGrammarResults; // show grammar results? Or show spellcheck results?
+
+ static void fillLangPopupMenu( PopupMenu *pPopupMenu, sal_uInt16 nLangStart,
+ const css::uno::Sequence< OUString >& aSeq, SwWrtShell* pWrtSh,
+ std::map< sal_Int16, OUString > &rLangTable );
+
+ /// Checks if any of the redline menu items should be hidden.
+ void checkRedline();
+
+public:
+ SwSpellPopup( SwWrtShell *pWrtSh,
+ css::uno::Reference< css::linguistic2::XSpellAlternatives > xAlt,
+ const OUString & rParaText );
+
+ SwSpellPopup( SwWrtShell *pWrtSh,
+ const css::linguistic2::ProofreadingResult &rResult,
+ sal_Int32 nErrorInResult,
+ const css::uno::Sequence< OUString > &rSuggestions,
+ const OUString & rParaText );
+
+ ~SwSpellPopup();
+
+ void InitItemCommands(const css::uno::Sequence< OUString >& aSuggestions);
+
+ PopupMenu& GetMenu()
+ {
+ return *m_xPopupMenu;
+ }
+
+ rtl::Reference<VCLXPopupMenu> CreateMenuInterface() { return new VCLXPopupMenu(m_xPopupMenu); }
+
+ void Execute( const tools::Rectangle& rPopupPos, vcl::Window* pWin );
+ void Execute( sal_uInt16 nId );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/optcomp.hxx b/sw/source/uibase/inc/optcomp.hxx
new file mode 100644
index 0000000000..d4ebbcb6b5
--- /dev/null
+++ b/sw/source/uibase/inc/optcomp.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+#include <sfx2/tabdlg.hxx>
+#include <unotools/compatibility.hxx>
+#include <rtl/ustring.hxx>
+
+class SwWrtShell;
+struct SwCompatibilityOptPage_Impl;
+
+class SwCompatibilityOptPage final : public SfxTabPage
+{
+private:
+ // config item
+ SvtCompatibilityOptions m_aConfigItem;
+ // text of the user entry
+ OUString m_sUserEntry;
+ // shell of the current document
+ SwWrtShell* m_pWrtShell;
+ // impl object
+ std::unique_ptr<SwCompatibilityOptPage_Impl> m_pImpl;
+ // saved options after "Reset"; used in "FillItemSet" for comparison
+ sal_uInt32 m_nSavedOptions;
+
+ // controls
+ std::unique_ptr<weld::Frame> m_xMain;
+ std::unique_ptr<weld::ComboBox> m_xFormattingLB;
+ std::unique_ptr<weld::TreeView> m_xOptionsLB;
+ std::unique_ptr<weld::Button> m_xDefaultPB;
+
+ // handler
+ DECL_LINK(SelectHdl, weld::ComboBox&, void);
+ DECL_LINK(UseAsDefaultHdl, weld::Button&, void);
+
+ // private methods
+ void InitControls( const SfxItemSet& rSet );
+ void SetCurrentOptions( sal_uInt32 nOptions );
+ sal_uInt32 GetDocumentOptions() const;
+ void WriteOptions();
+
+public:
+ SwCompatibilityOptPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~SwCompatibilityOptPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet );
+
+ virtual OUString GetAllStrings() override;
+
+ virtual bool FillItemSet( SfxItemSet* rSet ) override;
+ virtual void Reset( const SfxItemSet* rSet ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/optload.hxx b/sw/source/uibase/inc/optload.hxx
new file mode 100644
index 0000000000..c39283912d
--- /dev/null
+++ b/sw/source/uibase/inc/optload.hxx
@@ -0,0 +1,221 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <tools/globname.hxx>
+#include <tools/solar.h>
+#include <sfx2/tabdlg.hxx>
+
+#include <utility>
+#include <vcl/customweld.hxx>
+#include <vcl/textfilter.hxx>
+#include <vcl/weld.hxx>
+#include <sfx2/basedlgs.hxx>
+
+#include <SwCapObjType.hxx>
+#include <SwCapConfigProp.hxx>
+
+class SwFieldMgr;
+class SwWrtShell;
+
+class SwFieldUnitTable
+{
+public:
+ static OUString GetString(sal_uInt32 i);
+ static sal_uInt32 Count();
+ static FieldUnit GetValue(sal_uInt32 i);
+};
+
+class TextFilterAutoConvert final : public TextFilter
+{
+private:
+ OUString m_sLastGoodText;
+ OUString m_sNone;
+public:
+ TextFilterAutoConvert(OUString aNone)
+ : m_sNone(std::move(aNone))
+ {
+ }
+ virtual OUString filter(const OUString &rText) override;
+};
+
+class SwLoadOptPage final : public SfxTabPage
+{
+private:
+ SwWrtShell* m_pWrtShell;
+ sal_uInt16 m_nLastTab;
+ sal_Int32 m_nOldLinkMode;
+
+ std::unique_ptr<weld::RadioButton> m_xAlwaysRB;
+ std::unique_ptr<weld::RadioButton> m_xRequestRB;
+ std::unique_ptr<weld::RadioButton> m_xNeverRB;
+ std::unique_ptr<weld::Widget> m_xGridupdatelink;
+ std::unique_ptr<weld::Widget> m_xUpdateLinkImg;
+
+ std::unique_ptr<weld::CheckButton> m_xAutoUpdateFields;
+ std::unique_ptr<weld::Widget> m_xAutoUpdateFieldsImg;
+ std::unique_ptr<weld::CheckButton> m_xAutoUpdateCharts;
+ std::unique_ptr<weld::Widget> m_xAutoUpdateChartsImg;
+
+ std::unique_ptr<weld::ComboBox> m_xMetricLB;
+ std::unique_ptr<weld::Widget> m_xMetricImg;
+ std::unique_ptr<weld::Label> m_xTabFT;
+ std::unique_ptr<weld::MetricSpinButton> m_xTabMF;
+ std::unique_ptr<weld::Widget> m_xTabImg;
+ std::unique_ptr<weld::CheckButton> m_xUseSquaredPageMode;
+ std::unique_ptr<weld::Widget> m_xUseSquaredPageModeImg;
+ std::unique_ptr<weld::CheckButton> m_xUseCharUnit;
+ std::unique_ptr<weld::Widget> m_xUseCharUnitImg;
+ std::unique_ptr<weld::Entry> m_xWordCountED;
+ std::unique_ptr<weld::Widget> m_xWordCountImg;
+ std::unique_ptr<weld::CheckButton> m_xShowStandardizedPageCount;
+ std::unique_ptr<weld::Widget> m_xShowStandardizedPageCountImg;
+ std::unique_ptr<weld::SpinButton> m_xStandardizedPageSizeNF;
+ std::unique_ptr<weld::Widget> m_xStandardizedPageSizeImg;
+
+ DECL_LINK(MetricHdl, weld::ComboBox&, void);
+ DECL_LINK(StandardizedPageCountCheckHdl, weld::Toggleable&, void);
+
+public:
+ SwLoadOptPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~SwLoadOptPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet);
+
+ virtual OUString GetAllStrings() override;
+
+ virtual bool FillItemSet( SfxItemSet* rSet ) override;
+ virtual void Reset( const SfxItemSet* rSet ) override;
+};
+
+class SwCaptionOptDlg final : public SfxSingleTabDialogController
+{
+public:
+ SwCaptionOptDlg(weld::Window* pParent, const SfxItemSet& rSet);
+};
+
+class SwCaptionPreview final : public weld::CustomWidgetController
+{
+private:
+ OUString maText;
+ bool mbFontInitialized;
+ vcl::Font maFont;
+
+ void ApplySettings(vcl::RenderContext& rRenderContext);
+
+public:
+ SwCaptionPreview();
+ virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override;
+ void SetPreviewText(const OUString& rText);
+ virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
+};
+
+class SwCaptionOptPage final : public SfxTabPage
+{
+private:
+ OUString m_sSWTable;
+ OUString m_sSWFrame;
+ OUString m_sSWGraphic;
+ OUString m_sOLE;
+
+ OUString m_sIllustration;
+ OUString m_sTable;
+ OUString m_sText;
+ OUString m_sDrawing;
+
+ OUString m_sBegin;
+ OUString m_sEnd;
+ OUString m_sAbove;
+ OUString m_sBelow;
+
+ OUString m_sNone;
+
+ int m_nPrevSelectedEntry;
+
+ std::unique_ptr<SwFieldMgr> m_pMgr;
+ bool m_bHTMLMode;
+
+ TextFilterAutoConvert m_aTextFilter;
+
+ SwCaptionPreview m_aPreview;
+ std::unique_ptr<weld::TreeView> m_xCheckLB;
+ std::unique_ptr<weld::ComboBox> m_xLbCaptionOrder;
+ std::unique_ptr<weld::Widget> m_xLbCaptionOrderImg;
+
+ std::unique_ptr<weld::Widget> m_xSettingsGroup;
+ std::unique_ptr<weld::ComboBox> m_xCategoryBox;
+ std::unique_ptr<weld::Widget> m_xCategoryBoxImg;
+ std::unique_ptr<weld::Label> m_xFormatText;
+ std::unique_ptr<weld::ComboBox> m_xFormatBox;
+ std::unique_ptr<weld::Widget> m_xFormatBoxImg;
+ //#i61007# order of captions
+ std::unique_ptr<weld::Label> m_xNumberingSeparatorFT;
+ std::unique_ptr<weld::Entry> m_xNumberingSeparatorED;
+ std::unique_ptr<weld::Widget> m_xNumberingSeparatorImg;
+ std::unique_ptr<weld::Label> m_xTextText;
+ std::unique_ptr<weld::Entry> m_xTextEdit;
+ std::unique_ptr<weld::Widget> m_xTextEditImg;
+ std::unique_ptr<weld::ComboBox> m_xPosBox;
+ std::unique_ptr<weld::Widget> m_xPosBoxImg;
+
+ std::unique_ptr<weld::Widget> m_xNumCapt;
+ std::unique_ptr<weld::ComboBox> m_xLbLevel;
+ std::unique_ptr<weld::Widget> m_xLbLevelImg;
+ std::unique_ptr<weld::Entry> m_xEdDelim;
+ std::unique_ptr<weld::Widget> m_xEdDelimImg;
+
+ std::unique_ptr<weld::Widget> m_xCategory;
+ std::unique_ptr<weld::ComboBox> m_xCharStyleLB;
+ std::unique_ptr<weld::Widget> m_xCharStyleImg;
+ std::unique_ptr<weld::CheckButton> m_xApplyBorderCB;
+ std::unique_ptr<weld::Widget> m_xApplyBorderImg;
+ std::unique_ptr<weld::CustomWeld> m_xPreview;
+
+ DECL_LINK(SelectHdl, weld::ComboBox&, void);
+ DECL_LINK(SelectListBoxHdl, weld::ComboBox&, void);
+ DECL_LINK(ModifyEntryHdl, weld::Entry&, void);
+ DECL_LINK(ModifyComboHdl, weld::ComboBox&, void);
+ DECL_LINK(OrderHdl, weld::ComboBox&, void );
+ DECL_LINK(ShowEntryHdl, weld::TreeView&, void);
+ DECL_LINK(ToggleEntryHdl, const weld::TreeView::iter_col&, void);
+ DECL_LINK(TextFilterHdl, OUString&, bool);
+
+ void ModifyHdl();
+ void UpdateEntry(int nRow);
+ void DelUserData();
+ void SetOptions(const sal_uLong nPos, const SwCapObjType eType, const SvGlobalName *pOleId = nullptr);
+ void SaveEntry(int nEntry);
+ void InvalidatePreview();
+
+public:
+ SwCaptionOptPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~SwCaptionOptPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet);
+
+ virtual OUString GetAllStrings() override;
+
+ virtual bool FillItemSet( SfxItemSet* rSet ) override;
+ virtual void Reset( const SfxItemSet* rSet ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/optpage.hxx b/sw/source/uibase/inc/optpage.hxx
new file mode 100644
index 0000000000..e2641fd7fc
--- /dev/null
+++ b/sw/source/uibase/inc/optpage.hxx
@@ -0,0 +1,482 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+
+#include <vcl/weld.hxx>
+#include <svtools/ctrlbox.hxx>
+#include <svx/colorbox.hxx>
+#include <svx/fntctrl.hxx>
+#include "fontcfg.hxx"
+class SfxPrinter;
+class SwStdFontConfig;
+class SwWrtShell;
+class FontList;
+
+// Tools->Options->Writer->View
+// Tools->Options->Writer/Web->View
+class SwContentOptPage final : public SfxTabPage
+{
+ std::unique_ptr<weld::CheckButton> m_xCrossCB;
+ std::unique_ptr<weld::Widget> m_xCrossImg;
+
+ std::unique_ptr<weld::ComboBox> m_xHMetric;
+ std::unique_ptr<weld::Widget> m_xHMetricImg;
+ std::unique_ptr<weld::CheckButton> m_xVRulerCBox;
+ std::unique_ptr<weld::Widget> m_xVRulerImg;
+ std::unique_ptr<weld::CheckButton> m_xVRulerRightCBox;
+ std::unique_ptr<weld::Widget> m_xVRulerRightImg;
+ std::unique_ptr<weld::ComboBox> m_xVMetric;
+ std::unique_ptr<weld::CheckButton> m_xSmoothCBox;
+ std::unique_ptr<weld::Widget> m_xSmoothImg;
+
+ std::unique_ptr<weld::CheckButton> m_xGrfCB;
+ std::unique_ptr<weld::Widget> m_xGrfImg;
+ std::unique_ptr<weld::CheckButton> m_xTableCB;
+ std::unique_ptr<weld::Widget> m_xTableImg;
+ std::unique_ptr<weld::CheckButton> m_xDrwCB;
+ std::unique_ptr<weld::Widget> m_xDrwImg;
+ std::unique_ptr<weld::CheckButton> m_xPostItCB;
+
+ std::unique_ptr<weld::Frame> m_xSettingsFrame;
+ std::unique_ptr<weld::Label> m_xSettingsLabel;
+ std::unique_ptr<weld::Label> m_xMetricLabel;
+ std::unique_ptr<weld::ComboBox> m_xMetricLB;
+ std::unique_ptr<weld::Widget> m_xMetricImg;
+
+ std::unique_ptr<weld::CheckButton> m_xShowInlineTooltips;
+ std::unique_ptr<weld::Widget> m_xShowInlineTooltipsImg;
+ std::unique_ptr<weld::CheckButton> m_xShowOutlineContentVisibilityButton;
+ std::unique_ptr<weld::Widget> m_xShowOutlineContentVImg;
+ std::unique_ptr<weld::CheckButton> m_xTreatSubOutlineLevelsAsContent;
+ std::unique_ptr<weld::Widget> m_xTreatSubOutlineLevelsImg;
+ std::unique_ptr<weld::CheckButton> m_xShowChangesInMargin;
+ std::unique_ptr<weld::Widget> m_xShowChangesInMarginImg;
+ std::unique_ptr<weld::CheckButton> m_xFieldHiddenCB;
+ std::unique_ptr<weld::Widget> m_xFieldHiddenImg;
+ std::unique_ptr<weld::CheckButton> m_xFieldHiddenParaCB;
+ std::unique_ptr<weld::Widget> m_xFieldHiddenParaImg;
+
+ DECL_LINK(VertRulerHdl, weld::Toggleable&, void);
+ DECL_LINK(ShowOutlineContentVisibilityButtonHdl, weld::Toggleable&, void);
+public:
+ SwContentOptPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~SwContentOptPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+
+ virtual OUString GetAllStrings() override;
+
+ virtual bool FillItemSet(SfxItemSet* rSet) override;
+ virtual void Reset(const SfxItemSet* rSet) override;
+};
+
+// TabPage printer settings additions
+class SwAddPrinterTabPage final : public SfxTabPage
+{
+ OUString m_sNone;
+ bool m_bAttrModified;
+ bool m_bPreview;
+ bool m_bHTMLMode;
+
+ std::unique_ptr<weld::CheckButton> m_xGrfCB;
+ std::unique_ptr<weld::Widget> m_xGrfImg;
+ std::unique_ptr<weld::CheckButton> m_xCtrlFieldCB;
+ std::unique_ptr<weld::Widget> m_xCtrlFieldImg;
+ std::unique_ptr<weld::CheckButton> m_xBackgroundCB;
+ std::unique_ptr<weld::Widget> m_xBackgroundImg;
+ std::unique_ptr<weld::CheckButton> m_xBlackFontCB;
+ std::unique_ptr<weld::Widget> m_xBlackFontImg;
+ std::unique_ptr<weld::CheckButton> m_xPrintHiddenTextCB;
+ std::unique_ptr<weld::Widget> m_xPrintHiddenTextImg;
+ std::unique_ptr<weld::CheckButton> m_xPrintTextPlaceholderCB;
+ std::unique_ptr<weld::Widget> m_xPrintTextPlaceholderImg;
+
+ std::unique_ptr<weld::Widget> m_xPagesFrame;
+ std::unique_ptr<weld::CheckButton> m_xLeftPageCB;
+ std::unique_ptr<weld::Widget> m_xLeftPageImg;
+ std::unique_ptr<weld::CheckButton> m_xRightPageCB;
+ std::unique_ptr<weld::Widget> m_xRightPageImg;
+ std::unique_ptr<weld::CheckButton> m_xProspectCB;
+ std::unique_ptr<weld::Widget> m_xProspectImg;
+ std::unique_ptr<weld::CheckButton> m_xProspectCB_RTL;
+ std::unique_ptr<weld::Widget> m_xProspectImg_RTL;
+
+ std::unique_ptr<weld::Widget> m_xCommentsFrame;
+ std::unique_ptr<weld::RadioButton> m_xNoRB;
+ std::unique_ptr<weld::RadioButton> m_xOnlyRB;
+ std::unique_ptr<weld::RadioButton> m_xEndRB;
+ std::unique_ptr<weld::RadioButton> m_xEndPageRB;
+ std::unique_ptr<weld::RadioButton> m_xInMarginsRB;
+ std::unique_ptr<weld::Widget> m_xMarginsImg;
+
+ std::unique_ptr<weld::CheckButton> m_xPrintEmptyPagesCB;
+ std::unique_ptr<weld::Widget> m_xPrintEmptyPagesImg;
+ std::unique_ptr<weld::CheckButton> m_xPaperFromSetupCB;
+ std::unique_ptr<weld::Widget> m_xPaperFromSetupImg;
+ std::unique_ptr<weld::ComboBox> m_xFaxLB;
+ std::unique_ptr<weld::Widget> m_xFaxImg;
+
+ DECL_LINK(AutoClickHdl, weld::Toggleable&, void);
+ DECL_LINK(SelectHdl, weld::ComboBox&, void);
+
+public:
+ SwAddPrinterTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~SwAddPrinterTabPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+
+ virtual OUString GetAllStrings() override;
+
+ virtual bool FillItemSet(SfxItemSet* rSet) override;
+ virtual void Reset(const SfxItemSet* rSet) override;
+ void SetFax(const std::vector<OUString>& );
+ void SetPreview(bool bPrev);
+ virtual void PageCreated(const SfxAllItemSet& aSet) override;
+};
+
+class SwStdFontTabPage final : public SfxTabPage
+{
+ OUString m_sShellStd;
+ OUString m_sShellTitle;
+ OUString m_sShellList;
+ OUString m_sShellLabel;
+ OUString m_sShellIndex;
+
+ VclPtr<SfxPrinter> m_pPrt;
+ std::unique_ptr<FontList> m_pFontList;
+ SwStdFontConfig* m_pFontConfig;
+ SwWrtShell* m_pWrtShell;
+ LanguageType m_eLanguage;
+
+ // only defaults were there? they were signed with the boxes
+ bool m_bListDefault :1;
+ bool m_bSetListDefault :1;
+ bool m_bLabelDefault :1;
+ bool m_bSetLabelDefault :1;
+ bool m_bIdxDefault :1;
+ bool m_bSetIdxDefault :1;
+ bool m_bDisposePrinter :1;
+
+ sal_uInt8 m_nFontGroup; //fontcfg.hxx: FONT_GROUP_[STANDARD|CJK|CTL]
+
+ OUString m_sScriptWestern;
+ OUString m_sScriptAsian;
+ OUString m_sScriptComplex;
+
+ std::unique_ptr<weld::Label> m_xLabelFT;
+ std::unique_ptr<weld::ComboBox> m_xStandardBox;
+ std::unique_ptr<weld::Widget> m_xStandardBoxImg;
+ std::unique_ptr<FontSizeBox> m_xStandardHeightLB;
+ std::unique_ptr<weld::Widget> m_xStandardHeightImg;
+ std::unique_ptr<weld::ComboBox> m_xTitleBox;
+ std::unique_ptr<weld::Widget> m_xTitleBoxImg;
+ std::unique_ptr<FontSizeBox> m_xTitleHeightLB;
+ std::unique_ptr<weld::Widget> m_xTitleHeightImg;
+ std::unique_ptr<weld::ComboBox> m_xListBox;
+ std::unique_ptr<weld::Widget> m_xListBoxImg;
+ std::unique_ptr<FontSizeBox> m_xListHeightLB;
+ std::unique_ptr<weld::Widget> m_xListHeightImg;
+ std::unique_ptr<weld::ComboBox> m_xLabelBox;
+ std::unique_ptr<weld::Widget> m_xLabelBoxImg;
+ std::unique_ptr<FontSizeBox> m_xLabelHeightLB;
+ std::unique_ptr<weld::Widget> m_xLabelHeightImg;
+ std::unique_ptr<weld::ComboBox> m_xIdxBox;
+ std::unique_ptr<weld::Widget> m_xIdxBoxImg;
+ std::unique_ptr<FontSizeBox> m_xIndexHeightLB;
+ std::unique_ptr<weld::Widget> m_xIndexHeightImg;
+ std::unique_ptr<weld::Button> m_xStandardPB;
+
+ DECL_LINK(StandardHdl, weld::Button&, void );
+ DECL_LINK(ModifyHdl, weld::ComboBox&, void );
+ DECL_LINK(LoseFocusHdl, weld::Widget&, void );
+
+public:
+ SwStdFontTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+ virtual ~SwStdFontTabPage() override;
+
+ virtual OUString GetAllStrings() override;
+
+ virtual bool FillItemSet(SfxItemSet* rSet) override;
+ virtual void Reset(const SfxItemSet* rSet) override;
+
+ virtual void PageCreated(const SfxAllItemSet& aSet) override;
+};
+
+class SwTableOptionsTabPage final : public SfxTabPage
+{
+ SwWrtShell* m_pWrtShell;
+ bool m_bHTMLMode;
+
+ std::unique_ptr<weld::CheckButton> m_xHeaderCB;
+ std::unique_ptr<weld::Widget> m_xHeaderImg;
+ std::unique_ptr<weld::CheckButton> m_xRepeatHeaderCB;
+ std::unique_ptr<weld::Widget> m_xRepeatHeaderImg;
+ std::unique_ptr<weld::CheckButton> m_xDontSplitCB;
+ std::unique_ptr<weld::Widget> m_xDontSplitImg;
+ std::unique_ptr<weld::CheckButton> m_xBorderCB;
+ std::unique_ptr<weld::Widget> m_xBorderImg;
+
+ std::unique_ptr<weld::CheckButton> m_xNumFormattingCB;
+ std::unique_ptr<weld::Widget> m_xNumFormattingImg;
+ std::unique_ptr<weld::CheckButton> m_xNumFormatFormattingCB;
+ std::unique_ptr<weld::Widget> m_xNumFormatFormattingImg;
+ std::unique_ptr<weld::CheckButton> m_xNumAlignmentCB;
+ std::unique_ptr<weld::Widget> m_xNumAlignmentImg;
+
+ std::unique_ptr<weld::MetricSpinButton> m_xRowMoveMF;
+ std::unique_ptr<weld::Widget> m_xRowMoveImg;
+ std::unique_ptr<weld::MetricSpinButton> m_xColMoveMF;
+ std::unique_ptr<weld::Widget> m_xColMoveImg;
+
+ std::unique_ptr<weld::MetricSpinButton> m_xRowInsertMF;
+ std::unique_ptr<weld::Widget> m_xRowInsertImg;
+ std::unique_ptr<weld::MetricSpinButton> m_xColInsertMF;
+ std::unique_ptr<weld::Widget> m_xColInsertImg;
+
+ std::unique_ptr<weld::RadioButton> m_xFixRB;
+ std::unique_ptr<weld::RadioButton> m_xFixPropRB;
+ std::unique_ptr<weld::RadioButton> m_xVarRB;
+ std::unique_ptr<weld::Widget> m_xBehaviorOfImg;
+
+ DECL_LINK(CheckBoxHdl, weld::Toggleable&, void);
+
+public:
+ SwTableOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~SwTableOptionsTabPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+
+ virtual OUString GetAllStrings() override;
+
+ virtual bool FillItemSet(SfxItemSet* rSet) override;
+ virtual void Reset(const SfxItemSet* rSet) override;
+
+ virtual void PageCreated( const SfxAllItemSet& aSet) override;
+
+};
+
+// TabPage for ShadowCursor
+class SwShdwCursorOptionsTabPage final : public SfxTabPage
+{
+ SwWrtShell * m_pWrtShell;
+ bool m_bHTMLMode;
+
+ //nonprinting characters
+ std::unique_ptr<weld::CheckButton> m_xParaCB;
+ std::unique_ptr<weld::Widget> m_xParaImg;
+ std::unique_ptr<weld::CheckButton> m_xSHyphCB;
+ std::unique_ptr<weld::Widget> m_xSHyphImg;
+ std::unique_ptr<weld::CheckButton> m_xSpacesCB;
+ std::unique_ptr<weld::Widget> m_xSpacesImg;
+ std::unique_ptr<weld::CheckButton> m_xHSpacesCB;
+ std::unique_ptr<weld::Widget> m_xHSpacesImg;
+ std::unique_ptr<weld::CheckButton> m_xTabCB;
+ std::unique_ptr<weld::Widget> m_xTabImg;
+ std::unique_ptr<weld::Label> m_xTabLabel;
+ std::unique_ptr<weld::CheckButton> m_xBreakCB;
+ std::unique_ptr<weld::Widget> m_xBreakImg;
+ std::unique_ptr<weld::CheckButton> m_xCharHiddenCB;
+ std::unique_ptr<weld::Widget> m_xCharHiddenImg;
+ std::unique_ptr<weld::CheckButton> m_xBookmarkCB;
+ std::unique_ptr<weld::Widget> m_xBookmarkImg;
+ std::unique_ptr<weld::Label> m_xBookmarkLabel;
+
+ std::unique_ptr<weld::Frame> m_xDirectCursorFrame;
+ std::unique_ptr<weld::CheckButton> m_xOnOffCB;
+ std::unique_ptr<weld::Widget> m_xOnOffImg;
+
+ std::unique_ptr<weld::ComboBox> m_xDirectCursorFillMode;
+ std::unique_ptr<weld::Widget> m_xDirectCursorFillModeImg;
+ std::unique_ptr<weld::Frame> m_xCursorProtFrame;
+ std::unique_ptr<weld::Frame> m_xImageFrame;
+ std::unique_ptr<weld::CheckButton> m_xCursorInProtCB;
+ std::unique_ptr<weld::Widget> m_xCursorInProtImg;
+
+ std::unique_ptr<weld::ComboBox> m_xDefaultAnchorType;
+ std::unique_ptr<weld::Widget> m_xDefaultAnchorTypeImg;
+
+ std::unique_ptr<weld::CheckButton> m_xMathBaselineAlignmentCB;
+ std::unique_ptr<weld::Widget> m_xMathBaselineAlignmentImg;
+
+public:
+ SwShdwCursorOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~SwShdwCursorOptionsTabPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+
+ virtual OUString GetAllStrings() override;
+
+ virtual bool FillItemSet( SfxItemSet* rSet ) override;
+ virtual void Reset( const SfxItemSet* rSet ) override;
+
+ virtual void PageCreated( const SfxAllItemSet& aSet ) override;
+};
+
+// mark preview
+class SwMarkPreview final : public weld::CustomWidgetController
+{
+ Color m_aBgCol; // background
+ Color m_aTransCol; // transparency
+ Color m_aMarkCol; // marks
+ Color m_aLineCol; // general lines
+ Color m_aShadowCol; // shadow
+ Color m_aTextCol; // text
+ Color m_aPrintAreaCol; // frame for print area
+
+ tools::Rectangle m_aPage;
+ tools::Rectangle m_aLeftPagePrtArea;
+ tools::Rectangle m_aRightPagePrtArea;
+
+ sal_uInt16 m_nMarkPos;
+
+ virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) override;
+ void PaintPage(vcl::RenderContext& rRenderContext, const tools::Rectangle &rRect);
+ void InitColors();
+
+public:
+ SwMarkPreview();
+ virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override;
+ virtual ~SwMarkPreview() override;
+
+ void SetColor(const Color& rCol) { m_aMarkCol = rCol; }
+ void SetMarkPos(sal_uInt16 nPos) { m_nMarkPos = nPos; }
+};
+
+// redlining options
+class SwRedlineOptionsTabPage final : public SfxTabPage
+{
+ std::unique_ptr<weld::ComboBox> m_xInsertLB;
+ std::unique_ptr<weld::Widget> m_xInsertImg;
+ std::unique_ptr<ColorListBox> m_xInsertColorLB;
+ std::unique_ptr<weld::Widget> m_xInsertColorImg;
+ std::unique_ptr<SvxFontPrevWindow> m_xInsertedPreviewWN;
+ std::unique_ptr<weld::CustomWeld> m_xInsertedPreview;
+
+ std::unique_ptr<weld::ComboBox> m_xDeletedLB;
+ std::unique_ptr<weld::Widget> m_xDeletedImg;
+ std::unique_ptr<ColorListBox> m_xDeletedColorLB;
+ std::unique_ptr<weld::Widget> m_xDeletedColorImg;
+ std::unique_ptr<SvxFontPrevWindow> m_xDeletedPreviewWN;
+ std::unique_ptr<weld::CustomWeld> m_xDeletedPreview;
+
+ std::unique_ptr<weld::ComboBox> m_xChangedLB;
+ std::unique_ptr<weld::Widget> m_xChangedImg;
+ std::unique_ptr<ColorListBox> m_xChangedColorLB;
+ std::unique_ptr<weld::Widget> m_xChangedColorImg;
+ std::unique_ptr<SvxFontPrevWindow> m_xChangedPreviewWN;
+ std::unique_ptr<weld::CustomWeld> m_xChangedPreview;
+
+ std::unique_ptr<weld::ComboBox> m_xMarkPosLB;
+ std::unique_ptr<weld::Widget> m_xMarkPosImg;
+ std::unique_ptr<ColorListBox> m_xMarkColorLB;
+ std::unique_ptr<weld::Widget> m_xMarkColorImg;
+ std::unique_ptr<SwMarkPreview> m_xMarkPreviewWN;
+ std::unique_ptr<weld::CustomWeld> m_xMarkPreview;
+
+ DECL_LINK(AttribHdl, weld::ComboBox&, void);
+ void ChangedMaskPrev();
+ DECL_LINK(ChangedMaskPrevHdl, weld::ComboBox&, void);
+ DECL_LINK(ChangedMaskColorPrevHdl, ColorListBox&, void);
+ DECL_LINK(ColorHdl, ColorListBox&, void);
+
+ static void InitFontStyle(SvxFontPrevWindow& rExampleWin, const OUString& rText);
+
+public:
+ SwRedlineOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~SwRedlineOptionsTabPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+
+ virtual OUString GetAllStrings() override;
+
+ virtual bool FillItemSet( SfxItemSet* rSet ) override;
+ virtual void Reset( const SfxItemSet* rSet ) override;
+};
+
+// TabPage test settings for SW
+
+#ifdef DBG_UTIL
+
+class SwTestTabPage final : public SfxTabPage
+{
+public:
+ SwTestTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~SwTestTabPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+
+ virtual OUString GetAllStrings() override;
+
+ virtual bool FillItemSet( SfxItemSet* rSet ) override;
+ virtual void Reset( const SfxItemSet* rSet ) override;
+
+private:
+ bool m_bAttrModified;
+
+ std::unique_ptr<weld::CheckButton> m_xTest1CBox;
+ std::unique_ptr<weld::CheckButton> m_xTest2CBox;
+ std::unique_ptr<weld::CheckButton> m_xTest3CBox;
+ std::unique_ptr<weld::CheckButton> m_xTest4CBox;
+ std::unique_ptr<weld::CheckButton> m_xTest5CBox;
+ std::unique_ptr<weld::CheckButton> m_xTest6CBox;
+ std::unique_ptr<weld::CheckButton> m_xTest7CBox;
+ std::unique_ptr<weld::CheckButton> m_xTest8CBox;
+ std::unique_ptr<weld::CheckButton> m_xTest9CBox;
+ std::unique_ptr<weld::CheckButton> m_xTest10CBox;
+
+ void Init();
+ DECL_LINK(AutoClickHdl, weld::Toggleable&, void);
+};
+#endif // DBG_UTIL
+
+class SwCompareOptionsTabPage final : public SfxTabPage
+{
+ std::unique_ptr<weld::RadioButton> m_xAutoRB;
+ std::unique_ptr<weld::RadioButton> m_xWordRB;
+ std::unique_ptr<weld::RadioButton> m_xCharRB;
+ std::unique_ptr<weld::Widget> m_xCompareModeImg;
+ std::unique_ptr<weld::CheckButton> m_xRsidCB;
+ std::unique_ptr<weld::Widget> m_xRsidImg;
+ std::unique_ptr<weld::CheckButton> m_xIgnoreCB;
+ std::unique_ptr<weld::Widget> m_xIgnoreImg;
+ std::unique_ptr<weld::SpinButton> m_xLenNF;
+ std::unique_ptr<weld::Widget> m_xLenImg;
+ std::unique_ptr<weld::CheckButton> m_xStoreRsidCB;
+ std::unique_ptr<weld::Widget> m_xStoreRsidImg;
+
+ DECL_LINK(ComparisonHdl, weld::Toggleable&, void);
+ DECL_LINK(IgnoreHdl, weld::Toggleable&, void);
+
+public:
+ SwCompareOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~SwCompareOptionsTabPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet );
+
+ virtual OUString GetAllStrings() override;
+
+ virtual bool FillItemSet( SfxItemSet* rSet ) override;
+ virtual void Reset( const SfxItemSet* rSet ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/outline.hxx b/sw/source/uibase/inc/outline.hxx
new file mode 100644
index 0000000000..acb81b00f2
--- /dev/null
+++ b/sw/source/uibase/inc/outline.hxx
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+#include <sfx2/tabdlg.hxx>
+#include <swtypes.hxx>
+#include "numprevw.hxx"
+#include "numberingtypelistbox.hxx"
+#include <rtl/ustring.hxx>
+
+class SwWrtShell;
+class SwNumRule;
+class SwChapterNumRules;
+
+class SwOutlineTabDialog final : public SfxTabDialogController
+{
+ static sal_uInt16 s_nNumLevel;
+ static_assert(sizeof(s_nNumLevel) * CHAR_BIT >= MAXLEVEL);
+
+ OUString m_aCollNames[MAXLEVEL];
+
+ SwWrtShell& m_rWrtSh;
+ std::unique_ptr<SwNumRule> m_xNumRule;
+ SwChapterNumRules* m_pChapterNumRules;
+
+ bool m_bModified : 1;
+
+ std::unique_ptr<weld::MenuButton> m_xMenuButton;
+
+ DECL_LINK(CancelHdl, weld::Button&, void);
+ DECL_LINK(FormHdl, weld::Toggleable&, void);
+ DECL_LINK(MenuSelectHdl, const OUString&, void);
+
+ virtual void PageCreated(const OUString& rPageId, SfxTabPage& rPage) override;
+ virtual short Ok() override;
+
+public:
+ SwOutlineTabDialog(weld::Window* pParent, const SfxItemSet* pSwItemSet, SwWrtShell &);
+ virtual ~SwOutlineTabDialog() override;
+
+ SwNumRule* GetNumRule() { return m_xNumRule.get(); }
+ sal_uInt16 GetLevel(std::u16string_view rFormatName) const;
+ OUString* GetCollNames() {return m_aCollNames;}
+
+ static sal_uInt16 GetActNumLevel() {return s_nNumLevel;}
+ static void SetActNumLevel(sal_uInt16 nSet) {s_nNumLevel = nSet;}
+};
+
+class SwOutlineSettingsTabPage final : public SfxTabPage
+{
+ OUString m_aNoFormatName;
+ OUString m_aSaveCollNames[MAXLEVEL];
+ SwWrtShell* m_pSh;
+ SwNumRule* m_pNumRule;
+ OUString* m_pCollNames;
+ sal_uInt16 m_nActLevel;
+ NumberingPreview m_aPreviewWIN;
+
+ std::unique_ptr<weld::TreeView> m_xLevelLB;
+ std::unique_ptr<weld::ComboBox> m_xCollBox;
+ std::unique_ptr<SwNumberingTypeListBox> m_xNumberBox;
+ std::unique_ptr<weld::ComboBox> m_xCharFormatLB;
+ std::unique_ptr<weld::Label> m_xAllLevelFT;
+ std::unique_ptr<weld::SpinButton> m_xAllLevelNF;
+ std::unique_ptr<weld::Entry> m_xPrefixED;
+ std::unique_ptr<weld::Entry> m_xSuffixED;
+ std::unique_ptr<weld::SpinButton> m_xStartEdit;
+ std::unique_ptr<weld::CustomWeld> m_xPreviewWIN;
+
+ DECL_LINK( LevelHdl, weld::TreeView&, void );
+ DECL_LINK( ToggleComplete, weld::SpinButton&, void );
+ DECL_LINK( CollSelect, weld::ComboBox&, void );
+ void CollSave();
+ DECL_LINK( NumberSelect, weld::ComboBox&, void );
+ DECL_LINK( DelimModify, weld::Entry&, void );
+ DECL_LINK( StartModified, weld::SpinButton&, void );
+ DECL_LINK( CharFormatHdl, weld::ComboBox&, void );
+
+ void Update();
+
+ void SetModified() { m_aPreviewWIN.Invalidate(); }
+ void CheckForStartValue_Impl(sal_uInt16 nNumberingType);
+
+public:
+ SwOutlineSettingsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet);
+ virtual ~SwOutlineSettingsTabPage() override;
+
+ void SetWrtShell(SwWrtShell* pShell);
+
+ virtual void ActivatePage(const SfxItemSet& rSet) override;
+ virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override;
+
+ virtual bool FillItemSet( SfxItemSet* rSet ) override;
+ virtual void Reset( const SfxItemSet* rSet ) override;
+ void SetNumRule(SwNumRule *pRule)
+ {
+ m_pNumRule = pRule;
+ m_aPreviewWIN.SetNumRule(m_pNumRule);
+ }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/pagenumberdlg.hxx b/sw/source/uibase/inc/pagenumberdlg.hxx
new file mode 100644
index 0000000000..169c9209db
--- /dev/null
+++ b/sw/source/uibase/inc/pagenumberdlg.hxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sfx2/basedlgs.hxx>
+#include <svx/pagenumberlistbox.hxx>
+
+class SwWrtShell;
+
+/// Page number wizard for easy header/footer page number insertion
+class SwPageNumberDlg final : public SfxDialogController
+{
+ std::unique_ptr<weld::Button> m_xOk;
+ std::unique_ptr<weld::Button> m_xCancel;
+ std::unique_ptr<weld::ComboBox> m_xPageNumberPosition;
+ std::unique_ptr<weld::ComboBox> m_xPageNumberAlignment;
+ std::unique_ptr<weld::CheckButton> m_xMirrorOnEvenPages;
+ std::unique_ptr<weld::CheckButton> m_xIncludePageTotal;
+ std::unique_ptr<SvxPageNumberListBox> m_xPageNumberTypeLB;
+
+ std::unique_ptr<weld::Image> m_xPreviewImage;
+
+ int m_aPageNumberPosition;
+ int m_aPageNumberAlignment;
+ SvxNumType m_nPageNumberType;
+
+ DECL_LINK(OkHdl, weld::Button&, void);
+ DECL_LINK(IncludePageTotalChangeHdl, weld::Toggleable&, void);
+ DECL_LINK(PositionSelectHdl, weld::ComboBox&, void);
+ DECL_LINK(AlignmentSelectHdl, weld::ComboBox&, void);
+ DECL_LINK(NumberTypeSelectHdl, weld::ComboBox&, void);
+
+ void updateImage();
+
+public:
+ SwPageNumberDlg(weld::Window* pParent);
+ int GetPageNumberPosition() const { return m_aPageNumberPosition; }
+ int GetPageNumberAlignment() const { return m_aPageNumberAlignment; }
+ bool GetMirrorOnEvenPages();
+ bool GetIncludePageTotal();
+ SvxNumType GetPageNumberType() const { return m_nPageNumberType; }
+ void SetPageNumberType(SvxNumType nSet);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/pardlg.hxx b/sw/source/uibase/inc/pardlg.hxx
new file mode 100644
index 0000000000..ac8d0da9d7
--- /dev/null
+++ b/sw/source/uibase/inc/pardlg.hxx
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_PARDLG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_PARDLG_HXX
+
+//DialogModes:
+#define DLG_STD 0
+#define DLG_ENVELOP 2
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/pattern.hxx b/sw/source/uibase/inc/pattern.hxx
new file mode 100644
index 0000000000..06bb5bb06e
--- /dev/null
+++ b/sw/source/uibase/inc/pattern.hxx
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_PATTERN_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_PATTERN_HXX
+
+#include <sfx2/basedlgs.hxx>
+
+class SwBackgroundDlg final : public SfxSingleTabDialogController
+{
+public:
+ SwBackgroundDlg(weld::Window* pParent, const SfxItemSet& rSet);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/pgfnote.hxx b/sw/source/uibase/inc/pgfnote.hxx
new file mode 100644
index 0000000000..c239f1ed29
--- /dev/null
+++ b/sw/source/uibase/inc/pgfnote.hxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+
+#include <svtools/ctrlbox.hxx>
+#include <svx/colorbox.hxx>
+
+// footnote settings TabPage
+class SwFootNotePage final : public SfxTabPage
+{
+ static const WhichRangesContainer s_aPageRg;
+public:
+ SwFootNotePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet);
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet);
+ virtual ~SwFootNotePage() override;
+
+ static WhichRangesContainer GetRanges() { return s_aPageRg; }
+
+ virtual bool FillItemSet(SfxItemSet *rSet) override;
+ virtual void Reset(const SfxItemSet *rSet) override;
+
+private:
+
+ tools::Long m_lMaxHeight;
+
+ std::unique_ptr<weld::RadioButton> m_xMaxHeightPageBtn;
+ std::unique_ptr<weld::RadioButton> m_xMaxHeightBtn;
+ std::unique_ptr<weld::MetricSpinButton> m_xMaxHeightEdit;
+ std::unique_ptr<weld::MetricSpinButton> m_xDistEdit;
+ std::unique_ptr<weld::ComboBox> m_xLinePosBox;
+ std::unique_ptr<SvtLineListBox> m_xLineTypeBox;
+ std::unique_ptr<weld::MetricSpinButton> m_xLineWidthEdit;
+ std::unique_ptr<ColorListBox> m_xLineColorBox;
+ std::unique_ptr<weld::MetricSpinButton> m_xLineLengthEdit;
+ std::unique_ptr<weld::MetricSpinButton> m_xLineDistEdit;
+
+ DECL_LINK(HeightPage, weld::Toggleable&, void);
+ DECL_LINK(HeightMetric, weld::Toggleable&, void);
+ DECL_LINK(HeightModify, weld::MetricSpinButton&, void);
+ DECL_LINK(LineWidthChanged_Impl, weld::MetricSpinButton&, void);
+ DECL_LINK(LineColorSelected_Impl, ColorListBox&, void);
+
+ virtual void ActivatePage( const SfxItemSet& rSet ) override;
+ virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override;
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/pggrid.hxx b/sw/source/uibase/inc/pggrid.hxx
new file mode 100644
index 0000000000..12d6a8bae1
--- /dev/null
+++ b/sw/source/uibase/inc/pggrid.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_PGGRID_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_PGGRID_HXX
+
+#include <sfx2/tabdlg.hxx>
+#include "colex.hxx"
+#include <vcl/customweld.hxx>
+#include <vcl/weld.hxx>
+#include <svx/colorbox.hxx>
+
+// TabPage Format/(Styles/)Page/Text grid
+class SwTextGridPage final : public SfxTabPage
+{
+ sal_Int32 m_nRubyUserValue;
+ bool m_bRubyUserValue;
+ Size m_aPageSize;
+ bool m_bVertical;
+ bool m_bSquaredMode;
+ bool m_bHRulerChanged;
+ bool m_bVRulerChanged;
+
+ SwPageGridExample m_aExampleWN;
+ std::unique_ptr<weld::RadioButton> m_xNoGridRB;
+ std::unique_ptr<weld::RadioButton> m_xLinesGridRB;
+ std::unique_ptr<weld::RadioButton> m_xCharsGridRB;
+ std::unique_ptr<weld::CheckButton> m_xSnapToCharsCB;
+ std::unique_ptr<weld::CustomWeld> m_xExampleWN;
+ std::unique_ptr<weld::Widget> m_xLayoutFL;
+ std::unique_ptr<weld::SpinButton> m_xLinesPerPageNF;
+ std::unique_ptr<weld::Label> m_xLinesRangeFT;
+ std::unique_ptr<weld::MetricSpinButton> m_xTextSizeMF;
+ std::unique_ptr<weld::Label> m_xCharsPerLineFT;
+ std::unique_ptr<weld::SpinButton> m_xCharsPerLineNF;
+ std::unique_ptr<weld::Label> m_xCharsRangeFT;
+ std::unique_ptr<weld::Label> m_xCharWidthFT;
+ std::unique_ptr<weld::MetricSpinButton> m_xCharWidthMF;
+ std::unique_ptr<weld::Label> m_xRubySizeFT;
+ std::unique_ptr<weld::MetricSpinButton> m_xRubySizeMF;
+ std::unique_ptr<weld::CheckButton> m_xRubyBelowCB;
+ std::unique_ptr<weld::Widget> m_xDisplayFL;
+ std::unique_ptr<weld::CheckButton> m_xDisplayCB;
+ std::unique_ptr<weld::CheckButton> m_xPrintCB;
+ std::unique_ptr<ColorListBox> m_xColorLB;
+
+ void UpdatePageSize(const SfxItemSet& rSet);
+ void PutGridItem(SfxItemSet& rSet);
+ static void SetLinesOrCharsRanges(weld::Label& rField, const sal_Int32 nValue);
+
+ void GridModifyHdl();
+
+ DECL_LINK(GridTypeHdl, weld::Toggleable&, void);
+ DECL_LINK(CharorLineChangedHdl, weld::SpinButton&, void);
+ DECL_LINK(TextSizeChangedHdl, weld::MetricSpinButton&, void);
+ DECL_LINK(ColorModifyHdl, ColorListBox&, void);
+ DECL_LINK(GridModifyClickHdl, weld::Toggleable&, void);
+ DECL_LINK(DisplayGridHdl, weld::Toggleable&, void);
+
+public:
+ SwTextGridPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet);
+ virtual ~SwTextGridPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet);
+ static WhichRangesContainer GetRanges();
+
+ virtual bool FillItemSet(SfxItemSet *rSet) override;
+ virtual void Reset(const SfxItemSet *rSet) override;
+
+ virtual void ActivatePage( const SfxItemSet& rSet ) override;
+ virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/prcntfld.hxx b/sw/source/uibase/inc/prcntfld.hxx
new file mode 100644
index 0000000000..d8393d3097
--- /dev/null
+++ b/sw/source/uibase/inc/prcntfld.hxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_PRCNTFLD_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_PRCNTFLD_HXX
+
+#include <svtools/unitconv.hxx>
+#include <vcl/weld.hxx>
+#include <swdllapi.h>
+
+class SW_DLLPUBLIC SwPercentField
+{
+ std::unique_ptr<weld::MetricSpinButton> m_pField;
+
+ sal_Int64 m_nRefValue; // 100% value for conversion (in Twips)
+ sal_Int64 m_nOldMax;
+ sal_Int64 m_nOldMin;
+ int m_nOldSpinSize;
+ int m_nOldPageSize;
+ sal_Int64 m_nLastPercent;
+ sal_Int64 m_nLastValue;
+ sal_uInt16 m_nOldDigits;
+ FieldUnit m_eOldUnit;
+ bool m_bLockAutoCalculation; //prevent recalculation of percent values when the
+ //reference value is changed
+
+ SAL_DLLPRIVATE static int ImpPower10(sal_uInt16 n);
+
+public:
+
+ SwPercentField(std::unique_ptr<weld::MetricSpinButton> pControl);
+ const weld::MetricSpinButton* get() const { return m_pField.get(); }
+ weld::MetricSpinButton* get() { return m_pField.get(); }
+ void connect_value_changed(const Link<weld::MetricSpinButton&, void>& rLink) { m_pField->connect_value_changed(rLink); }
+ void SetMetric(FieldUnit eUnit) { ::SetFieldUnit(*m_pField, eUnit); }
+ void set_sensitive(bool bEnable) { m_pField->set_sensitive(bEnable); }
+ void show() { m_pField->show(); }
+ bool has_focus() const { return m_pField->has_focus(); }
+ void save_value() { m_pField->save_value(); }
+ bool get_value_changed_from_saved() const { return m_pField->get_value_changed_from_saved(); }
+ void set_text(const OUString& rStr) { m_pField->set_text(rStr); }
+ void set_accessible_name(const OUString& rStr) { m_pField->set_accessible_name(rStr); }
+ void SetMetricFieldMin(sal_Int64 nNewMin) { m_pField->set_min(nNewMin, FieldUnit::NONE); }
+ void SetMetricFieldMax(sal_Int64 nNewMax) { m_pField->set_max(nNewMax, FieldUnit::NONE); }
+ void SetMetricFieldRange(sal_Int64 nNewMin, sal_Int64 nNewMax) { m_pField->set_range(nNewMin, nNewMax, FieldUnit::NONE); }
+ void GetMetricFieldRange(sal_Int64 &rOldMin, sal_Int64& rOldMax) const { m_pField->get_range(rOldMin, rOldMax, FieldUnit::NONE); }
+
+ void set_value(sal_Int64 nNewValue, FieldUnit eInUnit = FieldUnit::NONE);
+ sal_Int64 get_value(FieldUnit eOutUnit = FieldUnit::NONE);
+
+ void set_min(sal_Int64 nNewMin, FieldUnit eInUnit);
+ void set_max(sal_Int64 nNewMax, FieldUnit eInUnit);
+
+ sal_Int64 get_min(FieldUnit eOutUnit = FieldUnit::NONE) const { return m_pField->get_min(eOutUnit); }
+
+ sal_Int64 NormalizePercent(sal_Int64 nValue);
+ sal_Int64 DenormalizePercent(sal_Int64 nValue);
+
+ void SetRefValue(sal_Int64 nValue);
+ sal_Int64 GetRealValue(FieldUnit eOutUnit);
+
+ sal_Int64 Convert(sal_Int64 nValue, FieldUnit eInUnit, FieldUnit eOutUnit);
+
+ void ShowPercent(bool bPercent);
+
+ void LockAutoCalculation(bool bLock) {m_bLockAutoCalculation = bLock;}
+};
+
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_PRCNTFLD_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/pview.hxx b/sw/source/uibase/inc/pview.hxx
new file mode 100644
index 0000000000..05e1a2a1c2
--- /dev/null
+++ b/sw/source/uibase/inc/pview.hxx
@@ -0,0 +1,303 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_PVIEW_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_PVIEW_HXX
+
+#include <tools/link.hxx>
+#include <tools/fract.hxx>
+#include <vcl/window.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/viewfac.hxx>
+#include <sfx2/viewsh.hxx>
+#include <sfx2/zoomitem.hxx>
+#include <swdllapi.h>
+#include <shellid.hxx>
+
+class SwViewOption;
+class SwDocShell;
+class SwScrollbar;
+class SwViewShell;
+class SwPagePreview;
+class ImageButton;
+class Button;
+class SwRect;
+class DataChangedEvent;
+class CommandEvent;
+class SvtAccessibilityOptions;
+class SwPagePreviewLayout;
+
+/// Provides the VCL widget that is used for the main area of the File -> Print Preview window.
+class SAL_DLLPUBLIC_RTTI SwPagePreviewWin final : public vcl::Window
+{
+ SwViewShell* mpViewShell;
+ sal_uInt16 mnSttPage;
+ sal_Int16 mnRow;
+ sal_Int16 mnCol;
+ Size maPxWinSize;
+ Fraction maScale;
+ SwPagePreview& mrView;
+ bool mbCalcScaleForPreviewLayout;
+ tools::Rectangle maPaintedPreviewDocRect;
+ SwPagePreviewLayout* mpPgPreviewLayout;
+
+ void SetPagePreview( sal_Int16 nRow, sal_Int16 nCol );
+
+ using Window::Scroll;
+
+public:
+ SwPagePreviewWin( vcl::Window* pParent, SwPagePreview& rView );
+ virtual ~SwPagePreviewWin() override;
+
+ // calls SwViewShell::Paint
+ virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override;
+ virtual void KeyInput( const KeyEvent & ) override;
+ virtual void Command( const CommandEvent& rCEvt ) override;
+ virtual void MouseButtonDown(const MouseEvent& rMEvt) override;
+ virtual void DataChanged( const DataChangedEvent& ) override;
+
+ void SetViewShell( SwViewShell* pShell );
+
+ SwViewShell* GetViewShell() const
+ {
+ return mpViewShell;
+ }
+
+ sal_Int16 GetRow() const
+ {
+ return mnRow;
+ }
+
+ sal_Int16 GetCol() const
+ {
+ return mnCol;
+ }
+
+ sal_uInt16 GetSttPage() const
+ {
+ return mnSttPage;
+ }
+
+ void SetSttPage(sal_uInt16 n)
+ {
+ mnSttPage = n;
+ }
+
+ /** get selected page number of document preview
+
+ @return selected page number
+ */
+ sal_uInt16 SelectedPage() const;
+
+ /** set selected page number in document preview
+
+ @param _nSelectedPageNum
+ input parameter - physical page number of page that will be the selected one.
+ */
+ void SetSelectedPage( sal_uInt16 _nSelectedPageNum );
+
+ // If we only have one column we do not have a oth page
+ sal_uInt16 GetDefSttPage() const { return 1 == mnCol ? 1 : 0; }
+
+ void CalcWish( sal_Int16 nNewRow, sal_Int16 nNewCol );
+
+ void SetWinSize( const Size& rNewSize );
+
+ // Add <MV_SELPAGE>, <MV_SCROLL>
+ enum MoveMode{ MV_CALC, MV_PAGE_UP, MV_PAGE_DOWN, MV_DOC_STT, MV_DOC_END,
+ MV_SELPAGE, MV_SCROLL, MV_NEWWINSIZE, MV_SPECIFIC_PAGE };
+ bool MovePage( int eMoveMode );
+
+ // Create the status bar's string
+ OUString GetStatusStr( sal_uInt16 nPageCount ) const;
+
+ void RepaintCoreRect( const SwRect& rRect );
+
+ /** Method to adjust preview to a new zoom factor
+ paint of preview is prepared for a new zoom factor
+ Zoom type has also been considered.
+ Thus, add new parameter <_eZoomType>
+ */
+ void AdjustPreviewToNewZoom( const sal_uInt16 _nZoomFactor,
+ const SvxZoomType _eZoomType );
+
+ const tools::Rectangle& GetPaintedPreviewDocRect() const
+ {
+ return maPaintedPreviewDocRect;
+ }
+
+ void Scroll(tools::Long nXMove, tools::Long nYMove, ScrollFlags nFlags = ScrollFlags::NONE) override;
+
+ /** Method to enable/disable book preview
+ @param _bBookPreview
+ input parameter - boolean indicating, if book preview mode has to
+ switch on <true> or of <false>
+
+ @return boolean indicating, if book preview mode has changed.
+ */
+ bool SetBookPreviewMode( const bool _bBookPreview );
+
+ virtual css::uno::Reference<css::accessibility::XAccessible> CreateAccessible() override;
+};
+
+/**
+ * View of a document
+ */
+class SW_DLLPUBLIC SwPagePreview final : public SfxViewShell
+{
+ // ViewWindow and handle to core
+ // current dispatcher shell
+ VclPtr<SwPagePreviewWin> m_pViewWin;
+ //viewdata of the previous SwView and the new cursor position
+ OUString m_sSwViewData;
+ //and the new cursor position if the user double click in the PagePreview
+ OUString m_sNewCursorPosition;
+ // to support keyboard the number of the page to go to can be set too
+ sal_uInt16 m_nNewPage;
+ // visible range
+ OUString m_sPageStr;
+ Size m_aDocSize;
+ tools::Rectangle m_aVisArea;
+
+ // MDI control elements
+ VclPtr<SwScrollbar> m_pHScrollbar;
+ VclPtr<SwScrollbar> m_pVScrollbar;
+ bool mbHScrollbarEnabled : 1;
+ bool mbVScrollbarEnabled : 1;
+
+ sal_uInt16 mnPageCount;
+ bool m_bNormalPrint;
+
+ // New members to reset design mode at draw view for form shell on switching
+ // back from writer page preview to normal view.
+ bool mbResetFormDesignMode:1;
+ bool mbFormDesignModeToReset:1;
+
+ SAL_DLLPRIVATE void Init();
+ SAL_DLLPRIVATE Point AlignToPixel(const Point& rPt) const;
+
+ SAL_DLLPRIVATE void CreateScrollbar( bool bHori);
+ DECL_DLLPRIVATE_LINK(HoriScrollHdl, weld::Scrollbar&, void);
+ DECL_DLLPRIVATE_LINK(VertScrollHdl, weld::Scrollbar&, void);
+ SAL_DLLPRIVATE void ScrollHdl(weld::Scrollbar&, bool bHorizontal);
+ SAL_DLLPRIVATE void EndScrollHdl(weld::Scrollbar&, bool bHorizontal);
+ SAL_DLLPRIVATE bool ChgPage( int eMvMode, bool bUpdateScrollbar = true );
+
+ SAL_DLLPRIVATE virtual SfxPrinter* GetPrinter( bool bCreate = false ) override;
+ SAL_DLLPRIVATE virtual sal_uInt16 SetPrinter( SfxPrinter *pNewPrinter, SfxPrinterChangeFlags nDiffFlags = SFX_PRINTER_ALL ) override;
+ SAL_DLLPRIVATE virtual bool HasPrintOptionsPage() const override;
+ SAL_DLLPRIVATE virtual std::unique_ptr<SfxTabPage> CreatePrintOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rOptions) override;
+
+ SAL_DLLPRIVATE void CalcAndSetBorderPixel( SvBorder &rToFill );
+
+ /** Helper method to execute SfxRequest FN_PAGE_UP and FN_PAGE_DOWN
+
+ @param _bPgUp
+ input parameter - boolean that indicates, if FN_PAGE_UP or FN_PAGE_DOWN
+ has to be executed.
+
+ @param _pReq
+ optional input parameter - pointer to the <SfxRequest> instance, if existing.
+ */
+ SAL_DLLPRIVATE void ExecPgUpAndPgDown( const bool _bPgUp,
+ SfxRequest* _pReq );
+
+ virtual void InnerResizePixel( const Point &rOfs, const Size &rSize, bool inplaceEditModeChange ) override;
+ virtual void OuterResizePixel( const Point &rOfs, const Size &rSize ) override;
+
+ void Activate(bool bMDI) override;
+
+ void SetZoom(SvxZoomType eSet, sal_uInt16 nFactor);
+
+public:
+ SFX_DECL_VIEWFACTORY(SwPagePreview);
+ SFX_DECL_INTERFACE(SW_PAGEPREVIEW)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwViewShell* GetViewShell() const
+ { return m_pViewWin->GetViewShell(); }
+ void RepaintCoreRect( const SwRect& rRect )
+ { m_pViewWin->RepaintCoreRect( rRect ); }
+
+ void DocSzChgd(const Size& rNewSize);
+
+ void SetVisArea( const tools::Rectangle& );
+
+ void ScrollViewSzChg();
+ void ScrollDocSzChg();
+ void ShowHScrollbar(bool bShow);
+ void ShowVScrollbar(bool bShow);
+ void EnableHScrollbar(bool bEnable);
+ void EnableVScrollbar(bool bEnable);
+
+ sal_uInt16 GetPageCount() const { return mnPageCount; }
+ sal_uInt16 GetSelectedPage() const {return m_pViewWin->SelectedPage();}
+
+ bool HandleWheelCommands( const CommandEvent& );
+
+ const OUString& GetPrevSwViewData() const { return m_sSwViewData; }
+ void SetNewCursorPos( const OUString& rStr ) { m_sNewCursorPosition = rStr; }
+ const OUString& GetNewCursorPos() const { return m_sNewCursorPosition; }
+
+ sal_uInt16 GetNewPage() const {return m_nNewPage;}
+
+ // Handler
+ void Execute(SfxRequest&);
+ void GetState(SfxItemSet&);
+ static void StateUndo(SfxItemSet&);
+
+ SwDocShell* GetDocShell();
+
+ // apply Accessibility options
+ void ApplyAccessibilityOptions();
+
+ // Inline method to request values of new members
+ // <mbResetFormDesignMode> and <mbFormDesignModeToReset>
+ bool ResetFormDesignMode() const
+ {
+ return mbResetFormDesignMode;
+ }
+
+ bool FormDesignModeToReset() const
+ {
+ return mbFormDesignModeToReset;
+ }
+
+ /** Adjust position of vertical scrollbar
+
+ Currently used, if the complete preview layout rows fit into to the given
+ window, if a new page is selected and this page is visible.
+
+ @param _nNewThumbPos
+ input parameter - new position, which will be assigned to the vertical
+ scrollbar.
+ */
+ void SetVScrollbarThumbPos( const sal_uInt16 _nNewThumbPos );
+
+ SwPagePreview(SfxViewFrame& rFrame, SfxViewShell*);
+ virtual ~SwPagePreview() override;
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/redlndlg.hxx b/sw/source/uibase/inc/redlndlg.hxx
new file mode 100644
index 0000000000..c8cfd8cc82
--- /dev/null
+++ b/sw/source/uibase/inc/redlndlg.hxx
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_REDLNDLG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_REDLNDLG_HXX
+#include <swdllapi.h>
+#include "chldwrap.hxx"
+#include <docary.hxx>
+#include <redline.hxx>
+#include <sfx2/sidebar/PanelLayout.hxx>
+#include <sfx2/basedlgs.hxx>
+#include <svl/lstner.hxx>
+#include <svx/ctredlin.hxx>
+#include <o3tl/sorted_vector.hxx>
+
+#include <memory>
+#include <vector>
+
+class SwChildWinWrapper;
+
+struct SwRedlineDataChild
+{
+ const SwRedlineData* pChild; // link to original stacked data
+ const SwRedlineDataChild* pNext; // link to stacked data
+ std::unique_ptr<weld::TreeIter> xTLBChild; // corresponding TreeListBox entry
+};
+
+struct SwRedlineDataParent
+{
+ const SwRedlineData* pData; // RedlineDataPtr
+ const SwRedlineDataChild* pNext; // link to stacked data
+ std::unique_ptr<weld::TreeIter> xTLBParent; // corresponding TreeListBox entry
+ OUString sComment; // redline comment
+
+ bool operator< ( const SwRedlineDataParent& rObj ) const
+ { return (pData && pData->GetSeqNo() < rObj.pData->GetSeqNo()); }
+};
+
+class SwRedlineDataParentSortArr : public o3tl::sorted_vector<SwRedlineDataParent*, o3tl::less_ptr_to<SwRedlineDataParent> > {};
+
+class SW_DLLPUBLIC SwRedlineAcceptDlg final
+{
+ std::shared_ptr<weld::Window> m_xParentDlg;
+ std::vector<std::unique_ptr<SwRedlineDataParent>> m_RedlineParents;
+ std::vector<std::unique_ptr<SwRedlineDataChild>>
+ m_RedlineChildren;
+ // purely here so we don't leak
+ std::vector<std::unique_ptr<RedlinData>>
+ m_RedlinData;
+ SwRedlineDataParentSortArr m_aUsedSeqNo;
+ Timer m_aSelectTimer;
+ OUString m_sInserted;
+ OUString m_sDeleted;
+ OUString m_sFormated;
+ OUString m_sTableChgd;
+ OUString m_sFormatCollSet;
+ OUString m_sFilterAction;
+ OUString m_sAutoFormat;
+ bool m_bOnlyFormatedRedlines;
+ bool m_bRedlnAutoFormat;
+
+ // prevent update dialog data during longer operations (cf #102657#)
+ bool m_bInhibitActivate;
+
+ // table column changes have not continuous redline ranges: it needs major tree list update
+ bool m_bHasTrackedColumn;
+
+ std::unique_ptr<SvxAcceptChgCtr> m_xTabPagesCTRL;
+ std::unique_ptr<weld::Menu> m_xPopup, m_xSortMenu;
+ SvxTPView* m_pTPView;
+ SvxRedlinTable* m_pTable; // PB 2006/02/02 #i48648 now SvHeaderTabListBox
+
+ DECL_DLLPRIVATE_LINK( AcceptHdl, SvxTPView*, void );
+ DECL_DLLPRIVATE_LINK( AcceptAllHdl, SvxTPView*, void );
+ DECL_DLLPRIVATE_LINK( RejectHdl, SvxTPView*, void );
+ DECL_DLLPRIVATE_LINK( RejectAllHdl, SvxTPView*, void );
+ DECL_DLLPRIVATE_LINK( UndoHdl, SvxTPView*, void );
+ DECL_DLLPRIVATE_LINK( SelectHdl, weld::TreeView&, void );
+ DECL_DLLPRIVATE_LINK( GotoHdl, Timer*, void );
+ DECL_DLLPRIVATE_LINK( CommandHdl, const CommandEvent&, bool );
+
+ SAL_DLLPRIVATE SwRedlineTable::size_type CalcDiff(SwRedlineTable::size_type nStart, bool bChild);
+ SAL_DLLPRIVATE void InsertChildren(SwRedlineDataParent *pParent, const SwRangeRedline& rRedln, bool bHasRedlineAutoFormat);
+ SAL_DLLPRIVATE void InsertParents(SwRedlineTable::size_type nStart, SwRedlineTable::size_type nEnd = SwRedlineTable::npos);
+ SAL_DLLPRIVATE void RemoveParents(SwRedlineTable::size_type nStart, SwRedlineTable::size_type nEnd);
+ SAL_DLLPRIVATE void InitAuthors();
+
+ SAL_DLLPRIVATE static OUString GetActionImage(const SwRangeRedline& rRedln, sal_uInt16 nStack = 0,
+ bool bTableChanges = false, bool bRowChanges = false);
+ SAL_DLLPRIVATE OUString GetActionText(const SwRangeRedline& rRedln, sal_uInt16 nStack = 0);
+ SAL_DLLPRIVATE SwRedlineTable::size_type GetRedlinePos(const weld::TreeIter& rEntry);
+
+ SwRedlineAcceptDlg(SwRedlineAcceptDlg const&) = delete;
+ SwRedlineAcceptDlg& operator=(SwRedlineAcceptDlg const&) = delete;
+
+public:
+ SwRedlineAcceptDlg(std::shared_ptr<weld::Window> xParent, weld::Builder *pBuilder, weld::Container *pContentArea, bool bAutoFormat = false);
+ ~SwRedlineAcceptDlg();
+
+ DECL_LINK( FilterChangedHdl, SvxTPFilter*, void );
+
+ SvxAcceptChgCtr& GetChgCtrl() { return *m_xTabPagesCTRL; }
+ bool HasRedlineAutoFormat() const { return m_bRedlnAutoFormat; }
+
+ void Init(SwRedlineTable::size_type nStart = 0);
+ void CallAcceptReject( bool bSelect, bool bAccept );
+
+ void Initialize(OUString &rExtraData);
+ void FillInfo(OUString &rExtraData) const;
+
+ void Activate();
+};
+
+class SwModelessRedlineAcceptDlg final : public SfxModelessDialogController
+{
+ std::unique_ptr<weld::Container> m_xContentArea;
+ std::unique_ptr<SwRedlineAcceptDlg> m_xImplDlg;
+ SwChildWinWrapper* m_pChildWin;
+
+public:
+ SwModelessRedlineAcceptDlg(SfxBindings*, SwChildWinWrapper*, weld::Window *pParent);
+ virtual ~SwModelessRedlineAcceptDlg() override;
+
+ virtual void Activate() override;
+ virtual void FillInfo(SfxChildWinInfo&) const override;
+ void Initialize(SfxChildWinInfo * pInfo);
+};
+
+class SwRedlineAcceptChild final : public SwChildWinWrapper
+{
+public:
+ SwRedlineAcceptChild(vcl::Window* ,
+ sal_uInt16 nId,
+ SfxBindings*,
+ SfxChildWinInfo*);
+
+ SFX_DECL_CHILDWINDOW_WITHID( SwRedlineAcceptChild );
+
+ virtual bool ReInitDlg(SwDocShell *pDocSh) override;
+};
+
+/// Redline (Manage Changes) panel for the sidebar.
+class SwRedlineAcceptPanel final : public PanelLayout, public SfxListener
+{
+ std::unique_ptr<SwRedlineAcceptDlg> mpImplDlg;
+ std::unique_ptr<weld::Container> mxContentArea;
+public:
+ SwRedlineAcceptPanel(weld::Widget* pParent);
+ virtual ~SwRedlineAcceptPanel() override;
+
+ /// We need to be a SfxListener to be able to update the list of changes when we get SfxHintId::DocChanged.
+ virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/regionsw.hxx b/sw/source/uibase/inc/regionsw.hxx
new file mode 100644
index 0000000000..410b9d6db8
--- /dev/null
+++ b/sw/source/uibase/inc/regionsw.hxx
@@ -0,0 +1,255 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_REGIONSW_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_REGIONSW_HXX
+
+#include <sfx2/basedlgs.hxx>
+#include <sfx2/tabdlg.hxx>
+
+#include "condedit.hxx"
+#include <section.hxx>
+#include <fmtftntx.hxx>
+#include "numberingtypelistbox.hxx"
+#include <svx/paraprev.hxx>
+
+#include <memory>
+#include <map>
+
+class SwWrtShell;
+
+namespace sfx2
+{
+ class DocumentInserter;
+ class FileDialogHelper;
+}
+
+// dialog "edit regions"
+class SectRepr;
+typedef std::map<size_t, std::unique_ptr<SectRepr>> SectReprs_t;
+
+class SwEditRegionDlg final : public SfxDialogController
+{
+ bool m_bSubRegionsFilled;
+
+ SwWrtShell& m_rSh;
+ SectReprs_t m_SectReprs;
+ const SwSection* m_pCurrSect;
+ std::unique_ptr<sfx2::DocumentInserter> m_pDocInserter;
+
+ bool m_bDontCheckPasswd :1;
+
+ std::unique_ptr<weld::Entry> m_xCurName;
+ std::unique_ptr<weld::TreeView> m_xTree;
+ std::unique_ptr<weld::CheckButton> m_xFileCB;
+ std::unique_ptr<weld::CheckButton> m_xDDECB;
+ std::unique_ptr<weld::Widget> m_xDDEFrame;
+ std::unique_ptr<weld::Label> m_xFileNameFT;
+ std::unique_ptr<weld::Label> m_xDDECommandFT;
+ std::unique_ptr<weld::Entry> m_xFileNameED;
+ std::unique_ptr<weld::Button> m_xFilePB;
+ std::unique_ptr<weld::Label> m_xSubRegionFT;
+ std::unique_ptr<weld::ComboBox> m_xSubRegionED;
+ std::unique_ptr<weld::CheckButton> m_xProtectCB;
+ std::unique_ptr<weld::CheckButton> m_xPasswdCB;
+ std::unique_ptr<weld::Button> m_xPasswdPB;
+ std::unique_ptr<weld::CheckButton> m_xHideCB;
+ std::unique_ptr<weld::Label> m_xConditionFT;
+ std::unique_ptr<ConditionEdit> m_xConditionED;
+ // #114856# edit in readonly sections
+ std::unique_ptr<weld::CheckButton> m_xEditInReadonlyCB;
+ std::unique_ptr<weld::Button> m_xOK;
+ std::unique_ptr<weld::Button> m_xOptionsPB;
+ std::unique_ptr<weld::Button> m_xDismiss;
+ std::unique_ptr<weld::Widget> m_xHideFrame;
+
+ void RecurseList(const SwSectionFormat* pFormat, const weld::TreeIter* pIter);
+ size_t FindArrPos(const SwSectionFormat* pFormat);
+
+ DECL_LINK( GetFirstEntryHdl, weld::TreeView&, void );
+
+ DECL_LINK( OkHdl, weld::Button&, void );
+ DECL_LINK( NameEditHdl, weld::Entry&, void );
+ DECL_LINK( ConditionEditHdl, weld::Entry&, void );
+
+ void ChangePasswd(bool bChange);
+ DECL_LINK( TogglePasswdHdl, weld::Toggleable&, void );
+ DECL_LINK( ChangePasswdHdl, weld::Button&, void );
+ DECL_LINK( ChangeProtectHdl, weld::Toggleable&, void );
+ DECL_LINK( ChangeHideHdl, weld::Toggleable&, void );
+ // #114856# edit in readonly sections
+ DECL_LINK( ChangeEditInReadonlyHdl, weld::Toggleable&, void );
+ DECL_LINK( ChangeDismissHdl, weld::Button&, void);
+ DECL_LINK( UseFileHdl, weld::Toggleable&, void );
+ DECL_LINK( FileSearchHdl, weld::Button&, void );
+ DECL_LINK( OptionsHdl, weld::Button&, void );
+ DECL_LINK( FileNameComboBoxHdl, weld::ComboBox&, void );
+ DECL_LINK( FileNameEntryHdl, weld::Entry&, void );
+ DECL_LINK( DDEHdl, weld::Toggleable&, void );
+ DECL_LINK( DlgClosedHdl, sfx2::FileDialogHelper*, void );
+ DECL_LINK( SubRegionEventHdl, weld::ComboBox&, void );
+
+ bool CheckPasswd(weld::Toggleable* pBox = nullptr);
+
+public:
+ SwEditRegionDlg(weld::Window* pParent, SwWrtShell& rWrtSh);
+ virtual ~SwEditRegionDlg() override;
+
+ void SelectSection(std::u16string_view rSectionName);
+
+};
+
+// dialog "insert region"
+class SwInsertSectionTabPage final : public SfxTabPage
+{
+ OUString m_sFileName;
+ OUString m_sFilterName;
+ OUString m_sFilePasswd;
+
+ css::uno::Sequence <sal_Int8 > m_aNewPasswd;
+ SwWrtShell* m_pWrtSh;
+ std::unique_ptr<sfx2::DocumentInserter> m_pDocInserter;
+
+ std::unique_ptr<weld::EntryTreeView> m_xCurName;
+ std::unique_ptr<weld::CheckButton> m_xFileCB;
+ std::unique_ptr<weld::CheckButton> m_xDDECB;
+ std::unique_ptr<weld::Label> m_xDDECommandFT;
+ std::unique_ptr<weld::Label> m_xFileNameFT;
+ std::unique_ptr<weld::Entry> m_xFileNameED;
+ std::unique_ptr<weld::Button> m_xFilePB;
+ std::unique_ptr<weld::Label> m_xSubRegionFT;
+ std::unique_ptr<weld::ComboBox> m_xSubRegionED;
+ std::unique_ptr<weld::CheckButton> m_xProtectCB;
+ std::unique_ptr<weld::CheckButton> m_xPasswdCB;
+ std::unique_ptr<weld::Button> m_xPasswdPB;
+ std::unique_ptr<weld::CheckButton> m_xHideCB;
+ std::unique_ptr<weld::Label> m_xConditionFT;
+ std::unique_ptr<ConditionEdit> m_xConditionED;
+ // #114856# edit in readonly sections
+ std::unique_ptr<weld::CheckButton> m_xEditInReadonlyCB;
+
+ void ChangePasswd(bool bChange);
+
+ DECL_LINK( ChangeHideHdl, weld::Toggleable&, void );
+ DECL_LINK( ChangeProtectHdl, weld::Toggleable&, void );
+ DECL_LINK( ChangePasswdHdl, weld::Button&, void );
+ DECL_LINK( TogglePasswdHdl, weld::Toggleable&, void );
+ DECL_LINK( NameEditHdl, weld::ComboBox&, void );
+ DECL_LINK( UseFileHdl, weld::Toggleable&, void );
+ DECL_LINK( FileSearchHdl, weld::Button&, void );
+ DECL_LINK( DDEHdl, weld::Toggleable&, void );
+ DECL_LINK( DlgClosedHdl, sfx2::FileDialogHelper*, void );
+
+public:
+ SwInsertSectionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rAttrSet);
+ virtual ~SwInsertSectionTabPage() override;
+
+ void SetWrtShell(SwWrtShell& rSh);
+
+ virtual bool FillItemSet( SfxItemSet* ) override;
+ virtual void Reset( const SfxItemSet* ) override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet);
+};
+
+class SwSectionFootnoteEndTabPage final : public SfxTabPage
+{
+ std::unique_ptr<weld::CheckButton> m_xFootnoteNtAtTextEndCB;
+ std::unique_ptr<weld::CheckButton> m_xFootnoteNtNumCB;
+ std::unique_ptr<weld::Label> m_xFootnoteOffsetLbl;
+ std::unique_ptr<weld::SpinButton> m_xFootnoteOffsetField;
+ std::unique_ptr<weld::CheckButton> m_xFootnoteNtNumFormatCB;
+ std::unique_ptr<weld::Label> m_xFootnotePrefixFT;
+ std::unique_ptr<weld::Entry> m_xFootnotePrefixED;
+ std::unique_ptr<SwNumberingTypeListBox> m_xFootnoteNumViewBox;
+ std::unique_ptr<weld::Label> m_xFootnoteSuffixFT;
+ std::unique_ptr<weld::Entry> m_xFootnoteSuffixED;
+ std::unique_ptr<weld::CheckButton> m_xEndNtAtTextEndCB;
+ std::unique_ptr<weld::CheckButton> m_xEndNtNumCB;
+ std::unique_ptr<weld::Label> m_xEndOffsetLbl;
+ std::unique_ptr<weld::SpinButton> m_xEndOffsetField;
+ std::unique_ptr<weld::CheckButton> m_xEndNtNumFormatCB;
+ std::unique_ptr<weld::Label> m_xEndPrefixFT;
+ std::unique_ptr<weld::Entry> m_xEndPrefixED;
+ std::unique_ptr<SwNumberingTypeListBox> m_xEndNumViewBox;
+ std::unique_ptr<weld::Label> m_xEndSuffixFT;
+ std::unique_ptr<weld::Entry> m_xEndSuffixED;
+
+ DECL_LINK(FootEndHdl, weld::Toggleable&, void);
+ void ResetState( bool bFootnote, const SwFormatFootnoteEndAtTextEnd& );
+
+public:
+ SwSectionFootnoteEndTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rAttrSet);
+ virtual ~SwSectionFootnoteEndTabPage() override;
+
+ virtual bool FillItemSet( SfxItemSet* ) override;
+ virtual void Reset( const SfxItemSet* ) override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet);
+};
+
+class SwSectionIndentTabPage final : public SfxTabPage
+{
+ SvxParaPrevWindow m_aPreviewWin;
+ std::unique_ptr<weld::MetricSpinButton> m_xBeforeMF;
+ std::unique_ptr<weld::MetricSpinButton> m_xAfterMF;
+ std::unique_ptr<weld::CustomWeld> m_xPreviewWin;
+
+ DECL_LINK(IndentModifyHdl, weld::MetricSpinButton&, void);
+public:
+ SwSectionIndentTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rAttrSet);
+ virtual ~SwSectionIndentTabPage() override;
+
+ virtual bool FillItemSet( SfxItemSet* ) override;
+ virtual void Reset( const SfxItemSet* ) override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+
+ void SetWrtShell(SwWrtShell const & rSh);
+};
+
+class SwInsertSectionTabDialog final : public SfxTabDialogController
+{
+ SwWrtShell& m_rWrtSh;
+ std::unique_ptr<SwSectionData> m_pSectionData;
+
+ virtual void PageCreated(const OUString& rId, SfxTabPage &rPage) override;
+ virtual short Ok() override;
+public:
+ SwInsertSectionTabDialog(weld::Window* pParent, const SfxItemSet& rSet, SwWrtShell& rSh);
+ virtual ~SwInsertSectionTabDialog() override;
+
+ void SetSectionData(SwSectionData const& rSect);
+ SwSectionData * GetSectionData() { return m_pSectionData.get(); }
+};
+
+class SwSectionPropertyTabDialog final : public SfxTabDialogController
+{
+ SwWrtShell& m_rWrtSh;
+
+ virtual void PageCreated(const OUString& rId, SfxTabPage &rPage) override;
+public:
+ SwSectionPropertyTabDialog(weld::Window* pParent, const SfxItemSet& rSet, SwWrtShell& rSh);
+ virtual ~SwSectionPropertyTabDialog() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/rowht.hxx b/sw/source/uibase/inc/rowht.hxx
new file mode 100644
index 0000000000..659b9ac633
--- /dev/null
+++ b/sw/source/uibase/inc/rowht.hxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_ROWHT_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_ROWHT_HXX
+
+#include <vcl/weld.hxx>
+
+class SwWrtShell;
+
+class SwTableHeightDlg final : public weld::GenericDialogController
+{
+ SwWrtShell& m_rSh;
+
+ std::unique_ptr<weld::MetricSpinButton> m_xHeightEdit;
+ std::unique_ptr<weld::CheckButton> m_xAutoHeightCB;
+
+private:
+ void Apply();
+
+public:
+ SwTableHeightDlg(weld::Window* pParent, SwWrtShell& rS);
+ virtual short run() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/scroll.hxx b/sw/source/uibase/inc/scroll.hxx
new file mode 100644
index 0000000000..dcf8bd174b
--- /dev/null
+++ b/sw/source/uibase/inc/scroll.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <svtools/scrolladaptor.hxx>
+
+class SwScrollbar final : public ScrollAdaptor
+{
+ Size m_aDocSz;
+ bool m_bAuto :1; // for scrolling mode
+ bool m_bVisible :1; // show/hide should only set this flag
+ bool m_bSizeSet :1; // was the size already set?
+
+ void AutoShow();
+
+public:
+ void ExtendedShow( bool bVisible = true );
+ void SetPosSizePixel( const Point& rNewPos, const Size& rNewSize ) override;
+ bool IsScrollbarVisible(bool bReal) const { return bReal ? ScrollAdaptor::IsVisible() : m_bVisible; }
+
+ // changing of document size
+ void DocSzChgd(const Size &rNewSize);
+ // changing of visible region
+ void ViewPortChgd(const tools::Rectangle &rRectangle);
+
+ void SetAuto(bool bSet);
+ bool IsAuto() const { return m_bAuto;}
+
+ SwScrollbar(vcl::Window *pParent, bool bHori );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/selglos.hxx b/sw/source/uibase/inc/selglos.hxx
new file mode 100644
index 0000000000..fd5de37963
--- /dev/null
+++ b/sw/source/uibase/inc/selglos.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <vcl/weld.hxx>
+
+class SwSelGlossaryDlg final : public weld::GenericDialogController
+{
+ std::unique_ptr<weld::Frame> m_xFrame;
+ std::unique_ptr<weld::TreeView> m_xGlosBox;
+
+ DECL_LINK(DoubleClickHdl, weld::TreeView&, bool);
+public:
+ SwSelGlossaryDlg(weld::Window * pParent, std::u16string_view rShortName);
+ virtual ~SwSelGlossaryDlg() override;
+
+ void InsertGlos(std::u16string_view rRegion, std::u16string_view rGlosName)
+ {
+ const OUString aTmp = OUString::Concat(rRegion) + ":" + rGlosName;
+ m_xGlosBox->append_text(aTmp);
+ }
+ sal_Int32 GetSelectedIdx() const
+ {
+ return m_xGlosBox->get_selected_index();
+ }
+ void SelectEntryPos(sal_Int32 nIdx)
+ {
+ m_xGlosBox->select(nIdx);
+ }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/sharedconnection.hxx b/sw/source/uibase/inc/sharedconnection.hxx
new file mode 100644
index 0000000000..58d5dfcfc3
--- /dev/null
+++ b/sw/source/uibase/inc/sharedconnection.hxx
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SHAREDCONNECTION_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SHAREDCONNECTION_HXX
+
+#include <unotools/sharedunocomponent.hxx>
+#include <com/sun/star/sdbc/XConnection.hpp>
+
+typedef ::utl::SharedUNOComponent<css::sdbc::XConnection> SharedConnection;
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_SHAREDCONNECTION_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/shdwcrsr.hxx b/sw/source/uibase/inc/shdwcrsr.hxx
new file mode 100644
index 0000000000..55f94f4563
--- /dev/null
+++ b/sw/source/uibase/inc/shdwcrsr.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SHDWCRSR_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SHDWCRSR_HXX
+
+#include <tools/gen.hxx>
+#include <vcl/vclptr.hxx>
+#include <vcl/window.hxx>
+#include <limits.h>
+
+class SwShadowCursor
+{
+ VclPtr<vcl::Window> m_pWin;
+ Point m_aOldPt;
+ tools::Long m_nOldHeight;
+ sal_uInt16 m_nOldMode;
+
+ void DrawCursor( sal_uInt16 nMode );
+
+public:
+ SwShadowCursor( vcl::Window& rWin )
+ : m_pWin( &rWin ), m_nOldHeight(0), m_nOldMode( USHRT_MAX ) {}
+ ~SwShadowCursor();
+
+ void SetPos( const Point& rPt, tools::Long nHeight, sal_uInt16 nMode );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/splittbl.hxx b/sw/source/uibase/inc/splittbl.hxx
new file mode 100644
index 0000000000..c579eea177
--- /dev/null
+++ b/sw/source/uibase/inc/splittbl.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <vcl/weld.hxx>
+#include <tblenum.hxx>
+#include <unotools/viewoptions.hxx>
+
+class SwWrtShell;
+
+class SwSplitTableDlg final : public weld::GenericDialogController
+{
+private:
+ std::unique_ptr<weld::RadioButton> m_xBoxAttrCopyWithParaRB;
+ std::unique_ptr<weld::RadioButton> m_xBoxAttrCopyNoParaRB;
+ std::unique_ptr<weld::RadioButton> m_xBorderCopyRB;
+
+ SwWrtShell& m_rShell;
+ SplitTable_HeadlineOption m_nSplit;
+
+ // tdf#131759 - remember last used option in split table dialog
+ static SplitTable_HeadlineOption m_eRememberedSplitOption;
+
+ void Apply();
+
+public:
+ SwSplitTableDlg(weld::Window* pParent, SwWrtShell& rSh);
+
+ virtual short run() override
+ {
+ short nRet = GenericDialogController::run();
+ if (nRet == RET_OK)
+ Apply();
+ return nRet;
+ }
+
+ SplitTable_HeadlineOption GetSplitMode() const
+ {
+ auto nSplit = SplitTable_HeadlineOption::ContentCopy;
+ if (m_xBoxAttrCopyWithParaRB->get_active())
+ nSplit = SplitTable_HeadlineOption::BoxAttrAllCopy;
+ else if (m_xBoxAttrCopyNoParaRB->get_active())
+ nSplit = SplitTable_HeadlineOption::BoxAttrCopy;
+ else if (m_xBorderCopyRB->get_active())
+ nSplit = SplitTable_HeadlineOption::BorderCopy;
+
+ // tdf#131759 - remember last used option in split table dialog
+ m_eRememberedSplitOption = nSplit;
+
+ return nSplit;
+ }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/srcedtw.hxx b/sw/source/uibase/inc/srcedtw.hxx
new file mode 100644
index 0000000000..7e71758191
--- /dev/null
+++ b/sw/source/uibase/inc/srcedtw.hxx
@@ -0,0 +1,144 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SRCEDTW_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SRCEDTW_HXX
+
+#include <vcl/window.hxx>
+#include <svl/lstner.hxx>
+#include <vcl/timer.hxx>
+#include <vcl/idle.hxx>
+
+#include <vcl/xtextedt.hxx>
+#include <mutex>
+#include <set>
+
+namespace com::sun::star::beans { class XMultiPropertySet; }
+namespace weld { class Scrollbar; }
+class ScrollAdaptor;
+class SwSrcView;
+class SwSrcEditWindow;
+class TextEngine;
+class TextView;
+class DataChangedEvent;
+
+class TextViewOutWin final : public vcl::Window
+{
+ TextView* m_pTextView;
+
+ virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& ) override;
+ virtual void KeyInput( const KeyEvent& rKeyEvt ) override;
+ virtual void MouseMove( const MouseEvent& rMEvt ) override;
+ virtual void MouseButtonDown( const MouseEvent& rMEvt ) override;
+ virtual void MouseButtonUp( const MouseEvent& rMEvt ) override;
+ virtual void Command( const CommandEvent& rCEvt ) override;
+ virtual void DataChanged( const DataChangedEvent& ) override;
+
+public:
+ TextViewOutWin(vcl::Window* pParent, WinBits nBits) :
+ Window(pParent, nBits), m_pTextView(nullptr){}
+
+ void SetTextView( TextView* pView ) {m_pTextView = pView;}
+
+};
+
+class SwSrcEditWindow final : public vcl::Window, public SfxListener
+{
+private:
+ class ChangesListener;
+ friend class ChangesListener;
+ std::unique_ptr<TextView> m_pTextView;
+ std::unique_ptr<ExtTextEngine> m_pTextEngine;
+
+ VclPtr<TextViewOutWin> m_pOutWin;
+ VclPtr<ScrollAdaptor> m_pHScrollbar,
+ m_pVScrollbar;
+
+ SwSrcView* m_pSrcView;
+
+ rtl::Reference< ChangesListener > m_xListener;
+ std::mutex mutex_;
+ css::uno::Reference< css::beans::XMultiPropertySet >
+ m_xNotifier;
+
+ tools::Long m_nCurTextWidth;
+ sal_uInt16 m_nStartLine;
+ rtl_TextEncoding m_eSourceEncoding;
+ bool m_bReadonly;
+ bool m_bHighlighting;
+
+ Idle m_aSyntaxIdle;
+ std::set<sal_uInt16> m_aSyntaxLineTable;
+
+ void ImpDoHighlight( std::u16string_view aSource, sal_uInt16 nLineOff );
+
+ void SetFont();
+
+ DECL_LINK( SyntaxTimerHdl, Timer *, void );
+
+ virtual void Resize() override;
+ virtual void DataChanged( const DataChangedEvent& ) override;
+ virtual void GetFocus() override;
+
+ void CreateTextEngine();
+ void DoSyntaxHighlight( sal_uInt16 nPara );
+
+ virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
+
+ DECL_LINK(HorzScrollHdl, weld::Scrollbar&, void);
+ DECL_LINK(VertScrollHdl, weld::Scrollbar&, void);
+
+public:
+ SwSrcEditWindow( vcl::Window* pParent, SwSrcView* pParentView );
+ virtual ~SwSrcEditWindow() override;
+ virtual void dispose() override;
+
+ void SetScrollBarRanges();
+ void InitScrollBars();
+ void Read(SvStream& rInput) { m_pTextEngine->Read(rInput); }
+ void Write(SvStream& rOutput) { m_pTextEngine->Write(rOutput); }
+
+ TextView* GetTextView()
+ {return m_pTextView.get();}
+ TextEngine* GetTextEngine()
+ {return m_pTextEngine.get();}
+ SwSrcView* GetSrcView() {return m_pSrcView;}
+
+ TextViewOutWin* GetOutWin() {return m_pOutWin;}
+
+ virtual void ImplInvalidate( const vcl::Region* pRegion, InvalidateFlags nFlags ) override;
+
+ void ClearModifyFlag()
+ { m_pTextEngine->SetModified(false); }
+ bool IsModified() const
+ { return m_pTextEngine->IsModified();}
+
+ void SetReadonly(bool bSet){m_bReadonly = bSet;}
+ bool IsReadonly() const {return m_bReadonly;}
+
+ void SetStartLine(sal_uInt16 nLine){m_nStartLine = nLine;}
+
+ virtual void Command( const CommandEvent& rCEvt ) override;
+ void HandleWheelCommand( const CommandEvent& rCEvt );
+
+ void SetTextEncoding(rtl_TextEncoding eEncoding);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/srcview.hxx b/sw/source/uibase/inc/srcview.hxx
new file mode 100644
index 0000000000..4b540aed2f
--- /dev/null
+++ b/sw/source/uibase/inc/srcview.hxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SRCVIEW_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SRCVIEW_HXX
+
+#include <sfx2/viewfac.hxx>
+#include <sfx2/viewsh.hxx>
+#include <vcl/outdev.hxx>
+
+#include "srcedtw.hxx"
+#include <shellid.hxx>
+
+class SwDocShell;
+class SvxSearchItem;
+class SfxMedium;
+
+class SwSrcView final : public SfxViewShell
+{
+ VclPtr<SwSrcEditWindow> m_aEditWin;
+
+ std::unique_ptr<SvxSearchItem> m_pSearchItem;
+
+ bool m_bSourceSaved :1;
+ rtl_TextEncoding m_eLoadEncoding;
+ void Init();
+
+ // for read-only switching
+ virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
+
+ void StartSearchAndReplace(const SvxSearchItem& rItem,
+ bool bApi,
+ bool bRecursive = false);
+
+public:
+ SFX_DECL_VIEWFACTORY(SwSrcView);
+ SFX_DECL_INTERFACE(SW_SRC_VIEWSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwSrcView(SfxViewFrame& rFrame, SfxViewShell*);
+
+ virtual ~SwSrcView() override;
+
+ SwDocShell* GetDocShell();
+ void SaveContent(const OUString& rTmpFile);
+ void SaveContentTo(SfxMedium& rMed);
+
+ bool IsModified() const {return m_aEditWin->IsModified();}
+
+ void Execute(SfxRequest&);
+ void GetState(SfxItemSet&);
+
+ SvxSearchItem* GetSearchItem();
+ void SetSearchItem( const SvxSearchItem& rItem );
+
+ void Load(SwDocShell* pDocShell);
+
+ virtual sal_uInt16 SetPrinter( SfxPrinter* pNew, SfxPrinterChangeFlags nDiff = SFX_PRINTER_ALL ) override;
+ virtual SfxPrinter* GetPrinter( bool bCreate = false ) override;
+
+ sal_Int32 PrintSource( OutputDevice *pOutDev, sal_Int32 nPage, bool bCalcNumPagesOnly );
+
+ bool HasSourceSaved() const {return m_bSourceSaved;}
+
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/srtdlg.hxx b/sw/source/uibase/inc/srtdlg.hxx
new file mode 100644
index 0000000000..5909887354
--- /dev/null
+++ b/sw/source/uibase/inc/srtdlg.hxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SRTDLG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SRTDLG_HXX
+
+#include <svtools/collatorres.hxx>
+#include <svx/langbox.hxx>
+#include <vcl/weld.hxx>
+
+class SwWrtShell;
+
+class SwSortDlg final : public weld::GenericDialogController
+{
+ weld::Window* m_pParent;
+ std::unique_ptr<weld::Label> m_xColLbl;
+
+ std::unique_ptr<weld::CheckButton> m_xKeyCB1;
+ std::unique_ptr<weld::SpinButton> m_xColEdt1;
+ std::unique_ptr<weld::ComboBox> m_xTypDLB1;
+ std::unique_ptr<weld::RadioButton> m_xSortUp1RB;
+ std::unique_ptr<weld::RadioButton> m_xSortDn1RB;
+
+ std::unique_ptr<weld::CheckButton> m_xKeyCB2;
+ std::unique_ptr<weld::SpinButton> m_xColEdt2;
+ std::unique_ptr<weld::ComboBox> m_xTypDLB2;
+ std::unique_ptr<weld::RadioButton> m_xSortUp2RB;
+ std::unique_ptr<weld::RadioButton> m_xSortDn2RB;
+
+ std::unique_ptr<weld::CheckButton> m_xKeyCB3;
+ std::unique_ptr<weld::SpinButton> m_xColEdt3;
+ std::unique_ptr<weld::ComboBox> m_xTypDLB3;
+ std::unique_ptr<weld::RadioButton> m_xSortUp3RB;
+ std::unique_ptr<weld::RadioButton> m_xSortDn3RB;
+
+ std::unique_ptr<weld::RadioButton> m_xColumnRB;
+ std::unique_ptr<weld::RadioButton> m_xRowRB;
+
+ std::unique_ptr<weld::RadioButton> m_xDelimTabRB;
+ std::unique_ptr<weld::RadioButton> m_xDelimFreeRB;
+ std::unique_ptr<weld::Entry> m_xDelimEdt;
+ std::unique_ptr<weld::Button> m_xDelimPB;
+
+ std::unique_ptr<SvxLanguageBox> m_xLangLB;
+
+ std::unique_ptr<weld::CheckButton> m_xCaseCB;
+
+ OUString m_aColText;
+ OUString m_aRowText;
+ OUString m_aNumericText;
+
+ SwWrtShell& m_rSh;
+ std::unique_ptr<CollatorResource> m_xColRes;
+
+ sal_uInt16 m_nX;
+ sal_uInt16 m_nY;
+
+ void Apply();
+ sal_Unicode GetDelimChar() const;
+
+ DECL_LINK(CheckHdl, weld::Toggleable&, void);
+ DECL_LINK(DelimHdl, weld::Toggleable&, void);
+ DECL_LINK(LanguageListBoxHdl, weld::ComboBox&, void);
+ void LanguageHdl(weld::ComboBox const*);
+ DECL_LINK(DelimCharHdl, weld::Button&, void);
+
+public:
+ SwSortDlg(weld::Window* pParent, SwWrtShell& rSh);
+ virtual short run() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/swcont.hxx b/sw/source/uibase/inc/swcont.hxx
new file mode 100644
index 0000000000..b29489f098
--- /dev/null
+++ b/sw/source/uibase/inc/swcont.hxx
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SWCONT_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SWCONT_HXX
+
+#include <rtl/ustring.hxx>
+#include <tools/long.hxx>
+#include <vcl/naturalsort.hxx>
+
+class SwContentType;
+
+enum class ContentTypeId
+{
+ OUTLINE = 0,
+ TABLE = 1,
+ FRAME = 2,
+ GRAPHIC = 3,
+ OLE = 4,
+ BOOKMARK = 5,
+ REGION = 6,
+ URLFIELD = 7,
+ REFERENCE = 8,
+ INDEX = 9,
+ POSTIT = 10,
+ DRAWOBJECT = 11,
+ TEXTFIELD = 12,
+ FOOTNOTE = 13,
+ ENDNOTE = 14,
+ LAST = ENDNOTE,
+ UNKNOWN = -1
+};
+
+// strings for context menus
+#define CONTEXT_COUNT 17
+#define GLOBAL_CONTEXT_COUNT 14
+
+// modes for Drag 'n Drop
+enum class RegionMode
+{
+ NONE = 0,
+ LINK = 1,
+ EMBEDDED = 2
+};
+
+//mini rtti
+class SwTypeNumber
+{
+ sal_uInt8 m_nTypeId;
+
+ public:
+ SwTypeNumber(sal_uInt8 nId) :m_nTypeId(nId){}
+ virtual ~SwTypeNumber();
+
+ sal_uInt8 GetTypeId() const { return m_nTypeId;}
+};
+
+class SwContent : public SwTypeNumber
+{
+ const SwContentType* m_pParent;
+ OUString m_sContentName;
+ double m_nYPosition;
+ // some subclasses appear to use this for a tools/gen.hxx-style
+ // geometric Y position, while e.g. SwOutlineContent wants to store
+ // the index in its subtree
+ bool m_bInvisible;
+public:
+ SwContent(const SwContentType* pCnt, OUString aName, double nYPos);
+
+ virtual bool IsProtect() const;
+ const SwContentType* GetParent() const {return m_pParent;}
+ const OUString& GetName() const {return m_sContentName;}
+ bool operator==(const SwContent& /*rCont*/) const
+ {
+ // they're never equal, otherwise they'd fall out of the array
+ return false;
+ }
+ bool operator<(const SwContent& rCont) const
+ {
+ // at first sort by position and then by name
+ if (m_nYPosition != rCont.m_nYPosition)
+ return m_nYPosition < rCont.m_nYPosition;
+ return vcl::NaturalSortCompare(m_sContentName, rCont.m_sContentName) < 0;
+ }
+
+ bool IsInvisible() const {return m_bInvisible;}
+ void SetInvisible(){ m_bInvisible = true;}
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/swdtflvr.hxx b/sw/source/uibase/inc/swdtflvr.hxx
new file mode 100644
index 0000000000..6234bd3729
--- /dev/null
+++ b/sw/source/uibase/inc/swdtflvr.hxx
@@ -0,0 +1,251 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SWDTFLVR_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SWDTFLVR_HXX
+
+#include <sfx2/objsh.hxx>
+
+#include <vcl/transfer.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/vclptr.hxx>
+#include <sfx2/lnkbase.hxx>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
+#include <o3tl/deleter.hxx>
+#include <o3tl/typed_flags_set.hxx>
+#include <svx/swframetypes.hxx>
+#include <svl/urlbmk.hxx>
+#include <memory>
+#include <optional>
+
+#include <swdllapi.h>
+
+class Graphic;
+class ImageMap;
+class INetImage;
+class SfxAbstractPasteDialog;
+class SwDoc;
+class SwDocFac;
+class SwPaM;
+class SwTextBlocks;
+class SwWrtShell;
+class SvxClipboardFormatItem;
+class SwFrameShell;
+class SwView_Impl;
+class SwPasteContext;
+enum class SwPasteSdr;
+
+enum class TransferBufferType : sal_uInt16
+{
+ NONE = 0x0000,
+ Document = 0x0001,
+ DocumentWord = 0x0002,
+ Graphic = 0x0004,
+ Table = 0x0008,
+ Ole = 0x0020,
+ InetField = 0x0040,
+ Drawing = 0x0081, // drawing is internal too!
+};
+namespace o3tl {
+ template<> struct typed_flags<TransferBufferType> : is_typed_flags<TransferBufferType, 0x00ef> {};
+}
+// paste table into a table
+enum class PasteTableType
+{
+ PASTE_DEFAULT, // paste table by overwriting table cells
+ PASTE_ROW, // paste table as rows above
+ PASTE_COLUMN, // paste table as columns before
+ PASTE_TABLE // paste table as nested table
+};
+
+class SwTransferDdeLink;
+
+class SW_DLLPUBLIC SwTransferable final : public TransferableHelper
+{
+ friend class SwView_Impl;
+ SfxObjectShellLock m_aDocShellRef;
+ TransferableObjectDescriptor m_aObjDesc;
+ tools::SvRef<SwTransferDdeLink> m_xDdeLink;
+
+ SwWrtShell *m_pWrtShell;
+ /* #96392# Added pCreatorView to distinguish SwFrameShell from
+ SwWrtShell. */
+ const SwFrameShell *m_pCreatorView;
+ std::unique_ptr<SwDocFac, o3tl::default_delete<SwDocFac>> m_pClpDocFac;
+ std::optional<Graphic> m_oClpGraphic;
+ std::optional<Graphic> m_oClpBitmap;
+ Graphic *m_pOrigGraphic;
+ std::optional<INetBookmark> m_oBookmark; // URL and description!
+ std::unique_ptr<ImageMap> m_pImageMap;
+ std::unique_ptr<INetImage> m_pTargetURL;
+
+ TransferBufferType m_eBufferType;
+
+ bool m_bOldIdle :1; //D&D Idle flag from the viewsettings
+ bool m_bCleanUp :1; //D&D cleanup after Drop (not by internal Drop)
+
+ // helper methods for the copy
+ css::uno::Reference < css::embed::XEmbeddedObject > FindOLEObj( sal_Int64& nAspect ) const;
+ const Graphic* FindOLEReplacementGraphic() const;
+ void DeleteSelection();
+
+ // helper methods for the paste
+ static SwTransferable* GetSwTransferable( const TransferableDataHelper& rData );
+ static void SetSelInShell( SwWrtShell& , bool , const Point* );
+ static bool CheckForURLOrLNKFile( const TransferableDataHelper& rData,
+ OUString& rFileName, OUString* pTitle = nullptr );
+ static bool TestAllowedFormat( const TransferableDataHelper& rData,
+ SotClipboardFormatId nFormat, SotExchangeDest nDestination );
+
+ static bool PasteFileContent( const TransferableDataHelper&,
+ SwWrtShell& rSh, SotClipboardFormatId nFormat, bool bMsg, bool bIgnoreComments = false );
+ static bool PasteOLE( TransferableDataHelper& rData, SwWrtShell& rSh,
+ SotClipboardFormatId nFormat, SotExchangeActionFlags nActionFlags, bool bMsg );
+ static bool PasteTargetURL( const TransferableDataHelper& rData, SwWrtShell& rSh,
+ SwPasteSdr nAction, const Point* pPt, bool bInsertGRF );
+
+ static bool PasteDDE( const TransferableDataHelper& rData, SwWrtShell& rWrtShell,
+ bool bReReadGrf, bool bMsg );
+
+ static bool PasteSdrFormat( const TransferableDataHelper& rData,
+ SwWrtShell& rSh, SwPasteSdr nAction,
+ const Point* pPt, SotExchangeActionFlags nActionFlags, bool bNeedToSelectBeforePaste);
+
+ static bool PasteGrf( const TransferableDataHelper& rData, SwWrtShell& rSh,
+ SotClipboardFormatId nFormat, SwPasteSdr nAction, const Point* pPt,
+ SotExchangeActionFlags nActionFlags, sal_Int8 nDropAction, bool bNeedToSelectBeforePaste, RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA );
+
+ static bool PasteImageMap( const TransferableDataHelper& rData,
+ SwWrtShell& rSh );
+
+ static bool PasteAsHyperlink( const TransferableDataHelper& rData,
+ SwWrtShell& rSh, SotClipboardFormatId nFormat );
+
+ static bool PasteFileName( TransferableDataHelper& rData,
+ SwWrtShell& rSh, SotClipboardFormatId nFormat, SwPasteSdr nAction,
+ const Point* pPt, SotExchangeActionFlags nActionFlags, bool * graphicInserted );
+
+ static bool PasteDBData( const TransferableDataHelper& rData, SwWrtShell& rSh,
+ SotClipboardFormatId nFormat, bool bLink, const Point* pDragPt,
+ bool bMsg );
+
+ static bool PasteFileList( const TransferableDataHelper& rData,
+ SwWrtShell& rSh, bool bLink,
+ const Point* pPt, bool bMsg );
+
+ bool PrivatePaste( SwWrtShell& rShell, SwPasteContext* pContext = nullptr, PasteTableType ePasteTable = PasteTableType::PASTE_DEFAULT );
+
+ void SetDataForDragAndDrop( const Point& rSttPos );
+
+ SwTransferable( const SwTransferable& ) = delete;
+ SwTransferable& operator=( const SwTransferable& ) = delete;
+
+ virtual void AddSupportedFormats() override;
+ virtual bool GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& rDestDoc ) override;
+ virtual bool WriteObject( tools::SvRef<SotTempStream>& rxOStm,
+ void* pUserObject,
+ sal_uInt32 nUserObjectId,
+ const css::datatransfer::DataFlavor& rFlavor ) override;
+ virtual void DragFinished( sal_Int8 nDropAction ) override;
+ virtual void ObjectReleased() override;
+ virtual sal_Bool SAL_CALL isComplex() override;
+
+ using TransferableHelper::StartDrag;
+
+public:
+ SwTransferable( SwWrtShell& );
+ virtual ~SwTransferable() override;
+
+ static SotExchangeDest GetSotDestination( const SwWrtShell& rSh );
+
+ // set properties on the document, like PageMargin, VisArea.
+ // And set real Size
+ static void InitOle( SfxObjectShell* pDoc );
+
+ // copy - methods and helper methods for the copy
+ int Cut();
+ int Copy( bool bIsCut = false );
+ int PrepareForCopy( bool bIsCut = false );
+ void PrepareForCopyTextRange(SwPaM & rPaM);
+ void CalculateAndCopy(); // special for Calculator
+ bool CopyGlossary( SwTextBlocks& rGlossary, const OUString& rStr );
+
+ // remove the DDE-Link format promise
+ void RemoveDDELinkFormat(vcl::Window& rWin);
+ // disconnect to not receive DataChanged listener notifications
+ void DisconnectDDE();
+
+ // paste - methods and helper methods for the paste
+ static bool IsPaste( const SwWrtShell&, const TransferableDataHelper& );
+ static bool Paste( SwWrtShell&, TransferableDataHelper&, RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA,
+ bool bIgnoreComments = false, PasteTableType ePasteTable = PasteTableType::PASTE_DEFAULT );
+ static bool PasteData( TransferableDataHelper& rData,
+ SwWrtShell& rSh, sal_uInt8 nAction, SotExchangeActionFlags nActionFlags,
+ SotClipboardFormatId nFormat,
+ SotExchangeDest nDestination, bool bIsPasteFormat,
+ bool bIsDefault,
+ const Point* pDDPos = nullptr, sal_Int8 nDropAction = 0,
+ bool bPasteSelection = false, RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA,
+ bool bIgnoreComments = false,
+ SwPasteContext* pContext = nullptr,
+ PasteTableType nPaste = PasteTableType::PASTE_DEFAULT );
+
+ static bool IsPasteSpecial( const SwWrtShell& rWrtShell,
+ const TransferableDataHelper& );
+ static bool IsPasteOwnFormat( const TransferableDataHelper& );
+ static bool PasteUnformatted( SwWrtShell& rSh, TransferableDataHelper& );
+ /**
+ * @brief PrePasteSpecial Prepares the given dialog without actually running it
+ * @param rSh
+ * @param rFormatUsed
+ */
+ static void PrePasteSpecial( const SwWrtShell& rSh, TransferableDataHelper&, const VclPtr<SfxAbstractPasteDialog>& pDlg );
+ static bool PasteFormat( SwWrtShell& rSh, TransferableDataHelper& rData,
+ SotClipboardFormatId nFormat );
+
+ static void FillClipFormatItem( const SwWrtShell& rSh,
+ const TransferableDataHelper& rData,
+ SvxClipboardFormatItem & rToFill );
+
+ // Interfaces for Drag & Drop
+ void StartDrag( vcl::Window* pWin, const Point& rPos );
+
+ SwWrtShell* GetShell() { return m_pWrtShell; }
+ void SetCleanUp( bool bFlag ) { m_bCleanUp = bFlag; }
+
+ // public only for testing
+ bool PrivateDrop( SwWrtShell& rSh, const Point& rDragPt, bool bMove,
+ bool bIsXSelection );
+
+ // Interfaces for Selection
+ /* #96392# Added pCreator to distinguish SwFrameShell from SwWrtShell. */
+ static void CreateSelection( SwWrtShell & rSh,
+ const SwFrameShell * pCreator = nullptr );
+ static void ClearSelection( const SwWrtShell& rSh,
+ const SwFrameShell * pCreator = nullptr );
+
+ // the related SwView is being closed and the SwTransferable is invalid now
+ void Invalidate() {m_pWrtShell = nullptr;}
+
+ static void SelectPasteFormat(TransferableDataHelper& rData, sal_uInt8& nAction,
+ SotClipboardFormatId& nFormat);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/swmessdialog.hxx b/sw/source/uibase/inc/swmessdialog.hxx
new file mode 100644
index 0000000000..14c4d8a510
--- /dev/null
+++ b/sw/source/uibase/inc/swmessdialog.hxx
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SWMESSDIALOG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SWMESSDIALOG_HXX
+
+#include <vcl/weld.hxx>
+
+class SwMessageAndEditDialog : public weld::MessageDialogController
+{
+protected:
+ std::unique_ptr<weld::Entry> m_xEdit;
+ std::unique_ptr<weld::Button> m_xOKPB;
+public:
+ SwMessageAndEditDialog(weld::Window* pParent, const OUString& rID,
+ const OUString& rUIXMLDescription);
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_SWMESSDIALOG_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/swmodalredlineacceptdlg.hxx b/sw/source/uibase/inc/swmodalredlineacceptdlg.hxx
new file mode 100644
index 0000000000..00d4e1e028
--- /dev/null
+++ b/sw/source/uibase/inc/swmodalredlineacceptdlg.hxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/basedlgs.hxx>
+
+class SwRedlineAcceptDlg;
+
+class SwModalRedlineAcceptDlg final : public SfxDialogController
+{
+ std::unique_ptr<weld::Container> m_xContentArea;
+ std::unique_ptr<SwRedlineAcceptDlg> m_xImplDlg;
+
+public:
+ SwModalRedlineAcceptDlg(weld::Window *pParent);
+ virtual ~SwModalRedlineAcceptDlg() override;
+
+ void AcceptAll( bool bAccept );
+ virtual void Activate() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/swrenamexnameddlg.hxx b/sw/source/uibase/inc/swrenamexnameddlg.hxx
new file mode 100644
index 0000000000..4575df5d41
--- /dev/null
+++ b/sw/source/uibase/inc/swrenamexnameddlg.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/textfilter.hxx>
+#include <vcl/weld.hxx>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+
+class SwRenameXNamedDlg final : public weld::GenericDialogController
+{
+ css::uno::Reference< css::container::XNamed > & m_xNamed;
+ css::uno::Reference< css::container::XNameAccess > & m_xNameAccess;
+ css::uno::Reference< css::container::XNameAccess > m_xSecondAccess;
+ css::uno::Reference< css::container::XNameAccess > m_xThirdAccess;
+
+ TextFilter m_aTextFilter;
+
+ std::unique_ptr<weld::Entry> m_xNewNameED;
+ std::unique_ptr<weld::Button> m_xOk;
+
+ DECL_LINK(TextFilterHdl, OUString&, bool);
+ DECL_LINK(OkHdl, weld::Button&, void);
+ DECL_LINK(ModifyHdl, weld::Entry&, void);
+
+public:
+ SwRenameXNamedDlg(weld::Widget* pParent,
+ css::uno::Reference< css::container::XNamed > & xNamed,
+ css::uno::Reference< css::container::XNameAccess > & xNameAccess );
+
+ void SetForbiddenChars(const OUString& rSet)
+ {
+ m_aTextFilter.SetForbiddenChars(rSet);
+ }
+
+ void SetAlternativeAccess(
+ css::uno::Reference< css::container::XNameAccess > const & xSecond,
+ css::uno::Reference< css::container::XNameAccess > const & xThird )
+ {
+ m_xSecondAccess = xSecond;
+ m_xThirdAccess = xThird;
+ }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/swruler.hxx b/sw/source/uibase/inc/swruler.hxx
new file mode 100644
index 0000000000..6c903f9ca9
--- /dev/null
+++ b/sw/source/uibase/inc/swruler.hxx
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SWRULER_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SWRULER_HXX
+
+#include <svx/ruler.hxx>
+#include <vcl/timer.hxx>
+#include <vcl/virdev.hxx>
+
+class SwViewShell;
+class View;
+namespace vcl { class Window; }
+class SwEditWin;
+namespace tools { class JsonWriter; }
+
+/**
+ * An horizontal ruler with a control for comment panel visibility for Writer.
+ *
+ * The comment control only appears when the document has comments already.
+ */
+class SwCommentRuler final : public SvxRuler
+{
+public:
+ SwCommentRuler (
+ SwViewShell* pViewSh,
+ vcl::Window* pParent,
+ SwEditWin* pWin,
+ SvxRulerSupportFlags nRulerFlags,
+ SfxBindings& rBindings,
+ WinBits nWinStyle);
+ virtual ~SwCommentRuler () override;
+ virtual void dispose() override;
+
+ /**
+ * Paint the ruler.
+ * \param rRect ignored
+ */
+ virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override;
+ void CreateJsonNotification(tools::JsonWriter& rJsonWriter);
+
+private:
+ SwViewShell * mpViewShell; //< Shell to check if there is any comments on doc and their visibility
+ VclPtr<SwEditWin> mpSwWin; //< Used to get SwView to change the SideBar visibility
+ bool mbIsHighlighted; //< If comment control is highlighted (mouse is over it)
+ Timer maFadeTimer; //< Timer for high/'low'light fading
+ int mnFadeRate; //< From 0 to 100. 0 means not highlighted.
+ ScopedVclPtr<VirtualDevice> maVirDev; //< VirtualDevice of this window. Just for convenience.
+
+ void NotifyKit();
+ /**
+ * Callback function to handle a mouse button down event.
+ *
+ * When on comment control, it toggles the comment panel visibility.
+ */
+ virtual void MouseButtonDown( const MouseEvent& rMEvt ) override;
+ /**
+ * Callback function to handle a mouse move event.
+ *
+ * When on comment control, it let the control responsive by highlighting.
+ */
+ virtual void MouseMove(const MouseEvent& rMEvt) override;
+ /**
+ * Callback function to handle a context menu call (mouse right button click).
+ *
+ * When on comment control, it does not do anything.
+ */
+ virtual void Command( const CommandEvent& rCEvt ) override;
+ /**
+ * Update the view.
+ *
+ * Update the ruler appearance according to the document view and
+ * current cursor position.
+ */
+ virtual void Update() override;
+
+ /**
+ * Get the rectangle area that should be used to draw the comment control.
+ *
+ * It is horizontally aligned to the SideBar panel.
+ * \return The area where the comment control is.
+ */
+ tools::Rectangle GetCommentControlRegion();
+
+ /**
+ * Paint the comment control on VirtualDevice.
+ */
+ void DrawCommentControl(vcl::RenderContext& rRenderContext);
+
+ /**
+ * Update the tooltip text.
+ */
+ void UpdateCommentHelpText();
+
+ /**
+ * Get the proper color between two options, according to current status.
+ *
+ * The return color can be one of the given colors, or a merged one.
+ * It depends on highlight fading status.
+ *
+ * \param rHighColor color used to highlight status
+ * \param rLowColor color used to normal status
+ * \return The proper color to used in moment
+ */
+ Color GetFadedColor(const Color &rHighColor, const Color &rLowColor);
+
+ /// Fade timer callback.
+ DECL_LINK(FadeHandler, Timer *, void);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/swtablerep.hxx b/sw/source/uibase/inc/swtablerep.hxx
new file mode 100644
index 0000000000..7b04e3dcff
--- /dev/null
+++ b/sw/source/uibase/inc/swtablerep.hxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SWTABLEREP_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SWTABLEREP_HXX
+
+#include <swdllapi.h>
+#include <swtypes.hxx>
+
+class SwTabCols;
+
+struct TColumn
+{
+ SwTwips nWidth;
+ bool bVisible;
+};
+
+class SW_DLLPUBLIC SwTableRep
+{
+ std::vector<TColumn> m_aTColumns;
+
+ SwTwips m_nTableWidth;
+ SwTwips m_nSpace;
+ SwTwips m_nLeftSpace;
+ SwTwips m_nRightSpace;
+ sal_uInt16 m_nAlign;
+ sal_uInt16 m_nColCount;
+ sal_uInt16 m_nAllCols;
+ sal_uInt16 m_nWidthPercent;
+ bool m_bLineSelected : 1;
+ bool m_bWidthChanged : 1;
+ bool m_bColsChanged : 1;
+
+public:
+ SwTableRep( const SwTabCols& rTabCol );
+ ~SwTableRep();
+
+ SwTableRep( const SwTableRep& rCopy ) = default;
+ SwTableRep( SwTableRep&& rCopy ) = default;
+ SwTableRep& operator=(const SwTableRep& rCopy) = default;
+ SwTableRep& operator=(SwTableRep&& rCopy) = default;
+
+ bool FillTabCols( SwTabCols& rTabCol ) const;
+
+ SwTwips GetLeftSpace() const {return m_nLeftSpace;}
+ void SetLeftSpace(SwTwips nSet) {m_nLeftSpace = nSet;}
+
+ SwTwips GetRightSpace() const {return m_nRightSpace;}
+ void SetRightSpace(SwTwips nSet) {m_nRightSpace = nSet;}
+
+ SwTwips GetWidth() const {return m_nTableWidth;}
+ void SetWidth(SwTwips nSet) {m_nTableWidth = nSet;}
+
+ sal_uInt16 GetWidthPercent() const {return m_nWidthPercent;}
+ void SetWidthPercent(sal_uInt16 nSet) {m_nWidthPercent = nSet;}
+
+ sal_uInt16 GetAlign() const {return m_nAlign;}
+ void SetAlign(sal_uInt16 nSet) {m_nAlign = nSet;}
+
+ sal_uInt16 GetColCount() const {return m_nColCount;}
+ sal_uInt16 GetAllColCount() const {return m_nAllCols;}
+
+ bool HasColsChanged() const {return m_bColsChanged;}
+ void SetColsChanged() {m_bColsChanged = true;}
+
+ bool HasWidthChanged() const {return m_bWidthChanged;}
+ void SetWidthChanged() {m_bWidthChanged = true;}
+
+ bool IsLineSelected() const {return m_bLineSelected;}
+ void SetLineSelected(bool bSet) {m_bLineSelected = bSet;}
+
+ SwTwips GetSpace() const { return m_nSpace;}
+ void SetSpace(SwTwips nSet) {m_nSpace = nSet;}
+
+ TColumn* GetColumns() {return m_aTColumns.data();}
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/swuiccoll.hxx b/sw/source/uibase/inc/swuiccoll.hxx
new file mode 100644
index 0000000000..74e6920b02
--- /dev/null
+++ b/sw/source/uibase/inc/swuiccoll.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SWUICCOLL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SWUICCOLL_HXX
+
+#include <sfx2/tabdlg.hxx>
+
+#include <ccoll.hxx>
+
+class SwWrtShell;
+class SwFormat;
+
+/// The Condition tab on the paragraph style dialog for conditional styles, e.g. Text Body.
+class SwCondCollPage final : public SfxTabPage
+{
+ std::vector<OUString> m_aStrArr;
+
+ const CommandStruct*m_pCmds;
+ SwFormat* m_pFormat;
+
+ std::unique_ptr<weld::TreeView> m_xTbLinks;
+ std::unique_ptr<weld::TreeView> m_xStyleLB;
+ std::unique_ptr<weld::ComboBox> m_xFilterLB;
+ std::unique_ptr<weld::Button> m_xRemovePB;
+ std::unique_ptr<weld::Button> m_xAssignPB;
+
+ virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override;
+
+ DECL_LINK(AssignRemoveTreeListBoxHdl, weld::TreeView&, bool);
+ DECL_LINK(AssignRemoveClickHdl, weld::Button&, void);
+ DECL_LINK(SelectTreeListBoxHdl, weld::TreeView&, void);
+ DECL_LINK(SelectListBoxHdl, weld::ComboBox&, void);
+ void AssignRemove(const weld::Widget*);
+ void SelectHdl(const weld::Widget*);
+
+ static const WhichRangesContainer s_aPageRg;
+
+public:
+ SwCondCollPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet);
+ virtual ~SwCondCollPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet);
+ static WhichRangesContainer GetRanges() { return s_aPageRg; }
+
+ virtual bool FillItemSet( SfxItemSet *rSet) override;
+ virtual void Reset (const SfxItemSet *rSet) override;
+
+ void SetCollection( SwFormat* pFormat );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/swuicnttab.hxx b/sw/source/uibase/inc/swuicnttab.hxx
new file mode 100644
index 0000000000..103f65e7cb
--- /dev/null
+++ b/sw/source/uibase/inc/swuicnttab.hxx
@@ -0,0 +1,449 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SWUICNTTAB_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SWUICNTTAB_HXX
+
+#include <sfx2/tabdlg.hxx>
+#include <svx/langbox.hxx>
+#include <vcl/idle.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/customweld.hxx>
+
+#include <tox.hxx>
+#include "toxmgr.hxx"
+#include "cnttab.hxx"
+#include <vector>
+
+class IndexEntryResource;
+class IndexEntrySupplierWrapper;
+class SwTOXWidget;
+class SwTOXEdit;
+class SwTOXButton;
+class SwTOXEntryTabPage;
+class SwOneExampleFrame;
+class SwWrtShell;
+
+namespace com::sun::star{
+ namespace text{
+ class XTextSection;
+ class XDocumentIndex;
+ }
+}
+
+struct SwIndexSections_Impl
+{
+ css::uno::Reference< css::text::XTextSection > xContainerSection;
+ css::uno::Reference< css::text::XDocumentIndex > xDocumentIndex;
+};
+
+class SwMultiTOXTabDialog final : public SfxTabDialogController
+{
+ std::unique_ptr<SwTOXMgr> m_pMgr;
+ SwWrtShell& m_rWrtShell;
+
+ struct TypeData
+ {
+ std::unique_ptr<SwForm> m_pForm;
+ std::unique_ptr<SwTOXDescription> m_pDescription;
+ std::optional<SwIndexSections_Impl> m_oIndexSections;
+ };
+ std::vector<TypeData> m_vTypeData;
+
+ SwTOXBase* m_pParamTOXBase;
+
+ CurTOXType m_eCurrentTOXType;
+
+ OUString m_sUserDefinedIndex;
+ sal_uInt16 m_nInitialTOXType;
+
+ bool m_bEditTOX;
+ bool m_bExampleCreated;
+ bool m_bGlobalFlag;
+
+ std::unique_ptr<SwOneExampleFrame> m_xExampleFrame;
+ std::unique_ptr<weld::CheckButton> m_xShowExampleCB;
+ std::unique_ptr<weld::CustomWeld> m_xExampleFrameWin;
+
+ virtual short Ok() override;
+ std::unique_ptr<SwTOXDescription> CreateTOXDescFromTOXBase(const SwTOXBase*pCurTOX);
+ void ShowPreview();
+
+ DECL_LINK(CreateExample_Hdl, SwOneExampleFrame&, void);
+ DECL_LINK(ShowPreviewHdl, weld::Toggleable&, void);
+
+public:
+ SwMultiTOXTabDialog(weld::Widget* pParent, const SfxItemSet& rSet,
+ SwWrtShell &rShell,
+ SwTOXBase* pCurTOX, sal_uInt16 nToxType,
+ bool bGlobal);
+ virtual ~SwMultiTOXTabDialog() override;
+
+ virtual void PageCreated(const OUString& rId, SfxTabPage &rPage) override;
+
+ SwForm* GetForm(CurTOXType eType);
+
+ const CurTOXType& GetCurrentTOXType() const { return m_eCurrentTOXType;}
+ void SetCurrentTOXType(const CurTOXType& eSet)
+ {
+ m_eCurrentTOXType = eSet;
+ }
+
+ bool IsTOXEditMode() const { return m_bEditTOX;}
+
+ SwWrtShell& GetWrtShell() {return m_rWrtShell;}
+
+ SwTOXDescription& GetTOXDescription(CurTOXType eTOXTypes);
+ void CreateOrUpdateExample(
+ TOXTypes nTOXIndex, sal_uInt16 nPage = 0, sal_uInt16 nCurLevel = USHRT_MAX);
+
+ static bool IsNoNum(SwWrtShell& rSh, const OUString& rName);
+};
+
+class SwTOXSelectTabPage final : public SfxTabPage
+{
+ std::unique_ptr<IndexEntryResource> m_pIndexRes;
+
+ OUString m_aStyleArr[MAXLEVEL];
+ OUString m_sAutoMarkURL;
+ OUString m_sAutoMarkType;
+ OUString m_sAddStyleUser;
+ OUString m_sAddStyleContent;
+
+ std::unique_ptr<const IndexEntrySupplierWrapper> m_pIndexEntryWrapper;
+
+ bool m_bWaitingInitialSettings;
+
+ std::unique_ptr<weld::Entry> m_xTitleED;
+ std::unique_ptr<weld::Label> m_xTypeFT;
+ std::unique_ptr<weld::ComboBox> m_xTypeLB;
+ std::unique_ptr<weld::CheckButton> m_xReadOnlyCB;
+
+ std::unique_ptr<weld::Widget> m_xAreaFrame;
+ std::unique_ptr<weld::ComboBox> m_xAreaLB;
+ std::unique_ptr<weld::Widget> m_xLevelFT; //content, user
+ std::unique_ptr<weld::SpinButton> m_xLevelNF; //content, user
+
+ //content
+ std::unique_ptr<weld::Widget> m_xCreateFrame; // content, user, illustration
+ std::unique_ptr<weld::CheckButton> m_xFromHeadingsCB;
+ std::unique_ptr<weld::CheckButton> m_xStylesCB;
+ std::unique_ptr<weld::CheckButton> m_xAddStylesCB;
+ std::unique_ptr<weld::Button> m_xAddStylesPB;
+ //user
+ std::unique_ptr<weld::CheckButton> m_xFromTablesCB;
+ std::unique_ptr<weld::CheckButton> m_xFromFramesCB;
+ std::unique_ptr<weld::CheckButton> m_xFromGraphicsCB;
+ std::unique_ptr<weld::CheckButton> m_xFromOLECB;
+ std::unique_ptr<weld::CheckButton> m_xLevelFromChapterCB;
+
+ //illustration + table
+ std::unique_ptr<weld::RadioButton> m_xFromCaptionsRB;
+ std::unique_ptr<weld::RadioButton> m_xFromObjectNamesRB;
+
+ //illustration and tables
+ std::unique_ptr<weld::Label> m_xCaptionSequenceFT;
+ std::unique_ptr<weld::ComboBox> m_xCaptionSequenceLB;
+ std::unique_ptr<weld::Label> m_xDisplayTypeFT;
+ std::unique_ptr<weld::ComboBox> m_xDisplayTypeLB;
+ std::unique_ptr<weld::CheckButton> m_xParaStyleCB;
+ std::unique_ptr<weld::ComboBox> m_xParaStyleLB;
+
+ //all but illustration and table
+ std::unique_ptr<weld::CheckButton> m_xTOXMarksCB;
+
+ //index only
+ std::unique_ptr<weld::Widget> m_xIdxOptionsFrame;
+ std::unique_ptr<weld::CheckButton> m_xCollectSameCB;
+ std::unique_ptr<weld::CheckButton> m_xUseFFCB;
+ std::unique_ptr<weld::CheckButton> m_xUseDashCB;
+ std::unique_ptr<weld::CheckButton> m_xCaseSensitiveCB;
+ std::unique_ptr<weld::CheckButton> m_xInitialCapsCB;
+ std::unique_ptr<weld::CheckButton> m_xKeyAsEntryCB;
+ std::unique_ptr<weld::CheckButton> m_xFromFileCB;
+ std::unique_ptr<weld::MenuButton> m_xAutoMarkPB;
+
+ // object only
+ std::unique_ptr<weld::TreeView> m_xFromObjCLB;
+ std::unique_ptr<weld::Widget> m_xFromObjFrame;
+
+ std::unique_ptr<weld::CheckButton> m_xSequenceCB;
+ std::unique_ptr<weld::ComboBox> m_xBracketLB;
+ std::unique_ptr<weld::Widget> m_xAuthorityFrame;
+
+ //all
+ std::unique_ptr<weld::Widget> m_xSortFrame;
+ std::unique_ptr<SvxLanguageBox> m_xLanguageLB;
+ std::unique_ptr<weld::ComboBox> m_xSortAlgorithmLB;
+
+ DECL_LINK(TOXTypeHdl, weld::ComboBox&, void );
+ DECL_LINK(AddStylesHdl, weld::Button&, void );
+ DECL_LINK(MenuEnableHdl, weld::Toggleable&, void);
+ DECL_LINK(MenuExecuteHdl, const OUString&, void);
+ DECL_LINK(LanguageListBoxHdl, weld::ComboBox&, void);
+ void LanguageHdl(const weld::ComboBox*);
+ DECL_LINK(CheckBoxHdl, weld::Toggleable&, void );
+ DECL_LINK(RadioButtonHdl, weld::Toggleable&, void);
+ DECL_LINK(ModifyEntryHdl, weld::Entry&, void);
+ DECL_LINK(ModifySpinHdl, weld::SpinButton&, void);
+ DECL_LINK(ModifyListBoxHdl, weld::ComboBox&, void);
+
+ void ModifyHdl();
+ void ApplyTOXDescription();
+ void FillTOXDescription();
+
+public:
+ SwTOXSelectTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttrSet);
+ virtual ~SwTOXSelectTabPage() override;
+
+ virtual bool FillItemSet( SfxItemSet* ) override;
+ virtual void Reset( const SfxItemSet* ) override;
+
+ virtual void ActivatePage( const SfxItemSet& ) override;
+ virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet);
+
+ void SelectType(TOXTypes eSet); //preset TOXType, GlobalDoc
+ void SetWrtShell(SwWrtShell const & rSh);
+};
+
+class SwTokenWindow
+{
+ SwForm* m_pForm;
+ sal_uInt16 m_nLevel;
+ bool m_bValid;
+ OUString m_aButtonTexts[TOKEN_END]; // Text of the buttons
+ OUString m_aButtonHelpTexts[TOKEN_END]; // QuickHelpText of the buttons
+ OUString m_sCharStyle;
+ Link<SwFormToken&,void> m_aButtonSelectedHdl;
+ SwTOXWidget* m_pActiveCtrl;
+ Link<LinkParamNone*,void> m_aModifyHdl;
+ OUString m_sAccessibleName;
+ OUString m_sAdditionalAccnameString1;
+ OUString m_sAdditionalAccnameString2;
+ OUString m_sAdditionalAccnameString3;
+
+ Idle m_aAdjustPositionsIdle;
+
+ SwTOXEntryTabPage* m_pParent;
+ std::unique_ptr<weld::Container> m_xParentWidget;
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Container> m_xContainer;
+ std::unique_ptr<weld::Button> m_xLeftScrollWin;
+ std::unique_ptr<weld::Container> m_xCtrlParentWin;
+ std::unique_ptr<weld::ScrolledWindow> m_xScrollWin;
+ std::unique_ptr<weld::Button> m_xRightScrollWin;
+ std::vector<std::unique_ptr<SwTOXWidget>> m_aControlList;
+
+ DECL_LINK(EditResize, SwTOXEdit&, void);
+ DECL_LINK(NextItemHdl, SwTOXEdit&, void);
+ DECL_LINK(TbxFocusHdl, SwTOXWidget&, void);
+ DECL_LINK(NextItemBtnHdl, SwTOXButton&, void);
+ DECL_LINK(TbxFocusBtnHdl, SwTOXWidget&, void);
+ DECL_LINK(ScrollBtnHdl, weld::Button&, void);
+ DECL_LINK(ScrollHdl, weld::ScrolledWindow&, void);
+ DECL_LINK(AdjustPositionsHdl, const Size&, void);
+
+ void SetActiveControl(SwTOXWidget* pSet);
+
+ SwTOXWidget* InsertItem(const OUString& rText, const SwFormToken& aToken);
+ void AdjustPositions();
+ void AdjustScrolling();
+ void MoveControls(tools::Long nOffset);
+
+public:
+ SwTokenWindow(std::unique_ptr<weld::Container> xParent);
+ weld::Container* get_child_container() { return m_xCtrlParentWin.get(); }
+ ~SwTokenWindow();
+
+ void SetTabPage(SwTOXEntryTabPage *pParent) { m_pParent = pParent; }
+
+ void SetForm(SwForm& rForm, sal_uInt16 nLevel);
+ sal_uInt16 GetLastLevel()const {return m_nLevel;};
+
+ bool IsValid() const {return m_bValid;}
+
+ void SetInvalid() {m_bValid = false;}
+
+ OUString GetPattern() const;
+
+ void SetButtonSelectedHdl(const Link<SwFormToken&,void>& rLink)
+ { m_aButtonSelectedHdl = rLink;}
+
+ void SetModifyHdl(const Link<LinkParamNone*,void>& rLink){m_aModifyHdl = rLink;}
+
+ SwTOXWidget* GetActiveControl() { return m_pActiveCtrl; }
+
+ void InsertAtSelection(const SwFormToken& aToken);
+ void RemoveControl(const SwTOXButton* pDel, bool bInternalCall = false);
+
+ bool Contains(FormTokenType) const;
+
+ //helper for pattern buttons and edits
+ OUString CreateQuickHelp(const SwFormToken& rToken);
+
+ void SetFocus2theAllBtn();
+private:
+ sal_uInt32 GetControlIndex(FormTokenType eType) const;
+};
+
+class SwTOXEntryTabPage final : public SfxTabPage
+{
+ OUString m_sDelimStr;
+ OUString m_sLevelStr;
+ OUString m_sAuthTypeStr;
+
+ OUString m_sNoCharStyle;
+ SwForm* m_pCurrentForm;
+
+ CurTOXType m_aLastTOXType;
+ bool m_bInLevelHdl;
+
+ std::unique_ptr<weld::Label> m_xTypeFT;
+ std::unique_ptr<weld::Label> m_xLevelFT;
+ std::unique_ptr<weld::TreeView> m_xLevelLB;
+ std::unique_ptr<weld::Button> m_xAllLevelsPB;
+ std::unique_ptr<weld::Button> m_xEntryNoPB;
+ std::unique_ptr<weld::Button> m_xEntryPB;
+ std::unique_ptr<weld::Button> m_xTabPB;
+ std::unique_ptr<weld::Button> m_xChapterInfoPB;
+ std::unique_ptr<weld::Button> m_xPageNoPB;
+ std::unique_ptr<weld::Button> m_xHyperLinkPB;
+ std::unique_ptr<weld::Widget> m_xFieldBox;
+ std::unique_ptr<weld::ComboBox> m_xAuthFieldsLB;
+ std::unique_ptr<weld::Button> m_xAuthInsertPB;
+ std::unique_ptr<weld::Button> m_xAuthRemovePB;
+ std::unique_ptr<weld::ComboBox> m_xCharStyleLB; // character style of the current token
+ std::unique_ptr<weld::Button> m_xEditStylePB;
+ std::unique_ptr<weld::Label> m_xChapterEntryFT;
+ std::unique_ptr<weld::ComboBox> m_xChapterEntryLB; // type of chapter info
+ std::unique_ptr<weld::Label> m_xNumberFormatFT;
+ std::unique_ptr<weld::ComboBox> m_xNumberFormatLB; //!< format for numbering (E#)
+ std::unique_ptr<weld::Label> m_xEntryOutlineLevelFT; //!< Fixed text, for i53420
+ std::unique_ptr<weld::SpinButton> m_xEntryOutlineLevelNF; //!< level to evaluate outline level to, for i53420
+ std::unique_ptr<weld::Label> m_xFillCharFT;
+ std::unique_ptr<weld::ComboBox> m_xFillCharCB; // fill char for tab stop
+ std::unique_ptr<weld::Label> m_xTabPosFT;
+ std::unique_ptr<weld::MetricSpinButton> m_xTabPosMF; // tab stop position
+ std::unique_ptr<weld::CheckButton> m_xAutoRightCB;
+ std::unique_ptr<weld::Widget> m_xFormatFrame;
+ std::unique_ptr<weld::Label> m_xMainEntryStyleFT;
+ std::unique_ptr<weld::ComboBox> m_xMainEntryStyleLB; // character style of main entries in indexes
+ std::unique_ptr<weld::CheckButton> m_xAlphaDelimCB;
+ std::unique_ptr<weld::CheckButton> m_xCommaSeparatedCB;
+ std::unique_ptr<weld::CheckButton> m_xRelToStyleCB; // position relative to the right margin of the para style
+ std::unique_ptr<weld::Widget> m_xSortingFrame;
+ std::unique_ptr<weld::RadioButton> m_xSortDocPosRB;
+ std::unique_ptr<weld::RadioButton> m_xSortContentRB;
+ std::unique_ptr<weld::Widget> m_xSortKeyFrame;
+ std::unique_ptr<weld::ComboBox> m_xFirstKeyLB;
+ std::unique_ptr<weld::ToggleButton> m_xFirstSortUpRB;
+ std::unique_ptr<weld::ToggleButton> m_xFirstSortDownRB;
+ std::unique_ptr<weld::ComboBox> m_xSecondKeyLB;
+ std::unique_ptr<weld::ToggleButton> m_xSecondSortUpRB;
+ std::unique_ptr<weld::ToggleButton> m_xSecondSortDownRB;
+ std::unique_ptr<weld::ComboBox> m_xThirdKeyLB;
+ std::unique_ptr<weld::ToggleButton> m_xThirdSortUpRB;
+ std::unique_ptr<weld::ToggleButton> m_xThirdSortDownRB;
+ std::unique_ptr<SwTokenWindow> m_xTokenWIN;
+
+ DECL_LINK(StyleSelectHdl, weld::ComboBox&, void);
+ DECL_LINK(EditStyleHdl, weld::Button&, void);
+ DECL_LINK(InsertTokenHdl, weld::Button&, void);
+ DECL_LINK(LevelHdl, weld::TreeView&, void);
+ DECL_LINK(AutoRightHdl, weld::Toggleable&, void);
+ DECL_LINK(TokenSelectedHdl, SwFormToken&, void);
+ DECL_LINK(TabPosHdl, weld::MetricSpinButton&, void);
+ DECL_LINK(FillCharHdl, weld::ComboBox&, void);
+ DECL_LINK(RemoveInsertAuthHdl, weld::Button&, void);
+ DECL_LINK(SortKeyHdl, weld::Toggleable&, void);
+ DECL_LINK(ChapterInfoHdl, weld::ComboBox&, void);
+ DECL_LINK(ChapterInfoOutlineHdl, weld::SpinButton&, void);
+ DECL_LINK(NumberFormatHdl, weld::ComboBox&, void);
+ DECL_LINK(ToggleHdl, weld::Toggleable&, void);
+
+ DECL_LINK(AllLevelsHdl, weld::Button&, void);
+
+ void WriteBackLevel();
+ void UpdateDescriptor();
+ DECL_LINK(ModifyHdl, LinkParamNone*, void);
+ void OnModify(bool bAllLevels);
+ DECL_LINK(ModifyClickHdl, weld::Toggleable&, void);
+
+ void ShowHideControls(int eType);
+
+public:
+ SwTOXEntryTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttrSet);
+ virtual ~SwTOXEntryTabPage() override;
+
+ virtual bool FillItemSet( SfxItemSet* ) override;
+ virtual void Reset( const SfxItemSet* ) override;
+ virtual void ActivatePage( const SfxItemSet& ) override;
+ virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet);
+ void SetWrtShell(SwWrtShell& rSh);
+
+ void PreTokenButtonRemoved(const SwFormToken& rToken);
+ void SetFocus2theAllBtn();
+};
+
+class SwTOXStylesTabPage final : public SfxTabPage
+{
+ std::unique_ptr<SwForm> m_pCurrentForm;
+
+ std::unique_ptr<weld::TreeView> m_xLevelLB;
+ std::unique_ptr<weld::Button> m_xAssignBT;
+ std::unique_ptr<weld::TreeView> m_xParaLayLB;
+ std::unique_ptr<weld::Button> m_xStdBT;
+ std::unique_ptr<weld::Button> m_xEditStyleBT;
+
+ DECL_LINK(EditStyleHdl, weld::Button&, void);
+ DECL_LINK(StdHdl, weld::Button&, void);
+ DECL_LINK(EnableSelectHdl, weld::TreeView&, void);
+ DECL_LINK(DoubleClickHdl, weld::TreeView&, bool);
+ DECL_LINK(AssignHdl, weld::Button&, void);
+ void Modify();
+
+ SwForm& GetForm()
+ {
+ SwMultiTOXTabDialog* pDlg = static_cast<SwMultiTOXTabDialog*>(GetDialogController());
+ return *pDlg->GetForm(pDlg->GetCurrentTOXType());
+ }
+
+public:
+ SwTOXStylesTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttrSet);
+ virtual ~SwTOXStylesTabPage() override;
+
+ virtual bool FillItemSet( SfxItemSet* ) override;
+ virtual void Reset( const SfxItemSet* ) override;
+
+ virtual void ActivatePage( const SfxItemSet& ) override;
+ virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet);
+
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_SWUICNTTAB_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/swuiidxmrk.hxx b/sw/source/uibase/inc/swuiidxmrk.hxx
new file mode 100644
index 0000000000..7f5460a8be
--- /dev/null
+++ b/sw/source/uibase/inc/swuiidxmrk.hxx
@@ -0,0 +1,236 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SWUIIDXMRK_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SWUIIDXMRK_HXX
+
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/i18n/XExtendedIndexEntrySupplier.hpp>
+#include <sfx2/basedlgs.hxx>
+#include <sfx2/childwin.hxx>
+#include <vcl/weld.hxx>
+#include <toxe.hxx>
+#include <memory>
+
+class SwWrtShell;
+class SwTOXMgr;
+class SwTOXMark;
+
+// insert mark for index entry
+class SwIndexMarkFloatDlg;
+class SwIndexMarkModalDlg;
+
+class SwIndexMarkPane
+{
+ std::shared_ptr<weld::Dialog> m_xDialog;
+
+ friend class SwIndexMarkFloatDlg;
+ friend class SwIndexMarkModalDlg;
+
+ OUString m_aOrgStr;
+ bool m_bDel;
+ bool const m_bNewMark;
+ bool m_bSelected;
+
+ bool m_bPhoneticED0_ChangedByUser;
+ bool m_bPhoneticED1_ChangedByUser;
+ bool m_bPhoneticED2_ChangedByUser;
+ LanguageType m_nLangForPhoneticReading; //Language of current text used for phonetic reading proposal
+ bool m_bIsPhoneticReadingEnabled; //this value states whether phonetic reading is enabled in principle dependent of global cjk settings and language of current entry
+ css::uno::Reference< css::i18n::XExtendedIndexEntrySupplier >
+ m_xExtendedIndexEntrySupplier;
+
+ std::unique_ptr<SwTOXMgr>
+ m_pTOXMgr;
+ SwWrtShell* m_pSh;
+
+ std::unique_ptr<weld::Label> m_xTypeFT;
+ std::unique_ptr<weld::ComboBox> m_xTypeDCB;
+ std::unique_ptr<weld::Button> m_xNewBT;
+ std::unique_ptr<weld::Entry> m_xEntryED;
+ std::unique_ptr<weld::Button> m_xSyncED;
+ std::unique_ptr<weld::Label> m_xPhoneticFT0;
+ std::unique_ptr<weld::Entry> m_xPhoneticED0;
+ std::unique_ptr<weld::Label> m_xKey1FT;
+ std::unique_ptr<weld::ComboBox> m_xKey1DCB;
+ std::unique_ptr<weld::Label> m_xPhoneticFT1;
+ std::unique_ptr<weld::Entry> m_xPhoneticED1;
+ std::unique_ptr<weld::Label> m_xKey2FT;
+ std::unique_ptr<weld::ComboBox> m_xKey2DCB;
+ std::unique_ptr<weld::Label> m_xPhoneticFT2;
+ std::unique_ptr<weld::Entry> m_xPhoneticED2;
+ std::unique_ptr<weld::Label> m_xLevelFT;
+ std::unique_ptr<weld::SpinButton> m_xLevelNF;
+ std::unique_ptr<weld::CheckButton> m_xMainEntryCB;
+ std::unique_ptr<weld::CheckButton> m_xApplyToAllCB;
+ std::unique_ptr<weld::CheckButton> m_xSearchCaseSensitiveCB;
+ std::unique_ptr<weld::CheckButton> m_xSearchCaseWordOnlyCB;
+ std::unique_ptr<weld::Button> m_xOKBT;
+ std::unique_ptr<weld::Button> m_xCloseBT;
+ std::unique_ptr<weld::Button> m_xDelBT;
+ std::unique_ptr<weld::Button> m_xPrevSameBT;
+ std::unique_ptr<weld::Button> m_xNextSameBT;
+ std::unique_ptr<weld::Button> m_xPrevBT;
+ std::unique_ptr<weld::Button> m_xNextBT;
+ std::unique_ptr<weld::Label> m_xForSelectedEntry;
+
+ void Apply();
+ void InitControls();
+ void InsertMark();
+ void UpdateMark();
+
+ DECL_LINK(InsertHdl, weld::Button&, void);
+ DECL_LINK(CloseHdl, weld::Button&, void);
+ DECL_LINK(SyncSelectionHdl, weld::Button&, void);
+ DECL_LINK(DelHdl, weld::Button&, void);
+ DECL_LINK( NextHdl, weld::Button&, void );
+ DECL_LINK( NextSameHdl, weld::Button&, void );
+ DECL_LINK( PrevHdl, weld::Button&, void );
+ DECL_LINK( PrevSameHdl, weld::Button&, void );
+ DECL_LINK( ModifyListBoxHdl, weld::ComboBox&, void );
+ DECL_LINK( ModifyEditHdl, weld::Entry&, void );
+ void ModifyHdl(const weld::Widget& rWidget);
+ DECL_LINK( KeyDCBModifyHdl, weld::ComboBox&, void );
+ DECL_LINK( NewUserIdxHdl, weld::Button&, void );
+ DECL_LINK( SearchTypeHdl, weld::Toggleable&, void );
+ DECL_LINK( PhoneticEDModifyHdl, weld::Entry&, void );
+
+ //this method updates the values from 'nLangForPhoneticReading' and 'bIsPhoneticReadingEnabled'
+ //it needs to be called ones if this dialog is opened to create a new entry (in InitControls),
+ //or otherwise it has to be called for each changed TOXMark (in UpdateDialog)
+ void UpdateLanguageDependenciesForPhoneticReading();
+ OUString GetDefaultPhoneticReading( const OUString& rText );
+
+ void UpdateKeyBoxes();
+
+ void UpdateDialog();
+ void InsertUpdate();
+
+ void Activate();
+
+public:
+
+ SwIndexMarkPane(std::shared_ptr<weld::Dialog> xDialog, weld::Builder& rBuilder,
+ bool bNewDlg, SwWrtShell* pWrtShell);
+
+ ~SwIndexMarkPane();
+
+ void ReInitDlg(SwWrtShell& rWrtShell, SwTOXMark const * pCurTOXMark = nullptr);
+ bool IsTOXType(const OUString& rName) { return m_xTypeDCB->find_text(rName) != -1; }
+};
+
+class SwIndexMarkFloatDlg final : public SfxModelessDialogController
+{
+ SwIndexMarkPane m_aContent;
+
+ virtual void Activate() override;
+public:
+ SwIndexMarkFloatDlg(SfxBindings* pBindings,
+ SfxChildWindow* pChild,
+ weld::Window *pParent,
+ SfxChildWinInfo const * pInfo,
+ bool bNew);
+ void ReInitDlg(SwWrtShell& rWrtShell);
+};
+
+class SwIndexMarkModalDlg final : public SfxDialogController
+{
+ SwIndexMarkPane m_aContent;
+public:
+ SwIndexMarkModalDlg(weld::Window *pParent, SwWrtShell& rSh, SwTOXMark const * pCurTOXMark);
+ virtual ~SwIndexMarkModalDlg() override;
+ virtual short int run() override;
+};
+
+class SwAuthMarkModalDlg;
+
+class SwAuthorMarkPane
+{
+ weld::DialogController& m_rDialog;
+
+ static bool s_bIsFromComponent;
+
+ friend class SwAuthMarkModalDlg;
+ friend class SwAuthMarkFloatDlg;
+
+ bool m_bNewEntry;
+ bool m_bBibAccessInitialized;
+
+ SwWrtShell* m_pSh;
+
+ OUString m_sColumnTitles[AUTH_FIELD_END];
+ OUString m_sFields[AUTH_FIELD_END];
+
+ OUString m_sCreatedEntry[AUTH_FIELD_END];
+
+ css::uno::Reference< css::container::XNameAccess > m_xBibAccess;
+
+ std::unique_ptr<weld::RadioButton> m_xFromComponentRB;
+ std::unique_ptr<weld::RadioButton> m_xFromDocContentRB;
+ std::unique_ptr<weld::Label> m_xAuthorFI;
+ std::unique_ptr<weld::Label> m_xTitleFI;
+ std::unique_ptr<weld::Entry> m_xEntryED;
+ std::unique_ptr<weld::ComboBox> m_xEntryLB;
+ std::unique_ptr<weld::Button> m_xActionBT;
+ std::unique_ptr<weld::Button> m_xCloseBT;
+ std::unique_ptr<weld::Button> m_xCreateEntryPB;
+ std::unique_ptr<weld::Button> m_xEditEntryPB;
+
+ DECL_LINK(InsertHdl, weld::Button&, void);
+ DECL_LINK(CloseHdl, weld::Button&, void);
+ DECL_LINK(CreateEntryHdl, weld::Button&, void);
+ DECL_LINK(CompEntryHdl, weld::ComboBox&, void);
+ DECL_LINK(ChangeSourceHdl, weld::Toggleable&, void);
+ DECL_LINK(IsEditAllowedHdl, weld::Entry&, bool);
+ DECL_LINK(IsEntryAllowedHdl, weld::Entry&, bool);
+ DECL_LINK(EditModifyHdl, weld::Entry&, void);
+
+ void InitControls();
+ void Activate();
+
+public:
+ SwAuthorMarkPane(weld::DialogController& rDialog, weld::Builder& rBuilder, bool bNew);
+ void ReInitDlg(SwWrtShell& rWrtShell);
+};
+
+class SwAuthMarkFloatDlg final : public SfxModelessDialogController
+{
+ SwAuthorMarkPane m_aContent;
+ virtual void Activate() override;
+public:
+ SwAuthMarkFloatDlg(SfxBindings* pBindings,
+ SfxChildWindow* pChild,
+ weld::Window *pParent,
+ SfxChildWinInfo const * pInfo,
+ bool bNew);
+ void ReInitDlg(SwWrtShell& rWrtShell);
+};
+
+class SwAuthMarkModalDlg final : public SfxDialogController
+{
+ SwAuthorMarkPane m_aContent;
+
+ void Apply();
+public:
+ SwAuthMarkModalDlg(weld::Window *pParent, SwWrtShell& rSh);
+ virtual short int run() override;
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_SWUIIDXMRK_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/swuipardlg.hxx b/sw/source/uibase/inc/swuipardlg.hxx
new file mode 100644
index 0000000000..cc270d4c81
--- /dev/null
+++ b/sw/source/uibase/inc/swuipardlg.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SWUIPARDLG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SWUIPARDLG_HXX
+
+#include <view.hxx>
+
+#include <sfx2/tabdlg.hxx>
+
+class SwParaDlg final : public SfxTabDialogController
+{
+ SwView& m_rView;
+ bool m_bDrawParaDlg;
+
+ void PageCreated(const OUString& rId, SfxTabPage& rPage) override;
+
+public:
+ SwParaDlg(weld::Window *pParent,
+ SwView& rVw,
+ const SfxItemSet&,
+ sal_uInt8 nDialogMode,
+ const OUString *pCollName,
+ bool bDraw = false,
+ const OUString& sDefPage = {});
+ virtual ~SwParaDlg() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/swwrtshitem.hxx b/sw/source/uibase/inc/swwrtshitem.hxx
new file mode 100644
index 0000000000..ab8f0f7690
--- /dev/null
+++ b/sw/source/uibase/inc/swwrtshitem.hxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SWWRTSHITEM_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SWWRTSHITEM_HXX
+#include <svl/poolitem.hxx>
+#include <swdllapi.h>
+
+class SwWrtShell;
+
+class SW_DLLPUBLIC SwWrtShellItem final : public SfxPoolItem
+{
+ SwWrtShell* m_pWrtSh;
+
+public:
+ SwWrtShellItem( SwWrtShell* pWrtSh );
+
+ virtual bool operator==( const SfxPoolItem& ) const override;
+ virtual SwWrtShellItem* Clone( SfxItemPool *pPool = nullptr ) const override;
+
+ SwWrtShell* GetValue() const { return m_pWrtSh; }
+
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/syncbtn.hxx b/sw/source/uibase/inc/syncbtn.hxx
new file mode 100644
index 0000000000..e100edc2ef
--- /dev/null
+++ b/sw/source/uibase/inc/syncbtn.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SYNCBTN_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_SYNCBTN_HXX
+
+#include <sfx2/basedlgs.hxx>
+#include <sfx2/childwin.hxx>
+
+class SwSyncBtnDlg final : public SfxModelessDialogController
+{
+ std::unique_ptr<weld::Button> m_xSyncBtn;
+
+ DECL_STATIC_LINK( SwSyncBtnDlg, BtnHdl, weld::Button&, void );
+
+public:
+ SwSyncBtnDlg(SfxBindings*, SfxChildWindow*, weld::Window *pParent);
+ virtual ~SwSyncBtnDlg() override;
+};
+
+class SwSyncChildWin final : public SfxChildWindow
+{
+public:
+ SwSyncChildWin(vcl::Window*,
+ sal_uInt16 nId,
+ SfxBindings*,
+ SfxChildWinInfo*);
+
+ SFX_DECL_CHILDWINDOW(SwSyncChildWin);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/tabledlg.hxx b/sw/source/uibase/inc/tabledlg.hxx
new file mode 100644
index 0000000000..41d9673a74
--- /dev/null
+++ b/sw/source/uibase/inc/tabledlg.hxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_TABLEDLG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_TABLEDLG_HXX
+
+#include <sfx2/tabdlg.hxx>
+
+class SwWrtShell;
+struct TColumn;
+
+// table dialog
+class SwTableTabDlg final : public SfxTabDialogController
+{
+ SwWrtShell* m_pShell;
+
+ virtual void PageCreated(const OUString& rId, SfxTabPage& rPage) override;
+
+public:
+ SwTableTabDlg(weld::Window* pParent, const SfxItemSet* pItemSet, SwWrtShell* pSh);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/tablemgr.hxx b/sw/source/uibase/inc/tablemgr.hxx
new file mode 100644
index 0000000000..d382d29b6c
--- /dev/null
+++ b/sw/source/uibase/inc/tablemgr.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_TABLEMGR_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_TABLEMGR_HXX
+
+#include <swdllapi.h>
+#include <swtypes.hxx>
+#include <tabcol.hxx>
+
+#include <vcl/weld.hxx>
+
+class SwFrameFormat;
+class SwWrtShell;
+class SwFlyFrameFormat;
+
+namespace com::sun::star {
+ namespace frame { class XModel; }
+ namespace chart2 {
+ namespace data {
+ class XDataProvider; } }
+}
+
+const SwTwips lAutoWidth = INVALID_TWIPS;
+const char cParaDelim = 0x0a;
+
+class SW_DLLPUBLIC SwTableFUNC
+{
+ SwFrameFormat *m_pFormat;
+ SwWrtShell *m_pSh;
+ SwTabCols m_aCols;
+
+private:
+ SAL_DLLPRIVATE int GetRightSeparator(int nNum) const;
+
+public:
+ SwTableFUNC(SwWrtShell *pShell);
+ ~SwTableFUNC();
+
+ void InitTabCols();
+ void ColWidthDlg(weld::Window *pParent);
+ SwTwips GetColWidth(sal_uInt16 nNum) const;
+ SwTwips GetMaxColWidth(sal_uInt16 nNum) const;
+ void SetColWidth(sal_uInt16 nNum, SwTwips nWidth );
+ sal_uInt16 GetColCount() const;
+ sal_uInt16 GetCurColNum() const;
+
+ SwWrtShell* GetShell() const { return m_pSh; }
+
+ // @deprecated
+ void UpdateChart();
+
+ /// @return the XModel of the newly inserted chart if successful
+ css::uno::Reference< css::frame::XModel >
+ InsertChart( css::uno::Reference< css::chart2::data::XDataProvider > const &rxDataProvider, bool bFillWithData, const OUString &rCellRange, SwFlyFrameFormat** ppFlyFrameFormat = nullptr );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/tabsh.hxx b/sw/source/uibase/inc/tabsh.hxx
new file mode 100644
index 0000000000..6816376c10
--- /dev/null
+++ b/sw/source/uibase/inc/tabsh.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_TABSH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_TABSH_HXX
+
+#include "basesh.hxx"
+#include <swdllapi.h>
+
+class SfxItemSet;
+class SwWrtShell;
+struct WhichRangesContainer;
+
+SW_DLLPUBLIC void ItemSetToTableParam( const SfxItemSet& rSet, SwWrtShell &rSh );
+
+SW_DLLPUBLIC const WhichRangesContainer& SwuiGetUITableAttrRange();
+
+class SwTableShell: public SwBaseShell
+{
+public:
+ SFX_DECL_INTERFACE(SW_TABSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ void Execute(SfxRequest &);
+ void GetState(SfxItemSet &);
+ void GetFrameBorderState(SfxItemSet &rSet);
+ void GetLineStyleState(SfxItemSet &rSet);
+ void ExecTableStyle(SfxRequest& rReq);
+
+ void ExecNumberFormat(SfxRequest const & rReq);
+
+ SwTableShell(SwView &rView);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/tautofmt.hxx b/sw/source/uibase/inc/tautofmt.hxx
new file mode 100644
index 0000000000..4c03bd981d
--- /dev/null
+++ b/sw/source/uibase/inc/tautofmt.hxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_TAUTOFMT_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_TAUTOFMT_HXX
+
+#include <tools/link.hxx>
+#include <sfx2/basedlgs.hxx>
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+#include <vcl/weld.hxx>
+
+#include "wrtsh.hxx"
+#include "autoformatpreview.hxx"
+#include <tblafmt.hxx>
+
+class SwTableAutoFormat;
+class SwTableAutoFormatTable;
+class SwWrtShell;
+
+class SwAutoFormatDlg final : public SfxDialogController
+{
+ OUString m_aStrTitle;
+ OUString m_aStrLabel;
+ OUString m_aStrClose;
+ OUString m_aStrDelTitle;
+ OUString m_aStrDelMsg;
+ OUString m_aStrRenameTitle;
+ OUString m_aStrInvalidFormat;
+
+ SwWrtShell* m_pShell;
+ sal_uInt8 m_nIndex;
+ sal_uInt8 m_nDfltStylePos;
+ bool m_bCoreDataChanged : 1;
+ bool m_bSetAutoFormat : 1;
+
+ AutoFormatPreview m_aWndPreview;
+ std::unique_ptr<SwTableAutoFormatTable> m_xTableTable;
+
+ std::unique_ptr<weld::TreeView> m_xLbFormat;
+ std::unique_ptr<weld::CheckButton> m_xBtnNumFormat;
+ std::unique_ptr<weld::CheckButton> m_xBtnBorder;
+ std::unique_ptr<weld::CheckButton> m_xBtnFont;
+ std::unique_ptr<weld::CheckButton> m_xBtnPattern;
+ std::unique_ptr<weld::CheckButton> m_xBtnAlignment;
+ std::unique_ptr<weld::Button> m_xBtnCancel;
+ std::unique_ptr<weld::Button> m_xBtnAdd;
+ std::unique_ptr<weld::Button> m_xBtnRemove;
+ std::unique_ptr<weld::Button> m_xBtnRename;
+ std::unique_ptr<weld::CustomWeld> m_xWndPreview;
+
+ void Init( const SwTableAutoFormat* pSelFormat );
+ void UpdateChecks( const SwTableAutoFormat&, bool bEnableBtn );
+
+ DECL_LINK(CheckHdl, weld::Toggleable&, void);
+ DECL_LINK(AddHdl, weld::Button&, void);
+ DECL_LINK(RemoveHdl, weld::Button&, void);
+ DECL_LINK(RenameHdl, weld::Button&, void);
+ DECL_LINK(SelFormatHdl, weld::TreeView&, void);
+
+public:
+ SwAutoFormatDlg(weld::Window* pParent, SwWrtShell* pShell,
+ bool bSetAutoFormat, const SwTableAutoFormat* pSelFormat);
+
+ virtual short run() override;
+
+ std::unique_ptr<SwTableAutoFormat> FillAutoFormatOfIndex() const;
+
+ virtual ~SwAutoFormatDlg() override;
+};
+
+#endif // SW_AUTOFMT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/tblnumfm.hxx b/sw/source/uibase/inc/tblnumfm.hxx
new file mode 100644
index 0000000000..81f065265d
--- /dev/null
+++ b/sw/source/uibase/inc/tblnumfm.hxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_TBLNUMFM_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_TBLNUMFM_HXX
+
+#include <sfx2/basedlgs.hxx>
+
+namespace weld
+{
+class Window;
+class Container;
+}
+class SfxItemSet;
+
+class SwNumFormatDlg final : public SfxSingleTabDialogController
+{
+ std::unique_ptr<weld::Container> m_xContent;
+
+public:
+ SwNumFormatDlg(weld::Widget* pParent, const SfxItemSet& rSet);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/textsh.hxx b/sw/source/uibase/inc/textsh.hxx
new file mode 100644
index 0000000000..f965370e08
--- /dev/null
+++ b/sw/source/uibase/inc/textsh.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_TEXTSH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_TEXTSH_HXX
+
+#include "basesh.hxx"
+#include <unotools/caserotate.hxx>
+#include <com/sun/star/ui/dialogs/DialogClosedEvent.hpp>
+
+class AbstractSvxPostItDialog;
+class SwFieldMgr;
+class SwFlyFrameAttrMgr;
+class SvxHyperlinkItem;
+class SwInsertChart;
+
+class SW_DLLPUBLIC SwTextShell: public SwBaseShell
+{
+ RotateTransliteration m_aRotateCase;
+
+ void InsertSymbol( SfxRequest& );
+ void InsertHyperlink( const SvxHyperlinkItem& rHlnkItem );
+ bool InsertMediaDlg( SfxRequest const & );
+
+public:
+ SFX_DECL_INTERFACE(SW_TEXTSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ DECL_DLLPRIVATE_LINK( RedlineNextHdl, AbstractSvxPostItDialog&, void );
+ DECL_DLLPRIVATE_LINK( RedlinePrevHdl, AbstractSvxPostItDialog&, void );
+ DECL_DLLPRIVATE_STATIC_LINK( SwTextShell, DialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, void );
+
+ void Execute(SfxRequest &);
+ void GetState(SfxItemSet &);
+
+ void ExecInsert(SfxRequest &);
+ void StateInsert(SfxItemSet&);
+ void ExecDelete(SfxRequest &);
+ void ExecEnterNum(SfxRequest &);
+ void ExecBasicMove(SfxRequest &);
+ void ExecMove(SfxRequest &);
+ void ExecMovePage(SfxRequest &);
+ void ExecMoveCol(SfxRequest &);
+ void ExecMoveLingu(SfxRequest &);
+ void ExecMoveMisc(SfxRequest &);
+ void ExecField(SfxRequest &rReq);
+ void ExecSetNumber(SfxRequest const &);
+ void StateField(SfxItemSet &);
+ void ExecIdx(SfxRequest const &);
+ void GetIdxState(SfxItemSet &);
+ void ExecGlossary(SfxRequest &);
+
+ void ExecCharAttr(SfxRequest &);
+ void ExecCharAttrArgs(SfxRequest &);
+ void ExecParaAttr(SfxRequest &);
+ void ExecParaAttrArgs(SfxRequest &);
+ void ExecDB(SfxRequest const &);
+ void ExecTransliteration(SfxRequest const &);
+ void ExecRotateTransliteration(SfxRequest const &);
+
+ void GetAttrState(SfxItemSet &);
+
+ SwTextShell(SwView &rView);
+ virtual ~SwTextShell() override;
+ /// Create item set for the insert frame dialog.
+ SfxItemSet CreateInsertFrameItemSet(SwFlyFrameAttrMgr& rMgr);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/titlepage.hxx b/sw/source/uibase/inc/titlepage.hxx
new file mode 100644
index 0000000000..13f1677863
--- /dev/null
+++ b/sw/source/uibase/inc/titlepage.hxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_TITLEPAGE_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_TITLEPAGE_HXX
+
+#include <sfx2/basedlgs.hxx>
+
+#include <fmtpdsc.hxx>
+
+namespace vcl
+{
+class Window;
+}
+class SwWrtShell;
+class SwPageDesc;
+
+class SwTitlePageDlg final : public SfxDialogController
+{
+private:
+ std::unique_ptr<const SwFormatPageDesc> mpPageFormatDesc;
+
+ SwPageDesc* mpTitleDesc;
+ const SwPageDesc* mpIndexDesc;
+ const SwPageDesc* mpNormalDesc;
+
+ std::unique_ptr<weld::RadioButton> m_xUseExistingPagesRB;
+ std::unique_ptr<weld::RadioButton> m_xInsertNewPagesRB; // required by LOK JSDialogs
+ std::unique_ptr<weld::SpinButton> m_xPageCountNF;
+ std::unique_ptr<weld::RadioButton> m_xDocumentStartRB;
+ std::unique_ptr<weld::RadioButton> m_xPageStartRB;
+ std::unique_ptr<weld::SpinButton> m_xPageStartNF;
+ std::unique_ptr<weld::CheckButton> m_xRestartNumberingCB;
+ std::unique_ptr<weld::SpinButton> m_xRestartNumberingNF;
+ std::unique_ptr<weld::CheckButton> m_xSetPageNumberCB;
+ std::unique_ptr<weld::SpinButton> m_xSetPageNumberNF;
+ std::unique_ptr<weld::ComboBox> m_xPagePropertiesLB;
+ std::unique_ptr<weld::Button> m_xPagePropertiesPB;
+ std::unique_ptr<weld::Button> m_xOkPB;
+
+ void FillList();
+
+ sal_uInt16 GetInsertPosition() const;
+
+ DECL_LINK(OKHdl, weld::Button&, void);
+ DECL_LINK(EditHdl, weld::Button&, void);
+ DECL_LINK(RestartNumberingHdl, weld::Toggleable&, void);
+ DECL_LINK(SetPageNumberHdl, weld::Toggleable&, void);
+ DECL_LINK(ValueChangeHdl, weld::SpinButton&, void);
+ DECL_LINK(StartPageHdl, weld::Toggleable&, void);
+
+public:
+ SwTitlePageDlg(weld::Window* pParent);
+ virtual ~SwTitlePageDlg() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/tmpdlg.hxx b/sw/source/uibase/inc/tmpdlg.hxx
new file mode 100644
index 0000000000..8135e5a746
--- /dev/null
+++ b/sw/source/uibase/inc/tmpdlg.hxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_TMPDLG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_TMPDLG_HXX
+
+#include <sfx2/styledlg.hxx>
+#include <svl/style.hxx>
+
+class SfxItemSet;
+class SwWrtShell;
+
+// the tab dialog carrier of TabPages
+class SwTemplateDlgController final : public SfxStyleDialogController
+{
+
+ SfxStyleFamily m_nType;
+ sal_uInt16 m_nHtmlMode;
+ SwWrtShell* m_pWrtShell;
+ bool m_bNewStyle;
+
+public:
+ /// @param sPage
+ /// Identifies name of page to open at by default
+ SwTemplateDlgController(weld::Window* pParent,
+ SfxStyleSheetBase& rBase,
+ SfxStyleFamily nRegion,
+ const OUString& sPage,
+ SwWrtShell* pActShell,
+ bool bNew);
+
+ virtual void RefreshInputSet() override;
+
+ virtual void PageCreated(const OUString& rId, SfxTabPage &rPage) override;
+ virtual short Ok() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/tmplctrl.hxx b/sw/source/uibase/inc/tmplctrl.hxx
new file mode 100644
index 0000000000..0b60c3a6be
--- /dev/null
+++ b/sw/source/uibase/inc/tmplctrl.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_TMPLCTRL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_TMPLCTRL_HXX
+
+#include <sfx2/stbitem.hxx>
+
+class SwTemplateControl final : public SfxStatusBarControl
+{
+ virtual void Command(const CommandEvent& rCEvt) override;
+
+public:
+ virtual void StateChangedAtStatusBarControl(sal_uInt16 nSID, SfxItemState eState,
+ const SfxPoolItem* pState) override;
+ virtual void Paint(const UserDrawEvent& rEvt) override;
+
+ SFX_DECL_STATUSBAR_CONTROL();
+
+ SwTemplateControl(sal_uInt16 nSlotId, sal_uInt16 nId, StatusBar& rStb);
+ virtual ~SwTemplateControl() override;
+
+private:
+ OUString m_sTemplate;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/toxmgr.hxx b/sw/source/uibase/inc/toxmgr.hxx
new file mode 100644
index 0000000000..84a49a5a25
--- /dev/null
+++ b/sw/source/uibase/inc/toxmgr.hxx
@@ -0,0 +1,275 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_TOXMGR_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_TOXMGR_HXX
+
+#include <swdllapi.h>
+#include <tox.hxx>
+#include <authfld.hxx>
+#include <memory>
+#include <optional>
+
+class SwWrtShell;
+class SwForm;
+
+// manager for directory functionality
+//one single method will be sufficient to insert AND update indexes
+class SW_DLLPUBLIC SwTOXDescription
+{
+ TOXTypes m_eTOXType;
+ OUString m_aStyleNames[MAXLEVEL];
+ OUString m_sSequenceName;
+ OUString m_sMainEntryCharStyle;
+ OUString m_sAutoMarkURL;
+ std::optional<OUString>
+ m_aTitle;
+ std::optional<OUString>
+ m_aTOUName;
+ std::unique_ptr<SwForm>
+ m_pForm;
+ SwTOXElement m_nContent;
+ SwTOIOptions m_nIndexOptions;
+ SwTOOElements m_nOLEOptions;
+ LanguageType m_eLanguage;
+ OUString m_sSortAlgorithm;
+
+ OUString m_sAuthBrackets;
+ SwCaptionDisplay m_eCaptionDisplay;
+ SwTOXSortKey m_eSortKey1;
+ SwTOXSortKey m_eSortKey2;
+ SwTOXSortKey m_eSortKey3;
+ sal_uInt8 m_nLevel;
+ bool m_bFromObjectNames : 1;
+ bool m_bFromChapter : 1;
+ bool m_bReadonly: 1;
+ bool m_bLevelFromChapter : 1;
+ bool m_bIsAuthSequence :1;
+ bool m_bSortByDocument :1;
+
+ //TODO: TemplateNames
+ //const String* pTemplateName = 0, ???
+
+ SwTOXDescription(SwTOXDescription const &) = delete;
+ SwTOXDescription & operator= (SwTOXDescription const &) = delete;
+
+public:
+ // single argument ctors shall be explicit.
+ explicit SwTOXDescription(TOXTypes eType) :
+ m_eTOXType(eType),
+ m_nContent(SwTOXElement::Mark | SwTOXElement::OutlineLevel),
+ m_nIndexOptions(SwTOIOptions::SameEntry|SwTOIOptions::FF|SwTOIOptions::CaseSensitive),
+ m_nOLEOptions(SwTOOElements::NONE),
+ m_eLanguage(::GetAppLanguage()),
+ m_eCaptionDisplay(CAPTION_COMPLETE),
+ m_nLevel(MAXLEVEL),
+ m_bFromObjectNames(false),
+ m_bFromChapter(false),
+ m_bReadonly(true),
+ m_bLevelFromChapter(false),
+ m_bIsAuthSequence(false),
+ m_bSortByDocument(true)
+ {}
+
+ TOXTypes GetTOXType() const { return m_eTOXType;}
+
+ const OUString& GetStyleNames(sal_uInt16 nLvl) const
+ {return m_aStyleNames[nLvl];}
+ void SetStyleNames(const OUString& rSet, sal_uInt16 nLvl)
+ {m_aStyleNames[nLvl] = rSet; }
+
+ const OUString& GetAutoMarkURL() const { return m_sAutoMarkURL;}
+ void SetAutoMarkURL(const OUString& rSet) {m_sAutoMarkURL = rSet;}
+
+ void SetTitle(const OUString& rSet) { m_aTitle = rSet; }
+ std::optional<OUString> const & GetTitle() const {return m_aTitle; }
+
+ void SetTOUName(const OUString& rSet) { m_aTOUName = rSet; }
+ std::optional<OUString> const & GetTOUName() const { return m_aTOUName; }
+
+ void SetForm(const SwForm& rSet) { m_pForm.reset( new SwForm(rSet) );}
+ const SwForm* GetForm() const {return m_pForm.get();}
+
+ void SetContentOptions(SwTOXElement nSet) { m_nContent = nSet;}
+ SwTOXElement GetContentOptions() const { return m_nContent;}
+
+ void SetIndexOptions(SwTOIOptions nSet) { m_nIndexOptions = nSet;}
+ SwTOIOptions GetIndexOptions() const { return m_nIndexOptions;}
+
+ const OUString& GetMainEntryCharStyle() const {return m_sMainEntryCharStyle;}
+ void SetMainEntryCharStyle(const OUString& rSet) {m_sMainEntryCharStyle = rSet;}
+
+ void SetLevel(sal_uInt8 nSet) {m_nLevel = nSet;}
+ sal_uInt8 GetLevel()const {return m_nLevel; }
+
+ void SetCreateFromObjectNames(bool bSet) { m_bFromObjectNames = bSet;}
+ bool IsCreateFromObjectNames() const {return m_bFromObjectNames;}
+
+ const OUString& GetSequenceName() const {return m_sSequenceName;}
+ void SetSequenceName(const OUString& rSet) {m_sSequenceName = rSet;}
+
+ SwCaptionDisplay GetCaptionDisplay() const { return m_eCaptionDisplay;}
+ void SetCaptionDisplay(SwCaptionDisplay eSet) {m_eCaptionDisplay = eSet;}
+
+ void SetFromChapter(bool bSet) { m_bFromChapter = bSet;}
+ bool IsFromChapter() const {return m_bFromChapter;}
+
+ void SetReadonly(bool bSet){m_bReadonly = bSet;}
+ bool IsReadonly() const {return m_bReadonly;}
+
+ SwTOOElements GetOLEOptions() const {return m_nOLEOptions;}
+ void SetOLEOptions(SwTOOElements nOpt) {m_nOLEOptions = nOpt;}
+
+ bool IsLevelFromChapter() const {return m_bLevelFromChapter;}
+ void SetLevelFromChapter(bool bSet) {m_bLevelFromChapter = bSet;}
+
+ const OUString& GetAuthBrackets() const {return m_sAuthBrackets;}
+ void SetAuthBrackets(const OUString& rSet) {m_sAuthBrackets = rSet;}
+
+ bool IsAuthSequence() const {return m_bIsAuthSequence;}
+ void SetAuthSequence(bool bSet){m_bIsAuthSequence = bSet;}
+
+ bool IsSortByDocument()const {return m_bSortByDocument ;}
+ void SetSortByDocument(bool bSet) {m_bSortByDocument = bSet;}
+
+ void SetSortKeys(SwTOXSortKey eKey1,
+ SwTOXSortKey eKey2,
+ SwTOXSortKey eKey3);
+
+ const SwTOXSortKey& GetSortKey1() const {return m_eSortKey1;}
+ const SwTOXSortKey& GetSortKey2() const {return m_eSortKey2;}
+ const SwTOXSortKey& GetSortKey3() const {return m_eSortKey3;}
+
+ LanguageType GetLanguage() const {return m_eLanguage;}
+ void SetLanguage(LanguageType nLang) {m_eLanguage = nLang;}
+
+ const OUString& GetSortAlgorithm()const {return m_sSortAlgorithm;}
+ void SetSortAlgorithm(const OUString& rSet) {m_sSortAlgorithm = rSet;}
+
+ void ApplyTo(SwTOXBase& rTOXBase);
+
+};
+
+class SwTOXMarkDescription
+{
+ TOXTypes meTOXType;
+ int mnLevel;
+ bool mbMainEntry;
+
+ std::optional<OUString> maPrimKey;
+ std::optional<OUString> maSecKey;
+ std::optional<OUString> maAltStr;
+ std::optional<OUString> maTOUName;
+
+ std::optional<OUString> maPhoneticReadingOfAltStr;
+ std::optional<OUString> maPhoneticReadingOfPrimKey;
+ std::optional<OUString> maPhoneticReadingOfSecKey;
+
+ SwTOXMarkDescription(SwTOXMarkDescription const &) = delete;
+ SwTOXMarkDescription & operator= (SwTOXMarkDescription const &) = delete;
+
+public:
+ // single argument ctors shall be explicit.
+ explicit SwTOXMarkDescription(TOXTypes eType) :
+ meTOXType(eType),
+ mnLevel(0),
+ mbMainEntry(false)
+ {
+ }
+
+ TOXTypes GetTOXType()const {return meTOXType;}
+
+ void SetLevel(int nSet) {mnLevel = nSet;}
+ int GetLevel() const {return mnLevel;}
+
+ void SetMainEntry(bool bSet) {mbMainEntry = bSet;}
+ bool IsMainEntry() const {return mbMainEntry;}
+
+ void SetPrimKey(const OUString& rSet) { maPrimKey = rSet; }
+ std::optional<OUString> const & GetPrimKey() const { return maPrimKey; }
+
+ void SetSecKey(const OUString& rSet) { maSecKey = rSet; }
+ std::optional<OUString> const & GetSecKey() const { return maSecKey; }
+
+ void SetAltStr(const OUString& rSet) { maAltStr = rSet; }
+ std::optional<OUString> const & GetAltStr() const { return maAltStr; }
+
+ void SetTOUName(const OUString& rSet) { maTOUName = rSet; }
+ std::optional<OUString> const & GetTOUName() const { return maTOUName; }
+
+ void SetPhoneticReadingOfAltStr(const OUString& rSet) { maPhoneticReadingOfAltStr = rSet; }
+ std::optional<OUString> const & GetPhoneticReadingOfAltStr() const { return maPhoneticReadingOfAltStr; }
+
+ void SetPhoneticReadingOfPrimKey(const OUString& rSet) { maPhoneticReadingOfPrimKey = rSet; }
+ std::optional<OUString> const & GetPhoneticReadingOfPrimKey() const { return maPhoneticReadingOfPrimKey; }
+
+ void SetPhoneticReadingOfSecKey(const OUString& rSet) { maPhoneticReadingOfSecKey = rSet; }
+ std::optional<OUString> const & GetPhoneticReadingOfSecKey() const { return maPhoneticReadingOfSecKey; }
+};
+
+/**
+ * Built on top of SwWrtShell, provides functionality to insert, update or perform other actions on
+ * various ToX types (table of contents, indexes and so on).
+ */
+class SW_DLLPUBLIC SwTOXMgr
+{
+ SwWrtShell* m_pSh;
+ SwTOXMark* m_pCurTOXMark;
+ SwTOXMarks m_aCurMarks;
+
+ SAL_DLLPRIVATE sal_uInt16 GetUserTypeID(const OUString& rStr);
+
+public:
+ // single argument ctors shall be explicit.
+ explicit SwTOXMgr(SwWrtShell* pShell);
+
+ // methods for directory marks
+
+ void InsertTOXMark(const SwTOXMarkDescription& rDesc);
+
+ void UpdateTOXMark(const SwTOXMarkDescription& rDesc);
+
+ void DeleteTOXMark();
+ void NextTOXMark(bool bSame=false);
+ void PrevTOXMark(bool bSame=false);
+
+ // get current TOXmarks
+ sal_uInt16 GetTOXMarkCount() const;
+ SwTOXMark* GetTOXMark(sal_uInt16 nId);
+ SwTOXMark* GetCurTOXMark();
+ void SetCurTOXMark(sal_uInt16 nId);
+
+ // methods for directories
+
+ bool UpdateOrInsertTOX(const SwTOXDescription& rDesc, SwTOXBase** ppBase, const SfxItemSet* pSet);
+
+ const SwTOXType* GetTOXType(TOXTypes eTyp) const;
+ SwWrtShell * GetShell() { return m_pSh; }
+};
+
+// inlines
+inline sal_uInt16 SwTOXMgr::GetTOXMarkCount() const
+ { return m_aCurMarks.size(); }
+
+inline SwTOXMark* SwTOXMgr::GetCurTOXMark()
+ { return m_pCurTOXMark; }
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/translatehelper.hxx b/sw/source/uibase/inc/translatehelper.hxx
new file mode 100644
index 0000000000..9e473d68e0
--- /dev/null
+++ b/sw/source/uibase/inc/translatehelper.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/config.h>
+
+#include <config_features.h>
+#include <config_wasm_strip.h>
+
+#include <swtypes.hxx>
+
+class SwWrtShell;
+class SwPaM;
+class SwNode;
+class SwTextNode;
+
+namespace SwTranslateHelper
+{
+struct SW_DLLPUBLIC TranslateAPIConfig final
+{
+ const OString m_xAPIUrl;
+ const OString m_xAuthKey;
+ const OString m_xTargetLanguage;
+};
+SW_DLLPUBLIC OString ExportPaMToHTML(SwPaM* pCursor);
+SW_DLLPUBLIC void PasteHTMLToPaM(SwWrtShell& rWrtSh, SwPaM* pCursor, const OString& rData);
+#if HAVE_FEATURE_CURL && !ENABLE_WASM_STRIP_EXTRA
+SW_DLLPUBLIC void TranslateDocument(SwWrtShell& rWrtSh, const TranslateAPIConfig& rConfig);
+SW_DLLPUBLIC void TranslateDocumentCancellable(SwWrtShell& rWrtSh,
+ const TranslateAPIConfig& rConfig,
+ bool& rCancelTranslation);
+#endif
+}
diff --git a/sw/source/uibase/inc/translatelangselect.hxx b/sw/source/uibase/inc/translatelangselect.hxx
new file mode 100644
index 0000000000..bd1c8c85e6
--- /dev/null
+++ b/sw/source/uibase/inc/translatelangselect.hxx
@@ -0,0 +1,68 @@
+
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+#include <vcl/weld.hxx>
+#include <rtl/string.h>
+#include <vector>
+#include <optional>
+#include "translatehelper.hxx"
+
+class SwWrtShell;
+
+// SwLanguageListItem Helper class for displaying available languages with their names and tags on the listbox.
+class SwLanguageListItem final
+{
+public:
+ SwLanguageListItem(const OString& sLanguage, const OString& sName)
+ : m_sLanguage(sLanguage)
+ , m_sName(sName)
+ {
+ }
+ const OString& getLanguage() const { return m_sLanguage; }
+ const OString& getName() const { return m_sName; }
+
+private:
+ const OString m_sLanguage;
+ const OString m_sName;
+};
+
+// SwTranslateLangSelectDlg Language selection dialog for translation API.
+class SwTranslateLangSelectDlg final : public weld::GenericDialogController
+{
+public:
+ static int selectedLangIdx;
+ SwTranslateLangSelectDlg(weld::Window* pParent, SwWrtShell& rSh);
+ static std::optional<SwLanguageListItem> GetSelectedLanguage();
+
+private:
+ SwWrtShell& m_rWrtSh;
+ std::unique_ptr<weld::ComboBox> m_xLanguageListBox;
+ std::unique_ptr<weld::Button> m_xBtnCancel;
+ std::unique_ptr<weld::Button> m_xBtnTranslate;
+
+ bool m_bTranslationStarted;
+ bool m_bCancelTranslation;
+
+ DECL_STATIC_LINK(SwTranslateLangSelectDlg, LangSelectHdl, weld::ComboBox&, void);
+ DECL_LINK(LangSelectCancelHdl, weld::Button&, void);
+ DECL_LINK(LangSelectTranslateHdl, weld::Button&, void);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/uiborder.hxx b/sw/source/uibase/inc/uiborder.hxx
new file mode 100644
index 0000000000..bd23157b7f
--- /dev/null
+++ b/sw/source/uibase/inc/uiborder.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_UIBORDER_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_UIBORDER_HXX
+
+#include <sfx2/basedlgs.hxx>
+#include <svx/flagsdef.hxx>
+
+class SwBorderDlg final : public SfxSingleTabDialogController
+{
+public:
+ // nType may be:
+ // SW_BORDER_MODE_PARA
+ // SW_BORDER_MODE_TABLE
+ // SW_BORDER_MODE_FRAME
+
+ SwBorderDlg(weld::Window* pParent, const SfxItemSet& rSet, SwBorderModes nType);
+ virtual ~SwBorderDlg() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/uiitems.hxx b/sw/source/uibase/inc/uiitems.hxx
new file mode 100644
index 0000000000..ded7155385
--- /dev/null
+++ b/sw/source/uibase/inc/uiitems.hxx
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_UIITEMS_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_UIITEMS_HXX
+
+#include <memory>
+#include <svl/poolitem.hxx>
+#include <swdllapi.h>
+#include <pagedesc.hxx>
+
+class SwNumRule;
+class IntlWrapper;
+class SwPaM;
+
+// container for FootNote
+class SW_DLLPUBLIC SwPageFootnoteInfoItem final : public SfxPoolItem
+{
+ SwPageFootnoteInfo m_aFootnoteInfo;
+
+public:
+
+ SwPageFootnoteInfoItem(SwPageFootnoteInfo const & rInfo);
+ virtual ~SwPageFootnoteInfoItem() override;
+
+ SwPageFootnoteInfoItem(SwPageFootnoteInfoItem const &) = default;
+ SwPageFootnoteInfoItem(SwPageFootnoteInfoItem &&) = default;
+ SwPageFootnoteInfoItem & operator =(SwPageFootnoteInfoItem const &) = delete; // due to SfxPoolItem
+ SwPageFootnoteInfoItem & operator =(SwPageFootnoteInfoItem &&) = delete; // due to SfxPoolItem
+
+ virtual SwPageFootnoteInfoItem* Clone( SfxItemPool *pPool = nullptr ) const override;
+ virtual bool operator==( const SfxPoolItem& ) const override;
+ virtual bool GetPresentation( SfxItemPresentation ePres,
+ MapUnit eCoreMetric,
+ MapUnit ePresMetric,
+ OUString &rText,
+ const IntlWrapper& rIntl ) const override;
+
+ virtual bool QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId = 0 ) const override;
+ virtual bool PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId ) override;
+
+ SwPageFootnoteInfo& GetPageFootnoteInfo() { return m_aFootnoteInfo; }
+ const SwPageFootnoteInfo& GetPageFootnoteInfo() const { return m_aFootnoteInfo; }
+};
+
+class SW_DLLPUBLIC SwPtrItem final : public SfxPoolItem
+{
+ void* m_pMisc;
+
+public:
+ SwPtrItem( const sal_uInt16 nId, void* pPtr);
+
+ virtual SwPtrItem* Clone( SfxItemPool *pPool = nullptr ) const override;
+ virtual bool operator==( const SfxPoolItem& ) const override;
+
+ void* GetValue() const { return m_pMisc; }
+};
+
+class SW_DLLPUBLIC SwUINumRuleItem final : public SfxPoolItem
+{
+ std::unique_ptr<SwNumRule> m_pRule;
+
+public:
+ SwUINumRuleItem( const SwNumRule& rRule );
+ SwUINumRuleItem( const SwUINumRuleItem& rItem );
+ virtual ~SwUINumRuleItem() override;
+
+ virtual SwUINumRuleItem* Clone( SfxItemPool *pPool = nullptr ) const override;
+ virtual bool operator==( const SfxPoolItem& ) const override;
+
+ virtual bool QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId = 0 ) const override;
+ virtual bool PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId ) override;
+
+ const SwNumRule* GetNumRule() const { return m_pRule.get(); }
+ SwNumRule* GetNumRule() { return m_pRule.get(); }
+};
+
+class SwPaMItem final : public SfxPoolItem
+{
+ SwPaM* m_pPaM;
+
+public:
+ SwPaMItem( const sal_uInt16 nId, SwPaM* pPaM);
+
+ virtual SwPaMItem* Clone( SfxItemPool *pPool = nullptr ) const override;
+ virtual bool operator==( const SfxPoolItem& ) const override;
+
+ SwPaM* GetValue() const { return m_pPaM; }
+};
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_UIITEMS_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/uinums.hxx b/sw/source/uibase/inc/uinums.hxx
new file mode 100644
index 0000000000..b0c49b0ca2
--- /dev/null
+++ b/sw/source/uibase/inc/uinums.hxx
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_UINUMS_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_UINUMS_HXX
+
+#include <numrule.hxx>
+#include <swdllapi.h>
+
+#include <memory>
+#include <vector>
+
+class SfxPoolItem;
+class SwWrtShell;
+class SvStream;
+
+namespace sw { class StoredChapterNumberingRules; }
+
+#define MAX_NUM_RULES 9
+
+class SW_DLLPUBLIC SwNumRulesWithName final
+{
+ OUString maName;
+ // the NumRule's formats _have_ to be independent of a document
+ // (They should always be there!)
+ class SAL_DLLPRIVATE SwNumFormatGlobal
+ {
+ friend class SwNumRulesWithName;
+ SwNumFormat m_aFormat;
+ OUString m_sCharFormatName;
+ sal_uInt16 m_nCharPoolId;
+ std::vector<std::unique_ptr<SfxPoolItem>> m_Items;
+
+ SwNumFormatGlobal& operator=( const SwNumFormatGlobal& ) = delete;
+
+ public:
+ SwNumFormatGlobal( const SwNumFormat& rFormat );
+ SwNumFormatGlobal( const SwNumFormatGlobal& );
+ ~SwNumFormatGlobal();
+
+ SwNumFormat MakeNumFormat(SwWrtShell& rSh) const;
+ };
+
+ std::unique_ptr<SwNumFormatGlobal> m_aFormats[ MAXLEVEL ];
+
+ friend class sw::StoredChapterNumberingRules;
+ friend class SwChapterNumRules;
+ void SetName(const OUString& rSet) {maName = rSet;}
+ void SetNumFormat(size_t, SwNumFormat const&, OUString const&);
+ SwNumRulesWithName() = default;
+
+public:
+ SwNumRulesWithName(const SwNumRule &, OUString );
+ SwNumRulesWithName( const SwNumRulesWithName & );
+ ~SwNumRulesWithName();
+
+ SwNumRulesWithName &operator=(const SwNumRulesWithName &);
+
+ const OUString& GetName() const { return maName; }
+ void ResetNumRule(SwWrtShell& rSh, SwNumRule& ) const;
+
+ void GetNumFormat(size_t, SwNumFormat const*&, OUString const*&) const;
+};
+
+class SW_DLLPUBLIC SwChapterNumRules final
+{
+public:
+ enum { nMaxRules = MAX_NUM_RULES }; // currently 9 defined forms
+private:
+ std::unique_ptr<SwNumRulesWithName> m_pNumRules[ MAX_NUM_RULES ];
+
+ void Init();
+ void Save();
+
+public:
+ SwChapterNumRules();
+ ~SwChapterNumRules();
+
+ inline const SwNumRulesWithName* GetRules(sal_uInt16 nIdx) const;
+ void CreateEmptyNumRule(sal_uInt16 nIdx); // for import
+ void ApplyNumRules( const SwNumRulesWithName &rCopy,
+ sal_uInt16 nIdx);
+};
+
+inline const SwNumRulesWithName *SwChapterNumRules::GetRules(sal_uInt16 nIdx) const
+{
+ assert(nIdx < nMaxRules);
+ return m_pNumRules[nIdx].get();
+}
+
+
+namespace sw
+{
+
+void ExportStoredChapterNumberingRules(
+ SwChapterNumRules & rRules, SvStream & rStream, OUString const&);
+void ImportStoredChapterNumberingRules(
+ SwChapterNumRules & rRules, SvStream & rStream, OUString const&);
+
+} // namespace sw
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/uiobject.hxx b/sw/source/uibase/inc/uiobject.hxx
new file mode 100644
index 0000000000..8911ef2a87
--- /dev/null
+++ b/sw/source/uibase/inc/uiobject.hxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+
+#ifndef SW_SOURCE_UIBASE_INC_UIOBJECT_HXX
+#define SW_SOURCE_UIBASE_INC_UIOBJECT_HXX
+
+#include <memory>
+#include <vcl/uitest/uiobject.hxx>
+
+#include "edtwin.hxx"
+#include "PageBreakWin.hxx"
+
+#include <AnnotationWin.hxx>
+
+class SwEditWinUIObject final : public WindowUIObject
+{
+public:
+
+ SwEditWinUIObject(const VclPtr<SwEditWin>& xEditWin);
+
+ virtual StringMap get_state() override;
+
+ virtual void execute(const OUString& rAction,
+ const StringMap& rParameters) override;
+
+ static std::unique_ptr<UIObject> create(vcl::Window* pWindow);
+
+ virtual OUString get_name() const override;
+
+private:
+
+ VclPtr<SwEditWin> mxEditWin;
+
+};
+
+// This class handles the Comments as a UIObject to be used in UITest Framework
+class CommentUIObject final : public WindowUIObject
+{
+ VclPtr<sw::annotation::SwAnnotationWin> mxCommentUIObject;
+
+public:
+
+ CommentUIObject(const VclPtr<sw::annotation::SwAnnotationWin>& xCommentUIObject);
+
+ virtual StringMap get_state() override;
+
+ virtual void execute(const OUString& rAction,
+ const StringMap& rParameters) override;
+
+ static std::unique_ptr<UIObject> create(vcl::Window* pWindow);
+
+private:
+
+ OUString get_name() const override;
+
+};
+
+class PageBreakUIObject final : public WindowUIObject
+{
+public:
+
+ PageBreakUIObject(const VclPtr<SwBreakDashedLine>& xEditWin);
+
+ virtual void execute(const OUString& rAction,
+ const StringMap& rParameters) override;
+
+ static std::unique_ptr<UIObject> create(vcl::Window* pWindow);
+
+private:
+
+ virtual OUString get_name() const override;
+
+ VclPtr<SwBreakDashedLine> mxPageBreakUIObject;
+
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/uitool.hxx b/sw/source/uibase/inc/uitool.hxx
new file mode 100644
index 0000000000..87eef4e84f
--- /dev/null
+++ b/sw/source/uibase/inc/uitool.hxx
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_UITOOL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_UITOOL_HXX
+
+#include <vcl/weld.hxx>
+#include <swtypes.hxx>
+#include <swdllapi.h>
+
+class SfxItemSet;
+class SwPageDesc;
+class SvxTabStopItem;
+class SwWrtShell;
+namespace com::sun::star::awt { class XPopupMenu; }
+namespace weld { class ComboBox; }
+namespace model { class ComplexColor; }
+class SwDocShell;
+class SwFrameFormat;
+class SwTabCols;
+class DateTime;
+class SfxViewFrame;
+class SwEditShell;
+
+// fill BoxInfo attribute
+SW_DLLPUBLIC void PrepareBoxInfo(SfxItemSet& rSet, const SwWrtShell& rSh);
+
+/**
+ * Convert character specific attributes to general ones used by tab pages.
+ *
+ * @param[in,out] rSet the set in which character attributes are stored
+ * @param[in] bIsPara is called by a paragraph style
+**/
+SW_DLLPUBLIC void ConvertAttrCharToGen(SfxItemSet& rSet, bool bPara = false);
+
+/**
+ * Convert general attributes to the corresponding character attributes.
+ * This method is used after executed a character dialog.
+ *
+ * @param[in,out] rSet the set in which character attributes are stored
+ * @param[in] rOrigSet original itemset used as input for the dialog
+ * @param[in] bIsPara is called by a paragraph style
+**/
+SW_DLLPUBLIC void ConvertAttrGenToChar(SfxItemSet& rSet, const SfxItemSet& rOrigSet, bool bPara = false);
+
+
+/**
+* Apply character background on the shell. Need to use this to hide the mixed
+* character background and character highlighting attribute, which were
+* added for MSO compatibility where there are two kind of character background.
+*
+* @param[in] rBackgroundColor the color to apply on the shell
+* @param[in,out] rShell the shell on which we apply the new attribute
+**/
+void ApplyCharBackground(Color const& rBackgroundColor, model::ComplexColor const& rComplexColor, SwWrtShell& rShell);
+
+// SfxItemSets <-> PageDesc
+void ItemSetToPageDesc( const SfxItemSet& rSet, SwPageDesc& rPageDesc );
+void PageDescToItemSet( const SwPageDesc& rPageDesc, SfxItemSet& rSet);
+
+// fill tabs with default tabs
+SW_DLLPUBLIC void MakeDefTabs(SwTwips nDefDist, SvxTabStopItem& rTabs);
+
+// erase DefaultTabs from TabStopArray
+//void EraseDefTabs(SvxTabStopItem& rTabs);
+
+// determine space between 1st and 2nd element
+SW_DLLPUBLIC SwTwips GetTabDist(const SvxTabStopItem& rTabs);
+
+// determine whether a Sfx-PageDesc combination exists in the set
+// and set this in the set and delete the transport items
+// (PageBreak & PageModel) from the set
+void SwToSfxPageDescAttr( SfxItemSet& rSet );
+void SfxToSwPageDescAttr( const SwWrtShell& rShell, SfxItemSet& rSet );
+
+SW_DLLPUBLIC FieldUnit GetDfltMetric(bool bWeb);
+void SetDfltMetric(FieldUnit eMetric, bool bWeb);
+
+bool HasCharUnit( bool bWeb );
+void SetApplyCharUnit(bool bApplyChar, bool bWeb);
+
+// fill ListBox with all char style templates, except the standard ones
+SW_DLLPUBLIC void FillCharStyleListBox(weld::ComboBox& rToFill, SwDocShell* pDocSh, bool bSorted = false, bool bWithDefault = false);
+
+//inserts a string sorted into a ListBox,
+SW_DLLPUBLIC void InsertStringSorted(const OUString& rId, const OUString& rEntry, weld::ComboBox& rToFill, int nOffset);
+
+// Get table width and alignment
+SwTwips GetTableWidth( SwFrameFormat const * pFormat, SwTabCols const & rCols, sal_uInt16 *pPercent,
+ SwWrtShell* pSh );
+
+OUString GetAppLangDateTimeString( const DateTime& );
+
+// search for a command string within the menu structure and execute it
+// at the dispatcher if there is one, if executed return true
+bool ExecuteMenuCommand(const css::uno::Reference<css::awt::XPopupMenu>& rMenu, const SfxViewFrame& rViewFrame, sal_uInt16 nId);
+
+#endif // INCLUDED_SW_SOURCE_UIBASE_INC_UITOOL_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/uivwimp.hxx b/sw/source/uibase/inc/uivwimp.hxx
new file mode 100644
index 0000000000..65a0bf4f23
--- /dev/null
+++ b/sw/source/uibase/inc/uivwimp.hxx
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_UIVWIMP_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_UIVWIMP_HXX
+
+#include <view.hxx>
+
+#include <sfx2/objsh.hxx>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboardListener.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <unotools/weakref.hxx>
+
+class SwXTextView;
+class SfxRequest;
+class SwTransferable;
+class SfxRequest;
+
+namespace sfx2 { class DocumentInserter; }
+namespace com::sun::star {
+ namespace frame {
+ class XDispatchProviderInterceptor;
+ }
+ namespace lang {
+ class XUnoTunnel;
+ }
+}
+
+class SwScannerEventListener final : public ::cppu::WeakImplHelper<
+ css::lang::XEventListener >
+{
+ SwView* m_pView;
+
+public:
+
+ SwScannerEventListener( SwView& rView ) : m_pView( &rView ) {}
+ virtual ~SwScannerEventListener() override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& rEventObject ) override;
+
+ void ViewDestroyed() { m_pView = nullptr; }
+};
+
+// Clipboard EventListener
+class SwClipboardChangeListener final : public ::cppu::WeakImplHelper<
+ css::datatransfer::clipboard::XClipboardListener >
+{
+ SwView* m_pView;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& rEventObject ) override;
+
+ // XClipboardListener
+ virtual void SAL_CALL changedContents( const css::datatransfer::clipboard::ClipboardEvent& rEventObject ) override;
+
+public:
+ SwClipboardChangeListener( SwView& rView ) : m_pView( &rView ) {}
+ virtual ~SwClipboardChangeListener() override;
+
+ void ViewDestroyed() { m_pView = nullptr; }
+
+ void AddRemoveListener( bool bAdd );
+};
+
+class SwMailMergeConfigItem;
+class SwXDispatchProviderInterceptor;
+
+class SwView_Impl
+{
+ rtl::Reference< SwXDispatchProviderInterceptor > m_xDispatchProviderInterceptor;
+ rtl::Reference< SwXTextView > mxXTextView; // UNO object
+ std::vector< unotools::WeakReference< SwTransferable > > mxTransferables;
+
+ // temporary document for printing text of selection / multi selection
+ // in PDF export.
+ SfxObjectShellLock m_xTmpSelDocShell;
+
+ SwView* m_pView;
+ rtl::Reference<SwScannerEventListener>
+ mxScanEvtLstnr;
+ rtl::Reference<SwClipboardChangeListener>
+ mxClipEvtLstnr;
+ ShellMode m_eShellMode;
+
+ std::shared_ptr<SwMailMergeConfigItem>
+ m_xConfigItem;
+
+ std::unique_ptr<sfx2::DocumentInserter> m_pDocInserter;
+ std::unique_ptr<SfxRequest> m_pRequest;
+ sal_Int16 m_nParam;
+
+ Point m_aEditingPosition;
+ bool m_bSelectObject;
+ bool m_bEditingPositionSet;
+
+ void DisconnectTransferableDDE();
+
+public:
+ /// Redline author that's specific to this view.
+ OUString m_sRedlineAuthor;
+
+ SwView_Impl(SwView* pShell);
+ ~SwView_Impl();
+
+ void SetShellMode(ShellMode eSet);
+
+ css::view::XSelectionSupplier* GetUNOObject();
+ SwXTextView* GetUNOObject_Impl();
+ void Invalidate();
+
+ ShellMode GetShellMode() const {return m_eShellMode;}
+
+ void ExecuteScan(SfxRequest& rReq);
+ SwScannerEventListener& GetScannerEventListener();
+
+ void AddClipboardListener();
+
+ void AddTransferable(SwTransferable& rTransferable);
+
+ void SetMailMergeConfigItem(std::shared_ptr<SwMailMergeConfigItem> const & rItem)
+ {
+ m_xConfigItem = rItem;
+ }
+ std::shared_ptr<SwMailMergeConfigItem> const & GetMailMergeConfigItem() const {return m_xConfigItem;}
+
+ //#i33307# restore editing position
+ void SetRestorePosition(const Point& rCursorPos, bool bSelectObj)
+ {
+ m_aEditingPosition = rCursorPos;
+ m_bSelectObject = bSelectObj;
+ m_bEditingPositionSet = true;
+ }
+ bool GetRestorePosition(Point& rCursorPos, bool& rbSelectObj)
+ {
+ rCursorPos = m_aEditingPosition;
+ rbSelectObj = m_bSelectObject;
+ return m_bEditingPositionSet;
+ }
+
+ void StartDocumentInserter(
+ const OUString& rFactory,
+ const Link<sfx2::FileDialogHelper*,void>& rEndDialogHdl,
+ const sal_uInt16 nSlotId
+ );
+ std::unique_ptr<SfxMedium> CreateMedium();
+ void InitRequest( const SfxRequest& rRequest );
+
+ SfxRequest* GetRequest() const { return m_pRequest.get(); }
+ sal_Int16 GetParam() const { return m_nParam; }
+ void SetParam( sal_Int16 nParam ) { m_nParam = nParam; }
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/unoatxt.hxx b/sw/source/uibase/inc/unoatxt.hxx
new file mode 100644
index 0000000000..48f0c81379
--- /dev/null
+++ b/sw/source/uibase/inc/unoatxt.hxx
@@ -0,0 +1,254 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_UNOATXT_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_UNOATXT_HXX
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/document/XEventsSupplier.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/text/XAutoTextGroup.hpp>
+#include <com/sun/star/text/XAutoTextEntry.hpp>
+#include <com/sun/star/text/XAutoTextContainer2.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <svl/itemprop.hxx>
+#include <svl/lstner.hxx>
+#include <comphelper/compbase.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <rtl/ref.hxx>
+#include <svtools/unoevent.hxx>
+
+class SwTextBlocks;
+class SwGlossaries;
+class SwDoc;
+class SwDocShell;
+class SwXBodyText;
+
+#ifndef SW_DECL_SWDOCSHELL_DEFINED
+#define SW_DECL_SWDOCSHELL_DEFINED
+#include <tools/ref.hxx>
+typedef tools::SvRef<SwDocShell> SwDocShellRef;
+#endif
+
+class SwXAutoTextContainer final : public cppu::WeakImplHelper
+<
+ css::text::XAutoTextContainer2,
+ css::lang::XServiceInfo
+>
+{
+ SwGlossaries *m_pGlossaries;
+
+ virtual ~SwXAutoTextContainer() override; // ref-counted objects are not to be deleted from outside -> protected dtor
+
+public:
+ SwXAutoTextContainer();
+
+ //XIndexAccess
+ virtual sal_Int32 SAL_CALL getCount( ) override;
+ virtual css::uno::Any SAL_CALL getByIndex(sal_Int32 nIndex) override;
+
+ //XNameAccess
+ virtual css::uno::Any SAL_CALL getByName(const OUString& Name) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override;
+ virtual sal_Bool SAL_CALL hasByName(const OUString& Name) override;
+
+ //XElementAccess
+ virtual css::uno::Type SAL_CALL getElementType( ) override;
+ virtual sal_Bool SAL_CALL hasElements( ) override;
+
+ //XAutoTextContainer
+ virtual css::uno::Reference< css::text::XAutoTextGroup > SAL_CALL insertNewByName(const OUString& aGroupName) override;
+ virtual void SAL_CALL removeByName(const OUString& aGroupName) override;
+
+ //XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+};
+
+class SwXAutoTextGroup final : public cppu::WeakImplHelper
+<
+ css::text::XAutoTextGroup,
+ css::beans::XPropertySet,
+ css::lang::XServiceInfo,
+ css::container::XIndexAccess,
+ css::container::XNamed
+>
+{
+ const SfxItemPropertySet* m_pPropSet;
+ SwGlossaries* m_pGlossaries;
+ OUString m_sName;
+ OUString m_sGroupName; // prefix m_ to disambiguate from some local vars in the implementation
+
+ virtual ~SwXAutoTextGroup() override; // ref-counted objects are not to be deleted from outside -> protected dtor
+
+public:
+ SwXAutoTextGroup(const OUString& rName, SwGlossaries* pGloss);
+
+ //XAutoTextGroup
+ virtual css::uno::Sequence< OUString > SAL_CALL getTitles() override;
+ virtual void SAL_CALL renameByName(const OUString& aElementName, const OUString& aNewElementName, const OUString& aNewElementTitle) override;
+ virtual css::uno::Reference< css::text::XAutoTextEntry > SAL_CALL insertNewByName(const OUString& aName, const OUString& aTitle, const css::uno::Reference< css::text::XTextRange > & xTextRange) override;
+ virtual void SAL_CALL removeByName(const OUString& aEntryName) override;
+
+ //XNamed
+ virtual OUString SAL_CALL getName() override;
+ virtual void SAL_CALL setName(const OUString& Name_) override;
+
+ //XIndexAccess
+ virtual sal_Int32 SAL_CALL getCount( ) override;
+ virtual css::uno::Any SAL_CALL getByIndex(sal_Int32 nIndex) override;
+
+ //XNameAccess
+ virtual css::uno::Any SAL_CALL getByName(const OUString& Name) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override;
+ virtual sal_Bool SAL_CALL hasByName(const OUString& Name) override;
+
+ //XElementAccess
+ virtual css::uno::Type SAL_CALL getElementType( ) override;
+ virtual sal_Bool SAL_CALL hasElements( ) override;
+
+ //XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ //XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+ virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override;
+ virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override;
+ virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ) override;
+ virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener ) override;
+ virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+ virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+
+ void Invalidate();
+};
+
+class SwXAutoTextEntry final
+ :public SfxListener
+ ,public comphelper::WeakComponentImplHelper
+ <
+ css::text::XAutoTextEntry,
+ css::lang::XServiceInfo,
+ css::text::XText,
+ css::document::XEventsSupplier
+ >
+{
+ SwGlossaries* m_pGlossaries;
+ OUString m_sGroupName;
+ OUString m_sEntryName;
+ SwDocShellRef m_xDocSh;
+ rtl::Reference<SwXBodyText>
+ mxBodyText;
+
+ void EnsureBodyText ()
+ {
+ if ( !mxBodyText.is() )
+ GetBodyText();
+ }
+ void GetBodyText ();
+
+ void disposing(std::unique_lock<std::mutex>&) override;
+
+ /** ensure that the current content (which may only be in-memory so far) is flushed to the auto text group file
+
+ <p>If somebody modifies an auto text via this class, then this is not directly reflected to the respective
+ glossaries file (on disk), instead we hold a copy of this text (in [p|x]BodyText). On the other hand,
+ in applyTo, we do not work with this _copy_, but just tell the target for the application to insert
+ the content which we're responsible for - and this target doesn't know about our copy, but only
+ about the persistent version.</br>
+ So we need to ensure that before somebody else does something with our auto text, we flush our
+ (in-memory) copy to disk.</p>
+
+ */
+ void implFlushDocument( bool _bCloseDoc = false );
+
+ // SfxListener overridables
+ virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
+
+ virtual ~SwXAutoTextEntry() override; // ref-counted objects are not to be deleted from outside -> protected dtor
+
+public:
+ SwXAutoTextEntry(SwGlossaries* , OUString aGroupName, OUString aEntryName);
+
+ //XText
+ virtual css::uno::Reference< css::text::XTextCursor > SAL_CALL createTextCursor() override;
+ virtual css::uno::Reference< css::text::XTextCursor > SAL_CALL createTextCursorByRange(const css::uno::Reference< css::text::XTextRange > & aTextPosition) override;
+ virtual void SAL_CALL insertString(const css::uno::Reference< css::text::XTextRange > & xRange, const OUString& aString, sal_Bool bAbsorb) override;
+ virtual void SAL_CALL insertControlCharacter(const css::uno::Reference< css::text::XTextRange > & xRange, sal_Int16 nControlCharacter, sal_Bool bAbsorb) override;
+ virtual void SAL_CALL insertTextContent(const css::uno::Reference< css::text::XTextRange > & xRange, const css::uno::Reference< css::text::XTextContent > & xContent, sal_Bool bAbsorb) override;
+ virtual void SAL_CALL removeTextContent(const css::uno::Reference< css::text::XTextContent > & xContent) override;
+
+ //XTextRange
+ virtual css::uno::Reference< css::text::XText > SAL_CALL getText() override;
+ virtual css::uno::Reference< css::text::XTextRange > SAL_CALL getStart() override;
+ virtual css::uno::Reference< css::text::XTextRange > SAL_CALL getEnd() override;
+ virtual OUString SAL_CALL getString() override;
+ virtual void SAL_CALL setString(const OUString& aString) override;
+
+ //XAutoTextEntry
+ virtual void SAL_CALL applyTo(const css::uno::Reference< css::text::XTextRange > & xRange) override;
+
+ //XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XEventsSupplier
+ virtual css::uno::Reference< css::container::XNameReplace > SAL_CALL getEvents( ) override;
+
+ void Invalidate() {m_pGlossaries = nullptr;}
+ const SwGlossaries* GetGlossaries() const { return m_pGlossaries; }
+ const OUString& GetGroupName() const {return m_sGroupName;}
+ const OUString& GetEntryName() const {return m_sEntryName;}
+};
+
+/** Implement the XNameAccess for the AutoText events */
+class SwAutoTextEventDescriptor final : public SvBaseEventDescriptor
+{
+ SwXAutoTextEntry& m_rAutoTextEntry;
+
+ using SvBaseEventDescriptor::replaceByName;
+ using SvBaseEventDescriptor::getByName;
+
+public:
+ SwAutoTextEventDescriptor( SwXAutoTextEntry& rAutoText );
+
+ virtual ~SwAutoTextEventDescriptor() override;
+
+ virtual OUString SAL_CALL getImplementationName() override;
+
+private:
+
+ virtual void replaceByName(
+ const SvMacroItemId nEvent, /// item ID of event
+ const SvxMacro& rMacro) /// event (will be copied)
+ override;
+
+ virtual void getByName(
+ SvxMacro& rMacro, /// macro to be filled
+ const SvMacroItemId nEvent ) /// item ID of event
+ override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/unodispatch.hxx b/sw/source/uibase/inc/unodispatch.hxx
new file mode 100644
index 0000000000..961637788f
--- /dev/null
+++ b/sw/source/uibase/inc/unodispatch.hxx
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_UNODISPATCH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_UNODISPATCH_HXX
+
+#include <com/sun/star/frame/XDispatchProviderInterception.hpp>
+#include <com/sun/star/frame/XDispatchProviderInterceptor.hpp>
+#include <com/sun/star/view/XSelectionChangeListener.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/frame/XInterceptorInfo.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <vector>
+#include <vcl/svapp.hxx>
+
+class SwView;
+
+class SwXDispatchProviderInterceptor final : public cppu::WeakImplHelper
+<
+ css::frame::XDispatchProviderInterceptor,
+ css::lang::XEventListener,
+ css::frame::XInterceptorInfo
+>
+{
+ class DispatchMutexLock_Impl
+ {
+ //::osl::MutexGuard aGuard; #102295# solar mutex has to be used currently
+ SolarMutexGuard aGuard;
+ public:
+ DispatchMutexLock_Impl();
+ ~DispatchMutexLock_Impl();
+ };
+ friend class DispatchMutexLock_Impl;
+
+// ::osl::Mutex m_aMutex;#102295# solar mutex has to be used currently
+
+ // the component which's dispatches we're intercepting
+ css::uno::Reference< css::frame::XDispatchProviderInterception> m_xIntercepted;
+
+ // chaining
+ css::uno::Reference< css::frame::XDispatchProvider> m_xSlaveDispatcher;
+ css::uno::Reference< css::frame::XDispatchProvider> m_xMasterDispatcher;
+
+ css::uno::Reference< css::frame::XDispatch> m_xDispatch;
+
+ SwView* m_pView;
+
+public:
+ SwXDispatchProviderInterceptor(SwView& rView);
+ virtual ~SwXDispatchProviderInterceptor() override;
+
+ //XDispatchProvider
+ virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch( const css::util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags ) override;
+ virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& aDescripts ) override;
+
+ //XDispatchProviderInterceptor
+ virtual css::uno::Reference< css::frame::XDispatchProvider > SAL_CALL getSlaveDispatchProvider( ) override;
+ virtual void SAL_CALL setSlaveDispatchProvider( const css::uno::Reference< css::frame::XDispatchProvider >& xNewDispatchProvider ) override;
+ virtual css::uno::Reference< css::frame::XDispatchProvider > SAL_CALL getMasterDispatchProvider( ) override;
+ virtual void SAL_CALL setMasterDispatchProvider( const css::uno::Reference< css::frame::XDispatchProvider >& xNewSupplier ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ // XInterceptorInfo
+ virtual css::uno::Sequence<OUString> SAL_CALL getInterceptedURLs() override;
+
+ // view destroyed
+ void Invalidate();
+};
+
+struct StatusStruct_Impl
+{
+ css::uno::Reference< css::frame::XStatusListener> xListener;
+ css::util::URL aURL;
+};
+class SwXDispatch final : public cppu::WeakImplHelper
+<
+ css::frame::XDispatch,
+ css::view::XSelectionChangeListener
+>
+{
+ SwView* m_pView;
+ std::vector< StatusStruct_Impl > m_aStatusListenerVector;
+ bool m_bOldEnable;
+ bool m_bListenerAdded;
+public:
+ SwXDispatch(SwView& rView);
+ virtual ~SwXDispatch() override;
+
+ virtual void SAL_CALL dispatch( const css::util::URL& aURL, const css::uno::Sequence< css::beans::PropertyValue >& aArgs ) override;
+ virtual void SAL_CALL addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xControl, const css::util::URL& aURL ) override;
+ virtual void SAL_CALL removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xControl, const css::util::URL& aURL ) override;
+
+ //XSelectionChangeListener
+ virtual void SAL_CALL selectionChanged( const css::lang::EventObject& aEvent ) override;
+
+ //XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ static const char* GetDBChangeURL();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/unomailmerge.hxx b/sw/source/uibase/inc/unomailmerge.hxx
new file mode 100644
index 0000000000..722d804483
--- /dev/null
+++ b/sw/source/uibase/inc/unomailmerge.hxx
@@ -0,0 +1,175 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_UNOMAILMERGE_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_UNOMAILMERGE_HXX
+
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/interfacecontainer2.hxx>
+#include <comphelper/interfacecontainer3.hxx>
+#include <comphelper/multiinterfacecontainer3.hxx>
+
+#include <com/sun/star/task/XJob.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/beans/PropertyChangeEvent.hpp>
+#include <com/sun/star/text/XMailMergeBroadcaster.hpp>
+#include <com/sun/star/util/XCancellable.hpp>
+#include <svl/itemprop.hxx>
+#include <sfx2/objsh.hxx>
+
+namespace com::sun::star {
+
+ namespace sdbc {
+ class XResultSet;
+ class XConnection;
+ }
+ namespace frame {
+ class XModel;
+ }
+ namespace lang {
+ class XMultiServiceFactory;
+ }
+ namespace text {
+ class XMailMergeListener;
+ struct MailMergeEvent;
+ }
+ namespace beans{
+ struct PropertyValue;
+ }
+
+}
+
+typedef comphelper::OMultiTypeInterfaceContainerHelperVar3<css::beans::XPropertyChangeListener, sal_Int32>
+ OPropertyListenerContainerHelper;
+
+class SwDBManager;
+class MailMergeExecuteFinalizer;
+
+/**
+ * Gives UNO access to the global mail merge functionality, via the com.sun.star.text.MailMerge
+ * service.
+ */
+class SwXMailMerge final :
+ public cppu::WeakImplHelper
+ <
+ css::task::XJob,
+ css::util::XCancellable,
+ css::beans::XPropertySet,
+ css::text::XMailMergeBroadcaster,
+ css::lang::XComponent,
+ css::lang::XServiceInfo
+ >
+{
+ friend class MailMergeExecuteFinalizer;
+
+ comphelper::OInterfaceContainerHelper3<css::lang::XEventListener> m_aEvtListeners;
+ comphelper::OInterfaceContainerHelper2 m_aMergeListeners;
+ OPropertyListenerContainerHelper m_aPropListeners;
+
+ const SfxItemPropertySet* m_pPropSet;
+
+ SfxObjectShellRef m_xDocSh; // the document
+
+ OUString m_aTmpFileName;
+
+ // properties of mail merge service
+ css::uno::Sequence< css::uno::Any > m_aSelection;
+ css::uno::Reference< css::sdbc::XResultSet > m_xResultSet;
+ css::uno::Reference< css::sdbc::XConnection > m_xConnection;
+ css::uno::Reference< css::frame::XModel > m_xModel;
+ OUString m_aDataSourceName;
+ OUString m_aDataCommand;
+ OUString m_aFilter;
+ OUString m_aDocumentURL;
+ OUString m_aOutputURL;
+ OUString m_aFileNamePrefix;
+ sal_Int32 m_nDataCommandType;
+ sal_Int16 m_nOutputType;
+ bool m_bEscapeProcessing;
+ bool m_bSinglePrintJobs;
+ bool m_bFileNameFromColumn;
+
+ OUString m_sInServerPassword;
+ OUString m_sOutServerPassword;
+ OUString m_sSubject;
+ OUString m_sAddressFromColumn;
+ OUString m_sMailBody;
+ OUString m_sAttachmentName;
+ OUString m_sAttachmentFilter;
+ css::uno::Sequence< OUString > m_aCopiesTo;
+ css::uno::Sequence< OUString > m_aBlindCopiesTo;
+ bool m_bSendAsHTML;
+ bool m_bSendAsAttachment;
+
+ css::uno::Sequence< css::beans::PropertyValue > m_aPrintSettings;
+
+ bool m_bSaveAsSingleFile;
+ OUString m_sSaveFilter;
+ OUString m_sSaveFilterOptions;
+ css::uno::Sequence< css::beans::PropertyValue > m_aSaveFilterData;
+
+ bool m_bDisposing;
+ SwDBManager *m_pMgr;
+
+ void launchEvent( const css::beans::PropertyChangeEvent &rEvt ) const;
+
+ SwXMailMerge( const SwXMailMerge & ) = delete;
+ SwXMailMerge & operator = ( const SwXMailMerge & ) = delete;
+
+ virtual ~SwXMailMerge() override;
+public:
+ SwXMailMerge();
+
+ void LaunchMailMergeEvent( const css::text::MailMergeEvent &rData ) const;
+
+ // XJob
+ virtual css::uno::Any SAL_CALL execute( const css::uno::Sequence< css::beans::NamedValue >& Arguments ) override;
+
+ // XCancellable
+ virtual void SAL_CALL cancel() override;
+
+ // XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+ virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override;
+ virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override;
+ virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ) override;
+ virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener ) override;
+ virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+ virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+
+ // XMailMergeBroadcaster
+ virtual void SAL_CALL addMailMergeEventListener( const css::uno::Reference< css::text::XMailMergeListener >& xListener ) override;
+ virtual void SAL_CALL removeMailMergeEventListener( const css::uno::Reference< css::text::XMailMergeListener >& xListener ) override;
+
+ // XComponent
+ virtual void SAL_CALL dispose( ) override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/unomod.hxx b/sw/source/uibase/inc/unomod.hxx
new file mode 100644
index 0000000000..758677f10b
--- /dev/null
+++ b/sw/source/uibase/inc/unomod.hxx
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/view/XPrintSettingsSupplier.hpp>
+#include <com/sun/star/view/XViewSettingsSupplier.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/ChainablePropertySet.hxx>
+#include <tools/fldunit.hxx>
+
+class SwView;
+class SwViewOption;
+class SwPrintData;
+class SwDoc;
+
+css::uno::Reference< css::uno::XInterface > SAL_CALL SwXModule_CreateInstance(const css::uno::Reference< css::lang::XMultiServiceFactory > & );
+
+class SwXModule final : public cppu::WeakImplHelper
+<
+ css::view::XViewSettingsSupplier,
+ css::view::XPrintSettingsSupplier,
+ css::lang::XServiceInfo
+>
+{
+
+ css::uno::Reference< css::beans::XPropertySet > mxViewSettings;
+ css::uno::Reference< css::beans::XPropertySet > mxPrintSettings;
+
+ virtual ~SwXModule() override;
+public:
+ SwXModule();
+
+ //XViewSettings
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getViewSettings() override;
+
+ //XPrintSettings
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getPrintSettings() override;
+
+ //XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+enum class SwXPrintSettingsType
+{
+ Module,
+ Document
+};
+
+class SwXPrintSettings final : public comphelper::ChainablePropertySet
+{
+ friend class SwXDocumentSettings;
+
+ SwXPrintSettingsType meType;
+ SwPrintData * mpPrtOpt;
+ SwDoc *mpDoc;
+
+ virtual void _preSetValues () override;
+ virtual void _setSingleValue( const comphelper::PropertyInfo & rInfo, const css::uno::Any &rValue ) override;
+ virtual void _postSetValues () override;
+
+ virtual void _preGetValues () override;
+
+ virtual void _getSingleValue( const comphelper::PropertyInfo & rInfo, css::uno::Any & rValue ) override;
+ virtual void _postGetValues () override;
+
+ virtual ~SwXPrintSettings()
+ noexcept override;
+public:
+ SwXPrintSettings( SwXPrintSettingsType eType, SwDoc * pDoc = nullptr );
+
+ //XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+/**
+ * Implements com.sun.star.text.ViewSettings: UNO access to per-view settings (e.g. if formatting
+ * marks are visible or not.)
+ */
+class SwXViewSettings final : public comphelper::ChainablePropertySet
+{
+ friend class SwXDocumentSettings;
+
+ SwView* m_pView;
+ std::unique_ptr<SwViewOption> mpViewOption;
+ const SwViewOption* mpConstViewOption;
+ bool m_bObjectValid:1, mbApplyZoom;
+
+ FieldUnit m_eHRulerUnit;
+ bool mbApplyHRulerMetric;
+ FieldUnit m_eVRulerUnit;
+ bool mbApplyVRulerMetric;
+
+ virtual void _preSetValues () override;
+ virtual void _setSingleValue( const comphelper::PropertyInfo & rInfo, const css::uno::Any &rValue ) override;
+ virtual void _postSetValues() override;
+
+ virtual void _preGetValues () override;
+ virtual void _getSingleValue( const comphelper::PropertyInfo & rInfo, css::uno::Any & rValue ) override;
+ virtual void _postGetValues () override;
+
+ virtual ~SwXViewSettings()
+ noexcept override;
+public:
+ SwXViewSettings(SwView* pView);
+
+ //XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ bool IsValid() const {return m_bObjectValid;}
+ void Invalidate() {m_bObjectValid = false;}
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/unotools.hxx b/sw/source/uibase/inc/unotools.hxx
new file mode 100644
index 0000000000..e472a2f927
--- /dev/null
+++ b/sw/source/uibase/inc/unotools.hxx
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_UNOTOOLS_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_UNOTOOLS_HXX
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <vcl/idle.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/customweld.hxx>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/text/XTextCursor.hpp>
+#include <swdllapi.h>
+#include <rtl/ref.hxx>
+
+#define EX_SHOW_ONLINE_LAYOUT 0x01
+// hard zoom value
+#define EX_SHOW_BUSINESS_CARDS 0x02
+//don't modify page size
+#define EX_SHOW_DEFAULT_PAGE 0x04
+//replace sample toc strings in the template to localized versions
+#define EX_LOCALIZE_TOC_STRINGS 0x08
+
+class SwView;
+class SwXTextCursor;
+
+class SW_DLLPUBLIC SwOneExampleFrame final : public weld::CustomWidgetController
+{
+ ScopedVclPtr<VirtualDevice> m_xVirDev;
+ css::uno::Reference< css::frame::XModel > m_xModel;
+ css::uno::Reference< css::frame::XController > m_xController;
+ rtl::Reference< SwXTextCursor > m_xCursor;
+
+ Idle m_aLoadedIdle;
+ Link<SwOneExampleFrame&,void> m_aInitializedLink;
+
+ OUString m_sArgumentURL;
+
+ SwView* m_pModuleView;
+
+ sal_uInt32 m_nStyleFlags;
+
+ bool m_bIsInitialized;
+
+ DECL_DLLPRIVATE_LINK( TimeoutHdl, Timer*, void );
+ void PopupHdl(std::u16string_view rId);
+
+ SAL_DLLPRIVATE void CreateControl();
+ SAL_DLLPRIVATE void DisposeControl();
+
+public:
+ SwOneExampleFrame(sal_uInt32 nStyleFlags,
+ const Link<SwOneExampleFrame&,void>* pInitializedLink,
+ const OUString* pURL = nullptr);
+ virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override;
+ virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
+ virtual bool Command(const CommandEvent& rCEvt) override;
+ virtual ~SwOneExampleFrame() override;
+
+ css::uno::Reference< css::frame::XModel > & GetModel() {return m_xModel;}
+ rtl::Reference< SwXTextCursor > & GetTextCursor() {return m_xCursor;}
+
+ void ClearDocument();
+
+ bool IsInitialized() const {return m_bIsInitialized;}
+
+ bool CreatePopup(const Point& rPt);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/unotxvw.hxx b/sw/source/uibase/inc/unotxvw.hxx
new file mode 100644
index 0000000000..e4f8b1a148
--- /dev/null
+++ b/sw/source/uibase/inc/unotxvw.hxx
@@ -0,0 +1,250 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_UNOTXVW_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_UNOTXVW_HXX
+
+#include <sfx2/sfxbasecontroller.hxx>
+#include <comphelper/interfacecontainer3.hxx>
+#include <com/sun/star/text/XTextViewCursor.hpp>
+#include <com/sun/star/text/XTextViewCursorSupplier.hpp>
+#include <com/sun/star/text/XTextViewTextRangeSupplier.hpp>
+#include <com/sun/star/text/XRubySelection.hpp>
+#include <com/sun/star/view/XFormLayerAccess.hpp>
+#include <com/sun/star/view/XScreenCursor.hpp>
+#include <com/sun/star/view/XViewSettingsSupplier.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/view/XLineCursor.hpp>
+#include <com/sun/star/view/XViewCursor.hpp>
+#include <com/sun/star/text/XPageCursor.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/datatransfer/XTransferableSupplier.hpp>
+#include <com/sun/star/datatransfer/XTransferableTextSupplier.hpp>
+#include <com/sun/star/qa/XDumper.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <svl/itemprop.hxx>
+#include <TextCursorHelper.hxx>
+#include <comphelper/uno3.hxx>
+
+#include <sfx2/objsh.hxx>
+
+class SdrObject;
+class SwView;
+class SwXViewSettings;
+class SwXTextViewCursor;
+
+typedef cppu::ImplInheritanceHelper<
+ SfxBaseController,
+ css::view::XSelectionSupplier,
+ css::lang::XServiceInfo,
+ css::view::XFormLayerAccess,
+ css::text::XTextViewCursorSupplier,
+ css::text::XTextViewTextRangeSupplier,
+ css::text::XRubySelection,
+ css::view::XViewSettingsSupplier,
+ css::beans::XPropertySet,
+ css::datatransfer::XTransferableSupplier,
+ css::datatransfer::XTransferableTextSupplier,
+ css::qa::XDumper> SwXTextView_Base;
+class SwXTextView final : public SwXTextView_Base
+{
+ ::comphelper::OInterfaceContainerHelper3<css::view::XSelectionChangeListener> m_SelChangedListeners;
+
+ SwView* m_pView;
+ const SfxItemPropertySet* m_pPropSet; // property map for SwXTextView properties
+ // (not related to mxViewSettings!)
+
+ rtl::Reference< SwXViewSettings > mxViewSettings;
+ rtl::Reference< SwXTextViewCursor > mxTextViewCursor;
+
+ SdrObject* GetControl(
+ const css::uno::Reference< css::awt::XControlModel > & Model,
+ css::uno::Reference< css::awt::XControl >& xToFill );
+
+ virtual ~SwXTextView() override;
+public:
+ SwXTextView(SwView* pSwView);
+
+ //XSelectionSupplier
+ virtual css::uno::Any SAL_CALL getSelection() override;
+ virtual sal_Bool SAL_CALL select(const css::uno::Any& rInterface) override;
+ virtual void SAL_CALL addSelectionChangeListener(const css::uno::Reference< css::view::XSelectionChangeListener > & xListener) override;
+ virtual void SAL_CALL removeSelectionChangeListener(const css::uno::Reference< css::view::XSelectionChangeListener > & xListener) override;
+
+ // XFormLayerAccess
+ virtual css::uno::Reference< css::form::runtime::XFormController > SAL_CALL getFormController( const css::uno::Reference< css::form::XForm >& Form ) override;
+ virtual sal_Bool SAL_CALL isFormDesignMode( ) override;
+ virtual void SAL_CALL setFormDesignMode( sal_Bool DesignMode ) override;
+
+ // XControlAccess
+ virtual css::uno::Reference< css::awt::XControl > SAL_CALL getControl(const css::uno::Reference< css::awt::XControlModel > & Model) override;
+
+ //XTextViewCursorSupplier
+ virtual css::uno::Reference< css::text::XTextViewCursor > SAL_CALL getViewCursor() override;
+
+ // XTextViewTextRangeSupplier
+ virtual css::uno::Reference<css::text::XTextRange>
+ SAL_CALL createTextRangeByPixelPosition(const css::awt::Point& rPixelPosition) override;
+
+ //XViewSettings
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getViewSettings() override;
+
+ //XRubySelection
+ virtual css::uno::Sequence<
+ css::uno::Sequence< css::beans::PropertyValue > > SAL_CALL getRubyList( sal_Bool bAutomatic ) override;
+
+ virtual void SAL_CALL setRubyList(
+ const css::uno::Sequence<
+ css::uno::Sequence< css::beans::PropertyValue > >& RubyList, sal_Bool bAutomatic ) override;
+
+ //XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+ virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override;
+ virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override;
+ virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ) override;
+ virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener ) override;
+ virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+ virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+
+ //XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ //XTransferableSupplier
+ virtual css::uno::Reference< css::datatransfer::XTransferable > SAL_CALL getTransferable( ) override;
+ virtual void SAL_CALL insertTransferable( const css::uno::Reference< css::datatransfer::XTransferable >& xTrans ) override;
+
+ // XTransferableTextSupplier
+ virtual css::uno::Reference<css::datatransfer::XTransferable> SAL_CALL getTransferableForTextRange(css::uno::Reference<css::text::XTextRange> const& xTextRange) override;
+
+ // XDumper
+ OUString SAL_CALL dump(const OUString& rKind) override;
+
+ void NotifySelChanged();
+ void NotifyDBChanged();
+
+ SwView* GetView() {return m_pView;}
+ void Invalidate();
+
+ // temporary document used for PDF export of selections/multi-selections
+ SfxObjectShellLock BuildTmpSelectionDoc();
+};
+
+typedef cppu::WeakImplHelper<
+ css::text::XTextViewCursor,
+ css::lang::XServiceInfo,
+ css::text::XPageCursor,
+ css::view::XScreenCursor,
+ css::view::XViewCursor,
+ css::view::XLineCursor,
+ css::beans::XPropertySet,
+ css::beans::XPropertyState
+ > SwXTextViewCursor_Base;
+
+class SwXTextViewCursor final: public SwXTextViewCursor_Base, public OTextCursorHelper
+{
+ SwView* m_pView;
+ const SfxItemPropertySet* m_pPropSet;
+ bool IsTextSelection( bool bAllowTables = true ) const;
+ virtual ~SwXTextViewCursor() override;
+
+public:
+ SwXTextViewCursor(SwView* pVw);
+
+ //XTextViewCursor
+ virtual sal_Bool SAL_CALL isVisible() override;
+ virtual void SAL_CALL setVisible(sal_Bool bVisible) override;
+ virtual css::awt::Point SAL_CALL getPosition() override;
+
+ //XTextCursor - new
+ virtual void SAL_CALL collapseToStart() override;
+ virtual void SAL_CALL collapseToEnd() override;
+ virtual sal_Bool SAL_CALL isCollapsed() override;
+ virtual sal_Bool SAL_CALL goLeft( sal_Int16 nCount, sal_Bool bExpand ) override;
+ virtual sal_Bool SAL_CALL goRight( sal_Int16 nCount, sal_Bool bExpand ) override;
+ virtual void SAL_CALL gotoStart( sal_Bool bExpand ) override;
+ virtual void SAL_CALL gotoEnd( sal_Bool bExpand ) override;
+ virtual void SAL_CALL gotoRange( const css::uno::Reference< css::text::XTextRange >& xRange, sal_Bool bExpand ) override;
+
+ //XPageCursor
+ virtual sal_Bool SAL_CALL jumpToFirstPage() override;
+ virtual sal_Bool SAL_CALL jumpToLastPage() override;
+ virtual sal_Bool SAL_CALL jumpToPage(sal_Int16 nPage) override;
+ virtual sal_Bool SAL_CALL jumpToNextPage() override;
+ virtual sal_Bool SAL_CALL jumpToPreviousPage() override;
+ virtual sal_Bool SAL_CALL jumpToEndOfPage() override;
+ virtual sal_Bool SAL_CALL jumpToStartOfPage() override;
+ virtual sal_Int16 SAL_CALL getPage() override;
+
+ //XTextRange
+ virtual css::uno::Reference< css::text::XText > SAL_CALL getText() override;
+ virtual css::uno::Reference< css::text::XTextRange > SAL_CALL getStart() override;
+ virtual css::uno::Reference< css::text::XTextRange > SAL_CALL getEnd() override;
+ virtual OUString SAL_CALL getString() override;
+ virtual void SAL_CALL setString(const OUString& aString) override;
+
+ //XScreenCursor
+ virtual sal_Bool SAL_CALL screenDown() override;
+ virtual sal_Bool SAL_CALL screenUp() override;
+
+ //XViewCursor
+ virtual sal_Bool SAL_CALL goDown(sal_Int16 nCount, sal_Bool bExpand) override;
+ virtual sal_Bool SAL_CALL goUp(sal_Int16 nCount, sal_Bool bExpand) override;
+
+ //XLineCursor
+ virtual sal_Bool SAL_CALL isAtStartOfLine() override;
+ virtual sal_Bool SAL_CALL isAtEndOfLine() override;
+ virtual void SAL_CALL gotoEndOfLine(sal_Bool bExpand) override;
+ virtual void SAL_CALL gotoStartOfLine(sal_Bool bExpand) override;
+
+ //XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+ virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override;
+ virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override;
+ virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ) override;
+ virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener ) override;
+ virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+ virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+
+ //XPropertyState
+ virtual css::beans::PropertyState SAL_CALL getPropertyState( const OUString& PropertyName ) override;
+ virtual css::uno::Sequence< css::beans::PropertyState > SAL_CALL getPropertyStates( const css::uno::Sequence< OUString >& aPropertyName ) override;
+ virtual void SAL_CALL setPropertyToDefault( const OUString& PropertyName ) override;
+ virtual css::uno::Any SAL_CALL getPropertyDefault( const OUString& aPropertyName ) override;
+
+ //XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ void Invalidate(){m_pView = nullptr;}
+
+ // ITextCursorHelper
+ virtual const SwPaM* GetPaM() const override;
+ virtual SwPaM* GetPaM() override;
+ virtual const SwDoc* GetDoc() const override;
+ virtual SwDoc* GetDoc() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/usrpref.hxx b/sw/source/uibase/inc/usrpref.hxx
new file mode 100644
index 0000000000..1464c90bce
--- /dev/null
+++ b/sw/source/uibase/inc/usrpref.hxx
@@ -0,0 +1,273 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_USRPREF_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_USRPREF_HXX
+
+#include <memory>
+#include <unotools/configitem.hxx>
+#include <fldupde.hxx>
+#include <viewopt.hxx>
+#include <tools/fldunit.hxx>
+
+class SwMasterUsrPref;
+
+class SwContentViewConfig final : public utl::ConfigItem
+{
+private:
+ SwMasterUsrPref& m_rParent;
+ bool m_bWeb;
+
+ css::uno::Sequence<OUString> GetPropertyNames() const;
+
+ virtual void ImplCommit() override;
+
+public:
+ SwContentViewConfig(bool bWeb, SwMasterUsrPref& rParent);
+ virtual ~SwContentViewConfig() override;
+
+ // utl::ConfigItem
+ virtual void Notify( const css::uno::Sequence< OUString > &rPropertyNames ) override;
+
+ void Load();
+ using ConfigItem::SetModified;
+};
+
+class SwLayoutViewConfig final : public utl::ConfigItem
+{
+private:
+ SwMasterUsrPref& m_rParent;
+ bool m_bWeb;
+
+ css::uno::Sequence<OUString> GetPropertyNames() const;
+
+ virtual void ImplCommit() override;
+
+public:
+ SwLayoutViewConfig(bool bWeb, SwMasterUsrPref& rParent);
+ virtual ~SwLayoutViewConfig() override;
+
+ virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+ void Load();
+ using ConfigItem::SetModified;
+};
+
+class SwGridConfig final : public utl::ConfigItem
+{
+private:
+ SwMasterUsrPref& m_rParent;
+
+ static css::uno::Sequence<OUString> GetPropertyNames();
+
+ virtual void ImplCommit() override;
+
+public:
+ SwGridConfig(bool bWeb, SwMasterUsrPref& rParent);
+ virtual ~SwGridConfig() override;
+
+ virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+ void Load();
+ using ConfigItem::SetModified;
+};
+
+class SwCursorConfig final : public utl::ConfigItem
+{
+private:
+ SwMasterUsrPref& m_rParent;
+
+ static css::uno::Sequence<OUString> GetPropertyNames();
+
+ virtual void ImplCommit() override;
+
+public:
+ SwCursorConfig(SwMasterUsrPref& rParent);
+ virtual ~SwCursorConfig() override;
+
+ virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+ void Load();
+ using ConfigItem::SetModified;
+};
+
+class SwWebColorConfig final : public utl::ConfigItem
+{
+private:
+ SwMasterUsrPref& m_rParent;
+ css::uno::Sequence<OUString> m_aPropNames;
+
+ virtual void ImplCommit() override;
+
+public:
+ SwWebColorConfig(SwMasterUsrPref& rParent);
+ virtual ~SwWebColorConfig() override;
+
+ virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+ void Load();
+ using ConfigItem::SetModified;
+};
+
+class SwMasterUsrPref : public SwViewOption
+{
+ friend class SwContentViewConfig;
+ friend class SwLayoutViewConfig;
+ friend class SwGridConfig;
+ friend class SwCursorConfig;
+ friend class SwWebColorConfig;
+
+ SwFieldUpdateFlags m_eFieldUpdateFlags; //update of fields and charts
+ sal_Int32 m_nLinkUpdateMode;
+ FieldUnit m_eUserMetric;
+ FieldUnit m_eHScrollMetric;
+ bool m_bIsHScrollMetricSet;
+ FieldUnit m_eVScrollMetric;
+ bool m_bIsVScrollMetricSet;
+
+ sal_Int32 m_nDefTabInMm100; //default tab stop distance, in 1/100 mm
+
+ bool m_bIsSquaredPageMode; //default page mode for text grid
+ bool m_bIsAlignMathObjectsToBaseline;
+
+ SwContentViewConfig m_aContentConfig;
+ SwLayoutViewConfig m_aLayoutConfig;
+ SwGridConfig m_aGridConfig;
+ SwCursorConfig m_aCursorConfig;
+ std::unique_ptr<SwWebColorConfig> m_pWebColorConfig;
+
+ bool m_bApplyCharUnit; // apply_char_unit
+public:
+ SwMasterUsrPref(bool bWeb);
+ ~SwMasterUsrPref();
+
+ void SetUsrPref(const SwViewOption &rCopy);
+
+ void SetModified()
+ {
+ m_aContentConfig.SetModified();
+ m_aLayoutConfig.SetModified();
+ m_aGridConfig.SetModified();
+ m_aCursorConfig.SetModified();
+ if(m_pWebColorConfig)
+ m_pWebColorConfig->SetModified();
+ }
+
+ void SetUpdateLinkMode(sal_Int32 nSet, bool bNoModify = false)
+ {
+ m_nLinkUpdateMode = nSet;
+ if(!bNoModify)
+ m_aContentConfig.SetModified();
+ }
+ sal_Int32 GetUpdateLinkMode() const {return m_nLinkUpdateMode; }
+
+ void SetUpdateFields(bool bSet)
+ {
+ if(bSet && m_eFieldUpdateFlags == AUTOUPD_OFF)
+ {
+ m_eFieldUpdateFlags = AUTOUPD_FIELD_ONLY;
+ }
+ else if(!bSet)
+ {
+ m_eFieldUpdateFlags = AUTOUPD_OFF;
+ }
+ };
+ bool IsUpdateFields()const {return m_eFieldUpdateFlags != AUTOUPD_OFF; }
+
+ SwFieldUpdateFlags GetFieldUpdateFlags()const {return m_eFieldUpdateFlags;}
+ void SetFieldUpdateFlags(SwFieldUpdateFlags eSet)
+ {
+ m_eFieldUpdateFlags = eSet;
+ m_aContentConfig.SetModified();
+ }
+
+ void SetUpdateCharts(bool bSet)
+ {
+ if(bSet)
+ {
+ m_eFieldUpdateFlags = AUTOUPD_FIELD_AND_CHARTS;
+ }
+ else if(m_eFieldUpdateFlags == AUTOUPD_FIELD_AND_CHARTS)
+ {
+ m_eFieldUpdateFlags = AUTOUPD_FIELD_ONLY;
+ }
+ };
+ bool IsUpdateCharts()const {return m_eFieldUpdateFlags == AUTOUPD_FIELD_AND_CHARTS; }
+
+ FieldUnit GetMetric() const { return m_eUserMetric;}
+ void SetMetric(FieldUnit eSet, bool bNoModify = false)
+ {
+ m_eUserMetric = eSet;
+ if(!bNoModify)
+ m_aLayoutConfig.SetModified();
+ }
+
+ bool IsHScrollMetric()const {return m_bIsHScrollMetricSet;}
+ FieldUnit GetHScrollMetric() const { return m_bIsHScrollMetricSet ? m_eHScrollMetric : m_eUserMetric;}
+ void SetHScrollMetric(FieldUnit eSet)
+ {
+ m_eHScrollMetric = eSet; m_bIsHScrollMetricSet = true;
+ m_aLayoutConfig.SetModified();
+ }
+
+ bool IsVScrollMetric()const {return m_bIsVScrollMetricSet;}
+ FieldUnit GetVScrollMetric() const { return m_bIsVScrollMetricSet ? m_eVScrollMetric : m_eUserMetric;}
+ void SetVScrollMetric(FieldUnit eSet)
+ {
+ m_eVScrollMetric = eSet; m_bIsVScrollMetricSet = true;
+ m_aLayoutConfig.SetModified();
+ }
+
+ bool IsApplyCharUnit() const
+ {
+ return m_bApplyCharUnit;
+ }
+ void SetApplyCharUnit(bool bSet, bool noModify = false)
+ {
+ m_bApplyCharUnit = bSet;
+ if (!noModify) {
+ m_aLayoutConfig.SetModified();
+ }
+ }
+
+ sal_Int32 GetDefTabInMm100() const { return m_nDefTabInMm100;}
+ void SetDefTabInMm100( sal_Int32 nSet, bool bNoModify = false )
+ {
+ m_nDefTabInMm100 = nSet;
+ if(!bNoModify)
+ m_aLayoutConfig.SetModified();
+ }
+
+ //default page mode for text grid
+ bool IsSquaredPageMode() const {return m_bIsSquaredPageMode;}
+ void SetDefaultPageMode( bool bVal, bool bNoModify = false )
+ {
+ m_bIsSquaredPageMode = bVal;
+ if(!bNoModify)
+ m_aLayoutConfig.SetModified();
+ }
+
+ bool IsAlignMathObjectsToBaseline() const { return m_bIsAlignMathObjectsToBaseline; }
+ void SetAlignMathObjectsToBaseline( bool bVal, bool noModify = false )
+ {
+ m_bIsAlignMathObjectsToBaseline = bVal;
+ if (!noModify) {
+ m_aLayoutConfig.SetModified();
+ }
+ }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/viewlayoutctrl.hxx b/sw/source/uibase/inc/viewlayoutctrl.hxx
new file mode 100644
index 0000000000..a13f9ff52b
--- /dev/null
+++ b/sw/source/uibase/inc/viewlayoutctrl.hxx
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_VIEWLAYOUTCTRL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_VIEWLAYOUTCTRL_HXX
+
+#include <sfx2/stbitem.hxx>
+#include <memory>
+
+class SwViewLayoutControl final : public SfxStatusBarControl
+{
+private:
+
+ struct SwViewLayoutControl_Impl;
+ std::unique_ptr<SwViewLayoutControl_Impl> mpImpl;
+
+public:
+
+ SFX_DECL_STATUSBAR_CONTROL();
+
+ SwViewLayoutControl( sal_uInt16 nSlotId, sal_uInt16 nId, StatusBar& rStb );
+ virtual ~SwViewLayoutControl() override;
+
+ virtual void StateChangedAtStatusBarControl( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState ) override;
+ virtual void Paint( const UserDrawEvent& rEvt ) override;
+ virtual bool MouseButtonDown( const MouseEvent & ) override;
+ virtual bool MouseMove( const MouseEvent & ) override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/watermarkdialog.hxx b/sw/source/uibase/inc/watermarkdialog.hxx
new file mode 100644
index 0000000000..57281a4d3f
--- /dev/null
+++ b/sw/source/uibase/inc/watermarkdialog.hxx
@@ -0,0 +1,40 @@
+/* -*- 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/.
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_WATERMARKDIALOG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_WATERMARKDIALOG_HXX
+
+#include <sfx2/bindings.hxx>
+#include <vcl/weld.hxx>
+#include <svx/colorbox.hxx>
+#include <sfx2/basedlgs.hxx>
+
+class SwWatermarkDialog final : public SfxDialogController
+{
+public:
+ SwWatermarkDialog(weld::Window* pParent, SfxBindings& rBindings);
+ virtual ~SwWatermarkDialog() override;
+
+ void InitFields();
+
+private:
+ DECL_LINK(OKButtonHdl, weld::Button&, void);
+
+ SfxBindings& m_rBindings;
+
+ std::unique_ptr<weld::Entry> m_xTextInput;
+ std::unique_ptr<weld::Button> m_xOKButton;
+ std::unique_ptr<weld::ComboBox> m_xFont;
+ std::unique_ptr<weld::MetricSpinButton> m_xAngle;
+ std::unique_ptr<weld::MetricSpinButton> m_xTransparency;
+ std::unique_ptr<ColorListBox> m_xColor;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/source/uibase/inc/wformsh.hxx b/sw/source/uibase/inc/wformsh.hxx
new file mode 100644
index 0000000000..a29e0f9404
--- /dev/null
+++ b/sw/source/uibase/inc/wformsh.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "drformsh.hxx"
+
+class SwWebDrawFormShell final : public SwDrawFormShell
+{
+public:
+ SwWebDrawFormShell(SwView& rShell);
+ virtual ~SwWebDrawFormShell() override;
+
+ SFX_DECL_INTERFACE(SW_WEBDRAWFORMSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/wfrmsh.hxx b/sw/source/uibase/inc/wfrmsh.hxx
new file mode 100644
index 0000000000..de87c87436
--- /dev/null
+++ b/sw/source/uibase/inc/wfrmsh.hxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_WFRMSH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_WFRMSH_HXX
+
+#include "frmsh.hxx"
+
+class SwWebFrameShell final : public SwFrameShell
+{
+public:
+ SFX_DECL_INTERFACE(SW_WEBFRAMESHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwWebFrameShell(SwView& rView);
+ virtual ~SwWebFrameShell() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/wgrfsh.hxx b/sw/source/uibase/inc/wgrfsh.hxx
new file mode 100644
index 0000000000..937556a6b9
--- /dev/null
+++ b/sw/source/uibase/inc/wgrfsh.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_WGRFSH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_WGRFSH_HXX
+
+#include "grfsh.hxx"
+
+class SwWebGrfShell final : public SwGrfShell
+{
+public:
+ SwWebGrfShell(SwView& rShell);
+ virtual ~SwWebGrfShell() override;
+
+ SFX_DECL_INTERFACE(SW_WEBGRFSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/wlistsh.hxx b/sw/source/uibase/inc/wlistsh.hxx
new file mode 100644
index 0000000000..556ebb8fd7
--- /dev/null
+++ b/sw/source/uibase/inc/wlistsh.hxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "listsh.hxx"
+
+class SwWebListShell final : public SwListShell
+{
+public:
+ SFX_DECL_INTERFACE(SW_WEBLISTSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwWebListShell(SwView& rView);
+ virtual ~SwWebListShell() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/wolesh.hxx b/sw/source/uibase/inc/wolesh.hxx
new file mode 100644
index 0000000000..497c952c72
--- /dev/null
+++ b/sw/source/uibase/inc/wolesh.hxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_WOLESH_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_WOLESH_HXX
+
+#include "olesh.hxx"
+
+class SwWebOleShell final : public SwOleShell
+{
+public:
+ SFX_DECL_INTERFACE(SW_WEBOLESHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwWebOleShell(SwView& rView);
+ virtual ~SwWebOleShell() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/wordcountctrl.hxx b/sw/source/uibase/inc/wordcountctrl.hxx
new file mode 100644
index 0000000000..8074253b36
--- /dev/null
+++ b/sw/source/uibase/inc/wordcountctrl.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_WORDCOUNTCTRL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_WORDCOUNTCTRL_HXX
+
+#include <sfx2/stbitem.hxx>
+
+/**
+Word count status bar control for Writer.
+
+@remarks This is a simple status bar control of type SfxStringItem, and it has no custom
+logic whatsoever. The actual updating of the word count string happens in
+SwView::StateStatusLine (see sw/source/ui/uiview/view2.cxx).
+*/
+class SwWordCountStatusBarControl final : public SfxStatusBarControl
+{
+public:
+ SFX_DECL_STATUSBAR_CONTROL();
+
+ SwWordCountStatusBarControl(sal_uInt16 nSlotId, sal_uInt16 nId, StatusBar& rStb);
+ virtual ~SwWordCountStatusBarControl() override;
+
+ virtual void StateChangedAtStatusBarControl(sal_uInt16 nSID, SfxItemState eState,
+ const SfxPoolItem* pState) override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/wordcountdialog.hxx b/sw/source/uibase/inc/wordcountdialog.hxx
new file mode 100644
index 0000000000..ffa0b6478d
--- /dev/null
+++ b/sw/source/uibase/inc/wordcountdialog.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_WORDCOUNTDIALOG_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_WORDCOUNTDIALOG_HXX
+#include <sfx2/basedlgs.hxx>
+struct SwDocStat;
+#include <sfx2/childwin.hxx>
+#include <swabstdlg.hxx>
+
+class SwWordCountFloatDlg final : public SfxModelessDialogController
+{
+ void SetValues(const SwDocStat& rCurrent, const SwDocStat& rDoc);
+ void showCJK(bool bShowCJK);
+ void showStandardizedPages(bool bShowStandardizedPages);
+
+ std::unique_ptr<weld::Label> m_xCurrentWordFT;
+ std::unique_ptr<weld::Label> m_xCurrentCharacterFT;
+ std::unique_ptr<weld::Label> m_xCurrentCharacterExcludingSpacesFT;
+ std::unique_ptr<weld::Label> m_xCurrentCjkcharsFT;
+ std::unique_ptr<weld::Label> m_xCurrentStandardizedPagesFT;
+ std::unique_ptr<weld::Label> m_xDocWordFT;
+ std::unique_ptr<weld::Label> m_xDocCharacterFT;
+ std::unique_ptr<weld::Label> m_xDocCharacterExcludingSpacesFT;
+ std::unique_ptr<weld::Label> m_xDocCjkcharsFT;
+ std::unique_ptr<weld::Label> m_xDocStandardizedPagesFT;
+ std::unique_ptr<weld::Label> m_xCjkcharsLabelFT;
+ std::unique_ptr<weld::Label> m_xCjkcharsLabelFT2;
+ std::unique_ptr<weld::Label> m_xStandardizedPagesLabelFT;
+ std::unique_ptr<weld::Label> m_xStandardizedPagesLabelFT2;
+ std::unique_ptr<weld::Label> m_xDocComments;
+
+public:
+ SwWordCountFloatDlg(SfxBindings* pBindings,
+ SfxChildWindow* pChild,
+ weld::Window *pParent,
+ SfxChildWinInfo const * pInfo);
+ virtual ~SwWordCountFloatDlg() override;
+ void UpdateCounts();
+
+ void SetCounts(const SwDocStat &rCurrCnt, const SwDocStat &rDocStat);
+};
+
+class SwWordCountWrapper final : public SfxChildWindow
+{
+ VclPtr<AbstractSwWordCountFloatDlg> m_xAbstDlg;
+
+public:
+ SwWordCountWrapper( vcl::Window *pParentWindow,
+ sal_uInt16 nId,
+ SfxBindings* pBindings,
+ SfxChildWinInfo* pInfo );
+ SFX_DECL_CHILDWINDOW_WITHID(SwWordCountWrapper);
+
+ virtual ~SwWordCountWrapper() override;
+ void UpdateCounts();
+ void SetCounts(const SwDocStat &rCurrCnt, const SwDocStat &rDocStat);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/workctrl.hxx b/sw/source/uibase/inc/workctrl.hxx
new file mode 100644
index 0000000000..9c6680d896
--- /dev/null
+++ b/sw/source/uibase/inc/workctrl.hxx
@@ -0,0 +1,190 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_WORKCTRL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_INC_WORKCTRL_HXX
+
+#include <sfx2/tbxctrl.hxx>
+#include <vcl/toolbox.hxx>
+#include <vcl/InterimItemWindow.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+class PopupMenu;
+class SwView;
+
+using namespace ::com::sun::star;
+
+// double entry! hrc and hxx
+// these Ids say what the buttons below the scrollbar are doing
+#define NID_START 20000
+#define NID_TBL 20000
+#define NID_FRM 20001
+#define NID_PGE 20002
+#define NID_DRW 20003
+#define NID_CTRL 20004
+#define NID_REG 20005
+#define NID_BKM 20006
+#define NID_GRF 20007
+#define NID_OLE 20008
+#define NID_OUTL 20009
+#define NID_SEL 20010
+#define NID_FTN 20011
+#define NID_MARK 20012
+#define NID_POSTIT 20013
+#define NID_SRCH_REP 20014
+#define NID_INDEX_ENTRY 20015
+#define NID_TABLE_FORMULA 20016
+#define NID_TABLE_FORMULA_ERROR 20017
+#define NID_RECENCY 20018
+#define NID_FIELD 20019
+#define NID_FIELD_BYTYPE 20020
+#define NID_COUNT 21
+
+class SwTbxAutoTextCtrl final : public SfxToolBoxControl
+{
+public:
+ SFX_DECL_TOOLBOX_CONTROL();
+
+ SwTbxAutoTextCtrl( sal_uInt16 nSlotId, ToolBoxItemId nId, ToolBox& rTbx );
+ virtual ~SwTbxAutoTextCtrl() override;
+
+ virtual void CreatePopupWindow() override;
+ virtual void StateChangedAtToolBoxControl( sal_uInt16 nSID,
+ SfxItemState eState,
+ const SfxPoolItem* pState ) override;
+
+ DECL_STATIC_LINK(SwTbxAutoTextCtrl, PopupHdl, Menu*, bool);
+};
+
+class SwPreviewZoomControl final : public SfxToolBoxControl
+{
+public:
+ SFX_DECL_TOOLBOX_CONTROL();
+
+ SwPreviewZoomControl( sal_uInt16 nSlotId, ToolBoxItemId nId, ToolBox& rTbx );
+ virtual ~SwPreviewZoomControl() override;
+
+ virtual void StateChangedAtToolBoxControl( sal_uInt16 nSID,
+ SfxItemState eState,
+ const SfxPoolItem* pState ) override;
+
+ virtual VclPtr<InterimItemWindow> CreateItemWindow( vcl::Window *pParent ) override;
+};
+
+class SwJumpToSpecificPageControl final : public SfxToolBoxControl
+{
+public:
+ SFX_DECL_TOOLBOX_CONTROL();
+
+ SwJumpToSpecificPageControl( sal_uInt16 nSlotId, ToolBoxItemId nId, ToolBox& rTbx );
+ virtual ~SwJumpToSpecificPageControl() override;
+
+ virtual VclPtr<InterimItemWindow> CreateItemWindow( vcl::Window *pParent ) override;
+};
+
+class NavElementToolBoxControl;
+
+class NavElementBox_Base
+{
+public:
+ NavElementBox_Base(std::unique_ptr<weld::ComboBox> xComboBox,
+ uno::Reference<frame::XFrame> xFrame);
+
+ virtual ~NavElementBox_Base() {}
+
+ void set_sensitive(bool bSensitive) {m_xComboBox->set_sensitive(bSensitive);}
+
+ weld::ComboBox* GetComboBox() {return m_xComboBox.get();}
+
+ void UpdateBox();
+
+
+protected:
+ std::unique_ptr<weld::ComboBox> m_xComboBox;
+ uno::Reference< frame::XFrame > m_xFrame;
+
+ virtual bool DoKeyInput(const KeyEvent& /*rKEvt*/);
+
+ DECL_STATIC_LINK(NavElementBox_Base, SelectHdl, weld::ComboBox&, void);
+ DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
+
+ void ReleaseFocus_Impl();
+};
+
+class NavElementBox_Impl final : public InterimItemWindow, public NavElementBox_Base
+{
+public:
+ NavElementBox_Impl(vcl::Window* pParent,
+ const uno::Reference<frame::XFrame>& xFrame);
+
+ virtual void dispose() override
+ {
+ m_xComboBox.reset();
+ InterimItemWindow::dispose();
+ }
+
+ virtual void GetFocus() override
+ {
+ if (m_xComboBox)
+ m_xComboBox->grab_focus();
+ InterimItemWindow::GetFocus();
+ }
+
+ virtual bool DoKeyInput(const KeyEvent& rKEvt) override;
+
+ virtual ~NavElementBox_Impl() override
+ {
+ disposeOnce();
+ }
+};
+
+typedef cppu::ImplInheritanceHelper< ::svt::ToolboxController, lang::XServiceInfo> NavElementToolBoxControl_Base;
+class NavElementToolBoxControl final : public NavElementToolBoxControl_Base
+{
+public:
+ explicit NavElementToolBoxControl(
+ const css::uno::Reference< css::uno::XComponentContext >& rServiceManager );
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XComponent
+ virtual void SAL_CALL dispose() override;
+
+ // XStatusListener
+ virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& Event ) override;
+
+ // XToolbarController
+ virtual void SAL_CALL execute( sal_Int16 KeyModifier ) override;
+ virtual void SAL_CALL click() override;
+ virtual void SAL_CALL doubleClick() override;
+ virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createPopupWindow() override;
+ virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createItemWindow( const css::uno::Reference< css::awt::XWindow >& Parent ) override;
+
+ weld::ComboBox* GetComboBox() {return m_pBox->GetComboBox();}
+
+private:
+ VclPtr<NavElementBox_Impl> m_xVclBox;
+ std::unique_ptr<NavElementBox_Base> m_xWeldBox;
+ NavElementBox_Base* m_pBox;
+};
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/wrap.hxx b/sw/source/uibase/inc/wrap.hxx
new file mode 100644
index 0000000000..c249b0233c
--- /dev/null
+++ b/sw/source/uibase/inc/wrap.hxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+#include <sfx2/basedlgs.hxx>
+#include <svx/swframetypes.hxx>
+
+class SfxItemSet;
+class SwWrtShell;
+
+class SwWrapDlg final : public SfxSingleTabDialogController
+{
+public:
+ SwWrapDlg(weld::Window* pParent, const SfxItemSet& rSet, SwWrtShell* pSh, bool bDrawMode);
+};
+
+// circulation TabPage
+class SwWrapTabPage final : public SfxTabPage
+{
+ RndStdIds m_nAnchorId;
+ sal_uInt16 m_nHtmlMode;
+
+ SwWrtShell* m_pWrtSh;
+
+ bool m_bFormat;
+ bool m_bNew;
+ bool m_bHtmlMode;
+ bool m_bDrawMode;
+ bool m_bContourImage;
+
+ // WRAPPING
+ std::unique_ptr<weld::Image> m_xNoWrapImg;
+ std::unique_ptr<weld::RadioButton> m_xNoWrapRB;
+ std::unique_ptr<weld::Image> m_xWrapLeftImg;
+ std::unique_ptr<weld::RadioButton> m_xWrapLeftRB;
+ std::unique_ptr<weld::Image> m_xWrapRightImg;
+ std::unique_ptr<weld::RadioButton> m_xWrapRightRB;
+ std::unique_ptr<weld::Image> m_xWrapParallelImg;
+ std::unique_ptr<weld::RadioButton> m_xWrapParallelRB;
+ std::unique_ptr<weld::Image> m_xWrapThroughImg;
+ std::unique_ptr<weld::RadioButton> m_xWrapThroughRB;
+ std::unique_ptr<weld::Image> m_xIdealWrapImg;
+ std::unique_ptr<weld::RadioButton> m_xIdealWrapRB;
+
+ // MARGIN
+ std::unique_ptr<weld::MetricSpinButton> m_xLeftMarginED;
+ std::unique_ptr<weld::MetricSpinButton> m_xRightMarginED;
+ std::unique_ptr<weld::MetricSpinButton> m_xTopMarginED;
+ std::unique_ptr<weld::MetricSpinButton> m_xBottomMarginED;
+
+ // OPTIONS
+ std::unique_ptr<weld::CheckButton> m_xWrapAnchorOnlyCB;
+ std::unique_ptr<weld::CheckButton> m_xWrapTransparentCB;
+ std::unique_ptr<weld::CheckButton> m_xWrapOutlineCB;
+ std::unique_ptr<weld::CheckButton> m_xWrapOutsideCB;
+ std::unique_ptr<weld::CheckButton> m_xAllowOverlapCB;
+
+ void SetImages();
+ virtual void ActivatePage(const SfxItemSet& rSet) override;
+ virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override;
+
+ DECL_LINK(RangeModifyHdl, weld::MetricSpinButton&, void);
+ DECL_LINK(WrapTypeHdl, weld::Toggleable&, void);
+ DECL_LINK(ContourHdl, weld::Toggleable&, void);
+
+ static const WhichRangesContainer s_aWrapPageRg;
+
+public:
+ SwWrapTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet);
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet);
+ virtual ~SwWrapTabPage() override;
+
+ virtual bool FillItemSet(SfxItemSet *rSet) override;
+ virtual void Reset(const SfxItemSet *rSet) override;
+
+ static WhichRangesContainer GetRanges() { return s_aWrapPageRg; }
+ void SetNewFrame(bool bNewFrame) { m_bNew = bNewFrame; }
+ void SetFormatUsed(bool bFormat, bool bDrawMode) { m_bFormat = bFormat; m_bDrawMode = bDrawMode; }
+ void SetShell(SwWrtShell* pSh) { m_pWrtSh = pSh; }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/wrtsh.hxx b/sw/source/uibase/inc/wrtsh.hxx
new file mode 100644
index 0000000000..741c28c8a6
--- /dev/null
+++ b/sw/source/uibase/inc/wrtsh.hxx
@@ -0,0 +1,724 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <swdllapi.h>
+#include <fesh.hxx>
+#include <swurl.hxx>
+#include <IMark.hxx>
+#include "navmgr.hxx"
+#include <optional>
+#include <com/sun/star/embed/EmbedVerbs.hpp>
+#include <o3tl/typed_flags_set.hxx>
+#include <svx/swframetypes.hxx>
+#include <vcl/weld.hxx>
+
+#include <doc.hxx>
+#include <docsh.hxx>
+#include <viewopt.hxx>
+
+namespace vcl { class Window; }
+class SbxArray;
+class SwFlyFrameAttrMgr;
+class SwField;
+class SwTOXBase;
+class SwView;
+class SvGlobalName;
+class SwInputFieldList;
+class SwSectionData;
+class Timer;
+class SvxMacro;
+class SwFormatINetFormat;
+class SvxAutoCorrect;
+class NaviContentBookmark;
+struct SwCallMouseEvent;
+class SfxStringListItem;
+enum class SvMacroItemId : sal_uInt16;
+class SwFieldMgr;
+class SfxRequest;
+enum class SwLineBreakClear;
+class SwContentControl;
+enum class SwContentControlType;
+
+namespace i18nutil {
+ struct SearchOptions2;
+}
+
+enum class SelectionType : sal_Int32
+{
+ NONE = 0x000000,
+ Text = CNT_TXT, // text, never frames too 0x0001
+ Graphic = CNT_GRF, // graphic 0x0002
+ Ole = CNT_OLE, // OLE 0x0010
+ Frame = 0x000020, // frame, no content type
+ NumberList = 0x000040, // NumList
+ Table = 0x000080, // cursor is in table
+ TableCell = 0x000100, // table cells are selected
+ DrawObject = 0x000200, // drawing objects (rectangle, circle...)
+ DrawObjectEditMode = 0x000400, // draw-textobjects in edit mode
+ Ornament = 0x000800, // edit ornament objects
+ DbForm = 0x001000, // drawing objects: DB-Forms
+ FormControl = 0x002000, // a form control is focused. Neither set nor evaluated by the SwWrtShell itself, only by its clients.
+ Media = 0x004000, // Media object
+ ExtrudedCustomShape = 0x008000, // extruded custom shape
+ FontWork = 0x010000, // fontwork
+ PostIt = 0x020000, // annotation
+ TableRow = 0x040000, // table rows are selected
+ TableCol = 0x080000, // table columns are selected
+ All = 0x0ffff3,
+};
+namespace o3tl {
+ template<> struct typed_flags<SelectionType> : is_typed_flags<SelectionType, 0x0ffff3> {};
+}
+
+/** Used by the UI to modify the document model.
+
+Eg. the Insert() method will take the current cursor position, insert the
+string, and take care of undo etc.
+*/
+class SW_DLLPUBLIC SwWrtShell final : public SwFEShell
+{
+private:
+ using SwCursorShell::Left;
+ using SwCursorShell::Right;
+ using SwCursorShell::Up;
+ using SwCursorShell::Down;
+ using SwCursorShell::LeftMargin;
+ using SwCursorShell::RightMargin;
+ using SwCursorShell::SelectTextAttr;
+ using SwCursorShell::GotoPage;
+ using SwFEShell::InsertObject;
+ using SwEditShell::AutoCorrect;
+ using SwCursorShell::GotoMark;
+
+ typedef tools::Long (SwWrtShell::*SELECTFUNC)(const Point *, bool bProp );
+ typedef void (SwWrtShell::*SELECTFUNC2)(const Point *, bool bProp );
+
+ SELECTFUNC2 m_fnDrag = &SwWrtShell::BeginDrag;
+ SELECTFUNC m_fnSetCursor = &SwWrtShell::SetCursor;
+ SELECTFUNC2 m_fnEndDrag = &SwWrtShell::DefaultEndDrag;
+ SELECTFUNC m_fnKillSel = &SwWrtShell::Ignore;
+
+public:
+ using SwCursorShell::GotoFootnoteAnchor;
+ using SwEditShell::Insert;
+
+ tools::Long CallSetCursor(const Point* pPt, bool bProp) { return (this->*m_fnSetCursor)(pPt, bProp); }
+ void Drag (const Point* pPt, bool bProp) { (this->*m_fnDrag)(pPt, bProp); }
+ void EndDrag (const Point* pPt, bool bProp) { (this->*m_fnEndDrag)(pPt, bProp); }
+ tools::Long KillSelection(const Point* pPt, bool bProp) { return (this->*m_fnKillSel)(pPt, bProp); }
+
+ bool IsSplitVerticalByDefault() const;
+ void SetSplitVerticalByDefault(bool value);
+
+ // reset all selections
+ tools::Long ResetSelect( const Point *, bool );
+
+ // resets the cursorstack after movement with PageUp/-Down if a stack is built up
+ inline void ResetCursorStack();
+ SelectionType GetSelectionType() const;
+
+ bool IsModePushed() const { return nullptr != m_pModeStack; }
+ void PushMode();
+ void PopMode();
+
+ void SttSelect();
+ void EndSelect();
+ bool IsInSelect() const { return m_bInSelect; }
+ void SetInSelect() { m_bInSelect = true; }
+ // is there a text- or frameselection?
+ bool HasSelection() const { return SwCursorShell::HasSelection() ||
+ IsMultiSelection() || IsSelFrameMode() || IsObjSelected(); }
+ bool Pop(SwCursorShell::PopMode, ::std::optional<SwCallLink>& roLink);
+ bool Pop(SwCursorShell::PopMode = SwCursorShell::PopMode::DeleteStack);
+
+ void EnterStdMode();
+ bool IsStdMode() const { return !m_bExtMode && !m_bAddMode && !m_bBlockMode; }
+
+ void AssureStdMode();
+
+ void EnterExtMode();
+ void LeaveExtMode();
+ void ToggleExtMode();
+ bool IsExtMode() const { return m_bExtMode; }
+
+ void EnterAddMode();
+ void LeaveAddMode();
+ void ToggleAddMode();
+ bool IsAddMode() const { return m_bAddMode; }
+
+ void EnterBlockMode();
+ void LeaveBlockMode();
+ void ToggleBlockMode();
+ bool IsBlockMode() const { return m_bBlockMode; }
+
+ void SetInsMode( bool bOn = true );
+ void ToggleInsMode() { SetInsMode( !m_bIns ); }
+ bool IsInsMode() const { return m_bIns; }
+ void SetRedlineFlagsAndCheckInsMode( RedlineFlags eMode );
+
+ void EnterSelFrameMode(const Point *pStartDrag = nullptr);
+ void LeaveSelFrameMode();
+ bool IsSelFrameMode() const { return m_bLayoutMode; }
+ // reset selection of frames
+ void UnSelectFrame();
+
+ void Invalidate();
+
+ // select table cells for editing of formulas in the ribbonbar
+ inline void SelTableCells( const Link<SwWrtShell&,void> &rLink );
+ inline void EndSelTableCells();
+
+ // leave per word or per line selection mode. Is usually called in MB-Up.
+ bool IsExtSel() const { return m_bSelWrd || m_bSelLn; }
+
+ // query whether the active m_fnDrag pointer is set to BeginDrag
+ // is needed for MouseMove to work around bugs 55592/55931
+ inline bool Is_FnDragEQBeginDrag() const;
+
+ // base requests
+ bool IsEndWrd();
+ bool IsSttOfPara() const { return IsSttPara(); }
+ bool IsEndOfPara() const { return IsEndPara(); }
+
+ // select word / sentence
+ bool SelNearestWrd();
+ bool SelWrd (const Point * = nullptr );
+ // #i32329# Enhanced selection
+ void SelSentence (const Point *);
+ void SelPara (const Point *);
+ void SelAll();
+
+ // basecursortravelling
+typedef bool (SwWrtShell::*FNSimpleMove)();
+ bool SimpleMove( FNSimpleMove, bool bSelect );
+
+ bool Left ( SwCursorSkipMode nMode, bool bSelect,
+ sal_uInt16 nCount, bool bBasicCall, bool bVisual = false );
+ bool Right ( SwCursorSkipMode nMode, bool bSelect,
+ sal_uInt16 nCount, bool bBasicCall, bool bVisual = false );
+ bool Up ( bool bSelect, sal_uInt16 nCount = 1, bool bBasicCall = false );
+ bool Down ( bool bSelect, sal_uInt16 nCount = 1, bool bBasicCall = false );
+ void NxtWrd ( bool bSelect = false ) { SimpleMove( &SwWrtShell::NxtWrd_, bSelect ); }
+ bool PrvWrd ( bool bSelect = false ) { return SimpleMove( &SwWrtShell::PrvWrd_, bSelect ); }
+
+ bool LeftMargin ( bool bSelect, bool bBasicCall );
+ bool RightMargin( bool bSelect, bool bBasicCall );
+
+ bool StartOfSection( bool bSelect = false );
+ bool EndOfSection ( bool bSelect = false );
+
+ bool SttNxtPg ( bool bSelect = false );
+ void SttPrvPg ( bool bSelect = false );
+ void EndNxtPg ( bool bSelect = false );
+ bool EndPrvPg ( bool bSelect = false );
+ bool SttPg ( bool bSelect = false );
+ bool EndPg ( bool bSelect = false );
+ bool SttPara ( bool bSelect = false );
+ void EndPara ( bool bSelect = false );
+ bool FwdPara ()
+ { return SimpleMove( &SwWrtShell::FwdPara_, false/*bSelect*/ ); }
+ void BwdPara ()
+ { SimpleMove( &SwWrtShell::BwdPara_, false/*bSelect*/ ); }
+ void FwdSentence( bool bSelect = false )
+ { SimpleMove( &SwWrtShell::FwdSentence_, bSelect ); }
+ void BwdSentence( bool bSelect = false )
+ { SimpleMove( &SwWrtShell::BwdSentence_, bSelect ); }
+
+ // #i20126# Enhanced table selection
+ bool SelectTableRowCol( const Point& rPt, const Point* pEnd = nullptr, bool bRowDrag = false );
+ void SelectTableRow();
+ void SelectTableCol();
+ void SelectTableCell();
+
+ bool SelectTextAttr( sal_uInt16 nWhich, const SwTextAttr* pAttr = nullptr );
+
+ // per column jumps
+ void StartOfColumn ();
+ void EndOfColumn ();
+ void StartOfNextColumn ();
+ void EndOfNextColumn ();
+ void StartOfPrevColumn ();
+ void EndOfPrevColumn ();
+
+ // set the cursor to page "nPage" at the beginning
+ // additionally to an identically named implementation in crsrsh.hxx
+ // here all existing selections are being reset before setting the
+ // cursor
+ bool GotoPage( sal_uInt16 nPage, bool bRecord );
+
+ // setting the cursor; remember the old position for turning back
+ DECL_DLLPRIVATE_LINK( ExecFlyMac, const SwFlyFrameFormat*, void );
+
+ bool PageCursor(SwTwips lOffset, bool bSelect);
+
+ // update fields
+ void UpdateInputFields( SwInputFieldList* pLst = nullptr );
+
+ void NoEdit(bool bHideCursor = true);
+ void Edit();
+
+ bool IsRetainSelection() const { return m_bRetainSelection; }
+ void SetRetainSelection( bool bRet ) { m_bRetainSelection = bRet; }
+
+ // change current data base and notify
+ void ChgDBData(const SwDBData& SwDBData);
+
+ // delete
+ void DelToEndOfLine();
+ void DelToStartOfLine();
+ void DelLine();
+ bool DelLeft();
+
+ // also deletes the frame or sets the cursor in the frame when bDelFrame == false
+ bool DelRight(bool isReplaceHeuristic = false);
+ void DelToEndOfPara();
+ void DelToStartOfPara();
+ bool DelToEndOfSentence();
+ void DelToStartOfSentence();
+ void DelNxtWord();
+ void DelPrvWord();
+
+ // checks whether a word selection exists.
+ // According to the rules for intelligent Cut / Paste
+ // surrounding spaces are cut out.
+ // returns type of word selection (see enum)
+ enum word {
+ NO_WORD = 0,
+ WORD_SPACE_BEFORE = 1,
+ WORD_SPACE_AFTER = 2,
+ WORD_NO_SPACE = 3
+ };
+ int IntelligentCut(SelectionType nSelectionType, bool bCut = true);
+
+ // edit
+ bool InsertField2(SwField const &, SwPaM* pAnnotationRange = nullptr);
+ void Insert(const OUString &);
+ // graphic
+ void InsertGraphic( const OUString &rPath, const OUString &rFilter,
+ const Graphic &, SwFlyFrameAttrMgr * = nullptr,
+ RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA);
+
+ void InsertByWord( const OUString & );
+ void InsertPageBreak(const OUString *pPageDesc = nullptr, const ::std::optional<sal_uInt16>& rPgNum = std::nullopt);
+ void InsertLineBreak(std::optional<SwLineBreakClear> oClear = std::nullopt);
+ void InsertColumnBreak();
+ void InsertContentControl(SwContentControlType eType);
+ void InsertFootnote(const OUString &, bool bEndNote = false, bool bEdit = true );
+ void SplitNode( bool bAutoFormat = false );
+ bool CanInsert();
+
+ // indexes
+ void InsertTableOf(const SwTOXBase& rTOX, const SfxItemSet* pSet = nullptr);
+ void UpdateTableOf(const SwTOXBase& rTOX, const SfxItemSet* pSet = nullptr);
+
+ // numbering and bullets
+ /**
+ Turns on numbering or bullets.
+
+ @param bNum true: turn on numbering
+ false: turn on bullets
+ */
+ void NumOrBulletOn(bool bNum); // #i29560#
+ void NumOrBulletOff(); // #i29560#
+ void NumOn();
+ void BulletOn();
+
+ //OLE
+ void InsertObject( /*SvInPlaceObjectRef *pObj, */ // != 0 for clipboard
+ const svt::EmbeddedObjectRef&,
+ SvGlobalName const *pName, // != 0 create object accordingly
+ sal_uInt16 nSlotId = 0); // SlotId for dialog
+
+ bool InsertOleObject( const svt::EmbeddedObjectRef& xObj, SwFlyFrameFormat **pFlyFrameFormat = nullptr );
+ void LaunchOLEObj(sal_Int32 nVerb = css::embed::EmbedVerbs::MS_OLEVERB_PRIMARY); // start server
+ virtual void MoveObjectIfActive( svt::EmbeddedObjectRef& xObj, const Point& rOffset ) override;
+ virtual void CalcAndSetScale( svt::EmbeddedObjectRef& xObj,
+ const SwRect *pFlyPrtRect = nullptr,
+ const SwRect *pFlyFrameRect = nullptr,
+ const bool bNoTextFramePrtAreaChanged = false ) override;
+ virtual void ConnectObj( svt::EmbeddedObjectRef& xIPObj, const SwRect &rPrt,
+ const SwRect &rFrame ) override;
+
+ // styles and formats
+
+ // enum tells when should happen when the style was not found
+ enum GetStyle { GETSTYLE_NOCREATE, // create none
+ GETSTYLE_CREATESOME, // if on PoolId create mapt
+ GETSTYLE_CREATEANY }; // return standard if applicable
+
+ SwTextFormatColl* GetParaStyle(const OUString &rCollName,
+ GetStyle eCreate = GETSTYLE_NOCREATE);
+ SwCharFormat* GetCharStyle(const OUString &rFormatName,
+ GetStyle eCreate = GETSTYLE_NOCREATE);
+ SwFrameFormat* GetTableStyle(std::u16string_view rFormatName);
+
+ void SetPageStyle(const OUString &rCollName);
+
+ OUString const & GetCurPageStyle() const;
+
+ // change current style using the attributes in effect
+ void QuickUpdateStyle();
+
+ enum DoType { UNDO, REDO, REPEAT };
+
+ enum class FieldDialogPressedButton { NONE, Previous, Next };
+
+ void Do(DoType eDoType, sal_uInt16 nCnt = 1, sal_uInt16 nOffset = 0);
+ OUString GetDoString( DoType eDoType ) const;
+ OUString GetRepeatString() const;
+ void GetDoStrings( DoType eDoType, SfxStringListItem& rStrLstItem ) const;
+
+ // search and replace
+ sal_Int32 SearchPattern(const i18nutil::SearchOptions2& rSearchOpt,
+ bool bSearchInNotes,
+ SwDocPositions eStart, SwDocPositions eEnd,
+ FindRanges eFlags = FindRanges::InBody,
+ bool bReplace = false );
+
+ sal_Int32 SearchTempl (const OUString &rTempl,
+ SwDocPositions eStart, SwDocPositions eEnd,
+ FindRanges eFlags = FindRanges::InBody,
+ const OUString* pReplTempl = nullptr );
+
+ sal_Int32 SearchAttr (const SfxItemSet& rFindSet,
+ bool bNoColls,
+ SwDocPositions eStart, SwDocPositions eEnd,
+ FindRanges eFlags = FindRanges::InBody,
+ const i18nutil::SearchOptions2* pSearchOpt = nullptr,
+ const SfxItemSet* pReplaceSet = nullptr);
+
+ void AutoCorrect( SvxAutoCorrect& rACorr, sal_Unicode cChar );
+
+ // action ahead of cursor movement
+ // resets selection if applicable, triggers timer and GCAttr()
+ void MoveCursor( bool bWithSelect = false );
+
+ // update input fields
+ bool StartInputFieldDlg(SwField*, bool bPrevButton, bool bNextButton, weld::Widget* pParentWin, FieldDialogPressedButton* pPressedButton = nullptr);
+ // update DropDown fields
+ bool StartDropDownFieldDlg(SwField*, bool bPrevButton, bool bNextButton, weld::Widget* pParentWin, FieldDialogPressedButton* pPressedButton = nullptr);
+
+ //"Handler" for changes at DrawView - for controls.
+ virtual void DrawSelChanged( ) override;
+
+ // jump to bookmark and set the "selections-flags" correctly again
+ void GotoMark( const ::sw::mark::IMark* const pMark );
+ bool GotoMark( const ::sw::mark::IMark* const pMark, bool bSelect );
+ void GotoMark( const OUString& rName );
+ bool GoNextBookmark(); // true when there still was one
+ bool GoPrevBookmark();
+
+ bool GotoFieldmark(::sw::mark::IFieldmark const * const pMark);
+
+ bool GotoField( const SwFormatField& rField );
+
+ /** @param bOnlyRefresh:
+ * false: run default actions (e.g. toggle checkbox, remove placeholder content)
+ * true: do not alter the content control, just refresh the doc model
+ */
+ bool GotoContentControl(const SwFormatContentControl& rContentControl,
+ bool bOnlyRefresh = false);
+
+ // jump to the next / previous hyperlink - inside text and also
+ // on graphics
+ void SelectNextPrevHyperlink( bool bNext );
+
+ // determine corresponding SwView
+ const SwView& GetView() const { return m_rView; }
+ SwView& GetView() { return m_rView; }
+
+ // Because nobody else is doing it, here is an ExecMacro()
+ void ExecMacro( const SvxMacro& rMacro, OUString* pRet = nullptr, SbxArray* pArgs = nullptr );
+ // call into the dark Basic/JavaScript
+ sal_uInt16 CallEvent( SvMacroItemId nEvent, const SwCallMouseEvent& rCallEvent,
+ bool bCheckPtr = false );
+
+ // a click at the given field. the cursor is on it.
+ // execute the predefined actions.
+ void ClickToField( const SwField& rField, bool bExecHyperlinks );
+ void ClickToINetAttr( const SwFormatINetFormat& rItem, LoadUrlFlags nFilter = LoadUrlFlags::NONE );
+ bool ClickToINetGrf( const Point& rDocPt, LoadUrlFlags nFilter );
+ inline bool IsInClickToEdit() const ;
+
+ // if a URL-Button is selected, return its URL; otherwise an empty string
+ bool GetURLFromButton( OUString& rURL, OUString& rDescr ) const;
+
+ void NavigatorPaste( const NaviContentBookmark& rBkmk,
+ const sal_uInt16 nAction );
+
+ virtual void ApplyViewOptions( const SwViewOption &rOpt ) override;
+ virtual void SetReadonlyOption( bool bSet ) override;
+
+ // automatic update of styles
+ void AutoUpdateFrame(SwFrameFormat* pFormat, const SfxItemSet& rStyleSet);
+ void AutoUpdatePara(SwTextFormatColl* pColl, const SfxItemSet& rStyleSet, SwPaM* pPaM = nullptr );
+
+ // starts dialog for inserting ranges via Drag&Drop/Clipboard
+ void StartInsertRegionDialog(const SwSectionData&);
+
+ // ctor, the first one is a kind of a controlled copy ctor for more views of a document
+ SwWrtShell( SwWrtShell&, vcl::Window *pWin, SwView &rShell);
+ SwWrtShell( SwDoc& rDoc, vcl::Window *pWin, SwView &rShell,
+ const SwViewOption *pViewOpt);
+ virtual ~SwWrtShell() override;
+
+ bool TryRemoveIndent(); // #i23725#
+
+ OUString GetSelDescr() const;
+
+ SwNavigationMgr& GetNavigationMgr() { return m_aNavigationMgr; }
+
+ void addCurrentPosition();
+ bool GotoFly( const OUString& rName, FlyCntType eType = FLYCNTTYPE_ALL,
+ bool bSelFrame = true );
+ bool GotoINetAttr( const SwTextINetFormat& rAttr );
+ void GotoOutline( SwOutlineNodes::size_type nIdx );
+ bool GotoOutline( const OUString& rName );
+ bool GotoRegion( std::u16string_view rName );
+ bool GotoRefMark( const OUString& rRefMark, sal_uInt16 nSubType = 0,
+ sal_uInt16 nSeqNo = 0, sal_uInt16 nFlags = 0 );
+ bool GotoNextTOXBase( const OUString* pName = nullptr);
+ bool GotoTable( const OUString& rName );
+ void GotoFormatField( const SwFormatField& rField );
+ const SwRangeRedline* GotoRedline( SwRedlineTable::size_type nArrPos, bool bSelect);
+ bool GotoDrawingObject(std::u16string_view rName);
+ void GotoFootnoteAnchor(const SwTextFootnote& rTextFootnote);
+ void ChangeHeaderOrFooter(std::u16string_view rStyleName, bool bHeader, bool bOn, bool bShowWarning);
+ virtual void SetShowHeaderFooterSeparator( FrameControlType eControl, bool bShow ) override;
+
+ /// Inserts a new annotation/comment at the current cursor position / selection.
+ void InsertPostIt(SwFieldMgr& rFieldMgr, const SfxRequest& rReq);
+
+ bool IsOutlineContentVisible(const size_t nPos);
+ void MakeOutlineContentVisible(const size_t nPos, bool bMakeVisible = true, bool bSetAttrOutlineVisibility = true);
+ void MakeAllFoldedOutlineContentVisible(bool bMakeVisible = true);
+ void InvalidateOutlineContentVisibility();
+ bool GetAttrOutlineContentVisible(const size_t nPos) const;
+
+ void MakeOutlineLevelsVisible(const int nLevel);
+
+ bool HasFoldedOutlineContentSelected() const;
+ virtual void InfoReadOnlyDialog(bool bAsync) const override;
+ virtual bool WarnHiddenSectionDialog() const override;
+ virtual bool WarnSwitchToDesignModeDialog() const override;
+
+ std::optional<OString> getLOKPayload(int nType, int nViewId) const;
+
+private:
+
+ SAL_DLLPRIVATE void OpenMark();
+ SAL_DLLPRIVATE void CloseMark( bool bOkFlag );
+
+ struct ModeStack
+ {
+ ModeStack *pNext;
+ bool bAdd,
+ bBlock,
+ bExt,
+ bIns;
+ ModeStack(ModeStack *pNextMode, bool _bIns, bool _bExt, bool _bAdd, bool _bBlock):
+ pNext(pNextMode),
+ bAdd(_bAdd),
+ bBlock(_bBlock),
+ bExt(_bExt),
+ bIns(_bIns)
+ {}
+ } *m_pModeStack = nullptr;
+
+ // carry cursor along when PageUp / -Down
+ enum PageMove
+ {
+ MV_NO,
+ MV_PAGE_UP,
+ MV_PAGE_DOWN
+ } m_ePageMove = MV_NO;
+
+ struct CursorStack
+ {
+ Point aDocPos;
+ std::unique_ptr<CursorStack> pNext;
+ bool bValidCurPos : 1;
+ bool bIsFrameSel : 1;
+ SwTwips lOffset;
+
+ CursorStack( bool bValid, bool bFrameSel, const Point &rDocPos,
+ SwTwips lOff, std::unique_ptr<CursorStack> pN )
+ : aDocPos(rDocPos),
+ pNext(std::move(pN)),
+ bValidCurPos( bValid ),
+ bIsFrameSel( bFrameSel ),
+ lOffset(lOff)
+ {
+ }
+
+ };
+ std::unique_ptr<CursorStack> m_pCursorStack;
+
+ SwView &m_rView;
+ SwNavigationMgr m_aNavigationMgr;
+
+ Point m_aDest;
+ bool m_bDestOnStack = false;
+ bool HasCursorStack() const { return nullptr != m_pCursorStack; }
+ SAL_DLLPRIVATE bool PushCursor(SwTwips lOffset, bool bSelect);
+ SAL_DLLPRIVATE bool PopCursor(bool bUpdate, bool bSelect = false);
+
+ // take END cursor along when PageUp / -Down
+ SAL_DLLPRIVATE void SttWrd();
+ SAL_DLLPRIVATE void EndWrd();
+ SAL_DLLPRIVATE bool NxtWrd_();
+ SAL_DLLPRIVATE bool PrvWrd_();
+ // #i92468#
+ SAL_DLLPRIVATE bool NxtWrdForDelete();
+ SAL_DLLPRIVATE bool PrvWrdForDelete();
+ SAL_DLLPRIVATE bool FwdSentence_();
+ SAL_DLLPRIVATE bool BwdSentence_();
+ bool FwdPara_();
+ SAL_DLLPRIVATE bool BwdPara_();
+
+ // selections
+ bool m_bIns :1;
+ bool m_bInSelect :1;
+ bool m_bExtMode :1;
+ bool m_bAddMode :1;
+ bool m_bBlockMode :1;
+ bool m_bLayoutMode :1;
+ bool m_bSelWrd :1;
+ bool m_bSelLn :1;
+ bool m_bIsInClickToEdit:1;
+ bool m_bClearMark :1; // don't delete selection for ChartAutoPilot
+ bool m_bRetainSelection :1; // Do not remove selections
+
+ Point m_aStart;
+ Link<SwWrtShell&,void> m_aSelTableLink;
+
+ // resets the cursor stack after movement by PageUp/-Down
+ SAL_DLLPRIVATE void ResetCursorStack_();
+
+ using SwCursorShell::SetCursor;
+ SAL_DLLPRIVATE tools::Long SetCursor(const Point *, bool bProp=false );
+
+ SAL_DLLPRIVATE tools::Long SetCursorKillSel(const Point *, bool bProp );
+
+ SAL_DLLPRIVATE void BeginDrag(const Point *, bool bProp );
+ SAL_DLLPRIVATE void DefaultDrag(const Point *, bool bProp );
+ SAL_DLLPRIVATE void DefaultEndDrag(const Point *, bool bProp );
+
+ SAL_DLLPRIVATE void ExtSelWrd(const Point *, bool bProp );
+ SAL_DLLPRIVATE void ExtSelLn(const Point *, bool bProp );
+
+ SAL_DLLPRIVATE void BeginFrameDrag(const Point *, bool bProp );
+
+ // after SSize/Move of a frame update; Point is destination.
+ SAL_DLLPRIVATE void UpdateLayoutFrame(const Point *, bool bProp );
+
+ SAL_DLLPRIVATE void SttLeaveSelect();
+ SAL_DLLPRIVATE void AddLeaveSelect();
+ SAL_DLLPRIVATE tools::Long Ignore(const Point *, bool bProp );
+
+ SAL_DLLPRIVATE void LeaveExtSel() { m_bSelWrd = m_bSelLn = false;}
+
+ SAL_DLLPRIVATE bool GoStart(bool KeepArea, bool *,
+ bool bSelect, bool bDontMoveRegion = false);
+ SAL_DLLPRIVATE bool GoEnd(bool KeepArea = false, const bool * = nullptr);
+
+ enum BookMarkMove
+ {
+ BOOKMARK_INDEX,
+ BOOKMARK_NEXT,
+ BOOKMARK_PREV
+ };
+
+ SAL_DLLPRIVATE bool MoveBookMark(BookMarkMove eFuncId, const ::sw::mark::IMark* const pMark=nullptr);
+};
+
+inline void SwWrtShell::ResetCursorStack()
+{
+ if ( HasCursorStack() )
+ ResetCursorStack_();
+}
+
+inline void SwWrtShell::SelTableCells(const Link<SwWrtShell&,void> &rLink )
+{
+ SetSelTableCells( true );
+ m_bClearMark = true;
+ m_aSelTableLink = rLink;
+}
+inline void SwWrtShell::EndSelTableCells()
+{
+ SetSelTableCells( false );
+ m_bClearMark = true;
+}
+
+inline bool SwWrtShell::IsInClickToEdit() const { return m_bIsInClickToEdit; }
+
+inline bool SwWrtShell::Is_FnDragEQBeginDrag() const
+{
+#ifdef __GNUC__
+ SELECTFUNC2 fnTmp = &SwWrtShell::BeginDrag;
+ return m_fnDrag == fnTmp;
+#else
+ return m_fnDrag == &SwWrtShell::BeginDrag;
+#endif
+}
+
+class MakeAllOutlineContentTemporarilyVisible
+{
+private:
+ SwWrtShell* m_pWrtSh = nullptr;
+ bool m_bDone = false;
+ bool m_bScrollToCursor = false;
+public:
+ static sal_uInt32 nLock;
+ MakeAllOutlineContentTemporarilyVisible(SwDoc* pDoc, bool bScrollToCursor = false)
+ {
+ ++nLock;
+ if (nLock > 1)
+ return;
+ if (SwDocShell* pDocSh = pDoc->GetDocShell())
+ if ((m_pWrtSh = pDocSh->GetWrtShell()) && m_pWrtSh->GetViewOptions() &&
+ m_pWrtSh->GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ {
+ m_pWrtSh->LockView(true);
+ m_pWrtSh->LockPaint(LockPaintReason::OutlineFolding);
+ m_pWrtSh->MakeAllFoldedOutlineContentVisible();
+ m_bScrollToCursor = bScrollToCursor;
+ m_bDone = true;
+ }
+ }
+
+ ~MakeAllOutlineContentTemporarilyVisible() COVERITY_NOEXCEPT_FALSE
+ {
+ --nLock;
+ if (nLock > 0)
+ return;
+ if (m_bDone && m_pWrtSh)
+ {
+ m_pWrtSh->MakeAllFoldedOutlineContentVisible(false);
+ m_pWrtSh->UnlockPaint();
+ m_pWrtSh->LockView(false);
+ if (m_bScrollToCursor)
+ m_pWrtSh->UpdateCursor(SwCursorShell::SCROLLWIN);
+ }
+ }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/wtabsh.hxx b/sw/source/uibase/inc/wtabsh.hxx
new file mode 100644
index 0000000000..9eff4052d0
--- /dev/null
+++ b/sw/source/uibase/inc/wtabsh.hxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "tabsh.hxx"
+
+class SwWebTableShell final : public SwTableShell
+{
+public:
+ SFX_DECL_INTERFACE(SW_WEBTABSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwWebTableShell(SwView& rView);
+ virtual ~SwWebTableShell() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/wtextsh.hxx b/sw/source/uibase/inc/wtextsh.hxx
new file mode 100644
index 0000000000..7958d688f8
--- /dev/null
+++ b/sw/source/uibase/inc/wtextsh.hxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "textsh.hxx"
+
+class SwWebTextShell final : public SwTextShell
+{
+public:
+ SFX_DECL_INTERFACE(SW_WEBTEXTSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwWebTextShell(SwView& rView);
+ virtual ~SwWebTextShell() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/wview.hxx b/sw/source/uibase/inc/wview.hxx
new file mode 100644
index 0000000000..90ce5af894
--- /dev/null
+++ b/sw/source/uibase/inc/wview.hxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <swdllapi.h>
+#include <view.hxx>
+
+class SW_DLLPUBLIC SwWebView final : public SwView
+{
+private:
+ virtual void SelectShell() override;
+
+public:
+ SFX_DECL_VIEWFACTORY(SwWebView);
+ SFX_DECL_INTERFACE(SW_WEBVIEWSHELL)
+
+private:
+ /// SfxInterface initializer.
+ static void InitInterface_Impl();
+
+public:
+ SwWebView(SfxViewFrame& rFrame, SfxViewShell*);
+ virtual ~SwWebView() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/zoomctrl.hxx b/sw/source/uibase/inc/zoomctrl.hxx
new file mode 100644
index 0000000000..b5af8ba9a5
--- /dev/null
+++ b/sw/source/uibase/inc/zoomctrl.hxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <svx/zoomctrl.hxx>
+
+class SwZoomControl final : public SvxZoomStatusBarControl
+{
+private:
+ OUString m_sPreviewZoom;
+
+public:
+ virtual void Command(const CommandEvent& rCEvt) override;
+ virtual void StateChangedAtStatusBarControl(sal_uInt16 nSID, SfxItemState eState,
+ const SfxPoolItem* pState) override;
+ virtual void Paint(const UserDrawEvent& rEvt) override;
+
+ SFX_DECL_STATUSBAR_CONTROL();
+
+ SwZoomControl(sal_uInt16 nSlotId, sal_uInt16 nId, StatusBar& rStb);
+ virtual ~SwZoomControl() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/index/idxmrk.cxx b/sw/source/uibase/index/idxmrk.cxx
new file mode 100644
index 0000000000..142d9fedad
--- /dev/null
+++ b/sw/source/uibase/index/idxmrk.cxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <idxmrk.hxx>
+#include <wrtsh.hxx>
+#include <cmdid.h>
+
+SFX_IMPL_CHILDWINDOW_WITHID(SwInsertIdxMarkWrapper, FN_INSERT_IDX_ENTRY_DLG)
+
+SwInsertIdxMarkWrapper::SwInsertIdxMarkWrapper( vcl::Window *pParentWindow,
+ sal_uInt16 nId,
+ SfxBindings* pBindings,
+ SfxChildWinInfo* pInfo ) :
+ SfxChildWindow(pParentWindow, nId)
+{
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ m_xAbstDlg = pFact->CreateIndexMarkFloatDlg(pBindings, this, pParentWindow->GetFrameWeld(), pInfo);
+ SetController(m_xAbstDlg->GetController());
+}
+
+SfxChildWinInfo SwInsertIdxMarkWrapper::GetInfo() const
+{
+ SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
+
+ return aInfo;
+}
+
+void SwInsertIdxMarkWrapper::ReInitDlg(SwWrtShell& rWrtShell)
+{
+ m_xAbstDlg->ReInitDlg(rWrtShell);
+}
+
+SFX_IMPL_CHILDWINDOW_WITHID(SwInsertAuthMarkWrapper, FN_INSERT_AUTH_ENTRY_DLG)
+
+SwInsertAuthMarkWrapper::SwInsertAuthMarkWrapper( vcl::Window *pParentWindow,
+ sal_uInt16 nId,
+ SfxBindings* pBindings,
+ SfxChildWinInfo* pInfo ) :
+ SfxChildWindow(pParentWindow, nId)
+{
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ m_xAbstDlg = pFact->CreateAuthMarkFloatDlg(pBindings, this, pParentWindow->GetFrameWeld(), pInfo);
+ SetController(m_xAbstDlg->GetController());
+}
+
+SfxChildWinInfo SwInsertAuthMarkWrapper::GetInfo() const
+{
+ SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
+ return aInfo;
+}
+
+void SwInsertAuthMarkWrapper::ReInitDlg(SwWrtShell& rWrtShell)
+{
+ m_xAbstDlg->ReInitDlg(rWrtShell);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/index/toxmgr.cxx b/sw/source/uibase/index/toxmgr.cxx
new file mode 100644
index 0000000000..8b8ff6dbd8
--- /dev/null
+++ b/sw/source/uibase/index/toxmgr.cxx
@@ -0,0 +1,495 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <wrtsh.hxx>
+#include <swwait.hxx>
+#include <view.hxx>
+#include <toxmgr.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <swundo.hxx>
+#include <osl/diagnose.h>
+
+// handle indexes with TOXMgr
+SwTOXMgr::SwTOXMgr(SwWrtShell* pShell):
+ m_pSh(pShell)
+{
+ m_pSh->GetCurTOXMarks(m_aCurMarks);
+ SetCurTOXMark(0);
+}
+
+SwTOXMark* SwTOXMgr::GetTOXMark(sal_uInt16 nId)
+{
+ if(!m_aCurMarks.empty())
+ return m_aCurMarks[nId];
+ return nullptr;
+}
+
+void SwTOXMgr::DeleteTOXMark()
+{
+ SwTOXMark* pNext = nullptr;
+ if( m_pCurTOXMark )
+ {
+ pNext = const_cast<SwTOXMark*>(&m_pSh->GotoTOXMark( *m_pCurTOXMark, TOX_NXT ));
+ if (SfxPoolItem::areSame( pNext, m_pCurTOXMark ))
+ pNext = nullptr;
+
+ m_pSh->DeleteTOXMark( m_pCurTOXMark );
+ m_pSh->SetModified();
+ }
+ // go to next one
+ m_pCurTOXMark = pNext;
+}
+
+void SwTOXMgr::InsertTOXMark(const SwTOXMarkDescription& rDesc)
+{
+ SwTOXMark* pMark = nullptr;
+ switch(rDesc.GetTOXType())
+ {
+ case TOX_CONTENT:
+ {
+ OSL_ENSURE(rDesc.GetLevel() > 0 && rDesc.GetLevel() <= MAXLEVEL,
+ "invalid InsertTOCMark level");
+ pMark = new SwTOXMark(m_pSh->GetTOXType(TOX_CONTENT, 0));
+ pMark->SetLevel( static_cast< sal_uInt16 >(rDesc.GetLevel()) );
+
+ if(rDesc.GetAltStr())
+ pMark->SetAlternativeText(*rDesc.GetAltStr());
+ }
+ break;
+ case TOX_INDEX:
+ {
+ pMark = new SwTOXMark(m_pSh->GetTOXType(TOX_INDEX, 0));
+
+ if( rDesc.GetPrimKey() && !rDesc.GetPrimKey()->isEmpty() )
+ {
+ pMark->SetPrimaryKey( *rDesc.GetPrimKey() );
+ if(rDesc.GetPhoneticReadingOfPrimKey())
+ pMark->SetPrimaryKeyReading( *rDesc.GetPhoneticReadingOfPrimKey() );
+
+ if( rDesc.GetSecKey() && !rDesc.GetSecKey()->isEmpty() )
+ {
+ pMark->SetSecondaryKey( *rDesc.GetSecKey() );
+ if(rDesc.GetPhoneticReadingOfSecKey())
+ pMark->SetSecondaryKeyReading( *rDesc.GetPhoneticReadingOfSecKey() );
+ }
+ }
+ if(rDesc.GetAltStr())
+ pMark->SetAlternativeText(*rDesc.GetAltStr());
+ if(rDesc.GetPhoneticReadingOfAltStr())
+ pMark->SetTextReading( *rDesc.GetPhoneticReadingOfAltStr() );
+ pMark->SetMainEntry(rDesc.IsMainEntry());
+ }
+ break;
+ case TOX_USER:
+ {
+ OSL_ENSURE(rDesc.GetLevel() > 0 && rDesc.GetLevel() <= MAXLEVEL,
+ "invalid InsertTOCMark level");
+ sal_uInt16 nId = rDesc.GetTOUName() ?
+ GetUserTypeID(*rDesc.GetTOUName()) : 0;
+ pMark = new SwTOXMark(m_pSh->GetTOXType(TOX_USER, nId));
+ pMark->SetLevel( static_cast< sal_uInt16 >(rDesc.GetLevel()) );
+
+ if(rDesc.GetAltStr())
+ pMark->SetAlternativeText(*rDesc.GetAltStr());
+ }
+ break;
+ case TOX_BIBLIOGRAPHY:
+ {
+ pMark = new SwTOXMark(m_pSh->GetTOXType(TOX_BIBLIOGRAPHY, 0));
+
+ if( rDesc.GetPrimKey() && !rDesc.GetPrimKey()->isEmpty() )
+ {
+ pMark->SetPrimaryKey( *rDesc.GetPrimKey() );
+ if(rDesc.GetPhoneticReadingOfPrimKey())
+ pMark->SetPrimaryKeyReading( *rDesc.GetPhoneticReadingOfPrimKey() );
+
+ if( rDesc.GetSecKey() && !rDesc.GetSecKey()->isEmpty() )
+ {
+ pMark->SetSecondaryKey( *rDesc.GetSecKey() );
+ if(rDesc.GetPhoneticReadingOfSecKey())
+ pMark->SetSecondaryKeyReading( *rDesc.GetPhoneticReadingOfSecKey() );
+ }
+ }
+ if(rDesc.GetAltStr())
+ pMark->SetAlternativeText(*rDesc.GetAltStr());
+ if(rDesc.GetPhoneticReadingOfAltStr())
+ pMark->SetTextReading( *rDesc.GetPhoneticReadingOfAltStr() );
+ pMark->SetMainEntry(rDesc.IsMainEntry());
+ }
+ break;
+ default:; //prevent warning
+ }
+
+ if (!pMark)
+ return;
+
+ m_pSh->StartAllAction();
+ m_pSh->SwEditShell::Insert(*pMark);
+ m_pSh->EndAllAction();
+}
+
+// Update of TOXMarks
+void SwTOXMgr::UpdateTOXMark(const SwTOXMarkDescription& rDesc)
+{
+ assert(m_pCurTOXMark && "no current TOXMark");
+ m_pSh->StartAllAction();
+ if(m_pCurTOXMark->GetTOXType()->GetType() == TOX_INDEX)
+ {
+ if(rDesc.GetPrimKey() && !rDesc.GetPrimKey()->isEmpty() )
+ {
+ m_pCurTOXMark->SetPrimaryKey( *rDesc.GetPrimKey() );
+ if(rDesc.GetPhoneticReadingOfPrimKey())
+ m_pCurTOXMark->SetPrimaryKeyReading( *rDesc.GetPhoneticReadingOfPrimKey() );
+ else
+ m_pCurTOXMark->SetPrimaryKeyReading(OUString());
+
+ if( rDesc.GetSecKey() && !rDesc.GetSecKey()->isEmpty() )
+ {
+ m_pCurTOXMark->SetSecondaryKey( *rDesc.GetSecKey() );
+ if(rDesc.GetPhoneticReadingOfSecKey())
+ m_pCurTOXMark->SetSecondaryKeyReading( *rDesc.GetPhoneticReadingOfSecKey() );
+ else
+ m_pCurTOXMark->SetSecondaryKeyReading(OUString());
+ }
+ else
+ {
+ m_pCurTOXMark->SetSecondaryKey(OUString());
+ m_pCurTOXMark->SetSecondaryKeyReading(OUString());
+ }
+ }
+ else
+ {
+ m_pCurTOXMark->SetPrimaryKey(OUString());
+ m_pCurTOXMark->SetPrimaryKeyReading(OUString());
+ m_pCurTOXMark->SetSecondaryKey(OUString());
+ m_pCurTOXMark->SetSecondaryKeyReading(OUString());
+ }
+ if(rDesc.GetPhoneticReadingOfAltStr())
+ m_pCurTOXMark->SetTextReading( *rDesc.GetPhoneticReadingOfAltStr() );
+ else
+ m_pCurTOXMark->SetTextReading(OUString());
+ m_pCurTOXMark->SetMainEntry(rDesc.IsMainEntry());
+ }
+ else
+ m_pCurTOXMark->SetLevel( static_cast< sal_uInt16 >(rDesc.GetLevel()) );
+
+ if(rDesc.GetAltStr())
+ {
+ // JP 26.08.96: Bug 30344 - either the text of a Doc or an alternative test,
+ // not both!
+ bool bReplace = m_pCurTOXMark->IsAlternativeText();
+ if( bReplace )
+ m_pCurTOXMark->SetAlternativeText( *rDesc.GetAltStr() );
+ else
+ {
+ SwTOXMark aCpy( *m_pCurTOXMark );
+ m_aCurMarks.clear();
+ m_pSh->DeleteTOXMark(m_pCurTOXMark);
+ aCpy.SetAlternativeText( *rDesc.GetAltStr() );
+ m_pSh->SwEditShell::Insert( aCpy );
+ m_pCurTOXMark = nullptr;
+ }
+ }
+ m_pSh->SetModified();
+ m_pSh->EndAllAction();
+ // Bug 36207 pCurTOXMark points nowhere here!
+ if(!m_pCurTOXMark)
+ {
+ m_pSh->Left(SwCursorSkipMode::Chars, false, 1, false );
+ m_pSh->GetCurTOXMarks(m_aCurMarks);
+ SetCurTOXMark(0);
+ }
+}
+
+// determine UserTypeID
+sal_uInt16 SwTOXMgr::GetUserTypeID(const OUString& rStr)
+{
+ sal_uInt16 nSize = m_pSh->GetTOXTypeCount(TOX_USER);
+ for(sal_uInt16 i=0; i < nSize; ++i)
+ {
+ const SwTOXType* pTmp = m_pSh->GetTOXType(TOX_USER, i);
+ if(pTmp && pTmp->GetTypeName() == rStr)
+ return i;
+ }
+ SwTOXType aUserType(*m_pSh->GetDoc(), TOX_USER, rStr);
+ m_pSh->InsertTOXType(aUserType);
+ return nSize;
+}
+
+// traveling between TOXMarks
+void SwTOXMgr::NextTOXMark(bool bSame)
+{
+ OSL_ENSURE(m_pCurTOXMark, "no current TOXMark");
+ if( m_pCurTOXMark )
+ {
+ SwTOXSearch eDir = bSame ? TOX_SAME_NXT : TOX_NXT;
+ m_pCurTOXMark = const_cast<SwTOXMark*>(&m_pSh->GotoTOXMark( *m_pCurTOXMark, eDir ));
+ }
+}
+
+void SwTOXMgr::PrevTOXMark(bool bSame)
+{
+ OSL_ENSURE(m_pCurTOXMark, "no current TOXMark");
+ if( m_pCurTOXMark )
+ {
+ SwTOXSearch eDir = bSame ? TOX_SAME_PRV : TOX_PRV;
+ m_pCurTOXMark = const_cast<SwTOXMark*>(&m_pSh->GotoTOXMark(*m_pCurTOXMark, eDir ));
+ }
+}
+
+const SwTOXType* SwTOXMgr::GetTOXType(TOXTypes eTyp) const
+{
+ return m_pSh->GetTOXType(eTyp, 0);
+}
+
+void SwTOXMgr::SetCurTOXMark(sal_uInt16 nId)
+{
+ m_pCurTOXMark = (nId < m_aCurMarks.size()) ? m_aCurMarks[nId] : nullptr;
+}
+
+bool SwTOXMgr::UpdateOrInsertTOX(const SwTOXDescription& rDesc,
+ SwTOXBase** ppBase,
+ const SfxItemSet* pSet)
+{
+ SwWait aWait( *m_pSh->GetView().GetDocShell(), true );
+ bool bRet = true;
+ const SwTOXBase *const pCurTOX = ppBase && *ppBase ? *ppBase : m_pSh->GetCurTOX();
+
+ SwTOXBase * pNewTOX = pCurTOX ? new SwTOXBase(*pCurTOX) : nullptr;
+
+ TOXTypes eCurTOXType = rDesc.GetTOXType();
+ if(pCurTOX && !ppBase && m_pSh->HasSelection())
+ m_pSh->EnterStdMode();
+
+ switch(eCurTOXType)
+ {
+ case TOX_INDEX :
+ {
+ if(!pCurTOX || (ppBase && !(*ppBase)))
+ {
+ const SwTOXType* pType = m_pSh->GetTOXType(eCurTOXType, 0);
+ SwForm aForm(eCurTOXType);
+ pNewTOX = new SwTOXBase(pType, aForm, SwTOXElement::Mark, pType->GetTypeName());
+ }
+ pNewTOX->SetOptions(rDesc.GetIndexOptions());
+ pNewTOX->SetMainEntryCharStyle(rDesc.GetMainEntryCharStyle());
+ m_pSh->SetTOIAutoMarkURL(rDesc.GetAutoMarkURL());
+ m_pSh->ApplyAutoMark();
+ }
+ break;
+ case TOX_CONTENT :
+ {
+ if(!pCurTOX || (ppBase && !(*ppBase)))
+ {
+ const SwTOXType* pType = m_pSh->GetTOXType(eCurTOXType, 0);
+ SwForm aForm(eCurTOXType);
+ pNewTOX = new SwTOXBase(pType, aForm, rDesc.GetContentOptions(), pType->GetTypeName());
+ }
+ pNewTOX->SetCreate(rDesc.GetContentOptions());
+ pNewTOX->SetLevel(rDesc.GetLevel());
+ }
+ break;
+ case TOX_USER :
+ {
+ if(!pCurTOX || (ppBase && !(*ppBase)))
+ {
+ sal_uInt16 nPos = 0;
+ sal_uInt16 nSize = m_pSh->GetTOXTypeCount(eCurTOXType);
+ for(sal_uInt16 i=0; rDesc.GetTOUName() && i < nSize; ++i)
+ { const SwTOXType* pType = m_pSh->GetTOXType(TOX_USER, i);
+ if(pType->GetTypeName() == *rDesc.GetTOUName())
+ { nPos = i;
+ break;
+ }
+ }
+ const SwTOXType* pType = m_pSh->GetTOXType(eCurTOXType, nPos);
+
+ SwForm aForm(eCurTOXType);
+ pNewTOX = new SwTOXBase(pType, aForm, rDesc.GetContentOptions(), pType->GetTypeName());
+
+ }
+ else
+ {
+ pNewTOX->SetCreate(rDesc.GetContentOptions());
+ }
+ pNewTOX->SetLevelFromChapter(rDesc.IsLevelFromChapter());
+ }
+ break;
+ case TOX_CITATION: /** TODO */break;
+ case TOX_OBJECTS:
+ case TOX_TABLES:
+ case TOX_AUTHORITIES:
+ case TOX_BIBLIOGRAPHY:
+ case TOX_ILLUSTRATIONS:
+ {
+ //Special handling for TOX_AUTHORITY
+ if(TOX_AUTHORITIES == eCurTOXType)
+ {
+ SwAuthorityFieldType* pFType = static_cast<SwAuthorityFieldType*>(
+ m_pSh->GetFieldType(SwFieldIds::TableOfAuthorities, OUString()));
+ if (!pFType)
+ {
+ SwAuthorityFieldType const type(m_pSh->GetDoc());
+ pFType = static_cast<SwAuthorityFieldType*>(
+ m_pSh->InsertFieldType(type));
+ }
+ OUString const& rBrackets(rDesc.GetAuthBrackets());
+ if (rBrackets.isEmpty())
+ {
+ pFType->SetPreSuffix('\0', '\0');
+ }
+ else
+ {
+ assert(rBrackets.getLength() == 2);
+ pFType->SetPreSuffix(rBrackets[0], rBrackets[1]);
+ }
+ pFType->SetSequence(rDesc.IsAuthSequence());
+ SwTOXSortKey rArr[3];
+ rArr[0] = rDesc.GetSortKey1();
+ rArr[1] = rDesc.GetSortKey2();
+ rArr[2] = rDesc.GetSortKey3();
+ pFType->SetSortKeys(3, rArr);
+ pFType->SetSortByDocument(rDesc.IsSortByDocument());
+ pFType->SetLanguage(rDesc.GetLanguage());
+ pFType->SetSortAlgorithm(rDesc.GetSortAlgorithm());
+
+ pFType->UpdateFields();
+ }
+ // TODO: consider properties of the current TOXType
+ if(!pCurTOX || (ppBase && !(*ppBase)))
+ {
+ const SwTOXType* pType = m_pSh->GetTOXType(eCurTOXType, 0);
+ SwForm aForm(eCurTOXType);
+ pNewTOX = new SwTOXBase(
+ pType, aForm,
+ TOX_AUTHORITIES == eCurTOXType ? SwTOXElement::Mark : SwTOXElement::NONE,
+ pType->GetTypeName());
+ }
+ pNewTOX->SetFromObjectNames(rDesc.IsCreateFromObjectNames());
+ pNewTOX->SetOLEOptions(rDesc.GetOLEOptions());
+ if (eCurTOXType == TOX_ILLUSTRATIONS
+ || eCurTOXType == TOX_TABLES
+ || eCurTOXType == TOX_OBJECTS)
+ {
+ pNewTOX->SetCreate(rDesc.GetContentOptions());
+ }
+ }
+ break;
+ }
+
+ OSL_ENSURE(pNewTOX, "no TOXBase created!" );
+ if(!pNewTOX)
+ return false;
+
+ pNewTOX->SetFromChapter(rDesc.IsFromChapter());
+ pNewTOX->SetSequenceName(rDesc.GetSequenceName());
+ pNewTOX->SetCaptionDisplay(rDesc.GetCaptionDisplay());
+ pNewTOX->SetProtected(rDesc.IsReadonly());
+
+ for(sal_uInt16 nLevel = 0; nLevel < MAXLEVEL; nLevel++)
+ pNewTOX->SetStyleNames(rDesc.GetStyleNames(nLevel), nLevel);
+
+ if(rDesc.GetTitle())
+ pNewTOX->SetTitle(*rDesc.GetTitle());
+ if(rDesc.GetForm())
+ pNewTOX->SetTOXForm(*rDesc.GetForm());
+ pNewTOX->SetLanguage(rDesc.GetLanguage());
+ pNewTOX->SetSortAlgorithm(rDesc.GetSortAlgorithm());
+
+ if(!pCurTOX || (ppBase && !(*ppBase)) )
+ {
+ // when ppBase is passed over, TOXBase is only created here
+ // and then inserted in a global document by the dialog
+ if(ppBase)
+ (*ppBase) = pNewTOX;
+ else
+ {
+ m_pSh->InsertTableOf(*pNewTOX, pSet);
+ delete pNewTOX;
+ }
+ }
+ else
+ {
+ SwDoc * pDoc = m_pSh->GetDoc();
+
+ if (pDoc->GetIDocumentUndoRedo().DoesUndo())
+ {
+ pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::TOXCHANGE, nullptr);
+ }
+
+ SwTOXBase *const pTOX = const_cast<SwTOXBase*>(pCurTOX);
+ pDoc->ChangeTOX(*pTOX, *pNewTOX);
+
+ pTOX->DisableKeepExpression();
+ m_pSh->UpdateTableOf(*pTOX, pSet);
+ bRet = false;
+ pTOX->EnableKeepExpression();
+
+ if (pDoc->GetIDocumentUndoRedo().DoesUndo())
+ {
+ pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::TOXCHANGE, nullptr);
+ }
+ }
+
+ return bRet;
+}
+
+void SwTOXDescription::SetSortKeys(SwTOXSortKey eKey1,
+ SwTOXSortKey eKey2,
+ SwTOXSortKey eKey3)
+{
+ SwTOXSortKey aArr[3];
+ sal_uInt16 nPos = 0;
+ if(AUTH_FIELD_END > eKey1.eField)
+ aArr[nPos++] = eKey1;
+ if(AUTH_FIELD_END > eKey2.eField)
+ aArr[nPos++] = eKey2;
+ if(AUTH_FIELD_END > eKey3.eField)
+ aArr[nPos++] = eKey3;
+
+ m_eSortKey1 = aArr[0];
+ m_eSortKey2 = aArr[1];
+ m_eSortKey3 = aArr[2];
+}
+
+void SwTOXDescription::ApplyTo(SwTOXBase& rTOXBase)
+{
+ for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
+ rTOXBase.SetStyleNames(GetStyleNames(i), i);
+ rTOXBase.SetTitle(GetTitle() ? *GetTitle() : OUString());
+ rTOXBase.SetCreate(GetContentOptions());
+
+ if(GetTOXType() == TOX_INDEX)
+ rTOXBase.SetOptions(GetIndexOptions());
+ if(GetTOXType() != TOX_INDEX)
+ rTOXBase.SetLevel(GetLevel());
+ rTOXBase.SetFromObjectNames(IsCreateFromObjectNames());
+ rTOXBase.SetSequenceName(GetSequenceName());
+ rTOXBase.SetCaptionDisplay(GetCaptionDisplay());
+ rTOXBase.SetFromChapter(IsFromChapter());
+ rTOXBase.SetProtected(IsReadonly());
+ rTOXBase.SetOLEOptions(GetOLEOptions());
+ rTOXBase.SetLevelFromChapter(IsLevelFromChapter());
+ rTOXBase.SetLanguage(m_eLanguage);
+ rTOXBase.SetSortAlgorithm(m_sSortAlgorithm);
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/lingu/hhcwrp.cxx b/sw/source/uibase/lingu/hhcwrp.cxx
new file mode 100644
index 0000000000..813f9d043c
--- /dev/null
+++ b/sw/source/uibase/lingu/hhcwrp.cxx
@@ -0,0 +1,680 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <swundo.hxx>
+#include <splargs.hxx>
+
+#include <editeng/langitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/text/RubyAdjust.hpp>
+#include <com/sun/star/i18n/XBreakIterator.hpp>
+#include <osl/diagnose.h>
+#include <hhcwrp.hxx>
+#include "sdrhhcwrap.hxx"
+#include <doc.hxx>
+#include <docsh.hxx>
+#include <mdiexp.hxx>
+#include <edtwin.hxx>
+#include <contentindex.hxx>
+#include <pam.hxx>
+#include <swcrsr.hxx>
+#include <ndtxt.hxx>
+#include <fmtruby.hxx>
+#include <breakit.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::linguistic2;
+using namespace ::com::sun::star::i18n;
+
+// Description: Turn off frame/object shell if applicable
+
+static void lcl_ActivateTextShell( SwWrtShell & rWrtSh )
+{
+ if( rWrtSh.IsSelFrameMode() || rWrtSh.IsObjSelected() )
+ rWrtSh.EnterStdMode();
+}
+
+namespace {
+
+class SwKeepConversionDirectionStateContext
+{
+public:
+ SwKeepConversionDirectionStateContext()
+ {
+ //!! hack to transport the current conversion direction state settings
+ //!! into the next incarnation that iterates over the drawing objects
+ //!! ( see SwHHCWrapper::~SwHHCWrapper() )
+ editeng::HangulHanjaConversion::SetUseSavedConversionDirectionState( true );
+ }
+
+ ~SwKeepConversionDirectionStateContext()
+ {
+ editeng::HangulHanjaConversion::SetUseSavedConversionDirectionState( false );
+ }
+};
+
+}
+
+SwHHCWrapper::SwHHCWrapper(
+ SwView* pSwView,
+ const uno::Reference< uno::XComponentContext >& rxContext,
+ LanguageType nSourceLanguage,
+ LanguageType nTargetLanguage,
+ const vcl::Font *pTargetFont,
+ sal_Int32 nConvOptions,
+ bool bIsInteractive,
+ bool bStart, bool bOther, bool bSelection )
+ : editeng::HangulHanjaConversion(pSwView->GetEditWin().GetFrameWeld(), rxContext,
+ LanguageTag::convertToLocale( nSourceLanguage ),
+ LanguageTag::convertToLocale( nTargetLanguage ),
+ pTargetFont,
+ nConvOptions,
+ bIsInteractive )
+ , m_pView( pSwView )
+ , m_rWrtShell( pSwView->GetWrtShell() )
+ , m_nLastPos( 0 )
+ , m_nUnitOffset( 0 )
+ , m_nPageCount( 0 )
+ , m_nPageStart( 0 )
+ , m_bIsDrawObj( false )
+ , m_bIsOtherContent( bOther )
+ , m_bStartChk( bOther )
+ , m_bIsSelection( bSelection )
+ , m_bStartDone( bOther || bStart )
+ , m_bEndDone( false )
+{
+}
+
+SwHHCWrapper::~SwHHCWrapper() COVERITY_NOEXCEPT_FALSE
+{
+ m_pConvArgs.reset();
+
+ SwViewShell::SetCareDialog(nullptr);
+
+ // check for existence of a draw view which means that there are
+ // (or previously were) draw objects present in the document.
+ // I.e. we like to check those too.
+ if ( m_bIsDrawObj /*&& bLastRet*/ && m_pView->GetWrtShell().HasDrawView() )
+ {
+ vcl::Cursor *pSave = m_pView->GetWindow()->GetCursor();
+ {
+ SwKeepConversionDirectionStateContext aContext;
+
+ SdrHHCWrapper aSdrConvWrap( m_pView, GetSourceLanguage(),
+ GetTargetLanguage(), GetTargetFont(),
+ GetConversionOptions(), IsInteractive() );
+ aSdrConvWrap.StartTextConversion();
+ }
+ m_pView->GetWindow()->SetCursor( pSave );
+ }
+
+ if( m_nPageCount )
+ ::EndProgress( m_pView->GetDocShell() );
+
+ // finally for chinese translation we need to change the documents
+ // default language and font to the new ones to be used.
+ LanguageType nTargetLang = GetTargetLanguage();
+ if (!IsChinese( nTargetLang ))
+ return;
+
+ SwDoc *pDoc = m_pView->GetDocShell()->GetDoc();
+
+ //!! Note: This also effects the default language of text boxes (EditEngine/EditView) !!
+ pDoc->SetDefault( SvxLanguageItem( nTargetLang, RES_CHRATR_CJK_LANGUAGE ) );
+
+ const vcl::Font *pFont = GetTargetFont();
+ if (pFont)
+ {
+ SvxFontItem aFontItem( pFont->GetFamilyType(), pFont->GetFamilyName(),
+ pFont->GetStyleName(), pFont->GetPitch(),
+ pFont->GetCharSet(), RES_CHRATR_CJK_FONT );
+ pDoc->SetDefault( aFontItem );
+ }
+}
+
+void SwHHCWrapper::GetNextPortion(
+ OUString& rNextPortion,
+ LanguageType& rLangOfPortion,
+ bool bAllowChanges )
+{
+ m_pConvArgs->bAllowImplicitChangesForNotConvertibleText = bAllowChanges;
+
+ FindConvText_impl();
+ rNextPortion = m_pConvArgs->aConvText;
+ rLangOfPortion = m_pConvArgs->nConvTextLang;
+
+ m_nUnitOffset = 0;
+
+ // build last pos from currently selected text
+ SwPaM* pCursor = m_rWrtShell.GetCursor();
+ m_nLastPos = pCursor->Start()->GetContentIndex();
+}
+
+void SwHHCWrapper::SelectNewUnit_impl( sal_Int32 nUnitStart, sal_Int32 nUnitEnd )
+{
+ SwPaM *pCursor = m_rWrtShell.GetCursor();
+ pCursor->GetPoint()->SetContent( m_nLastPos );
+ pCursor->DeleteMark();
+
+ m_rWrtShell.Right( SwCursorSkipMode::Chars, /*bExpand*/ false,
+ o3tl::narrowing<sal_uInt16>(m_nUnitOffset + nUnitStart), true );
+ pCursor->SetMark();
+ m_rWrtShell.Right( SwCursorSkipMode::Chars, /*bExpand*/ true,
+ o3tl::narrowing<sal_uInt16>(nUnitEnd - nUnitStart), true );
+ // end selection now. Otherwise SHIFT+HOME (extending the selection)
+ // won't work when the dialog is closed without any replacement.
+ // (see #116346#)
+ m_rWrtShell.EndSelect();
+}
+
+void SwHHCWrapper::HandleNewUnit(
+ const sal_Int32 nUnitStart, const sal_Int32 nUnitEnd )
+{
+ OSL_ENSURE( nUnitStart >= 0 && nUnitEnd >= nUnitStart, "wrong arguments" );
+ if (0 > nUnitStart || nUnitStart > nUnitEnd)
+ return;
+
+ lcl_ActivateTextShell( m_rWrtShell );
+
+ m_rWrtShell.StartAllAction();
+
+ // select current unit
+ SelectNewUnit_impl( nUnitStart, nUnitEnd );
+
+ m_rWrtShell.EndAllAction();
+}
+
+void SwHHCWrapper::ChangeText( const OUString &rNewText,
+ std::u16string_view aOrigText,
+ const uno::Sequence< sal_Int32 > *pOffsets,
+ SwPaM *pCursor )
+{
+ //!! please see also TextConvWrapper::ChangeText with is a modified
+ //!! copy of this code
+
+ OSL_ENSURE( !rNewText.isEmpty(), "unexpected empty string" );
+ if (rNewText.isEmpty())
+ return;
+
+ if (pOffsets && pCursor) // try to keep as much attributation as possible ?
+ {
+ // remember cursor start position for later setting of the cursor
+ const SwPosition *pStart = pCursor->Start();
+ const sal_Int32 nStartIndex = pStart->GetContentIndex();
+ SwTextNode *pStartTextNode = pStart->GetNode().GetTextNode();
+
+ const sal_Int32 nIndices = pOffsets->getLength();
+ const sal_Int32 *pIndices = pOffsets->getConstArray();
+ sal_Int32 nConvTextLen = rNewText.getLength();
+ sal_Int32 nPos = 0;
+ sal_Int32 nChgPos = -1;
+ sal_Int32 nChgLen = 0;
+ sal_Int32 nConvChgPos = -1;
+ sal_Int32 nConvChgLen = 0;
+
+ // offset to calculate the position in the text taking into
+ // account that text may have been replaced with new text of
+ // different length. Negative values allowed!
+ tools::Long nCorrectionOffset = 0;
+
+ OSL_ENSURE(nIndices == 0 || nIndices == nConvTextLen,
+ "mismatch between string length and sequence length!" );
+
+ // find all substrings that need to be replaced (and only those)
+ while (true)
+ {
+ // get index in original text that matches nPos in new text
+ sal_Int32 nIndex;
+ if (nPos < nConvTextLen)
+ nIndex = nPos < nIndices ? pIndices[nPos] : nPos;
+ else
+ {
+ nPos = nConvTextLen;
+ nIndex = aOrigText.size();
+ }
+
+ if (nPos == nConvTextLen || /* end of string also terminates non-matching char sequence */
+ aOrigText[nIndex] == rNewText[nPos])
+ {
+ // substring that needs to be replaced found?
+ if (nChgPos != -1 && nConvChgPos != -1)
+ {
+ nChgLen = nIndex - nChgPos;
+ nConvChgLen = nPos - nConvChgPos;
+ OUString aInNew( rNewText.copy( nConvChgPos, nConvChgLen ) );
+
+ // set selection to sub string to be replaced in original text
+ sal_Int32 nChgInNodeStartIndex = nStartIndex + nCorrectionOffset + nChgPos;
+ OSL_ENSURE( m_rWrtShell.GetCursor()->HasMark(), "cursor misplaced (nothing selected)" );
+ m_rWrtShell.GetCursor()->GetMark()->Assign( *pStartTextNode, nChgInNodeStartIndex );
+ m_rWrtShell.GetCursor()->GetPoint()->Assign( *pStartTextNode, nChgInNodeStartIndex + nChgLen );
+
+ // replace selected sub string with the corresponding
+ // sub string from the new text while keeping as
+ // much from the attributes as possible
+ ChangeText_impl( aInNew, true );
+
+ nCorrectionOffset += nConvChgLen - nChgLen;
+
+ nChgPos = -1;
+ nConvChgPos = -1;
+ }
+ }
+ else
+ {
+ // begin of non-matching char sequence found ?
+ if (nChgPos == -1 && nConvChgPos == -1)
+ {
+ nChgPos = nIndex;
+ nConvChgPos = nPos;
+ }
+ }
+ if (nPos >= nConvTextLen)
+ break;
+ ++nPos;
+ }
+
+ // set cursor to the end of all the new text
+ // (as it would happen after ChangeText_impl (Delete and Insert)
+ // of the whole text in the 'else' branch below)
+ m_rWrtShell.ClearMark();
+ m_rWrtShell.GetCursor()->Start()->Assign( *pStartTextNode, nStartIndex + nConvTextLen );
+ }
+ else
+ {
+ ChangeText_impl( rNewText, false );
+ }
+}
+
+void SwHHCWrapper::ChangeText_impl( const OUString &rNewText, bool bKeepAttributes )
+{
+ if (bKeepAttributes)
+ {
+ // get item set with all relevant attributes
+ SfxItemSetFixed<RES_CHRATR_BEGIN, RES_FRMATR_END> aItemSet( m_rWrtShell.GetAttrPool() );
+ // get all attributes spanning the whole selection in order to
+ // restore those for the new text
+ m_rWrtShell.GetCurAttr( aItemSet );
+
+ m_rWrtShell.Delete(true);
+ m_rWrtShell.Insert( rNewText );
+
+ // select new inserted text (currently the Point is right after the new text)
+ if (!m_rWrtShell.GetCursor()->HasMark())
+ m_rWrtShell.GetCursor()->SetMark();
+ SwPosition *pMark = m_rWrtShell.GetCursor()->GetMark();
+ pMark->SetContent( pMark->GetContentIndex() - rNewText.getLength() );
+
+ // since 'SetAttr' below functions like merging with the attributes
+ // from the itemset with any existing ones we have to get rid of all
+ // all attributes now. (Those attributes that may take effect left
+ // to the position where the new text gets inserted after the old text
+ // was deleted)
+ m_rWrtShell.ResetAttr();
+ // apply previously saved attributes to new text
+ m_rWrtShell.SetAttrSet( aItemSet );
+ }
+ else
+ {
+ m_rWrtShell.Delete(true);
+ m_rWrtShell.Insert( rNewText );
+ }
+}
+
+void SwHHCWrapper::ReplaceUnit(
+ const sal_Int32 nUnitStart, const sal_Int32 nUnitEnd,
+ const OUString& rOrigText,
+ const OUString& rReplaceWith,
+ const uno::Sequence< sal_Int32 > &rOffsets,
+ ReplacementAction eAction,
+ LanguageType *pNewUnitLanguage )
+{
+ OSL_ENSURE( nUnitStart >= 0 && nUnitEnd >= nUnitStart, "wrong arguments" );
+ if (nUnitStart < 0 || nUnitEnd < nUnitStart)
+ return;
+
+ lcl_ActivateTextShell( m_rWrtShell );
+
+ // replace the current word
+ m_rWrtShell.StartAllAction();
+
+ // select current unit
+ SelectNewUnit_impl( nUnitStart, nUnitEnd );
+
+ OUString aOrigText( m_rWrtShell.GetSelText() );
+ OUString aNewText( rReplaceWith );
+ OSL_ENSURE( aOrigText == rOrigText, "!! text mismatch !!" );
+ std::unique_ptr<SwFormatRuby> pRuby;
+ bool bRubyBelow = false;
+ OUString aNewOrigText;
+ switch (eAction)
+ {
+ case eExchange :
+ break;
+ case eReplacementBracketed :
+ {
+ aNewText = aOrigText + "(" + rReplaceWith + ")";
+ }
+ break;
+ case eOriginalBracketed :
+ {
+ aNewText = rReplaceWith + "(" + aOrigText + ")";
+ }
+ break;
+ case eReplacementAbove :
+ {
+ pRuby.reset(new SwFormatRuby( rReplaceWith ));
+ }
+ break;
+ case eOriginalAbove :
+ {
+ pRuby.reset(new SwFormatRuby( aOrigText ));
+ aNewOrigText = rReplaceWith;
+ }
+ break;
+ case eReplacementBelow :
+ {
+ pRuby.reset(new SwFormatRuby( rReplaceWith ));
+ bRubyBelow = true;
+ }
+ break;
+ case eOriginalBelow :
+ {
+ pRuby.reset(new SwFormatRuby( aOrigText ));
+ aNewOrigText = rReplaceWith;
+ bRubyBelow = true;
+ }
+ break;
+ default:
+ OSL_FAIL("unexpected case" );
+ }
+ m_nUnitOffset += nUnitStart + aNewText.getLength();
+
+ if (pRuby)
+ {
+ m_rWrtShell.StartUndo( SwUndoId::SETRUBYATTR );
+ if (!aNewOrigText.isEmpty())
+ {
+ // according to FT we currently should not bother about keeping
+ // attributes in Hangul/Hanja conversion
+ ChangeText( aNewOrigText, rOrigText, nullptr, nullptr );
+
+ //!! since Delete, Insert in 'ChangeText' do not set the WrtShells
+ //!! bInSelect flag
+ //!! back to false we do it now manually in order for the selection
+ //!! to be done properly in the following call to Left.
+ // We didn't fix it in Delete and Insert since it is currently
+ // unclear if someone depends on this incorrect behaviour
+ // of the flag.
+ m_rWrtShell.EndSelect();
+
+ m_rWrtShell.Left( SwCursorSkipMode::Chars, true, aNewOrigText.getLength(), true, true );
+ }
+
+ pRuby->SetPosition( o3tl::narrowing<sal_uInt16>(bRubyBelow) );
+ pRuby->SetAdjustment( RubyAdjust_CENTER );
+
+ m_rWrtShell.SetAttrItem(*pRuby);
+ pRuby.reset();
+ m_rWrtShell.EndUndo( SwUndoId::SETRUBYATTR );
+ }
+ else
+ {
+ m_rWrtShell.StartUndo( SwUndoId::OVERWRITE );
+
+ // according to FT we should currently not bother about keeping
+ // attributes in Hangul/Hanja conversion and leave that untouched.
+ // Thus we do this only for Chinese translation...
+ const bool bIsChineseConversion = IsChinese( GetSourceLanguage() );
+ if (bIsChineseConversion)
+ ChangeText( aNewText, rOrigText, &rOffsets, m_rWrtShell.GetCursor() );
+ else
+ ChangeText( aNewText, rOrigText, nullptr, nullptr );
+
+ // change language and font if necessary
+ if (bIsChineseConversion)
+ {
+ m_rWrtShell.SetMark();
+ m_rWrtShell.GetCursor()->GetMark()->AdjustContent( -aNewText.getLength() );
+
+ OSL_ENSURE( GetTargetLanguage() == LANGUAGE_CHINESE_SIMPLIFIED || GetTargetLanguage() == LANGUAGE_CHINESE_TRADITIONAL,
+ "SwHHCWrapper::ReplaceUnit : unexpected target language" );
+
+ SfxItemSetFixed<
+ RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONT,
+ RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_LANGUAGE>
+ aSet( m_rWrtShell.GetAttrPool() );
+ if (pNewUnitLanguage)
+ {
+ aSet.Put( SvxLanguageItem( *pNewUnitLanguage, RES_CHRATR_CJK_LANGUAGE ) );
+ }
+
+ const vcl::Font *pTargetFont = GetTargetFont();
+ OSL_ENSURE( pTargetFont, "target font missing?" );
+ if (pTargetFont && pNewUnitLanguage)
+ {
+ SvxFontItem aFontItem( aSet.Get( RES_CHRATR_CJK_FONT ) );
+ aFontItem.SetFamilyName( pTargetFont->GetFamilyName());
+ aFontItem.SetFamily( pTargetFont->GetFamilyType());
+ aFontItem.SetStyleName( pTargetFont->GetStyleName());
+ aFontItem.SetPitch( pTargetFont->GetPitch());
+ aFontItem.SetCharSet( pTargetFont->GetCharSet() );
+ aSet.Put( aFontItem );
+ }
+
+ m_rWrtShell.SetAttrSet( aSet );
+
+ m_rWrtShell.ClearMark();
+ }
+
+ m_rWrtShell.EndUndo( SwUndoId::OVERWRITE );
+ }
+
+ m_rWrtShell.EndAllAction();
+}
+
+bool SwHHCWrapper::HasRubySupport() const
+{
+ return true;
+}
+
+void SwHHCWrapper::Convert()
+{
+ OSL_ENSURE( m_pConvArgs == nullptr, "NULL pointer expected" );
+ {
+ SwPaM *pCursor = m_pView->GetWrtShell().GetCursor();
+ auto [pSttPos, pEndPos] = pCursor->StartEnd(); // SwPosition*
+
+ if (pSttPos->GetNode().IsTextNode() &&
+ pEndPos->GetNode().IsTextNode())
+ {
+ m_pConvArgs.reset( new SwConversionArgs( GetSourceLanguage(), *pSttPos, *pEndPos ) );
+ }
+ else // we are not in the text (maybe a graphic or OLE object is selected) let's start from the top
+ {
+ // get PaM that points to the start of the document
+ SwNode& rNode = m_pView->GetDocShell()->GetDoc()->GetNodes().GetEndOfContent();
+ SwPaM aPam(rNode);
+ aPam.Move( fnMoveBackward, GoInDoc ); // move to start of document
+
+ pSttPos = aPam.GetPoint(); //! using a PaM here makes sure we will get only text nodes
+ SwTextNode *pTextNode = pSttPos->GetNode().GetTextNode();
+ // just in case we check anyway...
+ if (!pTextNode || !pTextNode->IsTextNode())
+ return;
+ m_pConvArgs.reset( new SwConversionArgs( GetSourceLanguage(), *pSttPos, *pSttPos ) );
+ }
+ OSL_ENSURE( m_pConvArgs->pStartPos && m_pConvArgs->pStartPos->GetNode().IsTextNode(),
+ "failed to get proper start text node" );
+ OSL_ENSURE( m_pConvArgs->pEndPos && m_pConvArgs->pEndPos->GetNode().IsTextNode(),
+ "failed to get proper end text node" );
+
+ // chinese conversion specific settings
+ OSL_ENSURE( IsChinese( GetSourceLanguage() ) == IsChinese( GetTargetLanguage() ),
+ "source and target language mismatch?" );
+ if (IsChinese( GetTargetLanguage() ))
+ {
+ m_pConvArgs->nConvTargetLang = GetTargetLanguage();
+ m_pConvArgs->pTargetFont = GetTargetFont();
+ m_pConvArgs->bAllowImplicitChangesForNotConvertibleText = true;
+ }
+
+ // if it is not just a selection and we are about to begin
+ // with the current conversion for the very first time
+ // we need to find the start of the current (initial)
+ // convertible unit in order for the text conversion to give
+ // the correct result for that. Since it is easier to obtain
+ // the start of the word we use that though.
+ if (!pCursor->HasMark()) // is not a selection?
+ {
+ // since #118246 / #117803 still occurs if the cursor is placed
+ // between the two chinese characters to be converted (because both
+ // of them are words on their own!) using the word boundary here does
+ // not work. Thus since chinese conversion is not interactive we start
+ // at the begin of the paragraph to solve the problem, i.e. have the
+ // TextConversion service get those characters together in the same call.
+ sal_Int32 nStartIdx = -1;
+ if (editeng::HangulHanjaConversion::IsChinese( GetSourceLanguage() ) )
+ nStartIdx = 0;
+ else
+ {
+ OUString aText( m_pConvArgs->pStartPos->GetNode().GetTextNode()->GetText() );
+ const sal_Int32 nPos = m_pConvArgs->pStartPos->GetContentIndex();
+ Boundary aBoundary( g_pBreakIt->GetBreakIter()->
+ getWordBoundary( aText, nPos, g_pBreakIt->GetLocale( m_pConvArgs->nConvSrcLang ),
+ WordType::DICTIONARY_WORD, true ) );
+
+ // valid result found?
+ if (aBoundary.startPos < aText.getLength() &&
+ aBoundary.startPos != aBoundary.endPos)
+ {
+ nStartIdx = aBoundary.startPos;
+ }
+ }
+
+ if (nStartIdx != -1)
+ m_pConvArgs->pStartPos->SetContent( nStartIdx );
+ }
+ }
+
+ if ( m_bIsOtherContent )
+ ConvStart_impl( m_pConvArgs.get(), SvxSpellArea::Other );
+ else
+ {
+ m_bStartChk = false;
+ ConvStart_impl( m_pConvArgs.get(), SvxSpellArea::BodyEnd );
+ }
+
+ ConvertDocument();
+
+ ConvEnd_impl( m_pConvArgs.get() );
+}
+
+bool SwHHCWrapper::ConvNext_impl( )
+{
+ //! modified version of SvxSpellWrapper::SpellNext
+
+ // no change of direction so the desired region is fully processed
+ if( m_bStartChk )
+ m_bStartDone = true;
+ else
+ m_bEndDone = true;
+
+ if( m_bIsOtherContent && m_bStartDone && m_bEndDone ) // document completely checked?
+ {
+ return false;
+ }
+
+ bool bGoOn = false;
+
+ if ( m_bIsOtherContent )
+ {
+ m_bStartChk = false;
+ ConvStart_impl( m_pConvArgs.get(), SvxSpellArea::Body );
+ bGoOn = true;
+ }
+ else if ( m_bStartDone && m_bEndDone )
+ {
+ // body region done, ask about special region
+ if( !m_bIsSelection && m_rWrtShell.HasOtherCnt() )
+ {
+ ConvStart_impl( m_pConvArgs.get(), SvxSpellArea::Other );
+ m_bIsOtherContent = bGoOn = true;
+ }
+ }
+ else
+ {
+ m_bStartChk = !m_bStartDone;
+ ConvStart_impl( m_pConvArgs.get(), m_bStartChk ? SvxSpellArea::BodyStart : SvxSpellArea::BodyEnd );
+ bGoOn = true;
+ }
+ return bGoOn;
+}
+
+void SwHHCWrapper::FindConvText_impl()
+{
+ //! modified version of SvxSpellWrapper::FindSpellError
+
+ bool bFound = false;
+
+ weld::WaitObject aWait(GetUIParent());
+ bool bConv = true;
+
+ while ( bConv )
+ {
+ bFound = ConvContinue_impl( m_pConvArgs.get() );
+ if (bFound)
+ {
+ bConv = false;
+ }
+ else
+ {
+ ConvEnd_impl( m_pConvArgs.get() );
+ bConv = ConvNext_impl();
+ }
+ }
+}
+
+void SwHHCWrapper::ConvStart_impl( SwConversionArgs /* [out] */ *pConversionArgs, SvxSpellArea eArea )
+{
+ m_bIsDrawObj = SvxSpellArea::Other == eArea;
+ m_pView->SpellStart( eArea, m_bStartDone, m_bEndDone, /* [out] */ pConversionArgs );
+}
+
+void SwHHCWrapper::ConvEnd_impl( SwConversionArgs const *pConversionArgs )
+{
+ m_pView->SpellEnd( pConversionArgs );
+}
+
+bool SwHHCWrapper::ConvContinue_impl( SwConversionArgs *pConversionArgs )
+{
+ bool bProgress = !m_bIsDrawObj && !m_bIsSelection;
+ pConversionArgs->aConvText.clear();
+ pConversionArgs->nConvTextLang = LANGUAGE_NONE;
+ m_pView->GetWrtShell().SpellContinue( &m_nPageCount, bProgress ? &m_nPageStart : nullptr, pConversionArgs );
+ return !pConversionArgs->aConvText.isEmpty();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/lingu/hyp.cxx b/sw/source/uibase/lingu/hyp.cxx
new file mode 100644
index 0000000000..caf235bf79
--- /dev/null
+++ b/sw/source/uibase/lingu/hyp.cxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <view.hxx>
+#include <edtwin.hxx>
+#include <wrtsh.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <com/sun/star/linguistic2/XLinguProperties.hpp>
+#include <swwait.hxx>
+
+#include <hyp.hxx>
+#include <mdiexp.hxx>
+#include <strings.hrc>
+
+#include <memory>
+
+#define PSH (&m_pView->GetWrtShell())
+
+using namespace ::com::sun::star;
+
+// interactive separation
+SwHyphWrapper::SwHyphWrapper( SwView* pVw,
+ uno::Reference< linguistic2::XHyphenator > const &rxHyph,
+ bool bStart, bool bOther, bool bSelect ) :
+ SvxSpellWrapper( pVw->GetEditWin().GetFrameWeld(), rxHyph, bStart, bOther ),
+ m_pView( pVw ),
+ m_nPageCount( 0 ),
+ m_nPageStart( 0 ),
+ m_bInSelection( bSelect ),
+ m_bInfoBox( false )
+{
+ uno::Reference< linguistic2::XLinguProperties > xProp( GetLinguPropertySet() );
+ m_bAutomatic = xProp.is() && xProp->getIsHyphAuto();
+}
+
+void SwHyphWrapper::SpellStart( SvxSpellArea eSpell )
+{
+ if( SvxSpellArea::Other == eSpell && m_nPageCount )
+ {
+ ::EndProgress( m_pView->GetDocShell() );
+ m_nPageCount = 0;
+ m_nPageStart = 0;
+ }
+ m_pView->HyphStart( eSpell );
+}
+
+void SwHyphWrapper::SpellContinue()
+{
+ // for automatic separation, make actions visible only at the end
+ std::optional<SwWait> oWait;
+ if( m_bAutomatic )
+ {
+ PSH->StartAllAction();
+ oWait.emplace( *m_pView->GetDocShell(), true );
+ }
+
+ uno::Reference< uno::XInterface > xHyphWord = m_bInSelection ?
+ PSH->HyphContinue( nullptr, nullptr ) :
+ PSH->HyphContinue( &m_nPageCount, &m_nPageStart );
+ SetLast( xHyphWord );
+
+ // for automatic separation, make actions visible only at the end
+ if( m_bAutomatic )
+ {
+ PSH->EndAllAction();
+ oWait.reset();
+ }
+}
+
+void SwHyphWrapper::SpellEnd()
+{
+ PSH->HyphEnd();
+ SvxSpellWrapper::SpellEnd();
+}
+
+bool SwHyphWrapper::SpellMore()
+{
+ PSH->Push();
+ m_bInfoBox = true;
+ PSH->Combine();
+ return false;
+}
+
+void SwHyphWrapper::InsertHyphen( const sal_Int32 nPos )
+{
+ if( nPos)
+ SwEditShell::InsertSoftHyph(nPos + 1); // does nPos == 1 really mean
+ // insert hyphen after first char?
+ // (instead of nPos == 0)
+ else
+ PSH->HyphIgnore();
+}
+
+SwHyphWrapper::~SwHyphWrapper()
+{
+ if( m_nPageCount )
+ ::EndProgress( m_pView->GetDocShell() );
+ if( m_bInfoBox && !Application::IsHeadlessModeEnabled() )
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_pView->GetEditWin().GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_HYP_OK)));
+ xInfoBox->run();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/lingu/olmenu.cxx b/sw/source/uibase/lingu/olmenu.cxx
new file mode 100644
index 0000000000..acf06f2e41
--- /dev/null
+++ b/sw/source/uibase/lingu/olmenu.cxx
@@ -0,0 +1,885 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <SwRewriter.hxx>
+#include <cmdid.h>
+#include <strings.hrc>
+#include <doc.hxx>
+#include <edtwin.hxx>
+#include <helpids.h>
+#include <langhelper.hxx>
+#include <bitmaps.hlst>
+#include <olmenu.hxx>
+#include <swmodule.hxx>
+#include <swtypes.hxx>
+#include <swundo.hxx>
+#include <utility>
+#include <view.hxx>
+#include <wrtsh.hxx>
+
+#include <comphelper/lok.hxx>
+#include <comphelper/anytostring.hxx>
+#include <comphelper/processfactory.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <editeng/acorrcfg.hxx>
+#include <editeng/svxacorr.hxx>
+#include <editeng/splwrap.hxx>
+#include <editeng/unolingu.hxx>
+#include <editeng/editview.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <linguistic/misc.hxx>
+#include <rtl/string.hxx>
+#include <vcl/commandinfoprovider.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/itemset.hxx>
+#include <svl/languageoptions.hxx>
+#include <svl/stritem.hxx>
+#include <svl/voiditem.hxx>
+#include <svtools/langtab.hxx>
+#include <unotools/lingucfg.hxx>
+#include <unotools/linguprops.hxx>
+#include <vcl/settings.hxx>
+#include <osl/diagnose.h>
+
+#include <map>
+
+#include <com/sun/star/document/XDocumentLanguages.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/linguistic2/XLanguageGuessing.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/system/SystemShellExecuteFlags.hpp>
+#include <com/sun/star/system/SystemShellExecute.hpp>
+#include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
+
+using namespace ::com::sun::star;
+
+/// @returns : the language for the selected text that is set for the
+/// specified attribute (script type).
+/// If there are more than one languages used LANGUAGE_DONTKNOW will be returned.
+/// @param nLangWhichId : one of
+/// RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE,
+/// @returns: the language in use for the selected text.
+/// 'In use' means the language(s) matching the script type(s) of the
+/// selected text. Or in other words, the language a spell checker would use.
+/// If there is more than one language LANGUAGE_DONTKNOW will be returned.
+// check if nScriptType includes the script type associated to nLang
+static bool lcl_checkScriptType( SvtScriptType nScriptType, LanguageType nLang )
+{
+ return bool(nScriptType & SvtLanguageOptions::GetScriptTypeOfLanguage( nLang ));
+}
+
+void SwSpellPopup::fillLangPopupMenu(
+ PopupMenu *pPopupMenu,
+ sal_uInt16 nLangItemIdStart,
+ const uno::Sequence< OUString >& aSeq,
+ SwWrtShell* pWrtSh,
+ std::map< sal_Int16, OUString > &rLangTable )
+{
+ if (!pPopupMenu)
+ return;
+
+ // set of languages to be displayed in the sub menus
+ std::set< OUString > aLangItems;
+
+ OUString aCurLang( aSeq[0] );
+ SvtScriptType nScriptType = static_cast<SvtScriptType>(aSeq[1].toInt32());
+ OUString aKeyboardLang( aSeq[2] );
+ OUString aGuessedTextLang( aSeq[3] );
+
+ if (!aCurLang.isEmpty() &&
+ LANGUAGE_DONTKNOW != SvtLanguageTable::GetLanguageType( aCurLang ))
+ aLangItems.insert( aCurLang );
+
+ //2--System
+ const AllSettings& rAllSettings = Application::GetSettings();
+ LanguageType rSystemLanguage = rAllSettings.GetLanguageTag().getLanguageType();
+ if (rSystemLanguage != LANGUAGE_DONTKNOW)
+ {
+ if (lcl_checkScriptType( nScriptType, rSystemLanguage ))
+ aLangItems.insert( SvtLanguageTable::GetLanguageString(rSystemLanguage) );
+ }
+
+ //3--UI
+ LanguageType rUILanguage = rAllSettings.GetUILanguageTag().getLanguageType();
+ if (rUILanguage != LANGUAGE_DONTKNOW)
+ {
+ if (lcl_checkScriptType(nScriptType, rUILanguage ))
+ aLangItems.insert( SvtLanguageTable::GetLanguageString(rUILanguage) );
+ }
+
+ //4--guessed language
+ if (!aGuessedTextLang.isEmpty())
+ {
+ if (lcl_checkScriptType(nScriptType, SvtLanguageTable::GetLanguageType(aGuessedTextLang)))
+ aLangItems.insert( aGuessedTextLang );
+ }
+
+ //5--keyboard language
+ if (!aKeyboardLang.isEmpty())
+ {
+ if (lcl_checkScriptType(nScriptType, SvtLanguageTable::GetLanguageType(aKeyboardLang)))
+ aLangItems.insert( aKeyboardLang );
+ }
+
+ //6--all languages used in current document
+ uno::Reference< css::frame::XModel > xModel;
+ uno::Reference< css::frame::XController > xController = pWrtSh->GetView().GetViewFrame().GetFrame().GetFrameInterface()->getController();
+ if ( xController.is() )
+ xModel = xController->getModel();
+ uno::Reference< document::XDocumentLanguages > xDocumentLanguages( xModel, uno::UNO_QUERY );
+ /*the description of nScriptType flags
+ LATIN : 0x0001
+ ASIAN : 0x0002
+ COMPLEX: 0x0004
+ */
+ const sal_Int16 nMaxCount = 7;
+ if (xDocumentLanguages.is())
+ {
+ const uno::Sequence< lang::Locale > rLocales( xDocumentLanguages->getDocumentLanguages( static_cast<sal_Int16>(nScriptType), nMaxCount ) );
+ for (const lang::Locale& rLocale : rLocales)
+ {
+ if (aLangItems.size() == size_t(nMaxCount))
+ break;
+ if (lcl_checkScriptType( nScriptType, SvtLanguageTable::GetLanguageType( rLocale.Language )))
+ aLangItems.insert( rLocale.Language );
+ }
+ }
+
+ sal_uInt16 nItemId = nLangItemIdStart;
+ for (const OUString& aEntryText : aLangItems)
+ {
+ if (aEntryText != SvtLanguageTable::GetLanguageString( LANGUAGE_NONE ) &&
+ aEntryText != "*" && // multiple languages in current selection
+ !aEntryText.isEmpty()) // 'no language found' from language guessing
+ {
+ OSL_ENSURE( nLangItemIdStart <= nItemId && nItemId <= nLangItemIdStart + MN_MAX_NUM_LANG,
+ "nItemId outside of expected range!" );
+ pPopupMenu->InsertItem( nItemId, aEntryText, MenuItemBits::RADIOCHECK );
+ if (aEntryText == aCurLang)
+ {
+ //make a check mark for the current language
+ pPopupMenu->CheckItem( nItemId );
+ }
+ rLangTable[ nItemId ] = aEntryText;
+ ++nItemId;
+ }
+ }
+
+ pPopupMenu->InsertItem( nLangItemIdStart + MN_NONE_OFFSET, SwResId( STR_LANGSTATUS_NONE ), MenuItemBits::RADIOCHECK );
+ if ( SvtLanguageTable::GetLanguageString( LANGUAGE_NONE ) == aCurLang )
+ pPopupMenu->CheckItem( nLangItemIdStart + MN_NONE_OFFSET );
+
+ pPopupMenu->InsertItem( nLangItemIdStart + MN_RESET_OFFSET, SwResId( STR_RESET_TO_DEFAULT_LANGUAGE ) );
+ pPopupMenu->InsertItem( nLangItemIdStart + MN_MORE_OFFSET, SwResId( STR_LANGSTATUS_MORE ) );
+}
+
+SwSpellPopup::SwSpellPopup(
+ SwWrtShell* pWrtSh,
+ uno::Reference< linguistic2::XSpellAlternatives > xAlt,
+ const OUString &rParaText)
+ : m_aBuilder(nullptr, AllSettings::GetUIRootDir(), "modules/swriter/ui/spellmenu.ui", "")
+ , m_xPopupMenu(m_aBuilder.get_menu(u"menu"))
+ , m_nIgnoreWordId(m_xPopupMenu->GetItemId(u"ignoreall"))
+ , m_nAddMenuId(m_xPopupMenu->GetItemId(u"addmenu"))
+ , m_nAddId(m_xPopupMenu->GetItemId(u"add"))
+ , m_nSpellDialogId(m_xPopupMenu->GetItemId(u"spelldialog"))
+ , m_nCorrectMenuId(m_xPopupMenu->GetItemId(u"correctmenu"))
+ , m_nCorrectDialogId(m_xPopupMenu->GetItemId(u"correctdialog"))
+ , m_nLangSelectionMenuId(m_xPopupMenu->GetItemId(u"langselection"))
+ , m_nLangParaMenuId(m_xPopupMenu->GetItemId(u"langpara"))
+ , m_nRedlineAcceptId(m_xPopupMenu->GetItemId(u"accept"))
+ , m_nRedlineRejectId(m_xPopupMenu->GetItemId(u"reject"))
+ , m_nRedlineNextId(m_xPopupMenu->GetItemId(u"next"))
+ , m_nRedlinePrevId(m_xPopupMenu->GetItemId(u"prev"))
+ , m_pSh( pWrtSh )
+ , m_xSpellAlt(std::move(xAlt))
+ , m_bGrammarResults(false)
+{
+ OSL_ENSURE(m_xSpellAlt.is(), "no spelling alternatives available");
+
+ m_xPopupMenu->SetMenuFlags(MenuFlags::NoAutoMnemonics);
+ bool bUseImagesInMenus = Application::GetSettings().GetStyleSettings().GetUseImagesInMenus();
+
+ m_nCheckedLanguage = LANGUAGE_NONE;
+ css::uno::Sequence< OUString > aSuggestions;
+ if (m_xSpellAlt.is())
+ {
+ m_nCheckedLanguage = LanguageTag( m_xSpellAlt->getLocale() ).getLanguageType();
+ aSuggestions = m_xSpellAlt->getAlternatives();
+ }
+ sal_Int16 nStringCount = static_cast< sal_Int16 >( aSuggestions.getLength() );
+
+ SvtLinguConfig aCfg;
+
+ PopupMenu *pMenu = m_xPopupMenu->GetPopupMenu(m_nCorrectMenuId);
+ pMenu->SetMenuFlags(MenuFlags::NoAutoMnemonics);
+ bool bEnable = false;
+ if( nStringCount )
+ {
+ Image aImage;
+ OUString aSuggestionImageUrl;
+
+ if (bUseImagesInMenus)
+ {
+ uno::Reference< container::XNamed > xNamed( m_xSpellAlt, uno::UNO_QUERY );
+ if (xNamed.is())
+ {
+ aSuggestionImageUrl = aCfg.GetSpellAndGrammarContextSuggestionImage( xNamed->getName() );
+ aImage = Image( aSuggestionImageUrl );
+ }
+ }
+
+ m_xPopupMenu->InsertSeparator({}, 0);
+ bEnable = true;
+ sal_uInt16 nAutoCorrItemId = MN_AUTOCORR_START;
+ sal_uInt16 nItemId = MN_SUGGESTION_START;
+ for (sal_uInt16 i = 0; i < nStringCount; ++i)
+ {
+ const OUString aEntry = aSuggestions[ i ];
+ m_xPopupMenu->InsertItem(nItemId, aEntry, MenuItemBits::NONE, {}, i);
+ m_xPopupMenu->SetHelpId(nItemId, HID_LINGU_REPLACE);
+ if (!aSuggestionImageUrl.isEmpty())
+ m_xPopupMenu->SetItemImage(nItemId, aImage);
+
+ pMenu->InsertItem( nAutoCorrItemId, aEntry );
+ pMenu->SetHelpId( nAutoCorrItemId, HID_LINGU_AUTOCORR);
+
+ ++nAutoCorrItemId;
+ ++nItemId;
+ }
+ }
+
+ uno::Reference< frame::XFrame > xFrame = pWrtSh->GetView().GetViewFrame().GetFrame().GetFrameInterface();
+ OUString aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(xFrame));
+
+ {
+ auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(".uno:SpellingAndGrammarDialog", aModuleName);
+ m_xPopupMenu->SetItemText(m_nSpellDialogId,
+ vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties));
+ }
+ {
+ auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(".uno:AutoCorrectDlg", aModuleName);
+ m_xPopupMenu->SetItemText(m_nCorrectDialogId,
+ vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties));
+ }
+
+ sal_uInt16 nItemPos = m_xPopupMenu->GetItemPos(m_nIgnoreWordId);
+ OUString aIgnoreSelection( SwResId( STR_IGNORE_SELECTION ) );
+ m_xPopupMenu->InsertItem(MN_IGNORE_SELECTION, aIgnoreSelection, MenuItemBits::NONE, {}, nItemPos);
+ m_xPopupMenu->SetHelpId(MN_IGNORE_SELECTION, HID_LINGU_IGNORE_SELECTION);
+
+ m_xPopupMenu->EnableItem(m_nCorrectMenuId, bEnable);
+
+ uno::Reference< linguistic2::XLanguageGuessing > xLG = SW_MOD()->GetLanguageGuesser();
+ LanguageType nGuessLangWord = LANGUAGE_NONE;
+ LanguageType nGuessLangPara = LANGUAGE_NONE;
+ if (m_xSpellAlt.is() && xLG.is())
+ {
+ nGuessLangWord = EditView::CheckLanguage( m_xSpellAlt->getWord(), ::GetSpellChecker(), xLG, false );
+ nGuessLangPara = EditView::CheckLanguage( rParaText, ::GetSpellChecker(), xLG, true );
+ }
+ if (nGuessLangWord != LANGUAGE_NONE || nGuessLangPara != LANGUAGE_NONE)
+ {
+ // make sure LANGUAGE_NONE gets not used as menu entry
+ if (nGuessLangWord == LANGUAGE_NONE)
+ nGuessLangWord = nGuessLangPara;
+ if (nGuessLangPara == LANGUAGE_NONE)
+ nGuessLangPara = nGuessLangWord;
+ }
+
+ pMenu = m_xPopupMenu->GetPopupMenu(m_nAddMenuId);
+ pMenu->SetMenuFlags(MenuFlags::NoAutoMnemonics); //! necessary to retrieve the correct dictionary name in 'Execute' below
+ uno::Reference< linguistic2::XSearchableDictionaryList > xDicList( LinguMgr::GetDictionaryList() );
+ sal_uInt16 nItemId = MN_DICTIONARIES_START;
+ if (xDicList.is())
+ {
+ // add the default positive dictionary to dic-list (if not already done).
+ // This is to ensure that there is at least one dictionary to which
+ // words could be added.
+ uno::Reference< linguistic2::XDictionary > xDic( LinguMgr::GetStandardDic() );
+ if (xDic.is())
+ xDic->setActive( true );
+
+ m_aDics = xDicList->getDictionaries();
+
+ for( const uno::Reference< linguistic2::XDictionary >& rDic : std::as_const(m_aDics) )
+ {
+ uno::Reference< linguistic2::XDictionary > xDicTmp = rDic;
+ if (!xDicTmp.is() || LinguMgr::GetIgnoreAllList() == xDicTmp)
+ continue;
+
+ uno::Reference< frame::XStorable > xStor( xDicTmp, uno::UNO_QUERY );
+ LanguageType nActLanguage = LanguageTag( xDicTmp->getLocale() ).getLanguageType();
+ if( xDicTmp->isActive()
+ && xDicTmp->getDictionaryType() != linguistic2::DictionaryType_NEGATIVE
+ && (m_nCheckedLanguage == nActLanguage || LANGUAGE_NONE == nActLanguage )
+ && (!xStor.is() || !xStor->isReadonly()) )
+ {
+ // the extra 1 is because of the (possible) external
+ // linguistic entry above
+ pMenu->InsertItem( nItemId, xDicTmp->getName() );
+ m_aDicNameSingle = xDicTmp->getName();
+
+ if (bUseImagesInMenus)
+ {
+ uno::Reference< lang::XServiceInfo > xSvcInfo( xDicTmp, uno::UNO_QUERY );
+ if (xSvcInfo.is())
+ {
+ OUString aDictionaryImageUrl( aCfg.GetSpellAndGrammarContextDictionaryImage(
+ xSvcInfo->getImplementationName() ) );
+ if (!aDictionaryImageUrl.isEmpty())
+ {
+ Image aImage( aDictionaryImageUrl );
+ pMenu->SetItemImage( nItemId, aImage );
+ }
+ }
+ }
+
+ ++nItemId;
+ }
+ }
+ }
+ m_xPopupMenu->EnableItem(m_nAddMenuId, (nItemId - MN_DICTIONARIES_START) > 1);
+ m_xPopupMenu->EnableItem(m_nAddId, (nItemId - MN_DICTIONARIES_START) == 1);
+
+ //ADD NEW LANGUAGE MENU ITEM
+
+ OUString aScriptTypesInUse( OUString::number( static_cast<int>(pWrtSh->GetScriptType()) ) );
+
+ // get keyboard language
+ OUString aKeyboardLang;
+ SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin();
+ LanguageType nLang = rEditWin.GetInputLanguage();
+ if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
+ aKeyboardLang = SvtLanguageTable::GetLanguageString( nLang );
+
+ // get the language that is in use
+ OUString aCurrentLang("*");
+ nLang = SwLangHelper::GetCurrentLanguage( *pWrtSh );
+ if (nLang != LANGUAGE_DONTKNOW)
+ aCurrentLang = SvtLanguageTable::GetLanguageString( nLang );
+
+ // build sequence for status value
+ uno::Sequence< OUString > aSeq{ aCurrentLang,
+ aScriptTypesInUse,
+ aKeyboardLang,
+ SvtLanguageTable::GetLanguageString(nGuessLangWord) };
+
+ pMenu = m_xPopupMenu->GetPopupMenu(m_nLangSelectionMenuId);
+ fillLangPopupMenu( pMenu, MN_SET_LANGUAGE_SELECTION_START, aSeq, pWrtSh, m_aLangTable_Text );
+ m_xPopupMenu->EnableItem(m_nLangSelectionMenuId);
+
+ pMenu = m_xPopupMenu->GetPopupMenu(m_nLangParaMenuId);
+ fillLangPopupMenu( pMenu, MN_SET_LANGUAGE_PARAGRAPH_START, aSeq, pWrtSh, m_aLangTable_Paragraph );
+ m_xPopupMenu->EnableItem(m_nLangParaMenuId);
+
+ if (bUseImagesInMenus)
+ m_xPopupMenu->SetItemImage(m_nSpellDialogId,
+ vcl::CommandInfoProvider::GetImageForCommand(".uno:SpellingAndGrammarDialog", xFrame));
+
+ checkRedline();
+ m_xPopupMenu->RemoveDisabledEntries( true );
+
+ InitItemCommands(aSuggestions);
+}
+
+SwSpellPopup::SwSpellPopup(
+ SwWrtShell *pWrtSh,
+ const linguistic2::ProofreadingResult &rResult,
+ sal_Int32 nErrorInResult,
+ const uno::Sequence< OUString > &rSuggestions,
+ const OUString &rParaText )
+ : m_aBuilder(nullptr, AllSettings::GetUIRootDir(), "modules/swriter/ui/spellmenu.ui", "")
+ , m_xPopupMenu(m_aBuilder.get_menu(u"menu"))
+ , m_nIgnoreWordId(m_xPopupMenu->GetItemId(u"ignoreall"))
+ , m_nAddMenuId(m_xPopupMenu->GetItemId(u"addmenu"))
+ , m_nAddId(m_xPopupMenu->GetItemId(u"add"))
+ , m_nSpellDialogId(m_xPopupMenu->GetItemId(u"spelldialog"))
+ , m_nCorrectMenuId(m_xPopupMenu->GetItemId(u"correctmenu"))
+ , m_nCorrectDialogId(m_xPopupMenu->GetItemId(u"correctdialog"))
+ , m_nLangSelectionMenuId(m_xPopupMenu->GetItemId(u"langselection"))
+ , m_nLangParaMenuId(m_xPopupMenu->GetItemId(u"langpara"))
+ , m_nRedlineAcceptId(m_xPopupMenu->GetItemId(u"accept"))
+ , m_nRedlineRejectId(m_xPopupMenu->GetItemId(u"reject"))
+ , m_nRedlineNextId(m_xPopupMenu->GetItemId(u"next"))
+ , m_nRedlinePrevId(m_xPopupMenu->GetItemId(u"prev"))
+ , m_pSh(pWrtSh)
+ , m_bGrammarResults(true)
+{
+ m_nCheckedLanguage = LanguageTag::convertToLanguageType( rResult.aLocale );
+ bool bUseImagesInMenus = Application::GetSettings().GetStyleSettings().GetUseImagesInMenus();
+
+ sal_uInt16 nPos = 0;
+ OUString aMessageText( rResult.aErrors[ nErrorInResult ].aShortComment );
+ m_xPopupMenu->InsertSeparator({}, nPos++);
+ m_xPopupMenu->InsertItem(MN_SHORT_COMMENT, aMessageText, MenuItemBits::NOSELECT, {}, nPos++);
+ if (bUseImagesInMenus)
+ m_xPopupMenu->SetItemImage(MN_SHORT_COMMENT, Image(StockImage::Yes, BMP_INFO_16));
+
+ // Add an item to show detailed infos if the FullCommentURL property is defined
+ const beans::PropertyValues aProperties = rResult.aErrors[ nErrorInResult ].aProperties;
+ for ( const auto& rProp : aProperties )
+ {
+ if ( rProp.Name == "FullCommentURL" )
+ {
+ uno::Any aValue = rProp.Value;
+ aValue >>= m_sExplanationLink;
+
+ if ( !m_sExplanationLink.isEmpty( ) )
+ break;
+ }
+ }
+
+ if ( !m_sExplanationLink.isEmpty( ) )
+ {
+ m_xPopupMenu->InsertItem(MN_EXPLANATION_LINK, SwResId(STR_EXPLANATION_LINK), MenuItemBits::TEXT | MenuItemBits::HELP, {}, nPos++);
+ }
+
+ m_xPopupMenu->SetMenuFlags(MenuFlags::NoAutoMnemonics);
+
+ m_xPopupMenu->InsertSeparator({}, nPos++);
+ if ( rSuggestions.hasElements() ) // suggestions available...
+ {
+ Image aImage;
+ OUString aSuggestionImageUrl;
+
+ if (bUseImagesInMenus)
+ {
+ uno::Reference< lang::XServiceInfo > xInfo( rResult.xProofreader, uno::UNO_QUERY );
+ if (xInfo.is())
+ {
+ aSuggestionImageUrl = SvtLinguConfig().GetSpellAndGrammarContextSuggestionImage( xInfo->getImplementationName() );
+ aImage = Image( aSuggestionImageUrl );
+ }
+ }
+
+ sal_uInt16 nItemId = MN_SUGGESTION_START;
+ for (const OUString& aEntry : std::as_const(rSuggestions))
+ {
+ m_xPopupMenu->InsertItem(nItemId, aEntry, MenuItemBits::NONE, {}, nPos++);
+ m_xPopupMenu->SetHelpId(nItemId, HID_LINGU_REPLACE);
+ if (!aSuggestionImageUrl.isEmpty())
+ m_xPopupMenu->SetItemImage(nItemId, aImage);
+
+ ++nItemId;
+ }
+ m_xPopupMenu->InsertSeparator({}, nPos++);
+ }
+
+ uno::Reference< frame::XFrame > xFrame = pWrtSh->GetView().GetViewFrame().GetFrame().GetFrameInterface();
+ OUString aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(xFrame));
+
+ OUString aIgnoreSelection( SwResId( STR_IGNORE_SELECTION ) );
+ auto aCommandProperties = vcl::CommandInfoProvider::GetCommandProperties(".uno:SpellingAndGrammarDialog", aModuleName);
+ m_xPopupMenu->SetItemText(m_nSpellDialogId,
+ vcl::CommandInfoProvider::GetPopupLabelForCommand(aCommandProperties));
+ sal_uInt16 nItemPos = m_xPopupMenu->GetItemPos(m_nIgnoreWordId);
+ m_xPopupMenu->InsertItem(MN_IGNORE_SELECTION, aIgnoreSelection, MenuItemBits::NONE, {}, nItemPos);
+ m_xPopupMenu->SetHelpId(MN_IGNORE_SELECTION, HID_LINGU_IGNORE_SELECTION);
+
+ m_xPopupMenu->EnableItem(m_nCorrectMenuId, false);
+ m_xPopupMenu->EnableItem(m_nCorrectDialogId, false);
+
+ uno::Reference< linguistic2::XLanguageGuessing > xLG = SW_MOD()->GetLanguageGuesser();
+ LanguageType nGuessLangWord = LANGUAGE_NONE;
+ LanguageType nGuessLangPara = LANGUAGE_NONE;
+ if (xLG.is())
+ {
+ nGuessLangPara = EditView::CheckLanguage( rParaText, ::GetSpellChecker(), xLG, true );
+ }
+ if (nGuessLangWord != LANGUAGE_NONE || nGuessLangPara != LANGUAGE_NONE)
+ {
+ // make sure LANGUAGE_NONE gets not used as menu entry
+ if (nGuessLangWord == LANGUAGE_NONE)
+ nGuessLangWord = nGuessLangPara;
+ if (nGuessLangPara == LANGUAGE_NONE)
+ nGuessLangPara = nGuessLangWord;
+ }
+
+ m_xPopupMenu->EnableItem(m_nAddMenuId, false);
+ m_xPopupMenu->EnableItem(m_nAddId, false);
+
+ //ADD NEW LANGUAGE MENU ITEM
+
+ OUString aScriptTypesInUse( OUString::number( static_cast<int>(pWrtSh->GetScriptType()) ) );
+
+ // get keyboard language
+ OUString aKeyboardLang;
+ SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin();
+ LanguageType nLang = rEditWin.GetInputLanguage();
+ if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
+ aKeyboardLang = SvtLanguageTable::GetLanguageString( nLang );
+
+ // get the language that is in use
+ OUString aCurrentLang("*");
+ nLang = SwLangHelper::GetCurrentLanguage( *pWrtSh );
+ if (nLang != LANGUAGE_DONTKNOW)
+ aCurrentLang = SvtLanguageTable::GetLanguageString( nLang );
+
+ // build sequence for status value
+ uno::Sequence< OUString > aSeq{ aCurrentLang,
+ aScriptTypesInUse,
+ aKeyboardLang,
+ SvtLanguageTable::GetLanguageString(nGuessLangWord) };
+
+ PopupMenu *pMenu = m_xPopupMenu->GetPopupMenu(m_nLangSelectionMenuId);
+ fillLangPopupMenu( pMenu, MN_SET_LANGUAGE_SELECTION_START, aSeq, pWrtSh, m_aLangTable_Text );
+ m_xPopupMenu->EnableItem(m_nLangSelectionMenuId);
+
+ pMenu = m_xPopupMenu->GetPopupMenu(m_nLangParaMenuId);
+ fillLangPopupMenu( pMenu, MN_SET_LANGUAGE_PARAGRAPH_START, aSeq, pWrtSh, m_aLangTable_Paragraph );
+ m_xPopupMenu->EnableItem(m_nLangParaMenuId);
+
+ if (bUseImagesInMenus)
+ m_xPopupMenu->SetItemImage(m_nSpellDialogId,
+ vcl::CommandInfoProvider::GetImageForCommand(".uno:SpellingAndGrammarDialog", xFrame));
+
+ checkRedline();
+ m_xPopupMenu->RemoveDisabledEntries(true);
+
+ SvtLinguConfig().SetProperty( UPN_IS_GRAMMAR_INTERACTIVE, uno::Any( true ));
+
+ InitItemCommands(rSuggestions);
+}
+
+SwSpellPopup::~SwSpellPopup() {}
+
+void SwSpellPopup::InitItemCommands(const css::uno::Sequence< OUString >& aSuggestions)
+{
+ if (!comphelper::LibreOfficeKit::isActive())
+ return;
+
+ // None is added only for LOK, it means there is no need to execute anything
+ m_xPopupMenu->SetItemCommand(MN_SHORT_COMMENT, ".uno:None");
+ m_xPopupMenu->SetItemCommand(m_nSpellDialogId, ".uno:SpellingAndGrammarDialog");
+ if(m_bGrammarResults)
+ m_xPopupMenu->SetItemCommand(m_nIgnoreWordId, ".uno:SpellCheckIgnoreAll?Type:string=Grammar");
+ else
+ m_xPopupMenu->SetItemCommand(m_nIgnoreWordId, ".uno:SpellCheckIgnoreAll?Type:string=Spelling");
+ if(m_bGrammarResults)
+ m_xPopupMenu->SetItemCommand(MN_IGNORE_SELECTION, ".uno:SpellCheckIgnore?Type:string=Grammar");
+ else
+ m_xPopupMenu->SetItemCommand(MN_IGNORE_SELECTION, ".uno:SpellCheckIgnore?Type:string=Spelling");
+
+ for(int i = 0; i < aSuggestions.getLength(); ++i)
+ {
+ sal_uInt16 nItemId = MN_SUGGESTION_START + i;
+ OUString sCommandString = ".uno:SpellCheckApplySuggestion?ApplyRule:string=";
+ if(m_bGrammarResults)
+ sCommandString += "Grammar_";
+ else if (m_xSpellAlt.is())
+ sCommandString += "Spelling_";
+ sCommandString += m_xPopupMenu->GetItemText(nItemId);
+ m_xPopupMenu->SetItemCommand(nItemId, sCommandString);
+ }
+
+ PopupMenu *pMenu = m_xPopupMenu->GetPopupMenu(m_nLangSelectionMenuId);
+ m_xPopupMenu->SetItemCommand(m_nLangSelectionMenuId, ".uno:SetSelectionLanguageMenu");
+ if(pMenu)
+ {
+ for (const auto& item : m_aLangTable_Text)
+ {
+ OUString sCommandString = ".uno:LanguageStatus?Language:string=Current_" + item.second;
+ pMenu->SetItemCommand(item.first, sCommandString);
+ }
+
+ pMenu->SetItemCommand(MN_SET_SELECTION_NONE, ".uno:LanguageStatus?Language:string=Current_LANGUAGE_NONE");
+ pMenu->SetItemCommand(MN_SET_SELECTION_RESET, ".uno:LanguageStatus?Language:string=Current_RESET_LANGUAGES");
+ pMenu->SetItemCommand(MN_SET_SELECTION_MORE, ".uno:FontDialog?Page:string=font");
+ }
+
+ pMenu = m_xPopupMenu->GetPopupMenu(m_nLangParaMenuId);
+ m_xPopupMenu->SetItemCommand(m_nLangParaMenuId, ".uno:SetParagraphLanguageMenu");
+ if(pMenu)
+ {
+ for (const auto& item : m_aLangTable_Paragraph)
+ {
+ OUString sCommandString = ".uno:LanguageStatus?Language:string=Paragraph_" + item.second;
+ pMenu->SetItemCommand(item.first, sCommandString);
+ }
+
+ pMenu->SetItemCommand(MN_SET_PARA_NONE, ".uno:LanguageStatus?Language:string=Paragraph_LANGUAGE_NONE");
+ pMenu->SetItemCommand(MN_SET_PARA_RESET, ".uno:LanguageStatus?Language:string=Paragraph_RESET_LANGUAGES");
+ pMenu->SetItemCommand(MN_SET_PARA_MORE, ".uno:FontDialogForParagraph");
+ }
+}
+
+void SwSpellPopup::checkRedline()
+{
+ // Let SwView::GetState() already has the logic on when to disable the
+ // accept/reject and the next/prev change items, let it do the decision.
+
+ // Build an item set that contains a void item for each menu entry. The
+ // WhichId of each item is set, so SwView may clear it.
+ static const sal_uInt16 pRedlineIds[] = {
+ FN_REDLINE_ACCEPT_DIRECT,
+ FN_REDLINE_REJECT_DIRECT,
+ FN_REDLINE_NEXT_CHANGE,
+ FN_REDLINE_PREV_CHANGE
+ };
+ SwDoc *pDoc = m_pSh->GetDoc();
+ SfxItemSetFixed<FN_REDLINE_ACCEPT_DIRECT, FN_REDLINE_PREV_CHANGE> aSet(pDoc->GetAttrPool());
+ for (sal_uInt16 nWhich : pRedlineIds)
+ {
+ aSet.Put(SfxVoidItem(nWhich));
+ }
+ m_pSh->GetView().GetState(aSet);
+
+ // Enable/disable items based on if the which id of the void items are
+ // cleared or not.
+ for (sal_uInt16 nWhich : pRedlineIds)
+ {
+ sal_uInt16 nId(0);
+ if (nWhich == FN_REDLINE_ACCEPT_DIRECT)
+ nId = m_nRedlineAcceptId;
+ else if (nWhich == FN_REDLINE_REJECT_DIRECT)
+ nId = m_nRedlineRejectId;
+ else if (nWhich == FN_REDLINE_NEXT_CHANGE)
+ nId = m_nRedlineNextId;
+ else if (nWhich == FN_REDLINE_PREV_CHANGE)
+ nId = m_nRedlinePrevId;
+ m_xPopupMenu->EnableItem(nId, aSet.Get(nWhich).Which() != 0);
+ }
+}
+
+void SwSpellPopup::Execute( const tools::Rectangle& rWordPos, vcl::Window* pWin )
+{
+ sal_uInt16 nRet = m_xPopupMenu->Execute(pWin, pWin->LogicToPixel(rWordPos));
+ Execute( nRet );
+}
+
+void SwSpellPopup::Execute( sal_uInt16 nId )
+{
+ if (nId == USHRT_MAX)
+ return;
+
+ if (/*m_bGrammarResults && */nId == MN_SHORT_COMMENT)
+ return; // nothing to do since it is the error message (short comment)
+
+ if (MN_SUGGESTION_START <= nId && nId <= MN_SUGGESTION_END)
+ {
+ OUString sApplyRule("");
+ if(m_bGrammarResults)
+ sApplyRule += "Grammar_";
+ else if (m_xSpellAlt.is())
+ sApplyRule += "Spelling_";
+ sApplyRule += m_xPopupMenu->GetItemText(nId);
+
+ SfxStringItem aApplyItem(FN_PARAM_1, sApplyRule);
+ m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_SPELLCHECK_APPLY_SUGGESTION, SfxCallMode::SYNCHRON, { &aApplyItem });
+ }
+ else if(MN_AUTOCORR_START <= nId && nId <= MN_AUTOCORR_END)
+ {
+ if (m_xSpellAlt.is())
+ {
+ bool bOldIns = m_pSh->IsInsMode();
+ m_pSh->SetInsMode();
+
+ PopupMenu* pMenu = m_xPopupMenu->GetPopupMenu(m_nCorrectMenuId);
+ assert(pMenu);
+ OUString aTmp( pMenu->GetItemText(nId) );
+ OUString aOrig( m_xSpellAlt->getWord() );
+
+ // if original word has a trailing . (likely the end of a sentence)
+ // and the replacement text hasn't, then add it to the replacement
+ if (!aTmp.isEmpty() && !aOrig.isEmpty() &&
+ aOrig.endsWith(".") && /* !IsAlphaNumeric ??*/
+ !aTmp.endsWith("."))
+ {
+ aTmp += ".";
+ }
+
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UndoArg1, m_pSh->GetCursorDescr());
+ aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
+
+ OUString aTmpStr = SwResId(STR_START_QUOTE) +
+ aTmp + SwResId(STR_END_QUOTE);
+ aRewriter.AddRule(UndoArg3, aTmpStr);
+
+ m_pSh->StartUndo(SwUndoId::UI_REPLACE, &aRewriter);
+ m_pSh->StartAction();
+
+ m_pSh->Replace(aTmp, false);
+
+ /* #102505# EndAction/EndUndo moved down since insertion
+ of temporary auto correction is now undoable two and
+ must reside in the same undo group.*/
+
+ // record only if it's NOT already present in autocorrection
+ SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get().GetAutoCorrect();
+
+ OUString aOrigWord( m_xSpellAlt->getWord() ) ;
+ OUString aNewWord( pMenu->GetItemText(nId) );
+ SvxPrepareAutoCorrect( aOrigWord, aNewWord );
+
+ pACorr->PutText( aOrigWord, aNewWord, m_nCheckedLanguage );
+
+ /* #102505# EndAction/EndUndo moved down since insertion
+ of temporary auto correction is now undoable two and
+ must reside in the same undo group.*/
+ m_pSh->EndAction();
+ m_pSh->EndUndo();
+
+ m_pSh->SetInsMode( bOldIns );
+ }
+ }
+ else if (nId == m_nSpellDialogId)
+ {
+ m_pSh->Left(SwCursorSkipMode::Chars, false, 1, false );
+ {
+ m_pSh->GetView().GetViewFrame().GetDispatcher()->
+ Execute( FN_SPELL_GRAMMAR_DIALOG, SfxCallMode::ASYNCHRON );
+ }
+ }
+ else if (nId == m_nCorrectDialogId)
+ {
+ m_pSh->GetView().GetViewFrame().GetDispatcher()->Execute( SID_AUTO_CORRECT_DLG, SfxCallMode::ASYNCHRON );
+ }
+ else if (nId == MN_IGNORE_SELECTION)
+ {
+ SfxStringItem aIgnoreString(FN_PARAM_1, m_bGrammarResults ? OUString("Grammar") : OUString("Spelling"));
+ m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_SPELLCHECK_IGNORE, SfxCallMode::SYNCHRON, { &aIgnoreString });
+ }
+ else if (nId == m_nIgnoreWordId)
+ {
+ SfxStringItem aIgnoreString(FN_PARAM_1, m_bGrammarResults ? OUString("Grammar") : OUString("Spelling"));
+ m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_SPELLCHECK_IGNORE_ALL, SfxCallMode::SYNCHRON, { &aIgnoreString });
+ }
+ else if ((MN_DICTIONARIES_START <= nId && nId <= MN_DICTIONARIES_END) || nId == m_nAddId)
+ {
+ OUString sWord( m_xSpellAlt->getWord() );
+ OUString aDicName;
+
+ if (MN_DICTIONARIES_START <= nId && nId <= MN_DICTIONARIES_END)
+ {
+ PopupMenu *pMenu = m_xPopupMenu->GetPopupMenu(m_nAddMenuId);
+ aDicName = pMenu->GetItemText(nId);
+ }
+ else
+ aDicName = m_aDicNameSingle;
+
+ uno::Reference< linguistic2::XDictionary > xDic;
+ uno::Reference< linguistic2::XSearchableDictionaryList > xDicList( LinguMgr::GetDictionaryList() );
+ if (xDicList.is())
+ xDic = xDicList->getDictionaryByName( aDicName );
+
+ if (xDic.is())
+ {
+ linguistic::DictionaryError nAddRes = linguistic::AddEntryToDic(xDic, sWord, false, OUString());
+ // save modified user-dictionary if it is persistent
+ uno::Reference< frame::XStorable > xSavDic( xDic, uno::UNO_QUERY );
+ if (xSavDic.is())
+ xSavDic->store();
+
+ if (linguistic::DictionaryError::NONE != nAddRes && !xDic->getEntry(sWord).is())
+ {
+ SvxDicError(m_pSh->GetView().GetFrameWeld(), nAddRes);
+ }
+ }
+ }
+ else if ( nId == MN_EXPLANATION_LINK && !m_sExplanationLink.isEmpty() )
+ {
+ try
+ {
+ uno::Reference< css::system::XSystemShellExecute > xSystemShellExecute(
+ css::system::SystemShellExecute::create( ::comphelper::getProcessComponentContext() ) );
+ xSystemShellExecute->execute( m_sExplanationLink, OUString(),
+ css::system::SystemShellExecuteFlags::URIS_ONLY );
+ }
+ catch (const uno::Exception&)
+ {
+ uno::Any exc( ::cppu::getCaughtException() );
+ OUString msg( ::comphelper::anyToString( exc ) );
+ const SolarMutexGuard guard;
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_pSh->GetView().GetFrameWeld(),
+ VclMessageType::Warning, VclButtonsType::Ok, msg));
+ xBox->set_title("Explanations");
+ xBox->run();
+ }
+ }
+ else if (nId == m_nRedlineAcceptId || nId == m_nRedlineRejectId
+ || nId == m_nRedlineNextId || nId == m_nRedlinePrevId)
+ {
+ if (nId == m_nRedlineAcceptId)
+ nId = FN_REDLINE_ACCEPT_DIRECT;
+ else if (nId == m_nRedlineRejectId)
+ nId = FN_REDLINE_REJECT_DIRECT;
+ else if (nId == m_nRedlineNextId)
+ nId = FN_REDLINE_NEXT_CHANGE;
+ else if (nId == m_nRedlinePrevId)
+ nId = FN_REDLINE_PREV_CHANGE;
+ // Let SwView::Execute() handle the redline actions.
+ SfxRequest aReq(m_pSh->GetView().GetViewFrame(), nId);
+ m_pSh->GetView().Execute(aReq);
+ }
+ else
+ {
+ if (MN_SET_LANGUAGE_SELECTION_START <= nId && nId <= MN_SET_LANGUAGE_SELECTION_END)
+ {
+ SfxStringItem aLangString(SID_LANGUAGE_STATUS, "Current_" + m_aLangTable_Text[nId]);
+ m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_LANGUAGE_STATUS, SfxCallMode::SYNCHRON, { &aLangString });
+ }
+ else if (nId == MN_SET_SELECTION_NONE)
+ {
+ SfxStringItem aLangString(SID_LANGUAGE_STATUS, "Current_LANGUAGE_NONE");
+ m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_LANGUAGE_STATUS, SfxCallMode::SYNCHRON, { &aLangString });
+ }
+ else if (nId == MN_SET_SELECTION_RESET)
+ {
+ SfxStringItem aLangString(SID_LANGUAGE_STATUS, "Current_RESET_LANGUAGES");
+ m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_LANGUAGE_STATUS, SfxCallMode::SYNCHRON, { &aLangString });
+ }
+ else if (nId == MN_SET_SELECTION_MORE)
+ {
+ SfxStringItem aDlgString(FN_PARAM_1, "font");
+ m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_CHAR_DLG, SfxCallMode::SYNCHRON, { &aDlgString });
+ }
+ else if (MN_SET_LANGUAGE_PARAGRAPH_START <= nId && nId <= MN_SET_LANGUAGE_PARAGRAPH_END)
+ {
+ SfxStringItem aLangString(SID_LANGUAGE_STATUS, "Paragraph_" + m_aLangTable_Paragraph[nId]);
+ m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_LANGUAGE_STATUS, SfxCallMode::SYNCHRON, { &aLangString });
+ }
+ else if (nId == MN_SET_PARA_NONE)
+ {
+ SfxStringItem aLangString(SID_LANGUAGE_STATUS, "Paragraph_LANGUAGE_NONE");
+ m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_LANGUAGE_STATUS, SfxCallMode::SYNCHRON, { &aLangString });
+ }
+ else if (nId == MN_SET_PARA_RESET)
+ {
+ SfxStringItem aLangString(SID_LANGUAGE_STATUS, "Paragraph_RESET_LANGUAGES");
+ m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_LANGUAGE_STATUS, SfxCallMode::SYNCHRON, { &aLangString });
+ }
+ else if (nId == MN_SET_PARA_MORE)
+ {
+ m_pSh->GetView().GetViewFrame().GetDispatcher()->Execute( SID_CHAR_DLG_FOR_PARAGRAPH );
+ }
+ }
+
+ m_pSh->EnterStdMode();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/lingu/sdrhhcwrap.cxx b/sw/source/uibase/lingu/sdrhhcwrap.cxx
new file mode 100644
index 0000000000..6df5911fd2
--- /dev/null
+++ b/sw/source/uibase/lingu/sdrhhcwrap.cxx
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svdotext.hxx>
+#include <svx/svdpagv.hxx>
+#include <sfx2/printer.hxx>
+#include <svx/svdview.hxx>
+#include <osl/diagnose.h>
+#include <drawdoc.hxx>
+#include "sdrhhcwrap.hxx"
+#include <docsh.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <dcontact.hxx>
+#include <doc.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <edtwin.hxx>
+
+using namespace ::com::sun::star;
+
+SdrHHCWrapper::SdrHHCWrapper( SwView* pVw,
+ LanguageType nSourceLanguage, LanguageType nTargetLanguage,
+ const vcl::Font* pTargetFnt,
+ sal_Int32 nConvOptions,
+ bool bInteractive ) :
+ SdrOutliner(pVw->GetDocShell()->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->
+ GetDrawOutliner().GetEmptyItemSet().GetPool(),
+ OutlinerMode::TextObject ),
+ m_pView( pVw ),
+ m_pTextObj( nullptr ),
+ m_nOptions( nConvOptions ),
+ m_nDocIndex( 0 ),
+ m_nSourceLang( nSourceLanguage ),
+ m_nTargetLang( nTargetLanguage ),
+ m_pTargetFont( pTargetFnt ),
+ m_bIsInteractive( bInteractive )
+{
+ SetRefDevice( m_pView->GetDocShell()->GetDoc()->getIDocumentDeviceAccess().getPrinter( false ) );
+
+ MapMode aMapMode (MapUnit::MapTwip);
+ SetRefMapMode(aMapMode);
+
+ Size aSize( 1, 1 );
+ SetPaperSize( aSize );
+
+ m_pOutlView.reset( new OutlinerView( this, &(m_pView->GetEditWin()) ) );
+ m_pOutlView->GetOutliner()->SetRefDevice(m_pView->GetWrtShell().getIDocumentDeviceAccess().getPrinter( false ));
+
+ // Hack: all SdrTextObj attributes should be transferred to EditEngine
+ m_pOutlView->SetBackgroundColor( COL_WHITE );
+
+ InsertView( m_pOutlView.get() );
+ Point aPoint( 0, 0 );
+ tools::Rectangle aRect( aPoint, aSize );
+ m_pOutlView->SetOutputArea( aRect );
+// SetText( NULL );
+ ClearModifyFlag();
+}
+
+SdrHHCWrapper::~SdrHHCWrapper()
+{
+ if (m_pTextObj)
+ {
+ SdrView *pSdrView = m_pView->GetWrtShell().GetDrawView();
+ OSL_ENSURE( pSdrView, "SdrHHCWrapper without DrawView?" );
+ pSdrView->SdrEndTextEdit( true );
+ SetUpdateLayout(false);
+ m_pOutlView->SetOutputArea( tools::Rectangle( Point(), Size(1, 1) ) );
+ }
+ RemoveView( m_pOutlView.get() );
+ m_pOutlView.reset();
+}
+
+void SdrHHCWrapper::StartTextConversion()
+{
+ m_pOutlView->StartTextConversion(m_pView->GetFrameWeld(), m_nSourceLang, m_nTargetLang, m_pTargetFont, m_nOptions, m_bIsInteractive, true);
+}
+
+bool SdrHHCWrapper::ConvertNextDocument()
+{
+ bool bNextDoc = false;
+
+ if ( m_pTextObj )
+ {
+ SdrView *pSdrView = m_pView->GetWrtShell().GetDrawView();
+ OSL_ENSURE( pSdrView, "SdrHHCWrapper without DrawView?" );
+ pSdrView->SdrEndTextEdit( true );
+ SetUpdateLayout(false);
+ m_pOutlView->SetOutputArea( tools::Rectangle( Point(), Size(1, 1) ) );
+ SetPaperSize( Size(1, 1) );
+ Clear();
+ m_pTextObj = nullptr;
+ }
+
+ const auto n = m_nDocIndex;
+
+ std::list<SdrTextObj*> aTextObjs;
+ SwDrawContact::GetTextObjectsFromFormat(aTextObjs, *m_pView->GetDocShell()->GetDoc());
+ for (auto const& textObj : aTextObjs)
+ {
+ m_pTextObj = textObj;
+ if (textObj)
+ {
+ OutlinerParaObject* pParaObj = textObj->GetOutlinerParaObject();
+ if ( pParaObj )
+ {
+ SetPaperSize( textObj->GetLogicRect().GetSize() );
+ SetText( *pParaObj );
+
+ ClearModifyFlag();
+
+ //!! update mode needs to be set to true otherwise
+ //!! the call to 'HasConvertibleTextPortion' will not always
+ //!! work correctly because the document may not be properly
+ //!! formatted when some information is accessed, and thus
+ //!! incorrect results get returned.
+ SetUpdateLayout(true);
+ if (HasConvertibleTextPortion( m_nSourceLang ))
+ {
+ SdrView *pSdrView = m_pView->GetWrtShell().GetDrawView();
+ OSL_ENSURE( pSdrView, "SdrHHCWrapper without DrawView?" );
+ SdrPageView* pPV = pSdrView->GetSdrPageView();
+ m_nDocIndex = n;
+ bNextDoc = true;
+ m_pOutlView->SetOutputArea( tools::Rectangle( Point(), Size(1,1)));
+ SetPaperSize( m_pTextObj->GetLogicRect().GetSize() );
+ SetUpdateLayout(true);
+ m_pView->GetWrtShell().MakeVisible(SwRect(m_pTextObj->GetLogicRect()));
+
+ pSdrView->SdrBeginTextEdit(m_pTextObj, pPV, &m_pView->GetEditWin(), false, this, m_pOutlView.get(), true, true);
+ }
+ else
+ SetUpdateLayout(false);
+ }
+
+ if ( !bNextDoc )
+ m_pTextObj = nullptr;
+ else
+ break;
+ }
+ }
+
+ ClearModifyFlag();
+
+ return bNextDoc;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/lingu/sdrhhcwrap.hxx b/sw/source/uibase/lingu/sdrhhcwrap.hxx
new file mode 100644
index 0000000000..4965bb520e
--- /dev/null
+++ b/sw/source/uibase/lingu/sdrhhcwrap.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <svx/svdoutl.hxx>
+
+class SwView;
+class SdrTextObj;
+class OutlinerView;
+
+class SdrHHCWrapper : public SdrOutliner
+{
+ // modified version of SdrSpeller
+
+ SwView* m_pView;
+ SdrTextObj* m_pTextObj;
+ std::unique_ptr<OutlinerView> m_pOutlView;
+ sal_Int32 m_nOptions;
+ sal_uInt16 m_nDocIndex;
+ LanguageType m_nSourceLang;
+ LanguageType m_nTargetLang;
+ const vcl::Font* m_pTargetFont;
+ bool m_bIsInteractive;
+
+public:
+ SdrHHCWrapper( SwView* pVw,
+ LanguageType nSourceLanguage, LanguageType nTargetLanguage,
+ const vcl::Font* pTargetFnt,
+ sal_Int32 nConvOptions, bool bInteractive );
+
+ virtual ~SdrHHCWrapper() override;
+
+ virtual bool ConvertNextDocument() override;
+ void StartTextConversion();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/misc/glosdoc.cxx b/sw/source/uibase/misc/glosdoc.cxx
new file mode 100644
index 0000000000..7047fb6b6b
--- /dev/null
+++ b/sw/source/uibase/misc/glosdoc.cxx
@@ -0,0 +1,622 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <algorithm>
+#include <string_view>
+
+#include <com/sun/star/container/XNamed.hpp>
+#include <comphelper/servicehelper.hxx>
+
+#include <unotools/transliterationwrapper.hxx>
+
+#include <vcl/errinf.hxx>
+#include <osl/diagnose.h>
+#include <rtl/character.hxx>
+#include <svl/urihelper.hxx>
+#include <svl/fstathelper.hxx>
+#include <unotools/pathoptions.hxx>
+#include <unotools/tempfile.hxx>
+#include <o3tl/string_view.hxx>
+#include <swtypes.hxx>
+#include <glosdoc.hxx>
+#include <shellio.hxx>
+#include <swunohelper.hxx>
+
+#include <unoatxt.hxx>
+#include <swerror.h>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace
+{
+
+OUString lcl_FullPathName(std::u16string_view sPath, std::u16string_view sName)
+{
+ return OUString::Concat(sPath) + "/" + sName + SwGlossaries::GetExtension();
+}
+
+OUString lcl_CheckFileName( const OUString& rNewFilePath,
+ std::u16string_view aNewGroupName )
+{
+ const sal_Int32 nLen = aNewGroupName.size();
+ OUStringBuffer aBuf(nLen);
+ //group name should contain only A-Z and a-z and spaces
+ for( sal_Int32 i=0; i < nLen; ++i )
+ {
+ const sal_Unicode cChar = aNewGroupName[i];
+ if (rtl::isAsciiAlphanumeric(cChar) ||
+ cChar == '_' || cChar == 0x20)
+ {
+ aBuf.append(cChar);
+ }
+ }
+
+ const OUString sRet = aBuf.makeStringAndClear().trim();
+ if ( !sRet.isEmpty() )
+ {
+ if (!FStatHelper::IsDocument( lcl_FullPathName(rNewFilePath, sRet) ))
+ return sRet;
+ }
+
+ //generate generic name
+ utl::TempFileNamed aTemp(u"group", true, SwGlossaries::GetExtension(), &rNewFilePath);
+ aTemp.EnableKillingFile();
+
+ INetURLObject aTempURL( aTemp.GetURL() );
+ return aTempURL.GetBase();
+}
+
+}
+
+// supplies the default group's name
+OUString SwGlossaries::GetDefName()
+{
+ return "standard";
+
+}
+
+// supplies the number of text block groups
+size_t SwGlossaries::GetGroupCnt()
+{
+ return GetNameList().size();
+}
+
+// supplies the group's name
+bool SwGlossaries::FindGroupName(OUString& rGroup)
+{
+ // if the group name doesn't contain a path, a suitable group entry
+ // can the searched for here;
+ const size_t nCount = GetGroupCnt();
+ for(size_t i = 0; i < nCount; ++i)
+ {
+ const OUString sTemp(GetGroupName(i));
+ if (rGroup == o3tl::getToken(sTemp, 0, GLOS_DELIM))
+ {
+ rGroup = sTemp;
+ return true;
+ }
+ }
+ // you can search two times because for more directories the case sensitive
+ // name could occur multiple times
+ const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
+ for(size_t i = 0; i < nCount; ++i)
+ {
+ const OUString sTemp( GetGroupName( i ));
+ sal_uInt16 nPath = o3tl::toUInt32(o3tl::getToken(sTemp, 1, GLOS_DELIM));
+
+ if (!SWUnoHelper::UCB_IsCaseSensitiveFileName( m_PathArr[nPath] )
+ && rSCmp.isEqual( rGroup, sTemp.getToken( 0, GLOS_DELIM) ) )
+ {
+ rGroup = sTemp;
+ return true;
+ }
+ }
+ return false;
+}
+
+OUString const & SwGlossaries::GetGroupName(size_t nGroupId)
+{
+ OSL_ENSURE(nGroupId < m_GlosArr.size(),
+ "SwGlossaries::GetGroupName: index out of bounds");
+ return m_GlosArr[nGroupId];
+}
+
+OUString SwGlossaries::GetGroupTitle( const OUString& rGroupName )
+{
+ OUString sRet;
+ OUString sGroup(rGroupName);
+ if (sGroup.indexOf(GLOS_DELIM)<0)
+ FindGroupName(sGroup);
+ std::unique_ptr<SwTextBlocks> pGroup = GetGroupDoc(sGroup);
+ if(pGroup)
+ {
+ sRet = pGroup->GetName();
+ }
+ return sRet;
+}
+
+// supplies the group rName's text block document
+std::unique_ptr<SwTextBlocks> SwGlossaries::GetGroupDoc(const OUString &rName,
+ bool bCreate)
+{
+ // insert to the list of text blocks if applicable
+ if(bCreate && !m_GlosArr.empty())
+ {
+ if (std::none_of(m_GlosArr.begin(), m_GlosArr.end(),
+ [&rName](const OUString& rEntry) { return rEntry == rName; }))
+ { // block not in the list
+ m_GlosArr.push_back(rName);
+ }
+ }
+ return GetGlosDoc( rName, bCreate );
+}
+
+// Creates a new document with the group name. temporarily also created as file
+// so that groups remain there later (without access).
+bool SwGlossaries::NewGroupDoc(OUString& rGroupName, const OUString& rTitle)
+{
+ const std::u16string_view sNewPath(o3tl::getToken(rGroupName, 1, GLOS_DELIM));
+ sal_uInt16 nNewPath = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(sNewPath));
+ if (static_cast<size_t>(nNewPath) >= m_PathArr.size())
+ return false;
+ const OUString sNewFilePath(m_PathArr[nNewPath]);
+ const OUString sNewGroup = lcl_CheckFileName(sNewFilePath, o3tl::getToken(rGroupName, 0, GLOS_DELIM))
+ + OUStringChar(GLOS_DELIM) + sNewPath;
+ std::unique_ptr<SwTextBlocks> pBlock = GetGlosDoc( sNewGroup );
+ if(pBlock)
+ {
+ GetNameList().push_back(sNewGroup);
+ pBlock->SetName(rTitle);
+ rGroupName = sNewGroup;
+ return true;
+ }
+ return false;
+}
+
+bool SwGlossaries::RenameGroupDoc(
+ const OUString& rOldGroup, OUString& rNewGroup, const OUString& rNewTitle )
+{
+ sal_uInt16 nOldPath = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(o3tl::getToken(rOldGroup, 1, GLOS_DELIM)));
+ if (static_cast<size_t>(nOldPath) >= m_PathArr.size())
+ return false;
+
+ const OUString sOldFileURL =
+ lcl_FullPathName(m_PathArr[nOldPath], o3tl::getToken(rOldGroup, 0, GLOS_DELIM));
+
+ if (!FStatHelper::IsDocument( sOldFileURL ))
+ {
+ OSL_FAIL("group doesn't exist!");
+ return false;
+ }
+
+ sal_uInt16 nNewPath = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(o3tl::getToken(rNewGroup, 1, GLOS_DELIM)));
+ if (static_cast<size_t>(nNewPath) >= m_PathArr.size())
+ return false;
+
+ const OUString sNewFileName = lcl_CheckFileName(m_PathArr[nNewPath],
+ o3tl::getToken(rNewGroup, 0, GLOS_DELIM));
+ const OUString sNewFileURL = lcl_FullPathName(m_PathArr[nNewPath], sNewFileName);
+
+ if (FStatHelper::IsDocument( sNewFileURL ))
+ {
+ OSL_FAIL("group already exists!");
+ return false;
+ }
+
+ if (!SWUnoHelper::UCB_MoveFile(sOldFileURL, sNewFileURL ))
+ return false;
+
+ RemoveFileFromList( rOldGroup );
+
+ rNewGroup = sNewFileName + OUStringChar(GLOS_DELIM) + OUString::number(nNewPath);
+ if (m_GlosArr.empty())
+ {
+ GetNameList();
+ }
+ else
+ {
+ m_GlosArr.push_back(rNewGroup);
+ }
+
+ SwTextBlocks aNewBlock( sNewFileURL );
+ aNewBlock.SetName(rNewTitle);
+
+ return true;
+}
+
+// Deletes a text block group
+bool SwGlossaries::DelGroupDoc(std::u16string_view rName)
+{
+ sal_uInt16 nPath = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(o3tl::getToken(rName, 1, GLOS_DELIM)));
+ if (static_cast<size_t>(nPath) >= m_PathArr.size())
+ return false;
+ const std::u16string_view sBaseName(o3tl::getToken(rName, 0, GLOS_DELIM));
+ const OUString sFileURL = lcl_FullPathName(m_PathArr[nPath], sBaseName);
+ const OUString aName = sBaseName + OUStringChar(GLOS_DELIM) + OUString::number(nPath);
+ // Even if the file doesn't exist it has to be deleted from
+ // the list of text block regions
+ // no && because of CFfront
+ bool bRemoved = SWUnoHelper::UCB_DeleteFile( sFileURL );
+ OSL_ENSURE(bRemoved, "file has not been removed");
+ RemoveFileFromList( aName );
+ return bRemoved;
+}
+
+SwGlossaries::~SwGlossaries()
+{
+ InvalidateUNOOjects();
+}
+
+// read a block document
+std::unique_ptr<SwTextBlocks> SwGlossaries::GetGlosDoc( const OUString &rName, bool bCreate ) const
+{
+ sal_uInt16 nPath = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(o3tl::getToken(rName, 1, GLOS_DELIM)));
+ std::unique_ptr<SwTextBlocks> pTmp;
+ if (static_cast<size_t>(nPath) < m_PathArr.size())
+ {
+ const OUString sFileURL =
+ lcl_FullPathName(m_PathArr[nPath], o3tl::getToken(rName, 0, GLOS_DELIM));
+
+ bool bExist = false;
+ if(!bCreate)
+ bExist = FStatHelper::IsDocument( sFileURL );
+
+ if (bCreate || bExist)
+ {
+ pTmp.reset(new SwTextBlocks( sFileURL ));
+ bool bOk = true;
+ if( pTmp->GetError() )
+ {
+ ErrorHandler::HandleError( pTmp->GetError() );
+ bOk = ! pTmp->GetError().IsError();
+ }
+
+ if( bOk && pTmp->GetName().isEmpty() )
+ pTmp->SetName( rName );
+ }
+ }
+
+ return pTmp;
+}
+
+// access to the list of names; read in if applicable
+std::vector<OUString> & SwGlossaries::GetNameList()
+{
+ if (m_GlosArr.empty())
+ {
+ const OUString sExt( SwGlossaries::GetExtension() );
+ for (size_t i = 0; i < m_PathArr.size(); ++i)
+ {
+ std::vector<OUString> aFiles;
+
+ SWUnoHelper::UCB_GetFileListOfFolder(m_PathArr[i], aFiles, &sExt);
+ for (const OUString& aTitle : aFiles)
+ {
+ const OUString sName( aTitle.subView( 0, aTitle.getLength() - sExt.getLength() )
+ + OUStringChar(GLOS_DELIM) + OUString::number( static_cast<sal_Int16>(i) ));
+ m_GlosArr.push_back(sName);
+ }
+ }
+ if (m_GlosArr.empty())
+ {
+ // the standard block is inside of the path's first part
+ m_GlosArr.emplace_back(SwGlossaries::GetDefName() + OUStringChar(GLOS_DELIM) + "0" );
+ }
+ }
+ return m_GlosArr;
+}
+
+SwGlossaries::SwGlossaries()
+{
+ UpdateGlosPath(true);
+}
+
+// set new path and recreate internal array
+static OUString lcl_makePath(const std::vector<OUString>& rPaths)
+{
+ std::vector<OUString>::const_iterator aIt(rPaths.begin());
+ const std::vector<OUString>::const_iterator aEnd(rPaths.end());
+ OUStringBuffer aPath(*aIt);
+ for (++aIt; aIt != aEnd; ++aIt)
+ {
+ aPath.append(SVT_SEARCHPATH_DELIMITER);
+ const INetURLObject aTemp(*aIt);
+ aPath.append(aTemp.GetFull());
+ }
+ return aPath.makeStringAndClear();
+}
+
+void SwGlossaries::UpdateGlosPath(bool bFull)
+{
+ SvtPathOptions aPathOpt;
+ const OUString& aNewPath( aPathOpt.GetAutoTextPath() );
+ bool bPathChanged = m_aPath != aNewPath;
+ if (!(bFull || bPathChanged))
+ return;
+
+ m_aPath = aNewPath;
+
+ m_PathArr.clear();
+
+ std::vector<OUString> aDirArr;
+ std::vector<OUString> aInvalidPaths;
+ if (!m_aPath.isEmpty())
+ {
+ sal_Int32 nIndex = 0;
+ do
+ {
+ const OUString sPth = URIHelper::SmartRel2Abs(
+ INetURLObject(),
+ m_aPath.getToken(0, SVT_SEARCHPATH_DELIMITER, nIndex),
+ URIHelper::GetMaybeFileHdl());
+ if (!aDirArr.empty() &&
+ std::find(aDirArr.begin(), aDirArr.end(), sPth) != aDirArr.end())
+ {
+ continue;
+ }
+ aDirArr.push_back(sPth);
+ if( !FStatHelper::IsFolder( sPth ) )
+ aInvalidPaths.push_back(sPth);
+ else
+ m_PathArr.push_back(sPth);
+ }
+ while (nIndex>=0);
+ }
+
+ if (m_aPath.isEmpty() || !aInvalidPaths.empty())
+ {
+ std::sort(aInvalidPaths.begin(), aInvalidPaths.end());
+ aInvalidPaths.erase(std::unique(aInvalidPaths.begin(), aInvalidPaths.end()), aInvalidPaths.end());
+ if (bPathChanged || (m_aInvalidPaths != aInvalidPaths))
+ {
+ m_aInvalidPaths = aInvalidPaths;
+ // wrong path, that means AutoText directory doesn't exist
+
+ ErrorHandler::HandleError( ErrCodeMsg(
+ ERR_AUTOPATH_ERROR, lcl_makePath(m_aInvalidPaths),
+ DialogMask::ButtonsOk | DialogMask::MessageError ) );
+ m_bError = true;
+ }
+ else
+ m_bError = false;
+ }
+ else
+ m_bError = false;
+
+ if (!m_GlosArr.empty())
+ {
+ m_GlosArr.clear();
+ GetNameList();
+ }
+}
+
+void SwGlossaries::ShowError()
+{
+ ErrCodeMsg nPathError(ERR_AUTOPATH_ERROR, lcl_makePath(m_aInvalidPaths), DialogMask::ButtonsOk );
+ ErrorHandler::HandleError( nPathError );
+}
+
+OUString SwGlossaries::GetExtension()
+{
+ return ".bau";
+}
+
+void SwGlossaries::RemoveFileFromList( const OUString& rGroup )
+{
+ if (m_GlosArr.empty())
+ return;
+
+ auto it = std::find(m_GlosArr.begin(), m_GlosArr.end(), rGroup);
+ if (it == m_GlosArr.end())
+ return;
+
+ {
+ // tell the UNO AutoTextGroup object that it's not valid anymore
+ for ( UnoAutoTextGroups::iterator aLoop = m_aGlossaryGroups.begin();
+ aLoop != m_aGlossaryGroups.end();
+ )
+ {
+ rtl::Reference< SwXAutoTextGroup > xNamed( aLoop->get() );
+ if ( !xNamed.is() )
+ {
+ aLoop = m_aGlossaryGroups.erase(aLoop);
+ }
+ else if ( xNamed->getName() == rGroup )
+ {
+ xNamed->Invalidate();
+ // note that this static_cast works because we know that the array only
+ // contains SwXAutoTextGroup implementation
+ m_aGlossaryGroups.erase( aLoop );
+ break;
+ } else
+ ++aLoop;
+ }
+ }
+
+ {
+ // tell all our UNO AutoTextEntry objects that they're not valid anymore
+ for ( UnoAutoTextEntries::iterator aLoop = m_aGlossaryEntries.begin();
+ aLoop != m_aGlossaryEntries.end();
+ )
+ {
+ rtl::Reference<SwXAutoTextEntry> pEntry = aLoop->get();
+ if ( pEntry && ( pEntry->GetGroupName() == rGroup ) )
+ {
+ pEntry->Invalidate();
+ aLoop = m_aGlossaryEntries.erase( aLoop );
+ }
+ else
+ ++aLoop;
+ }
+ }
+
+ m_GlosArr.erase(it);
+}
+
+OUString SwGlossaries::GetCompleteGroupName( std::u16string_view rGroupName )
+{
+ const size_t nCount = GetGroupCnt();
+ // when the group name was created internally the path is here as well
+ sal_Int32 nIndex = 0;
+ const std::u16string_view sGroupName(o3tl::getToken(rGroupName, 0, GLOS_DELIM, nIndex));
+ const bool bPathLen = !o3tl::getToken(rGroupName, 0, GLOS_DELIM, nIndex).empty();
+ for ( size_t i = 0; i < nCount; i++ )
+ {
+ const OUString sGrpName = GetGroupName(i);
+ if (bPathLen)
+ {
+ if (rGroupName == sGrpName)
+ return sGrpName;
+ }
+ else
+ {
+ if (sGroupName == o3tl::getToken(sGrpName, 0, GLOS_DELIM))
+ return sGrpName;
+ }
+ }
+ return OUString();
+}
+
+void SwGlossaries::InvalidateUNOOjects()
+{
+ // invalidate all the AutoTextGroup-objects
+ for (const auto& rGroup : m_aGlossaryGroups)
+ {
+ rtl::Reference< SwXAutoTextGroup > xGroup( rGroup.get() );
+ if ( xGroup.is() )
+ xGroup->Invalidate();
+ }
+ UnoAutoTextGroups().swap(m_aGlossaryGroups);
+
+ // invalidate all the AutoTextEntry-objects
+ for (const auto& rEntry : m_aGlossaryEntries)
+ {
+ rtl::Reference<SwXAutoTextEntry> pEntry = rEntry.get();
+ if ( pEntry )
+ pEntry->Invalidate();
+ }
+ UnoAutoTextEntries().swap(m_aGlossaryEntries);
+}
+
+Reference< text::XAutoTextGroup > SwGlossaries::GetAutoTextGroup( std::u16string_view _rGroupName )
+{
+ bool _bCreate = true;
+ // first, find the name with path-extension
+ const OUString sCompleteGroupName = GetCompleteGroupName( _rGroupName );
+
+ rtl::Reference< SwXAutoTextGroup > xGroup;
+
+ // look up the group in the cache
+ UnoAutoTextGroups::iterator aSearch = m_aGlossaryGroups.begin();
+ for ( ; aSearch != m_aGlossaryGroups.end(); )
+ {
+ rtl::Reference<SwXAutoTextGroup> pSwGroup = aSearch->get();
+ if ( !pSwGroup )
+ {
+ // the object is dead in the meantime -> remove from cache
+ aSearch = m_aGlossaryGroups.erase( aSearch );
+ continue;
+ }
+
+ if ( _rGroupName == pSwGroup->getName() )
+ { // the group is already cached
+ if ( !sCompleteGroupName.isEmpty() )
+ { // the group still exists -> return it
+ xGroup = pSwGroup;
+ break;
+ }
+ else
+ {
+ // this group does not exist (anymore) -> release the cached UNO object for it
+ aSearch = m_aGlossaryGroups.erase( aSearch );
+ // so it won't be created below
+ _bCreate = false;
+ break;
+ }
+ }
+
+ ++aSearch;
+ }
+
+ if ( !xGroup.is() && _bCreate )
+ {
+ xGroup = new SwXAutoTextGroup( sCompleteGroupName, this );
+ // cache it
+ m_aGlossaryGroups.emplace_back( xGroup );
+ }
+
+ return xGroup;
+}
+
+Reference< text::XAutoTextEntry > SwGlossaries::GetAutoTextEntry(
+ const OUString& rCompleteGroupName,
+ const OUString& rGroupName,
+ const OUString& rEntryName )
+{
+ //standard must be created
+ bool bCreate = ( rCompleteGroupName == GetDefName() );
+ std::unique_ptr< SwTextBlocks > pGlosGroup( GetGroupDoc( rCompleteGroupName, bCreate ) );
+
+ if (!pGlosGroup || pGlosGroup->GetError())
+ throw lang::WrappedTargetException();
+
+ sal_uInt16 nIdx = pGlosGroup->GetIndex( rEntryName );
+ if ( USHRT_MAX == nIdx )
+ throw container::NoSuchElementException();
+
+ rtl::Reference< SwXAutoTextEntry > xReturn;
+
+ UnoAutoTextEntries::iterator aSearch( m_aGlossaryEntries.begin() );
+ for ( ; aSearch != m_aGlossaryEntries.end(); )
+ {
+ rtl::Reference< SwXAutoTextEntry > pEntry( aSearch->get() );
+
+ if ( !pEntry )
+ {
+ // the object is dead in the meantime -> remove from cache
+ aSearch = m_aGlossaryEntries.erase( aSearch );
+ continue;
+ }
+
+ if ( pEntry
+ && pEntry->GetGroupName() == rGroupName
+ && pEntry->GetEntryName() == rEntryName
+ )
+ {
+ xReturn = pEntry;
+ break;
+ }
+
+ ++aSearch;
+ }
+
+ if ( !xReturn.is() )
+ {
+ xReturn = new SwXAutoTextEntry( this, rGroupName, rEntryName );
+ // cache it
+ m_aGlossaryEntries.emplace_back( xReturn );
+ }
+
+ return xReturn;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/misc/glshell.cxx b/sw/source/uibase/misc/glshell.cxx
new file mode 100644
index 0000000000..59ede231e8
--- /dev/null
+++ b/sw/source/uibase/misc/glshell.cxx
@@ -0,0 +1,270 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/XTitle.hpp>
+#include <svl/eitem.hxx>
+#include <svl/stritem.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/request.hxx>
+#include <svl/macitem.hxx>
+#include <gloshdl.hxx>
+
+#include <editeng/acorrcfg.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <glshell.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentState.hxx>
+#include <glosdoc.hxx>
+#include <shellio.hxx>
+#include <initui.hxx>
+#include <cmdid.h>
+#include <strings.hrc>
+
+#define ShellClass_SwWebGlosDocShell
+#define ShellClass_SwGlosDocShell
+
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+#include <memory>
+#include <utility>
+
+using namespace ::com::sun::star;
+
+SFX_IMPL_SUPERCLASS_INTERFACE(SwGlosDocShell, SwDocShell)
+
+void SwGlosDocShell::InitInterface_Impl()
+{
+}
+
+SFX_IMPL_SUPERCLASS_INTERFACE(SwWebGlosDocShell, SwWebDocShell)
+
+void SwWebGlosDocShell::InitInterface_Impl()
+{
+}
+
+
+static void lcl_Execute( SwDocShell& rSh, SfxRequest& rReq )
+{
+ if ( rReq.GetSlot() != SID_SAVEDOC )
+ return;
+
+ if( !rSh.HasName() )
+ {
+ rReq.SetReturnValue( SfxBoolItem( 0, rSh.Save() ) );
+ }
+ else
+ {
+ const SfxPoolItemHolder& rResult(
+ rSh.ExecuteSlot(rReq,
+ rSh.SfxObjectShell::GetInterface()));
+ const SfxBoolItem* pRes(static_cast< const SfxBoolItem* >(rResult.getItem()));
+ if( pRes->GetValue() )
+ rSh.GetDoc()->getIDocumentState().ResetModified();
+ }
+}
+
+static void lcl_GetState( SwDocShell& rSh, SfxItemSet& rSet )
+{
+ if( SfxItemState::DEFAULT >= rSet.GetItemState( SID_SAVEDOC, false ))
+ {
+ if( !rSh.GetDoc()->getIDocumentState().IsModified() )
+ rSet.DisableItem( SID_SAVEDOC );
+ else
+ rSet.Put( SfxStringItem( SID_SAVEDOC, SwResId(STR_SAVE_GLOSSARY)));
+ }
+}
+
+static bool lcl_Save( SwWrtShell& rSh, const OUString& rGroupName,
+ const OUString& rShortNm, const OUString& rLongNm )
+{
+ const SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get();
+ std::unique_ptr<SwTextBlocks> pBlock(::GetGlossaries()->GetGroupDoc( rGroupName ));
+
+ SvxMacro aStart { OUString(), OUString() };
+ SvxMacro aEnd { OUString(), OUString() };
+ SwGlossaryHdl* pGlosHdl;
+
+ pGlosHdl = rSh.GetView().GetGlosHdl();
+ pGlosHdl->GetMacros( rShortNm, aStart, aEnd, pBlock.get() );
+
+ sal_uInt16 nRet = rSh.SaveGlossaryDoc( *pBlock, rLongNm, rShortNm,
+ rCfg.IsSaveRelFile(),
+ pBlock->IsOnlyTextBlock( rShortNm ) );
+
+ if(aStart.HasMacro() || aEnd.HasMacro() )
+ {
+ SvxMacro* pStart = aStart.HasMacro() ? &aStart : nullptr;
+ SvxMacro* pEnd = aEnd.HasMacro() ? &aEnd : nullptr;
+ pGlosHdl->SetMacros( rShortNm, pStart, pEnd, pBlock.get() );
+ }
+
+ rSh.EnterStdMode();
+ if( USHRT_MAX != nRet )
+ rSh.ResetModified();
+ return nRet != USHRT_MAX;
+}
+
+SwGlosDocShell::SwGlosDocShell(bool bNewShow)
+ : SwDocShell( bNewShow
+ ? SfxObjectCreateMode::STANDARD : SfxObjectCreateMode::INTERNAL )
+{
+}
+
+SwGlosDocShell::~SwGlosDocShell( )
+{
+}
+
+void SwGlosDocShell::Execute( SfxRequest& rReq )
+{
+ ::lcl_Execute( *this, rReq );
+}
+
+void SwGlosDocShell::GetState( SfxItemSet& rSet )
+{
+ ::lcl_GetState( *this, rSet );
+}
+
+bool SwGlosDocShell::Save()
+{
+ // In case of an API object which holds this document, it is possible that the WrtShell is already
+ // dead. For instance, if the doc is modified via this API object, and then, upon office shutdown,
+ // the document's view is closed (by the SFX framework) _before_ the API object is release and
+ // tries to save the doc, again.
+ // 96380 - 2002-03-03 - fs@openoffice.org
+ if ( GetWrtShell() )
+ return ::lcl_Save( *GetWrtShell(), m_aGroupName, m_aShortName, m_aLongName );
+ else
+ {
+ SetModified( false );
+ return false;
+ }
+}
+
+SwWebGlosDocShell::SwWebGlosDocShell()
+{
+}
+
+SwWebGlosDocShell::~SwWebGlosDocShell( )
+{
+}
+
+void SwWebGlosDocShell::Execute( SfxRequest& rReq )
+{
+ ::lcl_Execute( *this, rReq );
+}
+
+void SwWebGlosDocShell::GetState( SfxItemSet& rSet )
+{
+ ::lcl_GetState( *this, rSet );
+}
+
+bool SwWebGlosDocShell::Save()
+{
+ // same comment as in SwGlosDocShell::Save - see there
+ if ( GetWrtShell() )
+ return ::lcl_Save( *GetWrtShell(), m_aGroupName, m_aShortName, m_aLongName );
+ else
+ {
+ SetModified( false );
+ return false;
+ }
+}
+
+SwDocShellRef SwGlossaries::EditGroupDoc( const OUString& rGroup, const OUString& rShortName, bool bShow )
+{
+ SwDocShellRef xDocSh;
+
+ std::unique_ptr<SwTextBlocks> pGroup = GetGroupDoc( rGroup );
+ if (pGroup && pGroup->GetCount())
+ {
+ // query which view is registered. In WebWriter there is no normal view
+ SfxInterfaceId nViewId = nullptr != SwView::Factory() ? SFX_INTERFACE_SFXDOCSH : SfxInterfaceId(6);
+ const OUString sLongName = pGroup->GetLongName(pGroup->GetIndex( rShortName ));
+
+ if( SfxInterfaceId(6) == nViewId )
+ {
+ SwWebGlosDocShell* pDocSh = new SwWebGlosDocShell();
+ xDocSh = pDocSh;
+ pDocSh->DoInitNew();
+ pDocSh->SetLongName( sLongName );
+ pDocSh->SetShortName( rShortName);
+ pDocSh->SetGroupName( rGroup );
+ }
+ else
+ {
+ SwGlosDocShell* pDocSh = new SwGlosDocShell(bShow);
+ xDocSh = pDocSh;
+ pDocSh->DoInitNew();
+ pDocSh->SetLongName( sLongName );
+ pDocSh->SetShortName( rShortName );
+ pDocSh->SetGroupName( rGroup );
+ }
+
+ // set document title
+ SfxViewFrame* pFrame = bShow ? SfxViewFrame::LoadDocument( *xDocSh, nViewId ) : SfxViewFrame::LoadHiddenDocument( *xDocSh, nViewId );
+ const OUString aDocTitle(SwResId( STR_GLOSSARY ) + " " + sLongName);
+
+ bool const bDoesUndo =
+ xDocSh->GetDoc()->GetIDocumentUndoRedo().DoesUndo();
+ xDocSh->GetDoc()->GetIDocumentUndoRedo().DoUndo( false );
+
+ xDocSh->GetWrtShell()->InsertGlossary( *pGroup, rShortName );
+ if( !xDocSh->GetDoc()->getIDocumentDeviceAccess().getPrinter( false ) )
+ {
+ // we create a default SfxPrinter.
+ // ItemSet is deleted by Sfx!
+ auto pSet = std::make_unique<SfxItemSetFixed<
+ SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
+ SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
+ FN_PARAM_ADDPRINTER, FN_PARAM_ADDPRINTER>>
+ ( xDocSh->GetDoc()->GetAttrPool() );
+ VclPtr<SfxPrinter> pPrinter = VclPtr<SfxPrinter>::Create( std::move(pSet) );
+
+ // and append it to the document.
+ xDocSh->GetDoc()->getIDocumentDeviceAccess().setPrinter( pPrinter, true, true );
+ }
+
+ xDocSh->SetTitle( aDocTitle );
+ try
+ {
+ // set the UI-title
+ uno::Reference< frame::XTitle > xTitle( xDocSh->GetModel(), uno::UNO_QUERY_THROW );
+ xTitle->setTitle( aDocTitle );
+ }
+ catch (const uno::Exception&)
+ {
+ }
+
+ xDocSh->GetDoc()->GetIDocumentUndoRedo().DoUndo( bDoesUndo );
+ xDocSh->GetDoc()->getIDocumentState().ResetModified();
+ if ( bShow )
+ pFrame->GetFrame().Appear();
+ }
+ return xDocSh;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/misc/numberingtypelistbox.cxx b/sw/source/uibase/misc/numberingtypelistbox.cxx
new file mode 100644
index 0000000000..94a26bcb9f
--- /dev/null
+++ b/sw/source/uibase/misc/numberingtypelistbox.cxx
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <numberingtypelistbox.hxx>
+#include <com/sun/star/style/NumberingType.hpp>
+#include <com/sun/star/text/DefaultNumberingProvider.hpp>
+#include <com/sun/star/text/XDefaultNumberingProvider.hpp>
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/text/XNumberingTypeInfo.hpp>
+#include <editeng/numitem.hxx>
+#include <svx/strarray.hxx>
+#include <osl/diagnose.h>
+
+using namespace com::sun::star;
+
+struct SwNumberingTypeListBox_Impl
+{
+ uno::Reference<text::XNumberingTypeInfo> xInfo;
+};
+
+SwNumberingTypeListBox::SwNumberingTypeListBox(std::unique_ptr<weld::ComboBox> pWidget)
+ : m_xWidget(std::move(pWidget))
+ , m_xImpl(new SwNumberingTypeListBox_Impl)
+{
+ uno::Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext());
+ uno::Reference<text::XDefaultNumberingProvider> xDefNum
+ = text::DefaultNumberingProvider::create(xContext);
+ m_xImpl->xInfo.set(xDefNum, uno::UNO_QUERY);
+}
+
+SwNumberingTypeListBox::~SwNumberingTypeListBox() {}
+
+void SwNumberingTypeListBox::Reload(SwInsertNumTypes nTypeFlags)
+{
+ m_xWidget->clear();
+ uno::Sequence<sal_Int16> aTypes;
+ if (nTypeFlags & SwInsertNumTypes::Extended)
+ {
+ if (m_xImpl->xInfo.is())
+ aTypes = m_xImpl->xInfo->getSupportedNumberingTypes();
+ }
+
+ for (size_t i = 0; i < SvxNumberingTypeTable::Count(); i++)
+ {
+ sal_IntPtr nValue = SvxNumberingTypeTable::GetValue(i);
+ bool bInsert = true;
+ int nPos = -1;
+ switch (nValue)
+ {
+ case style::NumberingType::NUMBER_NONE:
+ bInsert = bool(nTypeFlags & SwInsertNumTypes::NoNumbering);
+ nPos = 0;
+
+ break;
+ case style::NumberingType::CHAR_SPECIAL:
+ bInsert = false;
+
+ break;
+ case style::NumberingType::PAGE_DESCRIPTOR:
+ bInsert = false;
+
+ break;
+ case style::NumberingType::BITMAP:
+ bInsert = false;
+
+ break;
+ case style::NumberingType::BITMAP | LINK_TOKEN:
+ bInsert = false;
+
+ break;
+ default:
+ if (nValue > style::NumberingType::CHARS_LOWER_LETTER_N)
+ {
+ // Insert only if offered by i18n framework per configuration.
+ bInsert = std::find(std::cbegin(aTypes), std::cend(aTypes), nValue)
+ != std::cend(aTypes);
+ }
+ }
+ if (bInsert)
+ {
+ OUString sId(OUString::number(nValue));
+ m_xWidget->insert(nPos, SvxNumberingTypeTable::GetString(i), &sId, nullptr, nullptr);
+ }
+ }
+ if (!(nTypeFlags & SwInsertNumTypes::Extended))
+ return;
+
+ for (sal_Int16 nCurrent : std::as_const(aTypes))
+ {
+ if (nCurrent > style::NumberingType::CHARS_LOWER_LETTER_N)
+ {
+ if (m_xWidget->find_id(OUString::number(nCurrent)) == -1)
+ {
+ m_xWidget->append(OUString::number(nCurrent),
+ m_xImpl->xInfo->getNumberingIdentifier(nCurrent));
+ }
+ }
+ }
+ m_xWidget->set_active(0);
+}
+
+SvxNumType SwNumberingTypeListBox::GetSelectedNumberingType() const
+{
+ SvxNumType nRet = SVX_NUM_CHARS_UPPER_LETTER;
+ int nSelPos = m_xWidget->get_active();
+ if (nSelPos != -1)
+ nRet = static_cast<SvxNumType>(m_xWidget->get_id(nSelPos).toInt32());
+#if OSL_DEBUG_LEVEL > 0
+ else
+ OSL_FAIL("NumberingTypeListBox not selected");
+#endif
+ return nRet;
+}
+
+bool SwNumberingTypeListBox::SelectNumberingType(SvxNumType nType)
+{
+ int nPos = m_xWidget->find_id(OUString::number(nType));
+ m_xWidget->set_active(nPos);
+ return nPos != -1;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/misc/redlndlg.cxx b/sw/source/uibase/misc/redlndlg.cxx
new file mode 100644
index 0000000000..0461276140
--- /dev/null
+++ b/sw/source/uibase/misc/redlndlg.cxx
@@ -0,0 +1,1550 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <redline.hxx>
+#include <tools/datetime.hxx>
+#include <tools/lineend.hxx>
+#include <svl/eitem.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/dispatch.hxx>
+#include <svx/ctredlin.hxx>
+#include <svx/postattr.hxx>
+#include <utility>
+#include <vcl/commandevent.hxx>
+#include <swtypes.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <swmodule.hxx>
+#include <redlndlg.hxx>
+#include <swwait.hxx>
+#include <uitool.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <cmdid.h>
+#include <strings.hrc>
+
+// -> #111827#
+#include <swundo.hxx>
+#include <SwRewriter.hxx>
+// <- #111827#
+
+#include <vector>
+#include <svx/svxdlg.hxx>
+#include <osl/diagnose.h>
+#include <bitmaps.hlst>
+
+#include <docsh.hxx>
+
+#include <IDocumentRedlineAccess.hxx>
+#include <usrpref.hxx>
+#include <memory>
+
+SFX_IMPL_MODELESSDIALOGCONTOLLER_WITHID(SwRedlineAcceptChild, FN_REDLINE_ACCEPT)
+
+SwRedlineAcceptChild::SwRedlineAcceptChild(vcl::Window* _pParent,
+ sal_uInt16 nId,
+ SfxBindings* pBindings,
+ SfxChildWinInfo* pInfo)
+ : SwChildWinWrapper(_pParent, nId)
+{
+ auto xDlg = std::make_shared<SwModelessRedlineAcceptDlg>(pBindings, this, _pParent->GetFrameWeld());
+ SetController(xDlg);
+ xDlg->Initialize(pInfo);
+}
+
+// newly initialise dialog after document switch
+bool SwRedlineAcceptChild::ReInitDlg(SwDocShell *pDocSh)
+{
+ bool bRet = SwChildWinWrapper::ReInitDlg(pDocSh);
+ if (bRet) // update immediately, doc switch!
+ static_cast<SwModelessRedlineAcceptDlg*>(GetController().get())->Activate();
+
+ return bRet;
+}
+
+SwModelessRedlineAcceptDlg::SwModelessRedlineAcceptDlg(
+ SfxBindings* _pBindings, SwChildWinWrapper* pChild, weld::Window *pParent)
+ : SfxModelessDialogController(_pBindings, pChild, pParent,
+ "svx/ui/acceptrejectchangesdialog.ui", "AcceptRejectChangesDialog")
+ , m_xContentArea(m_xBuilder->weld_container("container"))
+ , m_pChildWin(pChild)
+{
+ m_xImplDlg.reset(new SwRedlineAcceptDlg(m_xDialog, m_xBuilder.get(), m_xContentArea.get()));
+}
+
+void SwModelessRedlineAcceptDlg::Activate()
+{
+ SwView *pView = ::GetActiveView();
+ if (!pView) // can happen when switching to another app, when a Listbox in dialog
+ return; // had the focus previously (actually THs Bug)
+
+ SwDocShell *pDocSh = pView->GetDocShell();
+
+ if (m_pChildWin->GetOldDocShell() != pDocSh)
+ { // doc-switch
+ SwWait aWait( *pDocSh, false );
+ SwWrtShell* pSh = pView->GetWrtShellPtr();
+ if (!pSh)
+ return;
+
+ m_pChildWin->SetOldDocShell(pDocSh); // avoid recursion (using modified-Hdl)
+
+ bool bMod = pSh->IsModified();
+ SfxBoolItem aShow(FN_REDLINE_SHOW, true);
+ pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(
+ FN_REDLINE_SHOW, SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
+ { &aShow });
+ if (!bMod)
+ pSh->ResetModified();
+ m_xImplDlg->Init();
+ SfxModelessDialogController::Activate();
+
+ return;
+ }
+
+ SfxModelessDialogController::Activate();
+ m_xImplDlg->Activate();
+}
+
+void SwModelessRedlineAcceptDlg::Initialize(SfxChildWinInfo* pInfo)
+{
+ if (pInfo != nullptr)
+ m_xImplDlg->Initialize(pInfo->aExtraString);
+
+ SfxModelessDialogController::Initialize(pInfo);
+}
+
+void SwModelessRedlineAcceptDlg::FillInfo(SfxChildWinInfo& rInfo) const
+{
+ SfxModelessDialogController::FillInfo(rInfo);
+ m_xImplDlg->FillInfo(rInfo.aExtraString);
+}
+
+SwModelessRedlineAcceptDlg::~SwModelessRedlineAcceptDlg()
+{
+}
+
+SwRedlineAcceptDlg::SwRedlineAcceptDlg(std::shared_ptr<weld::Window> xParent, weld::Builder *pBuilder,
+ weld::Container *pContentArea, bool bAutoFormat)
+ : m_xParentDlg(std::move(xParent))
+ , m_aSelectTimer("SwRedlineAcceptDlg m_aSelectTimer")
+ , m_sInserted(SwResId(STR_REDLINE_INSERTED))
+ , m_sDeleted(SwResId(STR_REDLINE_DELETED))
+ , m_sFormated(SwResId(STR_REDLINE_FORMATTED))
+ , m_sTableChgd(SwResId(STR_REDLINE_TABLECHG))
+ , m_sFormatCollSet(SwResId(STR_REDLINE_FMTCOLLSET))
+ , m_sAutoFormat(SwResId(STR_REDLINE_AUTOFMT))
+ , m_bOnlyFormatedRedlines(false)
+ , m_bRedlnAutoFormat(bAutoFormat)
+ , m_bInhibitActivate(false)
+ , m_bHasTrackedColumn(false)
+ , m_xTabPagesCTRL(new SvxAcceptChgCtr(pContentArea))
+ , m_xPopup(pBuilder->weld_menu("writermenu"))
+ , m_xSortMenu(pBuilder->weld_menu("writersortmenu"))
+{
+ m_pTPView = m_xTabPagesCTRL->GetViewPage();
+
+ m_pTable = m_pTPView->GetTableControl();
+ m_pTable->SetWriterView();
+
+ m_pTPView->SetAcceptClickHdl(LINK(this, SwRedlineAcceptDlg, AcceptHdl));
+ m_pTPView->SetAcceptAllClickHdl(LINK(this, SwRedlineAcceptDlg, AcceptAllHdl));
+ m_pTPView->SetRejectClickHdl(LINK(this, SwRedlineAcceptDlg, RejectHdl));
+ m_pTPView->SetRejectAllClickHdl(LINK(this, SwRedlineAcceptDlg, RejectAllHdl));
+ m_pTPView->SetUndoClickHdl(LINK(this, SwRedlineAcceptDlg, UndoHdl));
+ //tdf#89227 default to disabled, and only enable if possible to accept/reject
+ m_pTPView->EnableAccept(false);
+ m_pTPView->EnableReject(false);
+ m_pTPView->EnableClearFormat(false);
+ m_pTPView->EnableAcceptAll(false);
+ m_pTPView->EnableRejectAll(false);
+ m_pTPView->EnableClearFormatAll(false);
+
+ m_xTabPagesCTRL->GetFilterPage()->SetReadyHdl(LINK(this, SwRedlineAcceptDlg, FilterChangedHdl));
+
+ weld::ComboBox* pActLB = m_xTabPagesCTRL->GetFilterPage()->GetLbAction();
+ pActLB->append_text(m_sInserted);
+ pActLB->append_text(m_sDeleted);
+ pActLB->append_text(m_sFormated);
+ pActLB->append_text(m_sTableChgd);
+
+ if (HasRedlineAutoFormat())
+ {
+ pActLB->append_text(m_sFormatCollSet);
+ pActLB->append_text(m_sAutoFormat);
+ m_pTPView->ShowUndo();
+ m_pTPView->DisableUndo(); // no UNDO events yet
+ }
+
+ pActLB->set_active(0);
+
+ weld::TreeView& rTreeView = m_pTable->GetWidget();
+ rTreeView.set_selection_mode(SelectionMode::Multiple);
+
+ rTreeView.connect_changed(LINK(this, SwRedlineAcceptDlg, SelectHdl));
+ rTreeView.connect_popup_menu(LINK(this, SwRedlineAcceptDlg, CommandHdl));
+
+ // avoid multiple selection of the same texts:
+ m_aSelectTimer.SetTimeout(100);
+ m_aSelectTimer.SetInvokeHandler(LINK(this, SwRedlineAcceptDlg, GotoHdl));
+}
+
+SwRedlineAcceptDlg::~SwRedlineAcceptDlg()
+{
+}
+
+void SwRedlineAcceptDlg::Init(SwRedlineTable::size_type nStart)
+{
+ std::optional<SwWait> oWait;
+ if (SwView *pView = GetActiveView())
+ oWait.emplace(*pView->GetDocShell(), false);
+ weld::TreeView& rTreeView = m_pTable->GetWidget();
+ m_aUsedSeqNo.clear();
+
+ rTreeView.freeze();
+ if (nStart)
+ RemoveParents(nStart, m_RedlineParents.size() - 1);
+ else
+ {
+ rTreeView.clear();
+ m_RedlinData.clear();
+ m_RedlineChildren.clear();
+ m_RedlineParents.erase(m_RedlineParents.begin() + nStart, m_RedlineParents.end());
+ }
+ rTreeView.thaw();
+
+ // insert parents
+ InsertParents(nStart);
+ InitAuthors();
+
+ // #i69618# this moves the list box to the right position, visually
+ std::unique_ptr<weld::TreeIter> xSelEntry(rTreeView.make_iterator());
+ if (rTreeView.get_selected(xSelEntry.get()))
+ rTreeView.scroll_to_row(*xSelEntry); //#i70937#, force the scroll
+}
+
+void SwRedlineAcceptDlg::InitAuthors()
+{
+ if (!m_xTabPagesCTRL)
+ return;
+
+ SwView *pView = ::GetActiveView();
+ if (!pView)
+ return;
+ SwWrtShell* pSh = pView->GetWrtShellPtr();
+
+ SvxTPFilter *pFilterPage = m_xTabPagesCTRL->GetFilterPage();
+
+ std::vector<OUString> aStrings;
+ OUString sOldAuthor(pFilterPage->GetSelectedAuthor());
+ pFilterPage->ClearAuthors();
+
+ SwRedlineTable::size_type nCount = pSh ? pSh->GetRedlineCount() : 0;
+
+ m_bOnlyFormatedRedlines = true;
+ bool bIsNotFormated = false;
+
+ // determine authors
+ for ( SwRedlineTable::size_type i = 0; i < nCount; i++)
+ {
+ const SwRangeRedline& rRedln = pSh->GetRedline(i);
+
+ if( m_bOnlyFormatedRedlines && RedlineType::Format != rRedln.GetType() )
+ m_bOnlyFormatedRedlines = false;
+
+ aStrings.push_back(rRedln.GetAuthorString());
+
+ for (sal_uInt16 nStack = 1; nStack < rRedln.GetStackCount(); nStack++)
+ {
+ aStrings.push_back(rRedln.GetAuthorString(nStack));
+ }
+ }
+
+ std::sort(aStrings.begin(), aStrings.end());
+ aStrings.erase(std::unique(aStrings.begin(), aStrings.end()), aStrings.end());
+
+ for (auto const & i: aStrings)
+ pFilterPage->InsertAuthor(i);
+
+ if (pFilterPage->SelectAuthor(sOldAuthor) == -1 && !aStrings.empty())
+ pFilterPage->SelectAuthor(aStrings[0]);
+
+ weld::TreeView& rTreeView = m_pTable->GetWidget();
+ bool const bEnable = pSh && !pSh->GetDoc()->GetDocShell()->IsReadOnly()
+ && rTreeView.n_children() != 0
+ && !pSh->getIDocumentRedlineAccess().GetRedlinePassword().hasElements();
+ bool bSel = rTreeView.get_selected(nullptr);
+
+ rTreeView.selected_foreach([this, pSh, &bIsNotFormated](weld::TreeIter& rEntry){
+ // find the selected redline
+ // (fdo#57874: ignore, if the redline is already gone)
+ SwRedlineTable::size_type nPos = GetRedlinePos(rEntry);
+ if( nPos != SwRedlineTable::npos )
+ {
+ const SwRangeRedline& rRedln = pSh->GetRedline( nPos );
+
+ bIsNotFormated |= RedlineType::Format != rRedln.GetType();
+ }
+ return false;
+ });
+
+ m_pTPView->EnableAccept( bEnable && bSel );
+ m_pTPView->EnableReject( bEnable && bSel );
+ m_pTPView->EnableClearFormat( bEnable && !bIsNotFormated && bSel );
+ m_pTPView->EnableAcceptAll( bEnable );
+ m_pTPView->EnableRejectAll( bEnable );
+ m_pTPView->EnableClearFormatAll( bEnable &&
+ m_bOnlyFormatedRedlines );
+}
+
+OUString SwRedlineAcceptDlg::GetActionImage(const SwRangeRedline& rRedln, sal_uInt16 nStack,
+ bool bTableChanges, bool bRowChanges)
+{
+ switch (rRedln.GetType(nStack))
+ {
+ case RedlineType::Insert: return bTableChanges
+ ? bRowChanges
+ ? BMP_REDLINE_ROW_INSERTION
+ : BMP_REDLINE_COL_INSERTION
+ : rRedln.IsMoved()
+ ? BMP_REDLINE_MOVED_INSERTION
+ : rRedln.IsAnnotation()
+ ? BMP_REDLINE_COMMENT_INSERTION
+ : BMP_REDLINE_INSERTED;
+ case RedlineType::Delete: return bTableChanges
+ ? bRowChanges
+ ? BMP_REDLINE_ROW_DELETION
+ : BMP_REDLINE_COL_DELETION
+ : rRedln.IsMoved()
+ ? BMP_REDLINE_MOVED_DELETION
+ : rRedln.IsAnnotation()
+ ? BMP_REDLINE_COMMENT_DELETION
+ : BMP_REDLINE_DELETED;
+ case RedlineType::Format: return BMP_REDLINE_FORMATTED;
+ case RedlineType::ParagraphFormat: return BMP_REDLINE_FORMATTED;
+ case RedlineType::Table: return BMP_REDLINE_TABLECHG;
+ case RedlineType::FmtColl: return BMP_REDLINE_FMTCOLLSET;
+ default: break;
+ }
+
+ return OUString();
+}
+
+OUString SwRedlineAcceptDlg::GetActionText(const SwRangeRedline& rRedln, sal_uInt16 nStack)
+{
+ switch( rRedln.GetType(nStack) )
+ {
+ case RedlineType::Insert: return m_sInserted;
+ case RedlineType::Delete: return m_sDeleted;
+ case RedlineType::Format: return m_sFormated;
+ case RedlineType::ParagraphFormat: return m_sFormated;
+ case RedlineType::Table: return m_sTableChgd;
+ case RedlineType::FmtColl: return m_sFormatCollSet;
+ default:;//prevent warning
+ }
+
+ return OUString();
+}
+
+// newly initialise after activation
+void SwRedlineAcceptDlg::Activate()
+{
+ // prevent update if flag is set (#102547#)
+ if( m_bInhibitActivate )
+ return;
+
+ SwView *pView = ::GetActiveView();
+ if (!pView) // can happen when switching to another app
+ {
+ m_pTPView->EnableAccept(false);
+ m_pTPView->EnableReject(false);
+ m_pTPView->EnableClearFormat(false);
+ m_pTPView->EnableAcceptAll(false);
+ m_pTPView->EnableRejectAll(false);
+ m_pTPView->EnableClearFormatAll(false);
+ return; // had the focus previously
+ }
+
+ SwWait aWait( *pView->GetDocShell(), false );
+
+ if (pView->GetDocShell()->IsReadOnly())
+ {
+ m_pTPView->EnableAccept(false);
+ m_pTPView->EnableReject(false);
+ m_pTPView->EnableClearFormat(false);
+ m_pTPView->EnableAcceptAll(false);
+ m_pTPView->EnableRejectAll(false);
+ m_pTPView->EnableClearFormatAll(false);
+ // note: enabling is done in InitAuthors below
+ }
+
+ m_aUsedSeqNo.clear();
+
+ // did something change?
+ SwWrtShell* pSh = pView->GetWrtShellPtr();
+ if (!pSh)
+ return;
+
+ SwRedlineTable::size_type nCount = pSh->GetRedlineCount();
+
+ // check the number of pointers
+ for ( SwRedlineTable::size_type i = 0; i < nCount; i++)
+ {
+ const SwRangeRedline& rRedln = pSh->GetRedline(i);
+
+ if (i >= m_RedlineParents.size())
+ {
+ // new entries have been appended
+ Init(i);
+ return;
+ }
+
+ SwRedlineDataParent *const pParent = m_RedlineParents[i].get();
+ if (&rRedln.GetRedlineData() != pParent->pData)
+ {
+ // Redline-Parents were inserted, changed or deleted
+ i = CalcDiff(i, false);
+ if (i == SwRedlineTable::npos)
+ return;
+ continue;
+ }
+
+ const SwRedlineData *pRedlineData = rRedln.GetRedlineData().Next();
+ const SwRedlineDataChild *pBackupData = pParent->pNext;
+
+ if (!pRedlineData && pBackupData)
+ {
+ // Redline-Children were deleted
+ i = CalcDiff(i, true);
+ if (i == SwRedlineTable::npos)
+ return;
+ continue;
+ }
+ else
+ {
+ while (pRedlineData)
+ {
+ if (!pBackupData || pRedlineData != pBackupData->pChild)
+ {
+ // Redline-Children were inserted, changed or deleted
+ i = CalcDiff(i, true);
+ if (i == SwRedlineTable::npos)
+ return;
+
+ // here was a continue; targetted to the outer loop
+ // now a break will do, as there is nothing after it in the outer loop
+ break;
+ }
+ pBackupData = pBackupData->pNext;
+ pRedlineData = pRedlineData->Next();
+ }
+ }
+ }
+
+ if (nCount != m_RedlineParents.size())
+ {
+ // Redlines were deleted at the end
+ Init(nCount);
+ return;
+ }
+
+ // check comment
+ weld::TreeView& rTreeView = m_pTable->GetWidget();
+ bool bIsShowChangesInMargin = SW_MOD()->GetUsrPref(false)->IsShowChangesInMargin();
+ for (SwRedlineTable::size_type i = 0; i < nCount; i++)
+ {
+ const SwRangeRedline& rRedln = pSh->GetRedline(i);
+ SwRedlineDataParent *const pParent = m_RedlineParents[i].get();
+
+ if(rRedln.GetComment() != pParent->sComment)
+ {
+ bool bShowDeletedTextAsComment = bIsShowChangesInMargin &&
+ RedlineType::Delete == rRedln.GetType() && rRedln.GetComment().isEmpty();
+ const OUString sComment = bShowDeletedTextAsComment
+ ? const_cast<SwRangeRedline&>(rRedln).GetDescr()
+ : rRedln.GetComment();
+ if (pParent->xTLBParent)
+ {
+ // update only comment
+ rTreeView.set_text(*pParent->xTLBParent, sComment.replace('\n', ' '), 3);
+ }
+ pParent->sComment = sComment;
+ }
+ }
+
+ InitAuthors();
+}
+
+SwRedlineTable::size_type SwRedlineAcceptDlg::CalcDiff(SwRedlineTable::size_type nStart, bool bChild)
+{
+ if (!nStart || m_bHasTrackedColumn)
+ {
+ Init();
+ return SwRedlineTable::npos;
+ }
+
+ weld::TreeView& rTreeView = m_pTable->GetWidget();
+ rTreeView.freeze();
+ SwView *pView = ::GetActiveView();
+ if (!pView)
+ return SwRedlineTable::npos;
+
+ SwWrtShell* pSh = pView->GetWrtShellPtr();
+ if (!pSh)
+ return SwRedlineTable::npos;
+
+ bool bHasRedlineAutoFormat = HasRedlineAutoFormat();
+ SwRedlineDataParent *const pParent = m_RedlineParents[nStart].get();
+ const SwRangeRedline& rRedln = pSh->GetRedline(nStart);
+
+ if (bChild) // should actually never happen, but just in case...
+ {
+ // throw away all entry's children and initialise newly
+ SwRedlineDataChild* pBackupData = const_cast<SwRedlineDataChild*>(pParent->pNext);
+ SwRedlineDataChild* pNext;
+
+ while (pBackupData)
+ {
+ pNext = const_cast<SwRedlineDataChild*>(pBackupData->pNext);
+ if (pBackupData->xTLBChild)
+ rTreeView.remove(*pBackupData->xTLBChild);
+
+ auto it = std::find_if(m_RedlineChildren.begin(), m_RedlineChildren.end(),
+ [&pBackupData](const std::unique_ptr<SwRedlineDataChild>& rChildPtr) { return rChildPtr.get() == pBackupData; });
+ if (it != m_RedlineChildren.end())
+ m_RedlineChildren.erase(it);
+
+ pBackupData = pNext;
+ }
+ pParent->pNext = nullptr;
+
+ // insert new children
+ InsertChildren(pParent, rRedln, bHasRedlineAutoFormat);
+
+ rTreeView.thaw();
+ return nStart;
+ }
+
+ // have entries been deleted?
+ const SwRedlineData *pRedlineData = &rRedln.GetRedlineData();
+ for (SwRedlineTable::size_type i = nStart + 1; i < m_RedlineParents.size(); i++)
+ {
+ if (m_RedlineParents[i]->pData == pRedlineData)
+ {
+ // remove entries from nStart to i-1
+ RemoveParents(nStart, i - 1);
+ rTreeView.thaw();
+ return nStart - 1;
+ }
+ }
+
+ // entries been inserted?
+ SwRedlineTable::size_type nCount = pSh->GetRedlineCount();
+ pRedlineData = m_RedlineParents[nStart]->pData;
+
+ for (SwRedlineTable::size_type i = nStart + 1; i < nCount; i++)
+ {
+ if (&pSh->GetRedline(i).GetRedlineData() == pRedlineData)
+ {
+ rTreeView.thaw();
+ // insert entries from nStart to i-1
+ InsertParents(nStart, i - 1);
+ return nStart - 1;
+ }
+ }
+
+ rTreeView.thaw();
+ Init(nStart); // adjust all entries until the end
+ return SwRedlineTable::npos;
+}
+
+void SwRedlineAcceptDlg::InsertChildren(SwRedlineDataParent *pParent, const SwRangeRedline& rRedln, bool bHasRedlineAutoFormat)
+{
+ SwRedlineDataChild *pLastRedlineChild = nullptr;
+ const SwRedlineData *pRedlineData = &rRedln.GetRedlineData();
+ bool bAutoFormatRedline = rRedln.IsAutoFormat();
+
+ weld::TreeView& rTreeView = m_pTable->GetWidget();
+
+ OUString sAction = GetActionText(rRedln);
+ bool bValidParent = m_sFilterAction.isEmpty() || m_sFilterAction == sAction;
+ bValidParent = bValidParent && m_pTable->IsValidEntry(rRedln.GetAuthorString(), rRedln.GetTimeStamp(), rRedln.GetComment());
+ if (bHasRedlineAutoFormat)
+ {
+
+ if (pParent->pData->GetSeqNo())
+ {
+ std::pair<SwRedlineDataParentSortArr::const_iterator,bool> const ret
+ = m_aUsedSeqNo.insert(pParent);
+ if (ret.second) // already there
+ {
+ if (pParent->xTLBParent)
+ {
+ rTreeView.set_text(*(*ret.first)->xTLBParent, m_sAutoFormat, 0);
+ rTreeView.remove(*pParent->xTLBParent);
+ pParent->xTLBParent.reset();
+ }
+ return;
+ }
+ }
+ bValidParent = bValidParent && bAutoFormatRedline;
+ }
+ bool bValidTree = bValidParent;
+
+ for (sal_uInt16 nStack = 1; nStack < rRedln.GetStackCount(); nStack++)
+ {
+ pRedlineData = pRedlineData->Next();
+
+ SwRedlineDataChild* pRedlineChild = new SwRedlineDataChild;
+ pRedlineChild->pChild = pRedlineData;
+ m_RedlineChildren.push_back(std::unique_ptr<SwRedlineDataChild>(pRedlineChild));
+
+ if ( pLastRedlineChild )
+ pLastRedlineChild->pNext = pRedlineChild;
+ else
+ pParent->pNext = pRedlineChild;
+
+ sAction = GetActionText(rRedln, nStack);
+ bool bValidChild = m_sFilterAction.isEmpty() || m_sFilterAction == sAction;
+ bValidChild = bValidChild && m_pTable->IsValidEntry(rRedln.GetAuthorString(nStack), rRedln.GetTimeStamp(nStack), rRedln.GetComment());
+ if (bHasRedlineAutoFormat)
+ bValidChild = bValidChild && bAutoFormatRedline;
+ bValidTree |= bValidChild;
+
+ if (bValidChild)
+ {
+ std::unique_ptr<RedlinData> pData(new RedlinData);
+ pData->pData = pRedlineChild;
+ pData->bDisabled = true;
+
+ OUString sImage(GetActionImage(rRedln, nStack));
+ OUString sAuthor = rRedln.GetAuthorString(nStack);
+ pData->aDateTime = rRedln.GetTimeStamp(nStack);
+ pData->eType = rRedln.GetType(nStack);
+ OUString sDateEntry = GetAppLangDateTimeString(pData->aDateTime);
+ OUString sComment = rRedln.GetComment(nStack);
+
+ std::unique_ptr<weld::TreeIter> xChild(rTreeView.make_iterator());
+ OUString sId(weld::toId(pData.get()));
+ rTreeView.insert(pParent->xTLBParent.get(), -1, nullptr, &sId, nullptr, nullptr,
+ false, xChild.get());
+ m_RedlinData.push_back(std::move(pData));
+
+ rTreeView.set_image(*xChild, sImage, -1);
+ rTreeView.set_text(*xChild, sAuthor, 1);
+ rTreeView.set_text(*xChild, sDateEntry, 2);
+ rTreeView.set_text(*xChild, sComment, 3);
+
+ pRedlineChild->xTLBChild = std::move(xChild);
+ if (!bValidParent)
+ rTreeView.expand_row(*pParent->xTLBParent);
+ }
+ else
+ pRedlineChild->xTLBChild.reset();
+
+ pLastRedlineChild = pRedlineChild;
+ }
+
+ if (pLastRedlineChild)
+ pLastRedlineChild->pNext = nullptr;
+
+ if (!bValidTree && pParent->xTLBParent)
+ {
+ rTreeView.remove(*pParent->xTLBParent);
+ pParent->xTLBParent.reset();
+ if (bHasRedlineAutoFormat)
+ m_aUsedSeqNo.erase(pParent);
+ }
+}
+
+void SwRedlineAcceptDlg::RemoveParents(SwRedlineTable::size_type nStart, SwRedlineTable::size_type nEnd)
+{
+ SwView *pView = ::GetActiveView();
+ if (!pView)
+ return;
+
+ SwWrtShell* pSh = pView->GetWrtShellPtr();
+ if (!pSh)
+ return;
+
+ SwRedlineTable::size_type nCount = pSh->GetRedlineCount();
+
+ std::vector<const weld::TreeIter*> aLBoxArr;
+
+ weld::TreeView& rTreeView = m_pTable->GetWidget();
+
+ // because of Bug of TLB that ALWAYS calls the SelectHandler at Remove:
+ rTreeView.connect_changed(Link<weld::TreeView&,void>());
+
+ bool bChildrenRemoved = false;
+ rTreeView.thaw();
+ rTreeView.unselect_all();
+
+ // set the cursor after the last entry because otherwise performance problem in TLB.
+ // TLB would otherwise reset the cursor at every Remove (expensive)
+ SwRedlineTable::size_type nPos = std::min(nCount, m_RedlineParents.size());
+ weld::TreeIter *pCurEntry = nullptr;
+ while( ( pCurEntry == nullptr ) && ( nPos > 0 ) )
+ {
+ --nPos;
+ pCurEntry = m_RedlineParents[nPos]->xTLBParent.get();
+ }
+
+ if (pCurEntry)
+ rTreeView.set_cursor(*pCurEntry);
+
+ rTreeView.freeze();
+
+ for (SwRedlineTable::size_type i = nStart; i <= nEnd; i++)
+ {
+ if (!bChildrenRemoved && m_RedlineParents[i]->pNext)
+ {
+ SwRedlineDataChild * pChildPtr =
+ const_cast<SwRedlineDataChild*>(m_RedlineParents[i]->pNext);
+ auto it = std::find_if(m_RedlineChildren.begin(), m_RedlineChildren.end(),
+ [&pChildPtr](const std::unique_ptr<SwRedlineDataChild>& rChildPtr) { return rChildPtr.get() == pChildPtr; });
+ if (it != m_RedlineChildren.end())
+ {
+ sal_uInt16 nChildren = 0;
+ while (pChildPtr)
+ {
+ pChildPtr = const_cast<SwRedlineDataChild*>(pChildPtr->pNext);
+ nChildren++;
+ }
+
+ m_RedlineChildren.erase(it, it + nChildren);
+ bChildrenRemoved = true;
+ }
+ }
+ weld::TreeIter *const pEntry = m_RedlineParents[i]->xTLBParent.get();
+ if (pEntry)
+ aLBoxArr.push_back(pEntry);
+ }
+
+ std::sort(aLBoxArr.begin(), aLBoxArr.end(), [&rTreeView](const weld::TreeIter* a, const weld::TreeIter* b) {
+ return rTreeView.iter_compare(*a, *b) == -1;
+ });
+ // clear TLB from behind
+ for (auto it = aLBoxArr.rbegin(); it != aLBoxArr.rend(); ++it)
+ {
+ const weld::TreeIter* pIter = *it;
+ rTreeView.remove(*pIter);
+ }
+
+ rTreeView.thaw();
+ rTreeView.connect_changed(LINK(this, SwRedlineAcceptDlg, SelectHdl));
+ // unfortunately by Remove it was selected from the TLB always again ...
+ rTreeView.unselect_all();
+ rTreeView.freeze();
+
+ m_RedlineParents.erase(m_RedlineParents.begin() + nStart, m_RedlineParents.begin() + nEnd + 1);
+}
+
+void SwRedlineAcceptDlg::InsertParents(SwRedlineTable::size_type nStart, SwRedlineTable::size_type nEnd)
+{
+ SwView *pView = ::GetActiveView();
+ if (!pView)
+ return;
+
+ SwWrtShell* pSh = pView->GetWrtShellPtr();
+ if (!pSh)
+ return;
+
+ bool bHasRedlineAutoFormat = HasRedlineAutoFormat();
+
+ SwRedlineTable::size_type nCount = pSh->GetRedlineCount();
+ nEnd = std::min(nEnd, (nCount - 1)); // also treats nEnd=SwRedlineTable::npos (until the end)
+
+ // reset m_bHasTrackedColumn before searching tracked column again
+ if ( m_bHasTrackedColumn && nStart == 0 )
+ m_bHasTrackedColumn = false;
+
+ if (nEnd == SwRedlineTable::npos)
+ return; // no redlines in the document
+
+ weld::TreeView& rTreeView = m_pTable->GetWidget();
+
+ SwRedlineDataParent* pRedlineParent;
+ const SwRangeRedline* pCurrRedline;
+ if (!nStart && !rTreeView.get_selected(nullptr))
+ {
+ pCurrRedline = pSh->GetCurrRedline();
+ if( !pCurrRedline )
+ {
+ pSh->SwCursorShell::Push();
+ pCurrRedline = pSh->SelNextRedline();
+ if( nullptr == pCurrRedline )
+ pCurrRedline = pSh->SelPrevRedline();
+ pSh->SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent);
+ }
+ }
+ else
+ pCurrRedline = nullptr;
+
+ rTreeView.freeze();
+ if (m_pTable->IsSorted())
+ rTreeView.make_unsorted();
+
+ bool bIsShowChangesInMargin = SW_MOD()->GetUsrPref(false)->IsShowChangesInMargin();
+
+ // collect redlines of tracked table/row/column insertion/deletions under a single tree list
+ // item to accept/reject the table change with a single click on Accept/Reject
+ // Note: because update of the tree list depends on parent count, we don't modify
+ // m_RedlineParents, only store the 2nd and more redlines as children of the tree list
+ // item of the first redline
+
+ // count of items stored as children (to adjust parent position)
+ SwRedlineTable::size_type nSkipRedlines = 0;
+ // count of items of the actual table change stored as children =
+ // redlines of the change - 1 (first redline is associated to the parent tree list item)
+ SwRedlineTable::size_type nSkipRedline = 0;
+
+ // descriptor redline of the tracked table row/column
+ SwRedlineTable::size_type nRowChange = 0;
+
+ // first redlines of the tracked table rows/columns, base of the parent tree lists
+ // of the other SwRangeRedlines of the tracked table rows or columns
+ std::vector<SwRedlineTable::size_type> aTableParents;
+
+ // show all redlines as tree list items,
+ // redlines of a tracked table (row) insertion/deletion showed as children of a single parent
+ for (SwRedlineTable::size_type i = nStart; i <= nEnd; i++)
+ {
+ const SwRangeRedline& rRedln = pSh->GetRedline(i);
+ const SwRedlineData *pRedlineData = &rRedln.GetRedlineData();
+ // redline is a child associated to this table row/column change
+ SwRedlineTable::size_type nTableParent = SwRedlineTable::npos;
+
+ pRedlineParent = new SwRedlineDataParent;
+ pRedlineParent->pData = pRedlineData;
+ pRedlineParent->pNext = nullptr;
+
+ // handle tracked table row changes
+ const SwTableBox* pTableBox;
+ const SwTableLine* pTableLine;
+ bool bChange = false;
+ bool bRowChange = false;
+ if ( // not recognized yet as tracked table row change
+ nullptr != ( pTableBox = pSh->GetRedline(i).Start()->GetNode().GetTableBox() ) &&
+ nullptr != ( pTableLine = pTableBox->GetUpper() ) &&
+ // it's a tracked row (or column change) based on the cached row data
+ ( RedlineType::None != pTableLine->GetRedlineType() ||
+ RedlineType::None != pTableBox->GetRedlineType() ) )
+ {
+ // start redline search from the start from the tracked row/column change
+ SwRedlineTable::size_type nStartPos =
+ nRowChange > nSkipRedline ? nRowChange - nSkipRedline : 0;
+ bChange = true;
+ bRowChange = RedlineType::None != pTableLine->GetRedlineType();
+ nRowChange = bRowChange
+ ? pTableLine->UpdateTextChangesOnly(nStartPos)
+ : pTableBox->GetRedline();
+ // redline is there in a tracked table change
+ if ( SwRedlineTable::npos != nRowChange )
+ {
+ // join the consecutive deleted/inserted rows/columns under a single treebox item,
+ // if they have the same redline data (equal type, author and time stamp)
+ for (size_t j = 0; j < aTableParents.size(); j++)
+ {
+ // note: CanCombine() allows a time frame to join the changes within a short
+ // time period: this avoid of falling apart of the tracked columns inserted
+ // by several clicks
+ if ( pSh->GetRedline(nRowChange).GetRedlineData()
+ .CanCombine(pSh->GetRedline(aTableParents[j]).GetRedlineData()) )
+ {
+ nSkipRedline++;
+ nTableParent = aTableParents[j];
+ break;
+ }
+
+ }
+
+ if ( SwRedlineTable::npos == nTableParent )
+ {
+ // table redline didn't fit in the stored ones, create new parent
+ aTableParents.push_back(i);
+ }
+
+ // it needs major tree update later because of tracked table columns
+ if ( !m_bHasTrackedColumn && !bRowChange )
+ {
+ m_bHasTrackedColumn = true;
+ }
+ }
+ else
+ {
+ // redline is not in a tracked table change
+ bChange = bRowChange = false;
+ }
+ }
+
+ // empty parent cache for the last table
+ if ( !pTableBox )
+ {
+ aTableParents.clear();
+ }
+
+ bool bShowDeletedTextAsComment = bIsShowChangesInMargin &&
+ RedlineType::Delete == rRedln.GetType() && rRedln.GetComment().isEmpty();
+ const OUString& sComment = bShowDeletedTextAsComment
+ ? const_cast<SwRangeRedline&>(rRedln).GetDescr()
+ : rRedln.GetComment();
+ pRedlineParent->sComment = sComment.replace('\n', ' ');
+ m_RedlineParents.insert(m_RedlineParents.begin() + i,
+ std::unique_ptr<SwRedlineDataParent>(pRedlineParent));
+
+ std::unique_ptr<RedlinData> pData(new RedlinData);
+ pData->pData = pRedlineParent;
+ pData->bDisabled = false;
+
+ // use descriptor SwRangeRedline of the changed row, if needed to show
+ // the correct redline type, author and time stamp of the tracked row change
+ const SwRangeRedline& rChangeRedln = pSh->GetRedline(bChange ? nRowChange : i);
+
+ OUString sImage = GetActionImage(rChangeRedln, 0, bChange && aTableParents.back() == i, bRowChange );
+ OUString sAuthor = rChangeRedln.GetAuthorString(0);
+ pData->aDateTime = rChangeRedln.GetTimeStamp(0);
+ pData->eType = rChangeRedln.GetType(0);
+ OUString sDateEntry = GetAppLangDateTimeString(pData->aDateTime);
+
+ OUString sId = weld::toId(pData.get());
+ std::unique_ptr<weld::TreeIter> xParent(rTreeView.make_iterator());
+
+ if ( !bChange || aTableParents.back() == i )
+ {
+ rTreeView.insert(nullptr, i - nSkipRedlines, nullptr, &sId, nullptr, nullptr, false, xParent.get());
+ // before this was a tracked table change with more than a single redline
+ if ( nSkipRedline > 0 )
+ {
+ nSkipRedlines += nSkipRedline;
+ nSkipRedline = 0;
+ }
+ }
+ else
+ {
+ // put 2nd or more redlines of deleted/inserted rows as children of their first redline
+ SwRedlineDataParent *const pParent = m_RedlineParents[nTableParent].get();
+ rTreeView.insert(pParent->xTLBParent.get(), -1, nullptr, &sId, nullptr, nullptr, false, xParent.get());
+ }
+
+ m_RedlinData.push_back(std::move(pData));
+
+ rTreeView.set_image(*xParent, sImage, -1);
+ rTreeView.set_text(*xParent, sAuthor, 1);
+ rTreeView.set_text(*xParent, sDateEntry, 2);
+ rTreeView.set_text(*xParent, sComment, 3);
+
+ if (pCurrRedline == &rRedln)
+ {
+ rTreeView.thaw();
+ rTreeView.set_cursor(*xParent);
+ rTreeView.select(*xParent);
+ rTreeView.scroll_to_row(*xParent);
+ rTreeView.freeze();
+ }
+
+ pRedlineParent->xTLBParent = std::move(xParent);
+
+ InsertChildren(pRedlineParent, rRedln, bHasRedlineAutoFormat);
+ }
+ rTreeView.thaw();
+ if (m_pTable->IsSorted())
+ rTreeView.make_sorted();
+}
+
+void SwRedlineAcceptDlg::CallAcceptReject( bool bSelect, bool bAccept )
+{
+ SwView *pView = ::GetActiveView();
+ if (!pView)
+ return;
+
+ SwWrtShell* pSh = pView->GetWrtShellPtr();
+ if (!pSh)
+ return;
+
+ int nPos = -1;
+
+ typedef std::vector<std::unique_ptr<weld::TreeIter>> ListBoxEntries_t;
+ ListBoxEntries_t aRedlines;
+
+ // don't activate
+ OSL_ENSURE( !m_bInhibitActivate,
+ "recursive call of CallAcceptReject?");
+ m_bInhibitActivate = true;
+
+ weld::TreeView& rTreeView = m_pTable->GetWidget();
+
+ auto lambda = [this, pSh, bSelect, bAccept, &rTreeView, &nPos, &aRedlines](weld::TreeIter& rEntry) {
+ if (!rTreeView.get_iter_depth(rEntry))
+ {
+ if (bSelect && nPos == -1)
+ nPos = rTreeView.get_iter_index_in_parent(rEntry);
+
+ RedlinData *pData = weld::fromId<RedlinData*>(rTreeView.get_id(rEntry));
+
+ bool bIsNotFormatted = true;
+
+ // first remove only changes with insertion/deletion, if they exist
+ // (format-only changes haven't had real rejection yet, only an
+ // approximation: clear direct formatting, so try to warn
+ // with the extended button label "Reject All/Clear formatting")
+ if ( !bSelect && !bAccept && !m_bOnlyFormatedRedlines )
+ {
+ SwRedlineTable::size_type nPosition = GetRedlinePos(rEntry);
+ const SwRangeRedline& rRedln = pSh->GetRedline(nPosition);
+
+ if( RedlineType::Format == rRedln.GetType() )
+ bIsNotFormatted = false;
+ }
+
+ if (!pData->bDisabled && bIsNotFormatted)
+ aRedlines.emplace_back(rTreeView.make_iterator(&rEntry));
+ }
+ return false;
+ };
+
+ // collect redlines-to-be-accepted/rejected in aRedlines vector
+ if (bSelect)
+ rTreeView.selected_foreach(lambda);
+ else
+ rTreeView.all_foreach(lambda);
+
+ bool (SwEditShell::*FnAccRej)( SwRedlineTable::size_type ) = &SwEditShell::AcceptRedline;
+ if( !bAccept )
+ FnAccRej = &SwEditShell::RejectRedline;
+
+ SwWait aWait( *pSh->GetView().GetDocShell(), true );
+ pSh->StartAction();
+
+ bool bMoreRedlines( aRedlines.size() > 1 ||
+ // single item with children, e.g. multiple redlines of a table or table row deletion/insertion
+ ( aRedlines.size() == 1 && rTreeView.iter_n_children(*aRedlines[0]) > 0 ) );
+
+ // don't add extra Undo label to a single item only with redline stack (i.e. old changes
+ // on the same text range, stored only in OOXML)
+ if ( bMoreRedlines && aRedlines.size() == 1 )
+ {
+ std::unique_ptr<weld::TreeIter> xChild(rTreeView.make_iterator( &*aRedlines[0] ));
+ RedlinData *pData = weld::fromId<RedlinData*>(rTreeView.get_id(*xChild));
+ if ( pData->bDisabled )
+ bMoreRedlines = false;
+ }
+
+ if ( bMoreRedlines )
+ {
+ OUString aTmpStr;
+ {
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1,
+ OUString::number(aRedlines.size()));
+ aTmpStr = aRewriter.Apply(SwResId(STR_N_REDLINES));
+ }
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, aTmpStr);
+
+ pSh->StartUndo(bAccept? SwUndoId::ACCEPT_REDLINE : SwUndoId::REJECT_REDLINE,
+ &aRewriter);
+ }
+
+ // accept/reject the redlines in aRedlines. The absolute
+ // position may change during the process (e.g. when two redlines
+ // are merged in result of another one being deleted), so the
+ // position must be resolved late and checked before using it.
+ // (cf #102547#)
+ for (const auto& rRedLine : aRedlines)
+ {
+ SwRedlineTable::size_type nPosition = GetRedlinePos( *rRedLine );
+ if( nPosition != SwRedlineTable::npos )
+ (pSh->*FnAccRej)( nPosition );
+
+ // handle redlines of table rows, stored as children of the item associated
+ // to the deleted/inserted table row(s)
+ std::unique_ptr<weld::TreeIter> xChild(rTreeView.make_iterator( &*rRedLine ));
+ if ( rTreeView.iter_children(*xChild) )
+ {
+ RedlinData *pData = weld::fromId<RedlinData*>(rTreeView.get_id(*xChild));
+ // disabled for redline stack, but not for redlines of table rows
+ if ( !pData->bDisabled )
+ {
+ do
+ {
+ nPosition = GetRedlinePos( *xChild );
+ if( nPosition != SwRedlineTable::npos )
+ (pSh->*FnAccRej)( nPosition );
+ }
+ while ( rTreeView.iter_next_sibling(*xChild) );
+ }
+ }
+ }
+
+ if ( bMoreRedlines )
+ {
+ pSh->EndUndo();
+ }
+
+ pSh->EndAction();
+
+ m_bInhibitActivate = false;
+ Activate();
+
+ if (nPos != -1 && rTreeView.n_children())
+ {
+ if (nPos >= rTreeView.n_children())
+ nPos = rTreeView.n_children() - 1;
+ rTreeView.select(nPos);
+ rTreeView.scroll_to_row(nPos);
+ rTreeView.set_cursor(nPos);
+ SelectHdl(rTreeView);
+ }
+ m_pTPView->EnableUndo();
+}
+
+SwRedlineTable::size_type SwRedlineAcceptDlg::GetRedlinePos(const weld::TreeIter& rEntry)
+{
+ SwView* pView = GetActiveView();
+ if (!pView)
+ return SwRedlineTable::npos;
+
+ SwWrtShell* pSh = pView->GetWrtShellPtr();
+ if (!pSh)
+ return SwRedlineTable::npos;
+
+ weld::TreeView& rTreeView = m_pTable->GetWidget();
+ return pSh->FindRedlineOfData( *static_cast<SwRedlineDataParent*>(weld::fromId<RedlinData*>(
+ rTreeView.get_id(rEntry))->pData)->pData );
+}
+
+IMPL_LINK_NOARG(SwRedlineAcceptDlg, AcceptHdl, SvxTPView*, void)
+{
+ CallAcceptReject( true, true );
+}
+
+IMPL_LINK_NOARG(SwRedlineAcceptDlg, AcceptAllHdl, SvxTPView*, void)
+{
+ CallAcceptReject( false, true );
+}
+
+IMPL_LINK_NOARG(SwRedlineAcceptDlg, RejectHdl, SvxTPView*, void)
+{
+ CallAcceptReject( true, false );
+}
+
+IMPL_LINK_NOARG(SwRedlineAcceptDlg, RejectAllHdl, SvxTPView*, void)
+{
+ CallAcceptReject( false, false );
+}
+
+IMPL_LINK_NOARG(SwRedlineAcceptDlg, UndoHdl, SvxTPView*, void)
+{
+ if (SwView* pView = GetActiveView())
+ {
+ pView->GetViewFrame().GetDispatcher()->
+ Execute(SID_UNDO, SfxCallMode::SYNCHRON);
+ const SfxPoolItemHolder aResult(pView->GetSlotState(SID_UNDO));
+ m_pTPView->EnableUndo(nullptr != aResult.getItem());
+ }
+
+ Activate();
+}
+
+IMPL_LINK_NOARG(SwRedlineAcceptDlg, FilterChangedHdl, SvxTPFilter*, void)
+{
+ SvxTPFilter *pFilterTP = m_xTabPagesCTRL->GetFilterPage();
+
+ if (pFilterTP->IsAction())
+ m_sFilterAction = pFilterTP->GetLbAction()->get_active_text();
+ else
+ m_sFilterAction.clear();
+
+ Init();
+}
+
+IMPL_LINK_NOARG(SwRedlineAcceptDlg, SelectHdl, weld::TreeView&, void)
+{
+ m_aSelectTimer.Start();
+}
+
+IMPL_LINK_NOARG(SwRedlineAcceptDlg, GotoHdl, Timer *, void)
+{
+ m_aSelectTimer.Stop();
+
+ SwView* pView = GetActiveView();
+ if (!pView)
+ return;
+
+ SwWrtShell* pSh = pView->GetWrtShellPtr();
+ if (!pSh)
+ return;
+
+ bool bIsNotFormated = false;
+ bool bSel = false;
+
+ //#98883# don't select redlines while the dialog is not focused
+ //#107938# But not only ask pTable if it has the focus. To move
+ // the selection to the selected redline any child of pParentDlg
+ // may the focus.
+ if (!m_xParentDlg || m_xParentDlg->has_toplevel_focus())
+ {
+ weld::TreeView& rTreeView = m_pTable->GetWidget();
+ std::unique_ptr<weld::TreeIter> xActEntry(rTreeView.make_iterator());
+ if (rTreeView.get_selected(xActEntry.get()))
+ {
+ pSh->StartAction();
+ pSh->EnterStdMode();
+ SwViewShell::SetCareDialog(m_xParentDlg);
+
+ rTreeView.selected_foreach([this, pSh, &rTreeView, &xActEntry, &bIsNotFormated, &bSel](weld::TreeIter& rEntry){
+ rTreeView.copy_iterator(rEntry, *xActEntry);
+ if (rTreeView.get_iter_depth(rEntry))
+ {
+ rTreeView.iter_parent(*xActEntry);
+ if (rTreeView.is_selected(*xActEntry))
+ return false; // don't select twice
+ }
+ else
+ bSel = true;
+
+ // #98864# find the selected redline (ignore, if the redline is already gone)
+ SwRedlineTable::size_type nPos = GetRedlinePos(*xActEntry);
+ if (nPos != SwRedlineTable::npos)
+ {
+
+ const SwRangeRedline& rRedln = pSh->GetRedline( nPos );
+ bIsNotFormated |= RedlineType::Format != rRedln.GetType();
+
+ if (pSh->GotoRedline(nPos, true))
+ {
+ pSh->SetInSelect();
+ pSh->EnterAddMode();
+ }
+ }
+
+ // select all redlines of tracked table rows
+ std::unique_ptr<weld::TreeIter> xChild(rTreeView.make_iterator( &*xActEntry ));
+ if ( rTreeView.iter_children(*xChild) )
+ {
+ RedlinData *pData = reinterpret_cast<RedlinData*>(rTreeView.get_id(*xChild).toInt64());
+ // disabled for redline stack, but not for redlines of table rows
+ if ( !pData->bDisabled )
+ {
+ do
+ {
+ nPos = GetRedlinePos(*xChild);
+ if (nPos != SwRedlineTable::npos)
+ {
+ const SwRangeRedline& rRedln = pSh->GetRedline( nPos );
+ bIsNotFormated |= RedlineType::Format != rRedln.GetType();
+
+ if (pSh->GotoRedline(nPos, true))
+ {
+ pSh->SetInSelect();
+ pSh->EnterAddMode();
+ }
+ }
+ }
+ while ( rTreeView.iter_next_sibling(*xChild) );
+ }
+ }
+ return false;
+ });
+
+ pSh->LeaveAddMode();
+ pSh->EndAction();
+ SwViewShell::SetCareDialog(nullptr);
+ }
+ }
+
+ bool const bEnable = !pSh->GetDoc()->GetDocShell()->IsReadOnly()
+ && !pSh->getIDocumentRedlineAccess().GetRedlinePassword().hasElements();
+ m_pTPView->EnableAccept( bEnable && bSel /*&& !bReadonlySel*/ );
+ m_pTPView->EnableReject( bEnable && bSel /*&& !bReadonlySel*/ );
+ m_pTPView->EnableClearFormat( bEnable && bSel && !bIsNotFormated /*&& !bReadonlySel*/ );
+ m_pTPView->EnableAcceptAll( bEnable );
+ m_pTPView->EnableRejectAll( bEnable );
+ m_pTPView->EnableClearFormatAll( bEnable && m_bOnlyFormatedRedlines );
+}
+
+IMPL_LINK(SwRedlineAcceptDlg, CommandHdl, const CommandEvent&, rCEvt, bool)
+{
+ if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
+ return false;
+
+ SwView* pView = GetActiveView();
+ if (!pView)
+ return false;
+
+ SwWrtShell* pSh = pView->GetWrtShellPtr();
+ if (!pSh)
+ return false;
+
+ const SwRangeRedline *pRed = nullptr;
+
+ weld::TreeView& rTreeView = m_pTable->GetWidget();
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator());
+ bool bEntry = rTreeView.get_selected(xEntry.get());
+ if (bEntry)
+ {
+ std::unique_ptr<weld::TreeIter> xTopEntry(rTreeView.make_iterator(xEntry.get()));
+
+ if (rTreeView.get_iter_depth(*xTopEntry))
+ rTreeView.iter_parent(*xTopEntry);
+
+ SwRedlineTable::size_type nPos = GetRedlinePos(*xTopEntry);
+
+ // disable commenting for protected areas
+ if (nPos != SwRedlineTable::npos && (pRed = pSh->GotoRedline(nPos, true)) != nullptr)
+ {
+ if( pSh->IsCursorPtAtEnd() )
+ pSh->SwapPam();
+ pSh->SetInSelect();
+ }
+ }
+
+ m_xPopup->set_sensitive("writeredit", bEntry && pRed &&
+ !rTreeView.get_iter_depth(*xEntry) &&
+ rTreeView.count_selected_rows() == 1);
+ m_xPopup->set_sensitive("writersort", rTreeView.n_children() != 0);
+ int nColumn = rTreeView.get_sort_column();
+ if (nColumn == -1)
+ nColumn = 4;
+ for (sal_Int32 i = 0; i < 5; ++i)
+ m_xSortMenu->set_active(u"writersort" + OUString::number(i), i == nColumn);
+
+ OUString sCommand = m_xPopup->popup_at_rect(&rTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)));
+
+ if (sCommand == "writeredit")
+ {
+ if (bEntry)
+ {
+ if (rTreeView.get_iter_depth(*xEntry))
+ rTreeView.iter_parent(*xEntry);
+
+ SwRedlineTable::size_type nPos = GetRedlinePos(*xEntry);
+
+ if (nPos == SwRedlineTable::npos)
+ return true;
+
+ const SwRangeRedline &rRedline = pSh->GetRedline(nPos);
+
+ /* enable again once we have redline comments in the margin
+ sComment = rRedline.GetComment();
+ if ( !sComment.Len() )
+ GetActiveView()->GetDocShell()->Broadcast(SwRedlineHint(&rRedline,SWREDLINE_INSERTED));
+ const_cast<SwRangeRedline&>(rRedline).Broadcast(SwRedlineHint(&rRedline,SWREDLINE_FOCUS));
+ */
+
+ OUString sComment = convertLineEnd(rRedline.GetComment(), GetSystemLineEnd());
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ::DialogGetRanges fnGetRange = pFact->GetDialogGetRangesFunc();
+ SfxItemSet aSet( pSh->GetAttrPool(), fnGetRange() );
+
+ aSet.Put(SvxPostItTextItem(sComment, SID_ATTR_POSTIT_TEXT));
+ aSet.Put(SvxPostItAuthorItem(rRedline.GetAuthorString(), SID_ATTR_POSTIT_AUTHOR));
+
+ aSet.Put(SvxPostItDateItem( GetAppLangDateTimeString(
+ rRedline.GetRedlineData().GetTimeStamp() ),
+ SID_ATTR_POSTIT_DATE ));
+
+ ScopedVclPtr<AbstractSvxPostItDialog> pDlg(pFact->CreateSvxPostItDialog(&rTreeView, aSet));
+
+ pDlg->HideAuthor();
+
+ TranslateId pResId;
+ switch( rRedline.GetType() )
+ {
+ case RedlineType::Insert:
+ pResId = STR_REDLINE_INSERTED;
+ break;
+ case RedlineType::Delete:
+ pResId = STR_REDLINE_DELETED;
+ break;
+ case RedlineType::Format:
+ case RedlineType::ParagraphFormat:
+ pResId = STR_REDLINE_FORMATTED;
+ break;
+ case RedlineType::Table:
+ pResId = STR_REDLINE_TABLECHG;
+ break;
+ default:;//prevent warning
+ }
+ OUString sTitle(SwResId(STR_REDLINE_COMMENT));
+ if (pResId)
+ sTitle += SwResId(pResId);
+ pDlg->SetText(sTitle);
+
+ SwViewShell::SetCareDialog(pDlg->GetDialog());
+
+ if ( pDlg->Execute() == RET_OK )
+ {
+ const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
+ OUString sMsg(pOutSet->Get(SID_ATTR_POSTIT_TEXT).GetValue());
+
+ // insert / change comment
+ pSh->SetRedlineComment(sMsg);
+ rTreeView.set_text(*xEntry, sMsg.replace('\n', ' '), 3);
+ Init();
+ }
+
+ SwViewShell::SetCareDialog(nullptr);
+ pDlg.disposeAndClear();
+ }
+ }
+ else if (!sCommand.isEmpty())
+ {
+ int nSortMode = o3tl::toInt32(sCommand.subView(10));
+
+ if (nSortMode == 4 && nColumn == 4)
+ return true; // we already have it
+ if (nSortMode == 4)
+ nSortMode = -1; // unsorted / sorted by position
+
+ SwWait aWait( *pView->GetDocShell(), false );
+ m_pTable->HeaderBarClick(nSortMode);
+ if (nSortMode == -1)
+ Init(); // newly fill everything
+ }
+ return true;
+}
+
+namespace
+{
+ OUString lcl_StripAcceptChgDat(OUString &rExtraString)
+ {
+ OUString aStr;
+ while(true)
+ {
+ sal_Int32 nPos = rExtraString.indexOf("AcceptChgDat:");
+ if (nPos == -1)
+ break;
+ // try to read the alignment string "ALIGN:(...)"; if none existing,
+ // it's an old version
+ sal_Int32 n1 = rExtraString.indexOf('(', nPos);
+ if (n1 != -1)
+ {
+ sal_Int32 n2 = rExtraString.indexOf(')', n1);
+ if (n2 != -1)
+ {
+ // cut out the alignment string
+ aStr = rExtraString.copy(nPos, n2 - nPos + 1);
+ rExtraString = rExtraString.replaceAt(nPos, n2 - nPos + 1, u"");
+ aStr = aStr.copy(n1 - nPos + 1);
+ }
+ }
+ }
+ return aStr;
+ }
+}
+
+void SwRedlineAcceptDlg::Initialize(OUString& rExtraString)
+{
+ if (rExtraString.isEmpty())
+ return;
+
+ OUString aStr = lcl_StripAcceptChgDat(rExtraString);
+ if (aStr.isEmpty())
+ return;
+
+ int nCount = aStr.toInt32();
+ if (nCount <= 2)
+ return;
+
+ std::vector<int> aEndPos;
+
+ for (int i = 0; i < nCount; ++i)
+ {
+ sal_Int32 n1 = aStr.indexOf(';');
+ aStr = aStr.copy( n1+1 );
+ aEndPos.push_back(aStr.toInt32());
+ }
+
+ bool bUseless = false;
+
+ std::vector<int> aWidths;
+ for (int i = 1; i < nCount; ++i)
+ {
+ aWidths.push_back(aEndPos[i] - aEndPos[i - 1]);
+ if (aWidths.back() <= 0)
+ bUseless = true;
+ }
+
+ if (!bUseless)
+ {
+ // turn column end points back to column widths, ignoring the small
+ // value used for the expander column
+ weld::TreeView& rTreeView = m_pTable->GetWidget();
+ rTreeView.set_column_fixed_widths(aWidths);
+ }
+}
+
+void SwRedlineAcceptDlg::FillInfo(OUString &rExtraData) const
+{
+ //remove any old one before adding a new one
+ lcl_StripAcceptChgDat(rExtraData);
+ rExtraData += "AcceptChgDat:(";
+
+ const int nTabCount = 4;
+
+ rExtraData += OUString::number(nTabCount);
+ rExtraData += ";";
+
+ weld::TreeView& rTreeView = m_pTable->GetWidget();
+ std::vector<int> aWidths;
+ // turn column widths back into column end points for compatibility
+ // with how they used to be stored, including a small value for the
+ // expander column
+ aWidths.push_back(rTreeView.get_checkbox_column_width());
+ for (int i = 0; i < nTabCount - 1; ++i)
+ {
+ int nWidth = rTreeView.get_column_width(i);
+ assert(nWidth > 0 && "suspicious to get a value like this");
+ aWidths.push_back(aWidths.back() + nWidth);
+ }
+
+ for (auto a : aWidths)
+ {
+ rExtraData += OUString::number(a);
+ rExtraData += ";";
+ }
+ rExtraData += ")";
+}
+
+SwRedlineAcceptPanel::SwRedlineAcceptPanel(weld::Widget* pParent)
+ : PanelLayout(pParent, "ManageChangesPanel", "modules/swriter/ui/managechangessidebar.ui")
+ , mxContentArea(m_xBuilder->weld_container("content_area"))
+{
+ mpImplDlg.reset(new SwRedlineAcceptDlg(nullptr, m_xBuilder.get(), mxContentArea.get()));
+
+ mpImplDlg->Init();
+
+ // we want to receive SfxHintId::DocChanged
+ StartListening(*(SW_MOD()->GetView()->GetDocShell()));
+}
+
+SwRedlineAcceptPanel::~SwRedlineAcceptPanel()
+{
+}
+
+void SwRedlineAcceptPanel::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
+{
+ if (mpImplDlg && rHint.GetId() == SfxHintId::DocChanged)
+ mpImplDlg->Activate();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/misc/swruler.cxx b/sw/source/uibase/misc/swruler.cxx
new file mode 100644
index 0000000000..0ccdec2f46
--- /dev/null
+++ b/sw/source/uibase/misc/swruler.cxx
@@ -0,0 +1,367 @@
+/* -*- 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/.
+ */
+
+// Design proposal: https://wiki.documentfoundation.org/Design/Whiteboards/Comments_Ruler_Control
+
+#include <swruler.hxx>
+
+#include <viewsh.hxx>
+#include <edtwin.hxx>
+#include <PostItMgr.hxx>
+#include <view.hxx>
+#include <cmdid.h>
+#include <sfx2/request.hxx>
+#include <tools/UnitConversion.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/event.hxx>
+#include <vcl/window.hxx>
+#include <vcl/settings.hxx>
+#include <tools/json_writer.hxx>
+#include <strings.hrc>
+#include <comphelper/lok.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+#define CONTROL_BORDER_WIDTH 1
+
+namespace
+{
+/**
+ * Draw a little arrow / triangle with different directions
+ *
+ * \param nX left coordinate of arrow square
+ * \param nY top coordinate of arrow square
+ * \param nSize size of the long triangle side / arrow square
+ * \param Color arrow color
+ * \param bCollapsed if the arrow should display the collapsed state
+ */
+void ImplDrawArrow(vcl::RenderContext& rRenderContext, tools::Long nX, tools::Long nY,
+ tools::Long nSize, const Color& rColor, bool bCollapsed)
+{
+ tools::Polygon aTrianglePolygon(4);
+
+ if (bCollapsed)
+ {
+ if (AllSettings::GetLayoutRTL()) // <
+ {
+ aTrianglePolygon.SetPoint({ nX + nSize / 2, nY }, 0);
+ aTrianglePolygon.SetPoint({ nX + nSize / 2, nY + nSize }, 1);
+ aTrianglePolygon.SetPoint({ nX, nY + nSize / 2 }, 2);
+ aTrianglePolygon.SetPoint({ nX + nSize / 2, nY }, 3);
+ }
+ else // >
+ {
+ aTrianglePolygon.SetPoint({ nX, nY }, 0);
+ aTrianglePolygon.SetPoint({ nX + nSize / 2, nY + nSize / 2 }, 1);
+ aTrianglePolygon.SetPoint({ nX, nY + nSize }, 2);
+ aTrianglePolygon.SetPoint({ nX, nY }, 3);
+ }
+ }
+ else // v
+ {
+ aTrianglePolygon.SetPoint({ nX, nY + nSize / 2 }, 0);
+ aTrianglePolygon.SetPoint({ nX + nSize, nY + nSize / 2 }, 1);
+ aTrianglePolygon.SetPoint({ nX + nSize / 2, nY + nSize }, 2);
+ aTrianglePolygon.SetPoint({ nX, nY + nSize / 2 }, 3);
+ }
+
+ rRenderContext.SetLineColor();
+ rRenderContext.SetFillColor(rColor);
+ rRenderContext.DrawPolygon(aTrianglePolygon);
+}
+}
+
+// Constructor
+SwCommentRuler::SwCommentRuler(SwViewShell* pViewSh, vcl::Window* pParent, SwEditWin* pWin,
+ SvxRulerSupportFlags nRulerFlags, SfxBindings& rBindings,
+ WinBits nWinStyle)
+ : SvxRuler(pParent, pWin, nRulerFlags, rBindings, nWinStyle | WB_HSCROLL)
+ , mpViewShell(pViewSh)
+ , mpSwWin(pWin)
+ , mbIsHighlighted(false)
+ , maFadeTimer("sw::SwCommentRuler maFadeTimer")
+ , mnFadeRate(0)
+ , maVirDev(VclPtr<VirtualDevice>::Create(*GetOutDev()))
+{
+ // Set fading timeout: 5 x 40ms = 200ms
+ maFadeTimer.SetTimeout(40);
+ maFadeTimer.SetInvokeHandler(LINK(this, SwCommentRuler, FadeHandler));
+
+ // we have a little bit more space, as we don't draw ruler ticks
+ vcl::Font aFont(maVirDev->GetFont());
+ aFont.SetFontHeight(aFont.GetFontHeight() + 1);
+ maVirDev->SetFont(aFont);
+}
+
+SwCommentRuler::~SwCommentRuler() { disposeOnce(); }
+
+void SwCommentRuler::dispose()
+{
+ mpSwWin.clear();
+ SvxRuler::dispose();
+}
+
+void SwCommentRuler::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ if (comphelper::LibreOfficeKit::isActive())
+ return; // no need to waste time on startup
+
+ SvxRuler::Paint(rRenderContext, rRect);
+
+ // Don't draw if there is not any note
+ if (mpViewShell->GetPostItMgr() && mpViewShell->GetPostItMgr()->HasNotes())
+ DrawCommentControl(rRenderContext);
+}
+
+void SwCommentRuler::DrawCommentControl(vcl::RenderContext& rRenderContext)
+{
+ const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
+ const bool bIsCollapsed = !mpViewShell->GetPostItMgr()->ShowNotes();
+ const tools::Rectangle aControlRect = GetCommentControlRegion();
+
+ maVirDev->SetOutputSizePixel(aControlRect.GetSize());
+
+ // set colors
+ if (!bIsCollapsed)
+ {
+ if (mbIsHighlighted)
+ maVirDev->SetFillColor(
+ GetFadedColor(rStyleSettings.GetHighlightColor(), rStyleSettings.GetDialogColor()));
+ else
+ maVirDev->SetFillColor(rStyleSettings.GetDialogColor());
+ maVirDev->SetLineColor(rStyleSettings.GetShadowColor());
+ }
+ else
+ {
+ if (mbIsHighlighted)
+ maVirDev->SetFillColor(GetFadedColor(rStyleSettings.GetHighlightColor(),
+ rStyleSettings.GetWorkspaceColor()));
+ else
+ maVirDev->SetFillColor(rStyleSettings.GetWorkspaceColor());
+ maVirDev->SetLineColor();
+ }
+ Color aTextColor = GetFadedColor(rStyleSettings.GetHighlightTextColor(),
+ rStyleSettings.GetButtonTextColor());
+ maVirDev->SetTextColor(aTextColor);
+
+ // calculate label and arrow positions
+ const OUString aLabel = SwResId(STR_COMMENTS_LABEL);
+ const tools::Long nTriangleSize = maVirDev->GetTextHeight() / 2 + 1;
+ const tools::Long nTrianglePad = maVirDev->GetTextHeight() / 4;
+
+ Point aLabelPos(0, (aControlRect.GetHeight() - maVirDev->GetTextHeight()) / 2);
+ Point aArrowPos(0, (aControlRect.GetHeight() - nTriangleSize) / 2);
+
+ if (!AllSettings::GetLayoutRTL()) // | > Comments |
+ {
+ aArrowPos.setX(nTrianglePad);
+ aLabelPos.setX(aArrowPos.X() + nTriangleSize + nTrianglePad);
+ }
+ else // RTL => | Comments < |
+ {
+ const tools::Long nLabelWidth = maVirDev->GetTextWidth(aLabel);
+ if (!bIsCollapsed)
+ {
+ aArrowPos.setX(aControlRect.GetWidth() - 1 - nTrianglePad - CONTROL_BORDER_WIDTH
+ - nTriangleSize);
+ aLabelPos.setX(aArrowPos.X() - nTrianglePad - nLabelWidth);
+ }
+ else
+ {
+ // if comments are collapsed, left align the text, because otherwise it's very likely to be invisible
+ aArrowPos.setX(nLabelWidth + nTrianglePad + nTriangleSize);
+ aLabelPos.setX(aArrowPos.X() - nTrianglePad - nLabelWidth);
+ }
+ }
+
+ // draw control
+ maVirDev->DrawRect(tools::Rectangle(Point(), aControlRect.GetSize()));
+ maVirDev->DrawText(aLabelPos, aLabel);
+ ImplDrawArrow(*maVirDev, aArrowPos.X(), aArrowPos.Y(), nTriangleSize, aTextColor, bIsCollapsed);
+ rRenderContext.DrawOutDev(aControlRect.TopLeft(), aControlRect.GetSize(), Point(),
+ aControlRect.GetSize(), *maVirDev);
+}
+
+// Just accept double-click outside comment control
+void SwCommentRuler::Command(const CommandEvent& rCEvt)
+{
+ Point aMousePos = rCEvt.GetMousePosPixel();
+ // Ignore command request if it is inside Comment Control
+ if (!mpViewShell->GetPostItMgr() || !mpViewShell->GetPostItMgr()->HasNotes()
+ || !GetCommentControlRegion().Contains(aMousePos))
+ SvxRuler::Command(rCEvt);
+}
+
+void SwCommentRuler::MouseMove(const MouseEvent& rMEvt)
+{
+ SvxRuler::MouseMove(rMEvt);
+ if (!mpViewShell->GetPostItMgr() || !mpViewShell->GetPostItMgr()->HasNotes())
+ return;
+
+ UpdateCommentHelpText();
+
+ Point aMousePos = rMEvt.GetPosPixel();
+ bool bWasHighlighted = mbIsHighlighted;
+ mbIsHighlighted = GetCommentControlRegion().Contains(aMousePos);
+ if (mbIsHighlighted != bWasHighlighted)
+ // Do start fading
+ maFadeTimer.Start();
+}
+
+void SwCommentRuler::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ Point aMousePos = rMEvt.GetPosPixel();
+ if (!rMEvt.IsLeft() || IsTracking() || !GetCommentControlRegion().Contains(aMousePos))
+ {
+ SvxRuler::MouseButtonDown(rMEvt);
+ return;
+ }
+
+ // Toggle notes visibility
+ SwView& rView = mpSwWin->GetView();
+ SfxRequest aRequest(rView.GetViewFrame(), SID_TOGGLE_NOTES);
+ rView.ExecViewOptions(aRequest);
+
+ // It is inside comment control, so update help text
+ UpdateCommentHelpText();
+
+ Invalidate();
+}
+
+void SwCommentRuler::CreateJsonNotification(tools::JsonWriter& rJsonWriter)
+{
+ // Note that GetMargin1(), GetMargin2(), GetNullOffset(), and GetPageOffset() return values in
+ // pixels. Not twips. So "converting" the returned values with convertTwipToMm100() is quite
+ // wrong. (Also, even if the return values actually were in twips, it is questionable why we
+ // would want to pass them in mm100, as all other length values in the LOKit protocol apparently
+ // are in twips.)
+
+ // Anyway, as the consuming code in Online mostly seems to work anyway, it is likely that it
+ // would work as well even if the values in pixels were passed without a bogus "conversion" to
+ // mm100. But let's keep this as is for now.
+
+ // Also note that in desktop LibreOffice, these pixel values for the ruler of course change as
+ // one changes the zoom level. (Can be seen if one temporarily modifies the NotifyKit() function
+ // below to call this CreateJsonNotification() function and print its result in all cases even
+ // without LibreOfficeKit::isActive().) But in both web-based Online and in the iOS app, the
+ // zoom level from the point of view of this code here apparently does not change even if one
+ // zooms from the Online code's point of view.
+ rJsonWriter.put("margin1", convertTwipToMm100(GetMargin1()));
+ rJsonWriter.put("margin2", convertTwipToMm100(GetMargin2()));
+ rJsonWriter.put("leftOffset", convertTwipToMm100(GetNullOffset()));
+ rJsonWriter.put("pageOffset", convertTwipToMm100(GetPageOffset()));
+
+ // GetPageWidth() on the other hand does return a value in twips.
+ // So here convertTwipToMm100() really does produce actual mm100. Fun.
+ rJsonWriter.put("pageWidth", convertTwipToMm100(GetPageWidth()));
+
+ {
+ auto tabsNode = rJsonWriter.startNode("tabs");
+
+ // The RulerTab array elements that GetTabs() returns have their nPos field in twips. So these
+ // too are actual mm100.
+ for (auto const& tab : GetTabs())
+ {
+ auto tabNode = rJsonWriter.startNode("");
+ rJsonWriter.put("position", convertTwipToMm100(tab.nPos));
+ rJsonWriter.put("style", tab.nStyle);
+ }
+ }
+
+ RulerUnitData aUnitData = GetCurrentRulerUnit();
+ rJsonWriter.put("unit", aUnitData.aUnitStr);
+}
+
+void SwCommentRuler::NotifyKit()
+{
+ if (!comphelper::LibreOfficeKit::isActive())
+ return;
+
+ tools::JsonWriter aJsonWriter;
+ CreateJsonNotification(aJsonWriter);
+ OString pJsonData = aJsonWriter.finishAndGetAsOString();
+ mpViewShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_RULER_UPDATE,
+ pJsonData);
+}
+
+void SwCommentRuler::Update()
+{
+ tools::Rectangle aPreviousControlRect = GetCommentControlRegion();
+ SvxRuler::Update();
+ if (aPreviousControlRect != GetCommentControlRegion())
+ Invalidate();
+ NotifyKit();
+}
+
+void SwCommentRuler::UpdateCommentHelpText()
+{
+ TranslateId pTooltipResId;
+ if (mpViewShell->GetPostItMgr()->ShowNotes())
+ pTooltipResId = STR_HIDE_COMMENTS;
+ else
+ pTooltipResId = STR_SHOW_COMMENTS;
+ SetQuickHelpText(SwResId(pTooltipResId));
+}
+
+// TODO Make Ruler return its central rectangle instead of margins.
+tools::Rectangle SwCommentRuler::GetCommentControlRegion()
+{
+ SwPostItMgr* pPostItMgr = mpViewShell->GetPostItMgr();
+
+ //rhbz#1006850 When the SwPostItMgr ctor is called from SwView::SwView it
+ //triggers an update of the uiview, but the result of the ctor hasn't been
+ //set into the mpViewShell yet, so GetPostItMgr is temporarily still NULL
+ if (!pPostItMgr)
+ return tools::Rectangle();
+
+ const tools::ULong nSidebarWidth = pPostItMgr->GetSidebarWidth(true);
+
+ //FIXME When the page width is larger then screen, the ruler is misplaced by one pixel
+ tools::Long nLeft = GetPageOffset();
+ if (GetTextRTL())
+ nLeft += GetBorderOffset() - nSidebarWidth;
+ else
+ nLeft += GetWinOffset() + mpSwWin->LogicToPixel(Size(GetPageWidth(), 0)).Width();
+
+ // Ruler::ImplDraw uses RULER_OFF (value: 3px) as offset, and Ruler::ImplFormat adds one extra pixel
+ tools::Long nTop = 4;
+ // Somehow pPostItMgr->GetSidebarBorderWidth() returns border width already doubled
+ tools::Long nRight = nLeft + nSidebarWidth + pPostItMgr->GetSidebarBorderWidth(true);
+ tools::Long nBottom = nTop + GetRulerVirHeight() - 3;
+
+ tools::Rectangle aRect(nLeft, nTop, nRight, nBottom);
+ return aRect;
+}
+
+Color SwCommentRuler::GetFadedColor(const Color& rHighColor, const Color& rLowColor)
+{
+ if (!maFadeTimer.IsActive())
+ return mbIsHighlighted ? rHighColor : rLowColor;
+
+ Color aColor = rHighColor;
+ aColor.Merge(rLowColor, mnFadeRate * 255 / 100.0f);
+ return aColor;
+}
+
+IMPL_LINK_NOARG(SwCommentRuler, FadeHandler, Timer*, void)
+{
+ const int nStep = 25;
+ if (mbIsHighlighted && mnFadeRate < 100)
+ mnFadeRate += nStep;
+ else if (!mbIsHighlighted && mnFadeRate > 0)
+ mnFadeRate -= nStep;
+ else
+ return;
+
+ Invalidate();
+
+ if (mnFadeRate != 0 && mnFadeRate != 100)
+ maFadeTimer.Start();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/ribbar/conarc.cxx b/sw/source/uibase/ribbar/conarc.cxx
new file mode 100644
index 0000000000..4e55dc59ce
--- /dev/null
+++ b/sw/source/uibase/ribbar/conarc.cxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svxids.hrc>
+#include <vcl/event.hxx>
+
+#include <view.hxx>
+#include <edtwin.hxx>
+#include <wrtsh.hxx>
+#include <drawbase.hxx>
+#include <conarc.hxx>
+
+ConstArc::ConstArc(SwWrtShell* pWrtShell, SwEditWin* pEditWin, SwView* pSwView)
+ : SwDrawBase(pWrtShell, pEditWin, pSwView)
+ , m_nButtonUpCount(0)
+{
+}
+
+bool ConstArc::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ bool bReturn = SwDrawBase::MouseButtonDown(rMEvt);
+ if (bReturn && !m_nButtonUpCount)
+ m_aStartPoint = m_pWin->PixelToLogic(rMEvt.GetPosPixel());
+ return bReturn;
+}
+
+bool ConstArc::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ bool bReturn = false;
+
+ if ((m_pSh->IsDrawCreate() || m_pWin->IsDrawAction()) && rMEvt.IsLeft())
+ {
+ Point aPnt(m_pWin->PixelToLogic(rMEvt.GetPosPixel()));
+ if (!m_nButtonUpCount && aPnt == m_aStartPoint)
+ {
+ SwDrawBase::MouseButtonUp(rMEvt);
+ bReturn = true;
+ }
+ else
+ {
+ m_nButtonUpCount++;
+
+ if (m_nButtonUpCount == 3) // Generating of circular arc finished
+ {
+ SwDrawBase::MouseButtonUp(rMEvt);
+ m_nButtonUpCount = 0;
+ bReturn = true;
+ }
+ else
+ m_pSh->EndCreate(SdrCreateCmd::NextPoint);
+ }
+ }
+
+ return bReturn;
+}
+
+void ConstArc::Activate(const sal_uInt16 nSlotId)
+{
+ switch (nSlotId)
+ {
+ case SID_DRAW_ARC:
+ m_pWin->SetSdrDrawMode(SdrObjKind::CircleArc);
+ break;
+ case SID_DRAW_PIE:
+ m_pWin->SetSdrDrawMode(SdrObjKind::CircleSection);
+ break;
+ case SID_DRAW_CIRCLECUT:
+ m_pWin->SetSdrDrawMode(SdrObjKind::CircleCut);
+ break;
+ default:
+ m_pWin->SetSdrDrawMode(SdrObjKind::NONE);
+ break;
+ }
+
+ SwDrawBase::Activate(nSlotId);
+}
+
+void ConstArc::Deactivate()
+{
+ m_nButtonUpCount = 0;
+
+ SwDrawBase::Deactivate();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/ribbar/concustomshape.cxx b/sw/source/uibase/ribbar/concustomshape.cxx
new file mode 100644
index 0000000000..56030fc42d
--- /dev/null
+++ b/sw/source/uibase/ribbar/concustomshape.cxx
@@ -0,0 +1,196 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svdobj.hxx>
+#include <svx/sdtagitm.hxx>
+#include <svx/svdview.hxx>
+#include <editeng/eeitem.hxx>
+#include <view.hxx>
+#include <edtwin.hxx>
+#include <wrtsh.hxx>
+#include <drawbase.hxx>
+#include <concustomshape.hxx>
+#include <svx/gallery.hxx>
+#include <sfx2/request.hxx>
+#include <svx/fmmodel.hxx>
+#include <svl/itempool.hxx>
+#include <svl/stritem.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdoashp.hxx>
+#include <svx/xfillit0.hxx>
+#include <editeng/adjustitem.hxx>
+
+using namespace com::sun::star;
+
+ConstCustomShape::ConstCustomShape( SwWrtShell* pWrtShell, SwEditWin* pEditWin, SwView* pSwView, SfxRequest const & rReq )
+ : SwDrawBase( pWrtShell, pEditWin, pSwView )
+{
+ m_aCustomShape = ConstCustomShape::GetShapeTypeFromRequest( rReq );
+}
+
+const OUString& ConstCustomShape::GetShapeType() const
+{
+ return m_aCustomShape;
+}
+
+OUString ConstCustomShape::GetShapeTypeFromRequest( SfxRequest const & rReq )
+{
+ OUString aRet;
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ if ( pArgs )
+ {
+ const SfxStringItem& rItm = static_cast<const SfxStringItem&>(pArgs->Get( rReq.GetSlot() ));
+ aRet = rItm.GetValue();
+ }
+ return aRet;
+}
+
+bool ConstCustomShape::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ bool bReturn = SwDrawBase::MouseButtonDown(rMEvt);
+ if ( bReturn )
+ {
+ SdrView *pSdrView = m_pSh->GetDrawView();
+ if ( pSdrView )
+ {
+ SdrObject* pObj = pSdrView->GetCreateObj();
+ if ( pObj )
+ {
+ SetAttributes( pObj );
+ bool bForceNoFillStyle = false;
+ if ( static_cast<SdrObjCustomShape*>(pObj)->UseNoFillStyle() )
+ bForceNoFillStyle = true;
+
+ SfxItemSet aAttr( m_pView->GetPool() );
+ if ( bForceNoFillStyle )
+ aAttr.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
+ pObj->SetMergedItemSet(aAttr);
+ }
+ }
+ }
+ return bReturn;
+}
+
+void ConstCustomShape::Activate(const sal_uInt16 nSlotId)
+{
+ m_pWin->SetSdrDrawMode( SdrObjKind::CustomShape );
+
+ SwDrawBase::Activate(nSlotId);
+}
+
+// applying attributes
+
+void ConstCustomShape::SetAttributes( SdrObject* pObj )
+{
+ bool bAttributesAppliedFromGallery = false;
+
+ if ( GalleryExplorer::GetSdrObjCount( GALLERY_THEME_POWERPOINT ) )
+ {
+ std::vector< OUString > aObjList;
+ if ( GalleryExplorer::FillObjListTitle( GALLERY_THEME_POWERPOINT, aObjList ) )
+ {
+ for ( std::vector<OUString>::size_type i = 0; i < aObjList.size(); i++ )
+ {
+ if ( aObjList[ i ].equalsIgnoreAsciiCase( m_aCustomShape ) )
+ {
+ FmFormModel aFormModel;
+ SfxItemPool& rPool(aFormModel.GetItemPool());
+ rPool.FreezeIdRanges();
+
+ if ( GalleryExplorer::GetSdrObj( GALLERY_THEME_POWERPOINT, i, &aFormModel ) )
+ {
+ const SdrObject* pSourceObj = aFormModel.GetPage( 0 )->GetObj( 0 );
+ if( pSourceObj )
+ {
+ const SfxItemSet& rSource = pSourceObj->GetMergedItemSet();
+ SfxItemSetFixed<
+ // Ranges from SdrAttrObj:
+ SDRATTR_START, SDRATTR_SHADOW_LAST,
+ SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST,
+ SDRATTR_TEXTDIRECTION,
+ SDRATTR_TEXTDIRECTION,
+ // Graphic attributes, 3D properties,
+ // CustomShape properties:
+ SDRATTR_GRAF_FIRST,
+ SDRATTR_CUSTOMSHAPE_LAST,
+ // Range from SdrTextObj:
+ EE_ITEMS_START, EE_ITEMS_END>
+ aDest( pObj->getSdrModelFromSdrObject().GetItemPool() );
+ aDest.Set( rSource );
+ pObj->SetMergedItemSet( aDest );
+ Degree100 nAngle = pSourceObj->GetRotateAngle();
+ if ( nAngle )
+ pObj->NbcRotate( pObj->GetSnapRect().Center(), nAngle );
+ bAttributesAppliedFromGallery = true;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ if ( !bAttributesAppliedFromGallery )
+ {
+ pObj->SetMergedItem( SvxAdjustItem( SvxAdjust::Center, RES_PARATR_ADJUST ) );
+ pObj->SetMergedItem( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER ) );
+ pObj->SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_BLOCK ) );
+ pObj->SetMergedItem( makeSdrTextAutoGrowHeightItem( false ) );
+ static_cast<SdrObjCustomShape*>(pObj)->MergeDefaultAttributes( &m_aCustomShape );
+ }
+}
+
+void ConstCustomShape::CreateDefaultObject()
+{
+ SwDrawBase::CreateDefaultObject();
+ SdrView *pSdrView = m_pSh->GetDrawView();
+ if ( pSdrView )
+ {
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ if ( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ if ( dynamic_cast< const SdrObjCustomShape *>( pObj ) )
+ SetAttributes( pObj );
+ }
+ }
+}
+
+void ConstCustomShape::CreateDefaultObjectAtPosWithSize(Point aPos, Size aSize)
+{
+ SwDrawBase::CreateDefaultObjectAtPosWithSize(aPos, aSize);
+ SdrView *pSdrView = m_pSh->GetDrawView();
+ if ( pSdrView )
+ {
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ if ( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ if ( dynamic_cast< const SdrObjCustomShape *>( pObj ) )
+ SetAttributes( pObj );
+ }
+ }
+}
+
+// #i33136#
+bool ConstCustomShape::doConstructOrthogonal() const
+{
+ return SdrObjCustomShape::doConstructOrthogonal(m_aCustomShape);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/ribbar/conform.cxx b/sw/source/uibase/ribbar/conform.cxx
new file mode 100644
index 0000000000..25cb8570d3
--- /dev/null
+++ b/sw/source/uibase/ribbar/conform.cxx
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svdview.hxx>
+#include <vcl/ptrstyle.hxx>
+
+#include <swmodule.hxx>
+#include <view.hxx>
+#include <edtwin.hxx>
+#include <wrtsh.hxx>
+#include <drawbase.hxx>
+#include <conform.hxx>
+
+ConstFormControl::ConstFormControl(SwWrtShell* pWrtShell, SwEditWin* pEditWin, SwView* pSwView, SdrObjKind eObjKind)
+ : SwDrawBase(pWrtShell, pEditWin, pSwView)
+ , m_eObjKind(eObjKind)
+{
+ m_bInsForm = true;
+}
+
+bool ConstFormControl::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ bool bReturn = false;
+
+ SdrView *pSdrView = m_pSh->GetDrawView();
+
+ pSdrView->SetOrtho(rMEvt.IsShift());
+ pSdrView->SetAngleSnapEnabled(rMEvt.IsShift());
+
+ if (rMEvt.IsMod2())
+ {
+ pSdrView->SetCreate1stPointAsCenter(true);
+ pSdrView->SetResizeAtCenter(true);
+ }
+ else
+ {
+ pSdrView->SetCreate1stPointAsCenter(false);
+ pSdrView->SetResizeAtCenter(false);
+ }
+
+ SdrViewEvent aVEvt;
+ SdrHitKind eHit = pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
+
+ // Only new object; if not in base mode (or pure selection mode)
+ if (rMEvt.IsLeft() && !m_pWin->IsDrawAction() &&
+ (eHit == SdrHitKind::UnmarkedObject || eHit == SdrHitKind::NONE || m_pSh->IsDrawCreate()))
+ {
+ g_bNoInterrupt = true;
+ m_pWin->CaptureMouse();
+
+ m_pWin->SetPointer(PointerStyle::DrawRect);
+
+ m_aStartPos = m_pWin->PixelToLogic(rMEvt.GetPosPixel());
+ bReturn = m_pSh->BeginCreate(m_pWin->GetSdrDrawMode(), SdrInventor::FmForm, m_aStartPos);
+
+ if (bReturn)
+ m_pWin->SetDrawAction(true);
+ }
+ else
+ bReturn = SwDrawBase::MouseButtonDown(rMEvt);
+
+ return bReturn;
+}
+
+void ConstFormControl::Activate(const sal_uInt16 nSlotId)
+{
+ m_pWin->SetSdrDrawMode(m_eObjKind);
+ SwDrawBase::Activate(nSlotId);
+ m_pSh->GetDrawView()->SetCurrentObj(m_eObjKind);
+
+ m_pWin->SetPointer(PointerStyle::DrawRect);
+}
+
+void ConstFormControl::CreateDefaultObject()
+{
+ constexpr tools::Long constTwips_5mm = o3tl::toTwips(5, o3tl::Length::mm);
+ constexpr tools::Long constTwips_10mm = o3tl::toTwips(10, o3tl::Length::mm);
+
+ Point aStartPos(GetDefaultCenterPos());
+ Point aEndPos(aStartPos);
+ aStartPos.AdjustX(-constTwips_10mm);
+ aStartPos.AdjustY(-constTwips_5mm);
+ aEndPos.AdjustX(constTwips_10mm);
+ aEndPos.AdjustY(constTwips_5mm);
+
+ if(!m_pSh->HasDrawView())
+ m_pSh->MakeDrawView();
+
+ SdrView *pSdrView = m_pSh->GetDrawView();
+ pSdrView->SetDesignMode();
+ m_pSh->BeginCreate(m_pWin->GetSdrDrawMode(), SdrInventor::FmForm, aStartPos);
+ m_pSh->MoveCreate(aEndPos);
+ m_pSh->EndCreate(SdrCreateCmd::ForceEnd);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/ribbar/conpoly.cxx b/sw/source/uibase/ribbar/conpoly.cxx
new file mode 100644
index 0000000000..c4a245fda8
--- /dev/null
+++ b/sw/source/uibase/ribbar/conpoly.cxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svxids.hrc>
+#include <vcl/event.hxx>
+
+#include <view.hxx>
+#include <edtwin.hxx>
+#include <wrtsh.hxx>
+#include <drawbase.hxx>
+#include <conpoly.hxx>
+
+ConstPolygon::ConstPolygon(SwWrtShell* pWrtShell, SwEditWin* pEditWin, SwView* pSwView) :
+ SwDrawBase(pWrtShell, pEditWin, pSwView)
+{
+}
+
+bool ConstPolygon::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ bool bReturn = false;
+
+ if (m_pSh->IsDrawCreate())
+ {
+ if (rMEvt.IsLeft() && rMEvt.GetClicks() == 1 &&
+ m_pWin->GetSdrDrawMode() != SdrObjKind::FreehandLine &&
+ m_pWin->GetSdrDrawMode() != SdrObjKind::FreehandFill)
+ {
+ if (!m_pSh->EndCreate(SdrCreateCmd::NextPoint))
+ {
+ m_pSh->BreakCreate();
+ EnterSelectMode(rMEvt);
+ return true;
+ }
+ }
+ else
+ {
+ bReturn = SwDrawBase::MouseButtonUp(rMEvt);
+
+ // #i85045# removed double mechanism to check for AutoClose polygon
+ // after construction; the method here did not check for already closed and
+ // also worked only for a single polygon. Removing.
+ }
+ }
+ else
+ bReturn = SwDrawBase::MouseButtonUp(rMEvt);
+
+ return bReturn;
+}
+
+void ConstPolygon::Activate(const sal_uInt16 nSlotId)
+{
+ switch (nSlotId)
+ {
+ case SID_DRAW_POLYGON_NOFILL:
+ case SID_DRAW_XPOLYGON_NOFILL:
+ m_pWin->SetSdrDrawMode(SdrObjKind::PolyLine);
+ break;
+
+ case SID_DRAW_POLYGON:
+ case SID_DRAW_XPOLYGON:
+ m_pWin->SetSdrDrawMode(SdrObjKind::Polygon);
+ break;
+
+ case SID_DRAW_BEZIER_NOFILL:
+ m_pWin->SetSdrDrawMode(SdrObjKind::PathLine);
+ break;
+
+ case SID_DRAW_BEZIER_FILL:
+ m_pWin->SetSdrDrawMode(SdrObjKind::PathFill);
+ break;
+
+ case SID_DRAW_FREELINE_NOFILL:
+ m_pWin->SetSdrDrawMode(SdrObjKind::FreehandLine);
+ break;
+
+ case SID_DRAW_FREELINE:
+ m_pWin->SetSdrDrawMode(SdrObjKind::FreehandFill);
+ break;
+
+ default:
+ break;
+ }
+
+ SwDrawBase::Activate(nSlotId);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/ribbar/conrect.cxx b/sw/source/uibase/ribbar/conrect.cxx
new file mode 100644
index 0000000000..8d9d468a92
--- /dev/null
+++ b/sw/source/uibase/ribbar/conrect.cxx
@@ -0,0 +1,214 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svx/sdtacitm.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/sdtagitm.hxx>
+#include <svx/sdtakitm.hxx>
+#include <svx/sdtaditm.hxx>
+#include <svx/sdtaaitm.hxx>
+#include <svx/svdview.hxx>
+#include <svx/svdocapt.hxx>
+#include <editeng/outlobj.hxx>
+#include <cmdid.h>
+#include <view.hxx>
+#include <edtwin.hxx>
+#include <wrtsh.hxx>
+#include <drawbase.hxx>
+#include <conrect.hxx>
+
+ConstRectangle::ConstRectangle( SwWrtShell* pWrtShell, SwEditWin* pEditWin,
+ SwView* pSwView )
+ : SwDrawBase( pWrtShell, pEditWin, pSwView )
+ , m_bMarquee(false)
+ , m_bCapVertical(false)
+ , mbVertical(false)
+{
+}
+
+bool ConstRectangle::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ bool bReturn = SwDrawBase::MouseButtonDown(rMEvt);
+
+ if (bReturn)
+ {
+ if (m_pWin->GetSdrDrawMode() == SdrObjKind::Caption)
+ {
+ m_pView->NoRotate();
+ if (m_pView->IsDrawSelMode())
+ {
+ m_pView->FlipDrawSelMode();
+ m_pSh->GetDrawView()->SetFrameDragSingles(m_pView->IsDrawSelMode());
+ }
+ }
+ else
+ {
+ SdrObject* pObj = m_pView->GetDrawView()->GetCreateObj();
+ if (pObj)
+ {
+ SfxItemSet aAttr(pObj->getSdrModelFromSdrObject().GetItemPool());
+ SwFEShell::SetLineEnds(aAttr, *pObj, m_nSlotId);
+ pObj->SetMergedItemSet(aAttr);
+ }
+ }
+ }
+
+ return bReturn;
+}
+
+bool ConstRectangle::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ bool bRet = SwDrawBase::MouseButtonUp(rMEvt);
+ if( bRet )
+ {
+ SdrView *pSdrView = m_pSh->GetDrawView();
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ SdrObject* pObj = rMarkList.GetMark(0) ? rMarkList.GetMark(0)->GetMarkedSdrObj()
+ : nullptr;
+ switch( m_pWin->GetSdrDrawMode() )
+ {
+ case SdrObjKind::Text:
+ if( m_bMarquee )
+ {
+ m_pSh->ChgAnchor(RndStdIds::FLY_AS_CHAR);
+
+ if( pObj )
+ {
+ // Set the attributes needed for scrolling
+ SfxItemSetFixed<SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST>
+ aItemSet(pSdrView->GetModel().GetItemPool());
+
+ aItemSet.Put( makeSdrTextAutoGrowWidthItem( false ) );
+ aItemSet.Put( makeSdrTextAutoGrowHeightItem( false ) );
+ aItemSet.Put( SdrTextAniKindItem( SdrTextAniKind::Scroll ) );
+ aItemSet.Put( SdrTextAniDirectionItem( SdrTextAniDirection::Left ) );
+ aItemSet.Put( SdrTextAniCountItem( 0 ) );
+ aItemSet.Put( SdrTextAniAmountItem(
+ static_cast<sal_Int16>(m_pWin->PixelToLogic(Size(2,1)).Width())) );
+
+ pObj->SetMergedItemSetAndBroadcast(aItemSet);
+ }
+ }
+ else if(mbVertical)
+ {
+ if (SdrTextObj* pText = DynCastSdrTextObj(pObj))
+ {
+ SfxItemSet aSet(pSdrView->GetModel().GetItemPool());
+
+ pText->SetVerticalWriting(true);
+
+ aSet.Put(makeSdrTextAutoGrowWidthItem(true));
+ aSet.Put(makeSdrTextAutoGrowHeightItem(false));
+ aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP));
+ aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
+
+ pText->SetMergedItemSet(aSet);
+ }
+ }
+
+ if( pObj )
+ {
+ SdrPageView* pPV = pSdrView->GetSdrPageView();
+ m_pView->BeginTextEdit( pObj, pPV, m_pWin, true );
+ }
+ m_pView->LeaveDrawCreate(); // Switch to selection mode
+ m_pSh->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW);
+ break;
+
+ case SdrObjKind::Caption:
+ {
+ SdrCaptionObj* pCaptObj = dynamic_cast<SdrCaptionObj*>(pObj);
+ if( m_bCapVertical && pCaptObj )
+ {
+ pCaptObj->ForceOutlinerParaObject();
+ OutlinerParaObject* pOPO = pCaptObj->GetOutlinerParaObject();
+ if( pOPO && !pOPO->IsEffectivelyVertical() )
+ pOPO->SetVertical( true );
+ }
+ }
+ break;
+ default:; //prevent warning
+ }
+ }
+ return bRet;
+}
+
+void ConstRectangle::Activate(const sal_uInt16 nSlotId)
+{
+ m_bMarquee = m_bCapVertical = false;
+ mbVertical = false;
+
+ switch (nSlotId)
+ {
+ case SID_LINE_ARROW_END:
+ case SID_LINE_ARROW_CIRCLE:
+ case SID_LINE_ARROW_SQUARE:
+ case SID_LINE_ARROW_START:
+ case SID_LINE_CIRCLE_ARROW:
+ case SID_LINE_SQUARE_ARROW:
+ case SID_LINE_ARROWS:
+ case SID_DRAW_LINE:
+ case SID_DRAW_XLINE:
+ m_pWin->SetSdrDrawMode(SdrObjKind::Line);
+ break;
+
+ case SID_DRAW_MEASURELINE:
+ m_pWin->SetSdrDrawMode(SdrObjKind::Measure);
+ break;
+
+ case SID_DRAW_RECT:
+ m_pWin->SetSdrDrawMode(SdrObjKind::Rectangle);
+ break;
+
+ case SID_DRAW_ELLIPSE:
+ m_pWin->SetSdrDrawMode(SdrObjKind::CircleOrEllipse);
+ break;
+
+ case SID_DRAW_TEXT_MARQUEE:
+ m_bMarquee = true;
+ m_pWin->SetSdrDrawMode(SdrObjKind::Text);
+ break;
+
+ case SID_DRAW_TEXT_VERTICAL:
+ mbVertical = true;
+ m_pWin->SetSdrDrawMode(SdrObjKind::Text);
+ break;
+
+ case SID_DRAW_TEXT:
+ m_pWin->SetSdrDrawMode(SdrObjKind::Text);
+ break;
+
+ case SID_DRAW_CAPTION_VERTICAL:
+ m_bCapVertical = true;
+ [[fallthrough]];
+ case SID_DRAW_CAPTION:
+ m_pWin->SetSdrDrawMode(SdrObjKind::Caption);
+ break;
+
+ default:
+ m_pWin->SetSdrDrawMode(SdrObjKind::NONE);
+ break;
+ }
+
+ SwDrawBase::Activate(nSlotId);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/ribbar/drawbase.cxx b/sw/source/uibase/ribbar/drawbase.cxx
new file mode 100644
index 0000000000..4e77bbc1f6
--- /dev/null
+++ b/sw/source/uibase/ribbar/drawbase.cxx
@@ -0,0 +1,576 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+#include <comphelper/lok.hxx>
+#include <svx/svdview.hxx>
+#include <svx/svdobj.hxx>
+#include <svl/ptitem.hxx>
+#include <editeng/sizeitem.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <fmtclds.hxx>
+#include <frmfmt.hxx>
+#include <cmdid.h>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <drawbase.hxx>
+#include <edtwin.hxx>
+#include <swmodule.hxx>
+#include <swundo.hxx>
+#include <SwCapObjType.hxx>
+#include <SwRewriter.hxx>
+#include <strings.hrc>
+
+using namespace ::com::sun::star;
+
+SwDrawBase::SwDrawBase(SwWrtShell* pSwWrtShell, SwEditWin* pWindow, SwView* pSwView) :
+ m_pView(pSwView),
+ m_pSh(pSwWrtShell),
+ m_pWin(pWindow),
+ m_nSlotId(USHRT_MAX),
+ m_bCreateObj(true),
+ m_bInsForm(false)
+{
+ if ( !m_pSh->HasDrawView() )
+ m_pSh->MakeDrawView();
+}
+
+SwDrawBase::~SwDrawBase()
+{
+ if (m_pView->GetWrtShellPtr()) // In the view-dtor could the wrtsh already been deleted...
+ m_pSh->GetDrawView()->SetEditMode();
+}
+
+bool SwDrawBase::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ bool bReturn = false;
+
+ SdrView *pSdrView = m_pSh->GetDrawView();
+
+ // #i33136#
+ pSdrView->SetOrtho(doConstructOrthogonal() ? !rMEvt.IsShift() : rMEvt.IsShift());
+ pSdrView->SetAngleSnapEnabled(rMEvt.IsShift());
+
+ if (rMEvt.IsMod2())
+ {
+ pSdrView->SetCreate1stPointAsCenter(true);
+ pSdrView->SetResizeAtCenter(true);
+ }
+ else
+ {
+ pSdrView->SetCreate1stPointAsCenter(false);
+ pSdrView->SetResizeAtCenter(false);
+ }
+
+ SdrViewEvent aVEvt;
+ SdrHitKind eHit = pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
+
+ // Only new object, if not in the basic mode (or pure selection mode).
+ if (rMEvt.IsLeft() && !m_pWin->IsDrawAction())
+ {
+ if (IsCreateObj() && (eHit == SdrHitKind::UnmarkedObject || eHit == SdrHitKind::NONE || m_pSh->IsDrawCreate()))
+ {
+ g_bNoInterrupt = true;
+ m_pWin->CaptureMouse();
+
+ m_aStartPos = m_pWin->PixelToLogic(rMEvt.GetPosPixel());
+
+ bReturn = m_pSh->BeginCreate(m_pWin->GetSdrDrawMode(), m_aStartPos);
+
+ SetDrawPointer();
+
+ if ( bReturn )
+ m_pWin->SetDrawAction(true);
+ }
+ else if (!pSdrView->IsAction())
+ {
+ // BEZIER-EDITOR
+ m_pWin->CaptureMouse();
+ m_aStartPos = m_pWin->PixelToLogic(rMEvt.GetPosPixel());
+ sal_uInt16 nEditMode = m_pWin->GetBezierMode();
+
+ if (eHit == SdrHitKind::Handle && aVEvt.mpHdl->GetKind() == SdrHdlKind::BezierWeight)
+ {
+ // Drag handle
+ g_bNoInterrupt = true;
+ bReturn = pSdrView->BegDragObj(m_aStartPos, nullptr, aVEvt.mpHdl);
+ m_pWin->SetDrawAction(true);
+ }
+ else if (eHit == SdrHitKind::MarkedObject && nEditMode == SID_BEZIER_INSERT)
+ {
+ // Insert gluepoint
+ g_bNoInterrupt = true;
+ bReturn = pSdrView->BegInsObjPoint(m_aStartPos, rMEvt.IsMod1());
+ m_pWin->SetDrawAction(true);
+ }
+ else if (eHit == SdrHitKind::MarkedObject && rMEvt.IsMod1())
+ {
+ // Select gluepoint
+ if (!rMEvt.IsShift())
+ pSdrView->UnmarkAllPoints();
+
+ bReturn = pSdrView->BegMarkPoints(m_aStartPos);
+ m_pWin->SetDrawAction(true);
+ }
+ else if (eHit == SdrHitKind::MarkedObject && !rMEvt.IsShift() && !rMEvt.IsMod2())
+ {
+ // Move object
+ return false;
+ }
+ else if (eHit == SdrHitKind::Handle)
+ {
+ // Select gluepoint
+ if (pSdrView->HasMarkablePoints() && (!pSdrView->IsPointMarked(*aVEvt.mpHdl) || rMEvt.IsShift()))
+ {
+ SdrHdl* pHdl = nullptr;
+
+ if (!rMEvt.IsShift())
+ {
+ pSdrView->UnmarkAllPoints();
+ pHdl = pSdrView->PickHandle(m_aStartPos);
+ }
+ else
+ {
+ if (pSdrView->IsPointMarked(*aVEvt.mpHdl))
+ {
+ bReturn = pSdrView->UnmarkPoint(*aVEvt.mpHdl);
+ pHdl = nullptr;
+ }
+ else
+ {
+ pHdl = pSdrView->PickHandle(m_aStartPos);
+ }
+ }
+
+ if (pHdl)
+ {
+ g_bNoInterrupt = true;
+ pSdrView->MarkPoint(*pHdl);
+ }
+ }
+ }
+ else
+ {
+ // Select or drag object
+ if (m_pSh->IsObjSelectable(m_aStartPos) && eHit == SdrHitKind::UnmarkedObject)
+ {
+ if (pSdrView->HasMarkablePoints())
+ pSdrView->UnmarkAllPoints();
+
+ g_bNoInterrupt = false;
+ // Use drag in edtwin
+ return false;
+ }
+
+ g_bNoInterrupt = true;
+
+ if (m_pSh->IsObjSelected())
+ {
+ if (!rMEvt.IsShift())
+ {
+ if (!pSdrView->HasMarkablePoints())
+ {
+ bool bUnlockView = !m_pSh->IsViewLocked();
+ m_pSh->LockView( true ); //lock visible section
+ m_pSh->SelectObj(Point(LONG_MAX, LONG_MAX)); // deselect all
+ if( bUnlockView )
+ m_pSh->LockView( false );
+ }
+ else
+ pSdrView->UnmarkAllPoints();
+ }
+ }
+ if (!m_pSh->IsSelFrameMode())
+ m_pSh->EnterSelFrameMode();
+
+ bReturn = m_pSh->BeginMark(m_aStartPos);
+ if( bReturn )
+ m_pWin->SetDrawAction(true);
+
+ SetDrawPointer();
+ }
+ }
+ }
+ return bReturn;
+}
+
+bool SwDrawBase::MouseMove(const MouseEvent& rMEvt)
+{
+ SdrView *pSdrView = m_pSh->GetDrawView();
+ Point aPnt(m_pWin->PixelToLogic(rMEvt.GetPosPixel()));
+ bool bRet = false;
+
+ if (IsCreateObj() && !m_pWin->IsDrawSelMode() && pSdrView->IsCreateObj())
+ {
+ // #i33136#
+ pSdrView->SetOrtho(doConstructOrthogonal() ? !rMEvt.IsShift() : rMEvt.IsShift());
+ pSdrView->SetAngleSnapEnabled(rMEvt.IsShift());
+
+ m_pSh->MoveCreate(aPnt);
+ bRet = true;
+ }
+ else if (pSdrView->IsAction() || pSdrView->IsInsObjPoint() || pSdrView->IsMarkPoints())
+ {
+ m_pSh->MoveMark(aPnt);
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+bool SwDrawBase::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ bool bReturn = false;
+ bool bCheckShell = false;
+ bool bAutoCap = false;
+
+ Point aPnt(m_pWin->PixelToLogic(rMEvt.GetPosPixel()));
+
+ if (IsCreateObj() && m_pSh->IsDrawCreate() && !m_pWin->IsDrawSelMode())
+ {
+ const SdrObjKind nDrawMode = m_pWin->GetSdrDrawMode();
+ //objects with multiple point may end at the start position
+ bool bMultiPoint = SdrObjKind::PolyLine == nDrawMode ||
+ SdrObjKind::Polygon == nDrawMode ||
+ SdrObjKind::PathLine == nDrawMode ||
+ SdrObjKind::PathFill == nDrawMode ||
+ SdrObjKind::FreehandLine == nDrawMode ||
+ SdrObjKind::FreehandFill == nDrawMode;
+ if(rMEvt.IsRight())
+ {
+ m_pSh->BreakCreate();
+ m_pView->LeaveDrawCreate();
+ }
+ else
+ {
+ if (SdrObjKind::NewFrame == nDrawMode)
+ {
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UndoArg1, SwResId(STR_FRAME));
+ m_pSh->StartUndo(SwUndoId::INSERT, &aRewriter);
+ }
+
+ bool didCreate = m_pSh->EndCreate(SdrCreateCmd::ForceEnd);
+ if(!didCreate && !bMultiPoint)
+ {
+ CreateDefaultObjectAtPosWithSize(aPnt, Size(1000, 1000));
+ }
+
+ if (SdrObjKind::NewFrame == nDrawMode) // Text border inserted
+ {
+ uno::Reference< frame::XDispatchRecorder > xRecorder =
+ m_pSh->GetView().GetViewFrame().GetBindings().GetRecorder();
+ if ( xRecorder.is() )
+ {
+ SfxRequest aReq(m_pSh->GetView().GetViewFrame(), FN_INSERT_FRAME);
+ aReq .AppendItem(SfxUInt16Item( FN_INSERT_FRAME,
+ static_cast<sal_uInt16>(RndStdIds::FLY_AT_PARA) ));
+ aReq.AppendItem(SfxPointItem( FN_PARAM_1, m_pSh->GetAnchorObjDiff()));
+ aReq.AppendItem(SvxSizeItem( FN_PARAM_2, m_pSh->GetObjSize()));
+ aReq.Done();
+ }
+ bAutoCap = true;
+ if(m_pWin->GetFrameColCount() > 1)
+ {
+ SfxItemSetFixed<RES_COL,RES_COL> aSet(m_pView->GetPool());
+ SwFormatCol aCol(aSet.Get(RES_COL));
+ aCol.Init(m_pWin->GetFrameColCount(), aCol.GetGutterWidth(), aCol.GetWishWidth());
+ aSet.Put(aCol);
+ // Template AutoUpdate
+ SwFrameFormat* pFormat = m_pSh->GetSelectedFrameFormat();
+ if(pFormat && pFormat->IsAutoUpdateOnDirectFormat())
+ m_pSh->AutoUpdateFrame(pFormat, aSet);
+ else
+ m_pSh->SetFlyFrameAttr( aSet );
+ }
+ }
+ if (m_pWin->GetSdrDrawMode() == SdrObjKind::NewFrame)
+ {
+ m_pSh->EndUndo();
+ }
+ }
+
+ bReturn = true;
+
+ EnterSelectMode(rMEvt);
+ }
+ else
+ {
+ SdrView *pSdrView = m_pSh->GetDrawView();
+
+ if (!pSdrView->HasMarkablePoints())
+ {
+ // NO BEZIER_EDITOR
+ if ((m_pSh->GetDrawView()->IsMarkObj() || m_pSh->GetDrawView()->IsMarkPoints())
+ && rMEvt.IsLeft())
+ {
+ bReturn = m_pSh->EndMark();
+
+ m_pWin->SetDrawAction(false);
+
+ if (aPnt == m_aStartPos && m_pSh->IsObjSelectable(aPnt))
+ {
+ m_pSh->SelectObj(aPnt, ( rMEvt.IsShift() &&
+ m_pSh->IsSelFrameMode()) ? SW_ADD_SELECT : 0);
+
+ if (!m_pSh->IsObjSelected())
+ {
+ m_pView->LeaveDrawCreate(); // Switch to selection mode
+
+ m_pSh->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW);
+
+ if (m_pSh->IsSelFrameMode())
+ m_pSh->LeaveSelFrameMode();
+ }
+ m_pView->NoRotate();
+
+ bCheckShell = true; // if necessary turn on BezierShell
+ }
+ else if (!m_pSh->IsObjSelected() && !m_pWin->IsDrawAction())
+ {
+ if (m_pSh->IsObjSelectable(aPnt))
+ m_pSh->SelectObj(aPnt, ( rMEvt.IsShift() &&
+ m_pSh->IsSelFrameMode() ) ? SW_ADD_SELECT : 0 );
+ else
+ {
+ m_pView->LeaveDrawCreate();
+ if (m_pSh->IsSelFrameMode())
+ m_pSh->LeaveSelFrameMode();
+ }
+ m_pView->NoRotate();
+
+ bReturn = true;
+ }
+ }
+ }
+ else
+ {
+ // BEZIER_EDITOR
+ if ( pSdrView->IsAction() )
+ {
+ if ( pSdrView->IsInsObjPoint() )
+ bReturn = pSdrView->EndInsObjPoint(SdrCreateCmd::ForceEnd);
+ else if (pSdrView->IsMarkPoints() )
+ bReturn = pSdrView->EndMarkPoints();
+ else
+ {
+ pSdrView->EndAction();
+ bReturn = true;
+ }
+ m_pWin->SetDrawAction(false);
+
+ if (aPnt == m_aStartPos)
+ {
+ if (!m_pSh->IsObjSelectable(aPnt))
+ m_pSh->SelectObj(Point(LONG_MAX, LONG_MAX));
+ else if (!bReturn)
+ {
+ if (!rMEvt.IsShift())
+ pSdrView->UnmarkAllPoints();
+ m_pSh->SelectObj(aPnt, (rMEvt.IsShift() &&
+ m_pSh->IsSelFrameMode()) ? SW_ADD_SELECT :0);
+ }
+
+ if (!m_pSh->IsObjSelected())
+ {
+ m_pView->LeaveDrawCreate(); // Switch to selection mode
+
+ m_pSh->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW);
+
+ if (m_pSh->IsSelFrameMode())
+ m_pSh->LeaveSelFrameMode();
+ }
+ m_pView->NoRotate();
+
+ bCheckShell = true; // if necessary turn on BezierShell
+ }
+ }
+
+ SetDrawPointer();
+
+ if (!m_pSh->IsObjSelected() && !m_pWin->IsDrawAction())
+ {
+ m_pView->LeaveDrawCreate();
+ if (m_pSh->IsSelFrameMode())
+ m_pSh->LeaveSelFrameMode();
+
+ m_pView->NoRotate();
+ bReturn = true;
+ }
+ }
+ }
+
+ if (bCheckShell)
+ m_pView->AttrChangedNotify(nullptr); // if necessary turn on BezierShell
+
+ //!!!!!!!!!! Attention suicide !!!!!!!!!!! Everything should be renewed once
+ if ( bAutoCap )
+ m_pView->AutoCaption(FRAME_CAP); //Can currently only be FRAME, otherwise convert
+ // to enums
+ return bReturn;
+}
+
+void SwDrawBase::Activate(const sal_uInt16 nSlot)
+{
+ SetSlotId(nSlot);
+ SdrView *pSdrView = m_pSh->GetDrawView();
+
+ pSdrView->SetCurrentObj(m_pWin->GetSdrDrawMode());
+ pSdrView->SetEditMode(false);
+
+ SetDrawPointer();
+ m_pSh->NoEdit();
+}
+
+void SwDrawBase::Deactivate()
+{
+ SdrView *pSdrView = m_pSh->GetDrawView();
+ pSdrView->SetOrtho(false);
+ pSdrView->SetAngleSnapEnabled(false);
+
+ if (m_pWin->IsDrawAction() && m_pSh->IsDrawCreate())
+ m_pSh->BreakCreate();
+
+ m_pWin->SetDrawAction(false);
+
+ if (m_pWin->IsMouseCaptured())
+ m_pWin->ReleaseMouse();
+ g_bNoInterrupt = false;
+
+ if (m_pWin->GetApplyTemplate())
+ m_pWin->SetApplyTemplate(SwApplyTemplate());
+ m_pSh->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW);
+}
+
+// Process keyboard events
+
+// If a KeyEvent is processed then the return value is true, otherwise
+// false.
+
+void SwDrawBase::BreakCreate()
+{
+ m_pSh->BreakCreate();
+ m_pWin->SetDrawAction(false);
+ m_pWin->ReleaseMouse();
+
+ Deactivate();
+}
+
+void SwDrawBase::SetDrawPointer()
+{
+ SdrView *pSdrView = m_pSh->GetDrawView();
+ Point aPnt(m_pWin->OutputToScreenPixel(m_pWin->GetPointerPosPixel()));
+ aPnt = m_pWin->PixelToLogic(m_pWin->ScreenToOutputPixel(aPnt));
+ PointerStyle aPointTyp = pSdrView->GetPreferredPointer(aPnt, m_pSh->GetOut());
+ m_pWin->SetPointer(aPointTyp);
+}
+
+// If necessary switch into selection mode
+
+void SwDrawBase::EnterSelectMode(const MouseEvent& rMEvt)
+{
+ m_pWin->SetDrawAction(false);
+
+ if (m_pSh->IsObjSelected() || m_pWin->IsDrawAction())
+ return;
+
+ Point aPnt(m_pWin->PixelToLogic(rMEvt.GetPosPixel()));
+
+ if (m_pSh->IsObjSelectable(aPnt))
+ {
+ m_pSh->SelectObj(aPnt);
+ if (rMEvt.GetModifier() == KEY_SHIFT || !m_pSh->IsObjSelected())
+ {
+ m_pView->LeaveDrawCreate(); // Switch to selection mode
+
+ m_pSh->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW);
+ }
+ }
+ else
+ {
+ m_pView->LeaveDrawCreate();
+ if (m_pSh->IsSelFrameMode())
+ m_pSh->LeaveSelFrameMode();
+ }
+ m_pView->NoRotate();
+}
+
+void SwDrawBase::CreateDefaultObject()
+{
+ constexpr tools::Long constTwips_3cm = o3tl::toTwips(3, o3tl::Length::cm);
+
+ Point aStartPos = GetDefaultCenterPos();
+ Point aEndPos(aStartPos);
+ aStartPos.AdjustX(-constTwips_3cm);
+ aStartPos.AdjustY(-constTwips_3cm);
+ aEndPos.AdjustX(constTwips_3cm);
+ aEndPos.AdjustY(constTwips_3cm);
+ tools::Rectangle aRect(aStartPos, aEndPos);
+ m_pSh->CreateDefaultShape(m_pWin->GetSdrDrawMode(), aRect, m_nSlotId);
+}
+
+void SwDrawBase::CreateDefaultObjectAtPosWithSize(Point aPos, Size aSize)
+{
+ aPos.AdjustX(-sal_Int32(aSize.getWidth() / 2));
+ aPos.AdjustY(-sal_Int32(aSize.getHeight() / 2));
+
+ SdrView* sdrView = m_pView->GetDrawView();
+ SdrPageView *pPV = sdrView->GetSdrPageView();
+
+ if(sdrView->IsSnapEnabled())
+ aPos = sdrView->GetSnapPos(aPos, pPV);
+
+ ::tools::Rectangle aNewObjectRectangle(aPos, aSize);
+ m_pSh->CreateDefaultShape(m_pWin->GetSdrDrawMode(), aNewObjectRectangle, m_nSlotId);
+}
+
+Point SwDrawBase::GetDefaultCenterPos() const
+{
+ Size aDocSz(m_pSh->GetDocSize());
+
+ SwRect aVisArea(m_pSh->VisArea());
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ aVisArea = SwRect(m_pSh->getLOKVisibleArea());
+ aVisArea.Intersection(SwRect(Point(), aDocSz));
+ }
+
+ Point aCenter = aVisArea.Center();
+ // To increase the chance that aCenter actually falls somewhere on a page (rather than on the
+ // background between pages), keep it centered horizontally for the "Single-page view"
+ // (GetViewLayoutColumns() == 1) and "Book view" (GetViewLayoutColumns() == 2) cases that
+ // display the pages centered on the background:
+ if (aVisArea.Width() > aDocSz.Width() && m_pSh->GetViewOptions()->GetViewLayoutColumns() == 0)
+ aCenter.setX(aDocSz.Width() / 2 + aVisArea.Left());
+ if (aVisArea.Height() > aDocSz.Height())
+ aCenter.setY(aDocSz.Height() / 2 + aVisArea.Top());
+
+ return aCenter;
+}
+
+// #i33136#
+bool SwDrawBase::doConstructOrthogonal() const
+{
+ return ( m_nSlotId == SID_DRAW_XPOLYGON || m_nSlotId == SID_DRAW_XPOLYGON_NOFILL || m_nSlotId == SID_DRAW_XLINE );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/ribbar/dselect.cxx b/sw/source/uibase/ribbar/dselect.cxx
new file mode 100644
index 0000000000..abbebc0445
--- /dev/null
+++ b/sw/source/uibase/ribbar/dselect.cxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <view.hxx>
+#include <edtwin.hxx>
+#include <wrtsh.hxx>
+#include <cmdid.h>
+#include <drawbase.hxx>
+#include <dselect.hxx>
+
+DrawSelection::DrawSelection(SwWrtShell* pWrtShell, SwEditWin* pEditWin, SwView* pSwView)
+ : SwDrawBase(pWrtShell, pEditWin, pSwView)
+{
+ m_bCreateObj = false;
+}
+
+void DrawSelection::Activate(const sal_uInt16 nSlotId)
+{
+ m_pWin->SetSdrDrawMode(SdrObjKind::NONE);
+ m_pWin->SetObjectSelect(true);
+ SwDrawBase::Activate(nSlotId);
+
+ m_pSh->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/ribbar/inputwin.cxx b/sw/source/uibase/ribbar/inputwin.cxx
new file mode 100644
index 0000000000..92a9f3fb21
--- /dev/null
+++ b/sw/source/uibase/ribbar/inputwin.cxx
@@ -0,0 +1,640 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <osl/diagnose.h>
+#include <comphelper/string.hxx>
+#include <o3tl/safeint.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <tools/gen.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/dispatch.hxx>
+#include <svx/ruler.hxx>
+#include <svl/stritem.hxx>
+#include <vcl/event.hxx>
+#include <vcl/weldutils.hxx>
+
+#include <swtypes.hxx>
+#include <cmdid.h>
+#include <swmodule.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <inputwin.hxx>
+#include <fldbas.hxx>
+#include <fldmgr.hxx>
+#include <frmfmt.hxx>
+#include <cellatr.hxx>
+#include <edtwin.hxx>
+#include <helpids.h>
+#include <strings.hrc>
+#include <bitmaps.hlst>
+
+// Only for the UpdateRange: Delete the box in which the stacked cursor is positioned.
+#include <pam.hxx>
+
+#include <swundo.hxx>
+
+#include <IDocumentContentOperations.hxx>
+
+constexpr ToolBoxItemId ED_POS(2);
+constexpr ToolBoxItemId ED_FORMULA(3);
+constexpr ToolBoxItemId FN_FORMULA_CALC(FN_FORMAT + 156); /* select formula */
+constexpr ToolBoxItemId FN_FORMULA_CANCEL(FN_FORMAT + 157); /* don't apply formula */
+constexpr ToolBoxItemId FN_FORMULA_APPLY(FN_FORMAT + 158); /* apply formula */
+
+SFX_IMPL_POS_CHILDWINDOW_WITHID( SwInputChild, FN_EDIT_FORMULA, SFX_OBJECTBAR_OBJECT )
+
+IMPL_LINK(PosEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool)
+{
+ return ChildKeyInput(rKEvt);
+}
+
+SwInputWindow::SwInputWindow(vcl::Window* pParent, SfxDispatcher const * pDispatcher)
+ : ToolBox(pParent, WB_3DLOOK|WB_BORDER)
+ , mxPos(VclPtr<PosEdit>::Create(this))
+ , mxEdit(VclPtr<InputEdit>::Create(this))
+ , m_pWrtShell(nullptr)
+ , m_pView(nullptr)
+ , m_bDoesUndo(true)
+ , m_bResetUndo(false)
+ , m_bCallUndo(false)
+{
+ m_bFirst = true;
+ m_bIsTable = m_bDelSel = false;
+
+ InsertItem(FN_FORMULA_CALC, Image(StockImage::Yes, RID_BMP_FORMULA_CALC),
+ SwResId(STR_FORMULA_CALC));
+ InsertItem(FN_FORMULA_CANCEL, Image(StockImage::Yes, RID_BMP_FORMULA_CANCEL),
+ SwResId(STR_FORMULA_CANCEL));
+ InsertItem(FN_FORMULA_APPLY, Image(StockImage::Yes, RID_BMP_FORMULA_APPLY),
+ SwResId(STR_FORMULA_APPLY));
+
+ SetHelpId(FN_FORMULA_CALC, HID_TBX_FORMULA_CALC);
+ SetHelpId(FN_FORMULA_CANCEL, HID_TBX_FORMULA_CANCEL);
+ SetHelpId(FN_FORMULA_APPLY, HID_TBX_FORMULA_APPLY);
+
+ SwView *pDispatcherView = dynamic_cast<SwView*>(pDispatcher ? pDispatcher->GetFrame()->GetViewShell() : nullptr);
+ SwView* pActiveView = ::GetActiveView();
+ if (pDispatcherView == pActiveView)
+ m_pView = pActiveView;
+ m_pWrtShell = m_pView ? m_pView->GetWrtShellPtr() : nullptr;
+
+ InsertWindow(ED_POS, mxPos.get(), ToolBoxItemBits::NONE, 0);
+ SetItemText(ED_POS, SwResId(STR_ACCESS_FORMULA_TYPE));
+ mxPos->set_accessible_name(SwResId(STR_ACCESS_FORMULA_TYPE));
+ SetAccessibleName(SwResId(STR_ACCESS_FORMULA_TOOLBAR));
+ InsertSeparator ( 1 );
+ InsertSeparator ();
+ InsertWindow(ED_FORMULA, mxEdit.get());
+ SetItemText(ED_FORMULA, SwResId(STR_ACCESS_FORMULA_TEXT));
+ mxEdit->set_accessible_name(SwResId(STR_ACCESS_FORMULA_TEXT));
+ SetHelpId(ED_FORMULA, HID_EDIT_FORMULA);
+
+ SetItemBits( FN_FORMULA_CALC, GetItemBits( FN_FORMULA_CALC ) | ToolBoxItemBits::DROPDOWNONLY );
+ SetDropdownClickHdl( LINK( this, SwInputWindow, DropdownClickHdl ));
+
+ Size aSizeTbx = CalcWindowSizePixel();
+ Size aEditSize = mxEdit->GetSizePixel();
+ tools::Rectangle aItemRect( GetItemRect(FN_FORMULA_CALC) );
+ tools::Long nMaxHeight = std::max(aEditSize.Height(), aItemRect.GetHeight());
+ if( nMaxHeight+2 > aSizeTbx.Height() )
+ aSizeTbx.setHeight( nMaxHeight+2 );
+ Size aSize = GetSizePixel();
+ aSize.setHeight( aSizeTbx.Height() );
+ SetSizePixel( aSize );
+
+ // align edit and item vcentered
+ Size aPosSize = mxPos->GetSizePixel();
+ aPosSize.setHeight( nMaxHeight );
+ aEditSize.setHeight( nMaxHeight );
+ Point aPosPos = mxPos->GetPosPixel();
+ Point aEditPos = mxEdit->GetPosPixel();
+ aPosPos.setY( (aSize.Height() - nMaxHeight)/2 + 1 );
+ aEditPos.setY( (aSize.Height() - nMaxHeight)/2 + 1 );
+ mxPos->SetPosSizePixel( aPosPos, aPosSize );
+ mxEdit->SetPosSizePixel( aEditPos, aEditSize );
+}
+
+SwInputWindow::~SwInputWindow()
+{
+ disposeOnce();
+}
+
+void SwInputWindow::dispose()
+{
+ // wake rulers
+ if(m_pView)
+ {
+ m_pView->GetHRuler().SetActive();
+ m_pView->GetVRuler().SetActive();
+ }
+ m_pMgr.reset();
+ if(m_pWrtShell)
+ m_pWrtShell->EndSelTableCells();
+
+ CleanupUglyHackWithUndo();
+
+ mxPos.disposeAndClear();
+ mxEdit.disposeAndClear();
+ ToolBox::dispose();
+}
+
+void SwInputWindow::CleanupUglyHackWithUndo()
+{
+ if (!m_bResetUndo)
+ return;
+
+ if (m_pWrtShell)
+ {
+ DelBoxContent();
+ m_pWrtShell->DoUndo(m_bDoesUndo);
+ if (m_bCallUndo)
+ {
+ m_pWrtShell->Undo();
+ }
+ }
+ m_bResetUndo = false; // #i117122# once is enough :)
+}
+
+void SwInputWindow::Resize()
+{
+ ToolBox::Resize();
+
+ tools::Long nWidth = GetSizePixel().Width();
+ tools::Long nLeft = mxEdit->GetPosPixel().X();
+ Size aEditSize = mxEdit->GetSizePixel();
+
+ aEditSize.setWidth( std::max( static_cast<tools::Long>(nWidth - nLeft - 5), tools::Long(0) ) );
+ mxEdit->SetSizePixel( aEditSize );
+}
+
+void SwInputWindow::ShowWin()
+{
+ m_bIsTable = false;
+ // stop rulers
+ if (m_pView && m_pWrtShell)
+ {
+ m_pView->GetHRuler().SetActive( false );
+ m_pView->GetVRuler().SetActive( false );
+
+ // Cursor in table
+ m_bIsTable = m_pWrtShell->IsCursorInTable();
+
+ if( m_bFirst )
+ m_pWrtShell->SelTableCells( LINK( this, SwInputWindow,
+ SelTableCellsNotify) );
+ if( m_bIsTable )
+ {
+ const OUString& rPos = m_pWrtShell->GetBoxNms();
+ sal_Int32 nPos = 0;
+ short nSrch = -1;
+ while( (nPos = rPos.indexOf( ':',nPos + 1 ) ) != -1 )
+ nSrch = static_cast<short>(nPos);
+ mxPos->set_text( rPos.copy( ++nSrch ) );
+ m_aCurrentTableName = m_pWrtShell->GetTableFormat()->GetName();
+ }
+ else
+ mxPos->set_text(SwResId(STR_TBL_FORMULA));
+
+ // Edit current field
+ OSL_ENSURE(m_pMgr == nullptr, "FieldManager not deleted");
+ m_pMgr.reset(new SwFieldMgr);
+
+ // Form should always begin with "=" , so set here
+ OUString sEdit('=');
+ if( m_pMgr->GetCurField() && SwFieldTypesEnum::Formel == m_pMgr->GetCurTypeId() )
+ {
+ sEdit += m_pMgr->GetCurFieldPar2();
+ }
+ else if( m_bFirst && m_bIsTable )
+ {
+ m_bResetUndo = true;
+ SAL_WARN_IF(
+ officecfg::Office::Common::Undo::Steps::get() <= 0,
+ "sw", "/org.openoffice.Office.Common/Undo/Steps <= 0");
+
+ m_bDoesUndo = m_pWrtShell->DoesUndo();
+ if( !m_bDoesUndo )
+ {
+ m_pWrtShell->DoUndo();
+ }
+
+ if( !m_pWrtShell->SwCursorShell::HasSelection() )
+ {
+ m_pWrtShell->MoveSection( GoCurrSection, fnSectionStart );
+ m_pWrtShell->SetMark();
+ m_pWrtShell->MoveSection( GoCurrSection, fnSectionEnd );
+ }
+ if( m_pWrtShell->SwCursorShell::HasSelection() )
+ {
+ m_pWrtShell->StartUndo( SwUndoId::DELETE );
+ m_pWrtShell->Delete(false);
+ if( SwUndoId::EMPTY != m_pWrtShell->EndUndo( SwUndoId::DELETE ))
+ {
+ m_bCallUndo = true;
+ }
+ }
+ m_pWrtShell->DoUndo(false);
+
+ SfxItemSetFixed<RES_BOXATR_FORMULA, RES_BOXATR_FORMULA> aSet( m_pWrtShell->GetAttrPool() );
+ if( m_pWrtShell->GetTableBoxFormulaAttrs( aSet ))
+ {
+ SwTableBoxFormula& rFormula
+ = const_cast<SwTableBoxFormula&>(aSet.Get(RES_BOXATR_FORMULA));
+ // rFormula could be ANY of the table's formulas.
+ // GetFormula returns the "current" formula - which is basically undefined,
+ // so do something that encourages the current position's formula to become current.
+ if (m_pWrtShell->GetCursor())
+ {
+ const SwNode* pNd = m_pWrtShell->GetCursor()->GetPointNode().FindTableNode();
+ if (pNd)
+ {
+ const SwTable& rTable = static_cast<const SwTableNode*>(pNd)->GetTable();
+ // get cell's external formula (for UI) by waving the magic wand.
+ rFormula.PtrToBoxNm(&rTable);
+ }
+ }
+
+ sEdit += rFormula.GetFormula();
+ }
+ }
+
+ if( m_bFirst )
+ {
+ // Set WrtShell flags correctly
+ m_pWrtShell->SttSelect();
+ m_pWrtShell->EndSelect();
+ }
+
+ m_bFirst = false;
+
+ mxEdit->connect_changed( LINK( this, SwInputWindow, ModifyHdl ));
+
+ mxEdit->set_text( sEdit );
+ m_sOldFormula = sEdit;
+
+ // For input cut the UserInterface
+
+ m_pView->GetEditWin().LockKeyInput(true);
+ m_pView->GetViewFrame().GetDispatcher()->Lock(true);
+ m_pWrtShell->Push();
+ }
+
+ ToolBox::Show();
+
+ // grab focus after ToolBox is shown so focus isn't potentially lost elsewhere
+ if (m_pView)
+ {
+ int nPos = mxEdit->get_text().getLength();
+ mxEdit->select_region(nPos, nPos);
+ mxEdit->GrabFocus();
+ }
+}
+
+void SwInputWindow::MenuHdl(std::u16string_view command)
+{
+ if (!command.empty())
+ mxEdit->replace_selection(OUString::Concat(command) + " ");
+}
+
+IMPL_LINK_NOARG(SwInputWindow, DropdownClickHdl, ToolBox *, void)
+{
+ ToolBoxItemId nCurID = GetCurItemId();
+ EndSelection(); // reset back CurItemId !
+ if (nCurID == FN_FORMULA_CALC)
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, "modules/swriter/ui/inputwinmenu.ui"));
+ std::unique_ptr<weld::Menu> xPopMenu(xBuilder->weld_menu("menu"));
+ tools::Rectangle aRect(GetItemRect(FN_FORMULA_CALC));
+ weld::Window* pParent = weld::GetPopupParent(*this, aRect);
+ MenuHdl(xPopMenu->popup_at_rect(pParent, aRect));
+ }
+}
+
+void SwInputWindow::Click( )
+{
+ ToolBoxItemId nCurID = GetCurItemId();
+ EndSelection(); // reset back CurItemId !
+ if ( nCurID == FN_FORMULA_CANCEL )
+ {
+ CancelFormula();
+ }
+ else if (nCurID == FN_FORMULA_APPLY)
+ {
+ ApplyFormula();
+ }
+}
+
+void SwInputWindow::ApplyFormula()
+{
+ // in case it was created while loading the document, the active view
+ // wasn't initialised at that time, so ShowWin() didn't initialise anything
+ // either - nothing to do
+ if (!m_pView || !m_pWrtShell)
+ {
+ // presumably there must be an active view now since the event arrived
+ if (SwView* pView = GetActiveView())
+ {
+ // this just makes the input window go away, so that the next time it works
+ pView->GetViewFrame().GetDispatcher()->Execute(FN_EDIT_FORMULA, SfxCallMode::ASYNCHRON);
+ }
+ return;
+ }
+
+ m_pView->GetViewFrame().GetDispatcher()->Lock(false);
+ m_pView->GetEditWin().LockKeyInput(false);
+ CleanupUglyHackWithUndo();
+ m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
+
+ // Form should always begin with "=", so remove it here again
+ OUString sEdit(comphelper::string::strip(mxEdit->get_text(), ' '));
+ if( !sEdit.isEmpty() && '=' == sEdit[0] )
+ sEdit = sEdit.copy( 1 );
+ SfxStringItem aParam(FN_EDIT_FORMULA, sEdit);
+
+ m_pWrtShell->EndSelTableCells();
+ m_pView->GetEditWin().GrabFocus();
+ const SfxPoolItem* aArgs[2];
+ aArgs[0] = &aParam;
+ aArgs[1] = nullptr;
+ m_pView->GetViewFrame().GetBindings().Execute( FN_EDIT_FORMULA, aArgs, SfxCallMode::ASYNCHRON );
+}
+
+void SwInputWindow::CancelFormula()
+{
+ // in case it was created while loading the document, the active view
+ // wasn't initialised at that time, so ShowWin() didn't initialise anything
+ // either - nothing to do
+ if (!m_pView || !m_pWrtShell)
+ {
+ // presumably there must be an active view now since the event arrived
+ if (SwView* pView = GetActiveView())
+ {
+ // this just makes the input window go away, so that the next time it works
+ pView->GetViewFrame().GetDispatcher()->Execute(FN_EDIT_FORMULA, SfxCallMode::ASYNCHRON);
+ }
+ return;
+ }
+
+ m_pView->GetViewFrame().GetDispatcher()->Lock( false );
+ m_pView->GetEditWin().LockKeyInput(false);
+ CleanupUglyHackWithUndo();
+ m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
+
+ if( m_bDelSel )
+ m_pWrtShell->EnterStdMode();
+
+ m_pWrtShell->EndSelTableCells();
+
+ m_pView->GetEditWin().GrabFocus();
+
+ m_pView->GetViewFrame().GetDispatcher()->Execute( FN_EDIT_FORMULA, SfxCallMode::ASYNCHRON);
+}
+
+const sal_Unicode CH_LRE = 0x202a;
+const sal_Unicode CH_PDF = 0x202c;
+
+IMPL_LINK( SwInputWindow, SelTableCellsNotify, SwWrtShell&, rCaller, void )
+{
+ if(m_pWrtShell && m_bIsTable)
+ {
+ SwFrameFormat* pTableFormat = rCaller.GetTableFormat();
+ OUString sBoxNms( rCaller.GetBoxNms() );
+ OUString sTableNm;
+ if( pTableFormat && m_aCurrentTableName != pTableFormat->GetName() )
+ sTableNm = pTableFormat->GetName();
+
+ mxEdit->UpdateRange( sBoxNms, sTableNm );
+
+ OUString sNew = OUStringChar(CH_LRE) + mxEdit->get_text()
+ + OUStringChar(CH_PDF);
+
+ if( sNew != m_sOldFormula )
+ {
+ // The WrtShell is in the table selection,
+ // then cancel the table selection otherwise, the cursor is
+ // positioned "in the forest" and the live update does not work!
+ m_pWrtShell->StartAllAction();
+
+ SwPaM aPam( *m_pWrtShell->GetStackCursor()->GetPoint() );
+ aPam.Move( fnMoveBackward, GoInSection );
+ aPam.SetMark();
+ aPam.Move( fnMoveForward, GoInSection );
+
+ IDocumentContentOperations& rIDCO = m_pWrtShell->getIDocumentContentOperations();
+ rIDCO.DeleteRange( aPam );
+ rIDCO.InsertString( aPam, sNew );
+ m_pWrtShell->EndAllAction();
+ m_sOldFormula = sNew;
+ }
+ }
+ else
+ mxEdit->GrabFocus();
+}
+
+void SwInputWindow::SetFormula( const OUString& rFormula )
+{
+ OUString sEdit('=');
+ if( !rFormula.isEmpty() )
+ {
+ if( '=' == rFormula[0] )
+ sEdit = rFormula;
+ else
+ sEdit += rFormula;
+ }
+ mxEdit->set_text( sEdit );
+ mxEdit->select_region(sEdit.getLength(), sEdit.getLength());
+ m_bDelSel = true;
+}
+
+IMPL_LINK_NOARG(SwInputWindow, ModifyHdl, weld::Entry&, void)
+{
+ if (m_pWrtShell && m_bIsTable && m_bResetUndo)
+ {
+ m_pWrtShell->StartAllAction();
+ DelBoxContent();
+ OUString sNew = OUStringChar(CH_LRE) + mxEdit->get_text()
+ + OUStringChar(CH_PDF);
+ m_pWrtShell->SwEditShell::Insert2( sNew );
+ m_pWrtShell->EndAllAction();
+ m_sOldFormula = sNew;
+ }
+}
+
+void SwInputWindow::DelBoxContent()
+{
+ if( m_pWrtShell && m_bIsTable )
+ {
+ m_pWrtShell->StartAllAction();
+ m_pWrtShell->ClearMark();
+ m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
+ m_pWrtShell->Push();
+ m_pWrtShell->MoveSection( GoCurrSection, fnSectionStart );
+ m_pWrtShell->SetMark();
+ m_pWrtShell->MoveSection( GoCurrSection, fnSectionEnd );
+ m_pWrtShell->SwEditShell::Delete(false);
+ m_pWrtShell->EndAllAction();
+ }
+}
+
+IMPL_LINK(InputEdit, KeyInputHdl, const KeyEvent&, rEvent, bool)
+{
+ bool bHandled = false;
+ const vcl::KeyCode aCode = rEvent.GetKeyCode();
+ if (aCode == KEY_RETURN || aCode == KEY_F2)
+ {
+ bHandled = ActivateHdl(*m_xWidget);
+ }
+ else if(aCode == KEY_ESCAPE )
+ {
+ static_cast<SwInputWindow*>(GetParent())->CancelFormula();
+ bHandled = true;
+ }
+ return bHandled || ChildKeyInput(rEvent);
+}
+
+IMPL_LINK_NOARG(InputEdit, ActivateHdl, weld::Entry&, bool)
+{
+ static_cast<SwInputWindow*>(GetParent())->ApplyFormula();
+ return true;
+}
+
+void InputEdit::UpdateRange(std::u16string_view rBoxes,
+ const OUString& rName )
+{
+ if( rBoxes.empty() )
+ {
+ GrabFocus();
+ return;
+ }
+ const sal_Unicode cOpen = '<', cClose = '>',
+ cOpenBracket = '(';
+ OUString aPrefix = rName;
+ if(!rName.isEmpty())
+ aPrefix += ".";
+ OUString aBoxes = aPrefix + rBoxes;
+
+ int nSelStartPos, nSelEndPos;
+ m_xWidget->get_selection_bounds(nSelStartPos, nSelEndPos);
+
+ Selection aSelection(nSelStartPos, nSelEndPos);
+ sal_uInt16 nSel = o3tl::narrowing<sal_uInt16>(aSelection.Len());
+ // OS: The following expression ensures that in the overwrite mode,
+ // the selected closing parenthesis will be not deleted.
+ if( nSel && ( nSel > 1 ||
+ m_xWidget->get_text()[ o3tl::narrowing<sal_uInt16>(aSelection.Min()) ] != cClose ))
+ m_xWidget->cut_clipboard();
+ else
+ aSelection.Max() = aSelection.Min();
+ OUString aActText(m_xWidget->get_text());
+ const sal_uInt16 nLen = aActText.getLength();
+ if( !nLen )
+ {
+ OUString aStr = OUStringChar(cOpen) + aBoxes + OUStringChar(cClose);
+ m_xWidget->set_text(aStr);
+ sal_Int32 nPos = aStr.indexOf( cClose );
+ OSL_ENSURE(nPos != -1, "delimiter not found");
+ ++nPos;
+ m_xWidget->select_region(nPos, nPos);
+ }
+ else
+ {
+ bool bFound = false;
+ sal_Unicode cCh;
+ sal_uInt16 nPos, nEndPos = 0, nStartPos = o3tl::narrowing<sal_uInt16>(aSelection.Min());
+ if( nStartPos-- )
+ {
+ do {
+ if( cOpen == (cCh = aActText[ nStartPos ] ) ||
+ cOpenBracket == cCh )
+ {
+ bFound = cCh == cOpen;
+ break;
+ }
+ } while( nStartPos-- > 0 );
+ }
+ if( bFound )
+ {
+ bFound = false;
+ nEndPos = nStartPos;
+ while( nEndPos < nLen )
+ {
+ if( cClose == aActText[ nEndPos ] )
+ {
+ bFound = true;
+ break;
+ }
+ ++nEndPos;
+ }
+ // Only if the current position lies in the range or right behind.
+ if( bFound && ( nStartPos >= o3tl::make_unsigned(aSelection.Max()) ||
+ o3tl::narrowing<sal_uInt16>(aSelection.Max()) > nEndPos + 1 ))
+ bFound = false;
+ }
+ if( bFound )
+ {
+ nPos = ++nStartPos + 1; // We want behind
+ aActText = aActText.replaceAt( nStartPos, nEndPos - nStartPos, aBoxes );
+ nPos = nPos + aBoxes.getLength();
+ }
+ else
+ {
+ OUString aTmp = OUStringChar(cOpen) + aBoxes + OUStringChar(cClose);
+ nPos = o3tl::narrowing<sal_uInt16>(aSelection.Min());
+ aActText = aActText.replaceAt( nPos, 0, aTmp );
+ nPos = nPos + aTmp.getLength();
+ }
+ if( m_xWidget->get_text() != aActText )
+ {
+ m_xWidget->set_text(aActText);
+ m_xWidget->select_region(nPos, nPos);
+ }
+ }
+ GrabFocus();
+
+}
+
+SwInputChild::SwInputChild(vcl::Window* _pParent,
+ sal_uInt16 nId,
+ SfxBindings const * pBindings,
+ SfxChildWinInfo* ) :
+ SfxChildWindow( _pParent, nId )
+{
+ m_pDispatch = pBindings->GetDispatcher();
+ SetWindow(VclPtr<SwInputWindow>::Create(_pParent, m_pDispatch));
+ static_cast<SwInputWindow*>(GetWindow())->ShowWin();
+ SetAlignment(SfxChildAlignment::LOWESTTOP);
+}
+
+SwInputChild::~SwInputChild()
+{
+ if(m_pDispatch)
+ m_pDispatch->Lock(false);
+}
+
+SfxChildWinInfo SwInputChild::GetInfo() const
+{
+ SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
+ return aInfo;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/ribbar/workctrl.cxx b/sw/source/uibase/ribbar/workctrl.cxx
new file mode 100644
index 0000000000..9a9b288e14
--- /dev/null
+++ b/sw/source/uibase/ribbar/workctrl.cxx
@@ -0,0 +1,900 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <i18nutil/unicode.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/bindings.hxx>
+#include <swmodule.hxx>
+#include <utility>
+#include <view.hxx>
+#include <initui.hxx>
+#include <docsh.hxx>
+#include <gloshdl.hxx>
+#include <gloslst.hxx>
+#include <workctrl.hxx>
+#include <strings.hrc>
+#include <cmdid.h>
+#include <helpids.h>
+#include <wrtsh.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <svl/voiditem.hxx>
+#include <vcl/event.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/settings.hxx>
+#include <rtl/ustring.hxx>
+#include <swabstdlg.hxx>
+#include <sfx2/zoomitem.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weldutils.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/strings.hrc>
+#include <bitmaps.hlst>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <com/sun/star/frame/XFrame.hpp>
+
+#include <sfx2/viewfrm.hxx>
+
+// Size check
+#define NAVI_ENTRIES 21
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::frame;
+
+SFX_IMPL_TOOLBOX_CONTROL( SwTbxAutoTextCtrl, SfxVoidItem );
+
+SwTbxAutoTextCtrl::SwTbxAutoTextCtrl(
+ sal_uInt16 nSlotId,
+ ToolBoxItemId nId,
+ ToolBox& rTbx ) :
+ SfxToolBoxControl( nSlotId, nId, rTbx )
+{
+ rTbx.SetItemBits( nId, ToolBoxItemBits::DROPDOWN | rTbx.GetItemBits( nId ) );
+}
+
+SwTbxAutoTextCtrl::~SwTbxAutoTextCtrl()
+{
+}
+
+void SwTbxAutoTextCtrl::CreatePopupWindow()
+{
+ SwView* pView = ::GetActiveView();
+ if(pView && !pView->GetDocShell()->IsReadOnly() &&
+ !pView->GetWrtShell().HasReadonlySel() )
+ {
+ Link<Menu*,bool> aLnk = LINK(this, SwTbxAutoTextCtrl, PopupHdl);
+
+ ScopedVclPtrInstance<PopupMenu> pPopup;
+ SwGlossaryList* pGlossaryList = ::GetGlossaryList();
+ const size_t nGroupCount = pGlossaryList->GetGroupCount();
+ o3tl::sorted_vector<OUString> titles;
+ for(size_t i = 1; i <= nGroupCount; ++i)
+ {
+ OUString sTitle = pGlossaryList->GetGroupTitle(i - 1);
+ const sal_uInt16 nBlockCount = pGlossaryList->GetBlockCount(i -1);
+ auto const [it, _] = titles.insert(sTitle);
+ size_t const menuIndex(::std::distance(titles.begin(), it));
+ if(nBlockCount)
+ {
+ sal_uInt16 nIndex = o3tl::narrowing<sal_uInt16>(100*i);
+ // but insert without extension
+ pPopup->InsertItem(i, sTitle, MenuItemBits::NONE, {}, menuIndex);
+ VclPtrInstance<PopupMenu> pSub;
+ pSub->SetSelectHdl(aLnk);
+ pPopup->SetPopupMenu(i, pSub);
+ for(sal_uInt16 j = 0; j < nBlockCount; j++)
+ {
+ OUString sLongName(pGlossaryList->GetBlockLongName(i - 1, j));
+ OUString sShortName(pGlossaryList->GetBlockShortName(i - 1, j));
+
+ OUString sEntry = sShortName + " - " + sLongName;
+ pSub->InsertItem(++nIndex, sEntry);
+ }
+ }
+ }
+
+ ToolBox* pToolBox = &GetToolBox();
+ ToolBoxItemId nId = GetId();
+ pToolBox->SetItemDown( nId, true );
+
+ pPopup->Execute( pToolBox, pToolBox->GetItemRect( nId ),
+ (pToolBox->GetAlign() == WindowAlign::Top || pToolBox->GetAlign() == WindowAlign::Bottom) ?
+ PopupMenuFlags::ExecuteDown : PopupMenuFlags::ExecuteRight );
+
+ pToolBox->SetItemDown( nId, false );
+ }
+ GetToolBox().EndSelection();
+}
+
+void SwTbxAutoTextCtrl::StateChangedAtToolBoxControl( sal_uInt16,
+ SfxItemState,
+ const SfxPoolItem* pState )
+{
+ GetToolBox().EnableItem( GetId(), (GetItemState(pState) != SfxItemState::DISABLED) );
+}
+
+IMPL_STATIC_LINK(SwTbxAutoTextCtrl, PopupHdl, Menu*, pMenu, bool)
+{
+ sal_uInt16 nId = pMenu->GetCurItemId();
+
+ sal_uInt16 nBlock = nId / 100;
+
+ SwGlossaryList* pGlossaryList = ::GetGlossaryList();
+ OUString sGroup = pGlossaryList->GetGroupName(nBlock - 1);
+ OUString sShortName =
+ pGlossaryList->GetBlockShortName(nBlock - 1, nId - (100 * nBlock) - 1);
+
+ if (SwView* pView = GetActiveView())
+ {
+ SwGlossaryHdl* pGlosHdl = pView->GetGlosHdl();
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ::GlossarySetActGroup fnSetActGroup = pFact->SetGlossaryActGroupFunc();
+ if ( fnSetActGroup )
+ (*fnSetActGroup)( sGroup );
+ pGlosHdl->SetCurGroup(sGroup, true);
+ pGlosHdl->InsertGlossary(sShortName);
+ }
+
+ return false;
+}
+
+// Navigation-Popup
+// determine the order of the toolbox items
+static sal_uInt16 aNavigationInsertIds[ NAVI_ENTRIES ] =
+{
+ NID_TBL,
+ NID_FRM,
+ NID_GRF,
+ NID_OLE,
+ NID_PGE,
+ NID_OUTL,
+ NID_MARK,
+ NID_DRW,
+ NID_CTRL,
+ NID_REG,
+ NID_BKM,
+ NID_SEL,
+ NID_FTN,
+ NID_POSTIT,
+ NID_SRCH_REP,
+ NID_INDEX_ENTRY,
+ NID_TABLE_FORMULA,
+ NID_TABLE_FORMULA_ERROR,
+ NID_RECENCY,
+ NID_FIELD,
+ NID_FIELD_BYTYPE
+};
+
+OUString constexpr aNavigationImgIds[ NAVI_ENTRIES ] =
+{
+ RID_BMP_RIBBAR_TBL,
+ RID_BMP_RIBBAR_FRM,
+ RID_BMP_RIBBAR_GRF,
+ RID_BMP_RIBBAR_OLE,
+ RID_BMP_RIBBAR_PGE,
+ RID_BMP_RIBBAR_OUTL,
+ RID_BMP_RIBBAR_MARK,
+ RID_BMP_RIBBAR_DRW,
+ RID_BMP_RIBBAR_CTRL,
+ RID_BMP_RIBBAR_REG,
+ RID_BMP_RIBBAR_BKM,
+ RID_BMP_RIBBAR_SEL,
+ RID_BMP_RIBBAR_FTN,
+ RID_BMP_RIBBAR_POSTIT,
+ RID_BMP_RIBBAR_REP,
+ RID_BMP_RIBBAR_ENTRY,
+ RID_BMP_RIBBAR_FORMULA,
+ RID_BMP_RIBBAR_ERROR,
+ RID_BMP_RIBBAR_RECENCY,
+ RID_BMP_RIBBAR_FIELD,
+ RID_BMP_RIBBAR_FIELD_BYTYPE
+};
+
+const TranslateId aNavigationStrIds[ NAVI_ENTRIES ] =
+{
+ STR_CONTENT_TYPE_TABLE,
+ STR_CONTENT_TYPE_FRAME,
+ STR_CONTENT_TYPE_GRAPHIC,
+ STR_CONTENT_TYPE_OLE,
+ ST_PGE,
+ STR_CONTENT_TYPE_OUTLINE,
+ ST_MARK,
+ STR_CONTENT_TYPE_DRAWOBJECT,
+ ST_CTRL,
+ STR_CONTENT_TYPE_REGION,
+ STR_CONTENT_TYPE_BOOKMARK,
+ ST_SEL,
+ STR_CONTENT_TYPE_FOOTNOTE,
+ STR_CONTENT_TYPE_POSTIT,
+ ST_SRCH_REP,
+ STR_CONTENT_TYPE_INDEX,
+ ST_TABLE_FORMULA,
+ ST_TABLE_FORMULA_ERROR,
+ ST_RECENCY,
+ STR_CONTENT_TYPE_TEXTFIELD,
+ ST_FIELD_BYTYPE
+};
+
+// these are global strings
+const TranslateId STR_IMGBTN_ARY[] =
+{
+ STR_IMGBTN_TBL_DOWN,
+ STR_IMGBTN_FRM_DOWN,
+ STR_IMGBTN_PGE_DOWN,
+ STR_IMGBTN_DRW_DOWN,
+ STR_IMGBTN_CTRL_DOWN,
+ STR_IMGBTN_REG_DOWN,
+ STR_IMGBTN_BKM_DOWN,
+ STR_IMGBTN_GRF_DOWN,
+ STR_IMGBTN_OLE_DOWN,
+ STR_IMGBTN_OUTL_DOWN,
+ STR_IMGBTN_SEL_DOWN,
+ STR_IMGBTN_FTN_DOWN,
+ STR_IMGBTN_MARK_DOWN,
+ STR_IMGBTN_POSTIT_DOWN,
+ STR_IMGBTN_SRCH_REP_DOWN,
+ STR_IMGBTN_INDEX_ENTRY_DOWN,
+ STR_IMGBTN_TBLFML_DOWN,
+ STR_IMGBTN_TBLFML_ERR_DOWN,
+ STR_IMGBTN_RECENCY_DOWN,
+ STR_IMGBTN_FIELD_DOWN,
+ STR_IMGBTN_FIELD_BYTYPE_DOWN,
+ STR_IMGBTN_TBL_UP,
+ STR_IMGBTN_FRM_UP,
+ STR_IMGBTN_PGE_UP,
+ STR_IMGBTN_DRW_UP,
+ STR_IMGBTN_CTRL_UP,
+ STR_IMGBTN_REG_UP,
+ STR_IMGBTN_BKM_UP,
+ STR_IMGBTN_GRF_UP,
+ STR_IMGBTN_OLE_UP,
+ STR_IMGBTN_OUTL_UP,
+ STR_IMGBTN_SEL_UP,
+ STR_IMGBTN_FTN_UP,
+ STR_IMGBTN_MARK_UP,
+ STR_IMGBTN_POSTIT_UP,
+ STR_IMGBTN_SRCH_REP_UP,
+ STR_IMGBTN_INDEX_ENTRY_UP,
+ STR_IMGBTN_TBLFML_UP,
+ STR_IMGBTN_TBLFML_ERR_UP,
+ STR_IMGBTN_RECENCY_UP,
+ STR_IMGBTN_FIELD_UP,
+ STR_IMGBTN_FIELD_BYTYPE_UP,
+};
+
+static OUString lcl_GetScrollToolTip(bool bNext)
+{
+ sal_uInt16 nResId = SwView::GetMoveType();
+ OUString sToolTip = SwResId(STR_IMGBTN_ARY[(!bNext ? NID_COUNT : 0) + nResId - NID_START]);
+ if (nResId == NID_FIELD_BYTYPE)
+ {
+ OUString sFieldType;
+ SwWrtShell* pWrtSh = GetActiveWrtShell();
+ if (pWrtSh)
+ {
+ SwField* pCurField = pWrtSh->GetCurField(true);
+ if (pCurField)
+ sFieldType = SwFieldType::GetTypeStr(pCurField->GetTypeId());
+ }
+ if (!sFieldType.isEmpty())
+ sToolTip = sToolTip.replaceFirst(u"%FIELDTYPE", sFieldType);
+ else
+ sToolTip = SwResId(SW_STR_NONE);
+ }
+ return sToolTip;
+}
+
+namespace {
+
+class SwZoomBox_Impl final : public InterimItemWindow
+{
+ std::unique_ptr<weld::ComboBox> m_xWidget;
+ sal_uInt16 m_nSlotId;
+ bool m_bRelease;
+
+ DECL_LINK(SelectHdl, weld::ComboBox&, void);
+ DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
+ DECL_LINK(ActivateHdl, weld::ComboBox&, bool);
+ DECL_LINK(FocusOutHdl, weld::Widget&, void);
+
+ void Select();
+
+ void ReleaseFocus();
+
+public:
+ SwZoomBox_Impl(vcl::Window* pParent, sal_uInt16 nSlot);
+
+ virtual void dispose() override
+ {
+ m_xWidget.reset();
+ InterimItemWindow::dispose();
+ }
+
+ void save_value()
+ {
+ m_xWidget->save_value();
+ }
+
+ void set_entry_text(const OUString& rText)
+ {
+ m_xWidget->set_entry_text(rText);
+ }
+
+ virtual ~SwZoomBox_Impl() override
+ {
+ disposeOnce();
+ }
+};
+
+}
+
+SwZoomBox_Impl::SwZoomBox_Impl(vcl::Window* pParent, sal_uInt16 nSlot)
+ : InterimItemWindow(pParent, "modules/swriter/ui/zoombox.ui", "ZoomBox")
+ , m_xWidget(m_xBuilder->weld_combo_box("zoom"))
+ , m_nSlotId(nSlot)
+ , m_bRelease(true)
+{
+ InitControlBase(m_xWidget.get());
+
+ m_xWidget->set_help_id(HID_PVIEW_ZOOM_LB);
+ m_xWidget->set_entry_completion(false);
+ m_xWidget->connect_changed(LINK(this, SwZoomBox_Impl, SelectHdl));
+ m_xWidget->connect_key_press(LINK(this, SwZoomBox_Impl, KeyInputHdl));
+ m_xWidget->connect_entry_activate(LINK(this, SwZoomBox_Impl, ActivateHdl));
+ m_xWidget->connect_focus_out(LINK(this, SwZoomBox_Impl, FocusOutHdl));
+
+ const TranslateId aZoomValues[] =
+ { RID_SVXSTR_ZOOM_25 , RID_SVXSTR_ZOOM_50 ,
+ RID_SVXSTR_ZOOM_75 , RID_SVXSTR_ZOOM_100 ,
+ RID_SVXSTR_ZOOM_150 , RID_SVXSTR_ZOOM_200 ,
+ RID_SVXSTR_ZOOM_WHOLE_PAGE, RID_SVXSTR_ZOOM_PAGE_WIDTH ,
+ RID_SVXSTR_ZOOM_OPTIMAL_VIEW };
+ for(const TranslateId& pZoomValue : aZoomValues)
+ {
+ OUString sEntry = SvxResId(pZoomValue);
+ m_xWidget->append_text(sEntry);
+ }
+
+ int nWidth = m_xWidget->get_pixel_size(SvxResId(RID_SVXSTR_ZOOM_200)).Width();
+ m_xWidget->set_entry_width_chars(std::ceil(nWidth / m_xWidget->get_approximate_digit_width()));
+
+ SetSizePixel(m_xWidget->get_preferred_size());
+}
+
+IMPL_LINK(SwZoomBox_Impl, SelectHdl, weld::ComboBox&, rComboBox, void)
+{
+ if (rComboBox.changed_by_direct_pick()) // only when picked from the list
+ Select();
+}
+
+IMPL_LINK_NOARG(SwZoomBox_Impl, ActivateHdl, weld::ComboBox&, bool)
+{
+ Select();
+ return true;
+}
+
+void SwZoomBox_Impl::Select()
+{
+ if( FN_PREVIEW_ZOOM == m_nSlotId )
+ {
+ bool bNonNumeric = true;
+
+ OUString sEntry = m_xWidget->get_active_text().replaceAll("%", "");
+ SvxZoomItem aZoom(SvxZoomType::PERCENT,100);
+ if(sEntry == SvxResId( RID_SVXSTR_ZOOM_PAGE_WIDTH ) )
+ aZoom.SetType(SvxZoomType::PAGEWIDTH);
+ else if(sEntry == SvxResId( RID_SVXSTR_ZOOM_OPTIMAL_VIEW ) )
+ aZoom.SetType(SvxZoomType::OPTIMAL);
+ else if(sEntry == SvxResId( RID_SVXSTR_ZOOM_WHOLE_PAGE) )
+ aZoom.SetType(SvxZoomType::WHOLEPAGE);
+ else
+ {
+ bNonNumeric = false;
+
+ sal_uInt16 nZoom = o3tl::narrowing<sal_uInt16>(sEntry.toInt32());
+ if(nZoom < MINZOOM)
+ nZoom = MINZOOM;
+ if(nZoom > MAXZOOM)
+ nZoom = MAXZOOM;
+ aZoom.SetValue(nZoom);
+ }
+
+ if (bNonNumeric)
+ {
+ // put old value back, in case its effectively the same
+ // as the picked option and no update to number comes
+ // back from writer
+ m_xWidget->set_entry_text(m_xWidget->get_saved_value());
+ }
+
+ if (SfxObjectShell* pCurrentShell = SfxObjectShell::Current())
+ {
+ pCurrentShell->GetDispatcher()->ExecuteList(SID_ATTR_ZOOM,
+ SfxCallMode::ASYNCHRON, { &aZoom });
+ }
+ }
+ ReleaseFocus();
+}
+
+IMPL_LINK(SwZoomBox_Impl, KeyInputHdl, const KeyEvent&, rKEvt, bool)
+{
+ bool bHandled = false;
+
+ sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
+
+ switch (nCode)
+ {
+ case KEY_TAB:
+ m_bRelease = false;
+ Select();
+ break;
+
+ case KEY_ESCAPE:
+ m_xWidget->set_entry_text(m_xWidget->get_saved_value());
+ ReleaseFocus();
+ bHandled = true;
+ break;
+ }
+
+ return bHandled || ChildKeyInput(rKEvt);
+}
+
+IMPL_LINK_NOARG(SwZoomBox_Impl, FocusOutHdl, weld::Widget&, void)
+{
+ if (!m_xWidget->has_focus()) // a combobox can be comprised of different subwidget so double-check if none of those has focus
+ m_xWidget->set_entry_text(m_xWidget->get_saved_value());
+}
+
+void SwZoomBox_Impl::ReleaseFocus()
+{
+ if ( !m_bRelease )
+ {
+ m_bRelease = true;
+ return;
+ }
+ SfxViewShell* pCurSh = SfxViewShell::Current();
+
+ if ( pCurSh )
+ {
+ vcl::Window* pShellWnd = pCurSh->GetWindow();
+
+ if ( pShellWnd )
+ pShellWnd->GrabFocus();
+ }
+}
+
+SFX_IMPL_TOOLBOX_CONTROL( SwPreviewZoomControl, SfxUInt16Item);
+
+SwPreviewZoomControl::SwPreviewZoomControl(
+ sal_uInt16 nSlotId,
+ ToolBoxItemId nId,
+ ToolBox& rTbx) :
+ SfxToolBoxControl( nSlotId, nId, rTbx )
+{
+}
+
+SwPreviewZoomControl::~SwPreviewZoomControl()
+{
+}
+
+void SwPreviewZoomControl::StateChangedAtToolBoxControl( sal_uInt16 /*nSID*/,
+ SfxItemState eState,
+ const SfxPoolItem* pState )
+{
+ ToolBoxItemId nId = GetId();
+ GetToolBox().EnableItem( nId, (GetItemState(pState) != SfxItemState::DISABLED) );
+ SwZoomBox_Impl* pBox = static_cast<SwZoomBox_Impl*>(GetToolBox().GetItemWindow( GetId() ));
+ if(SfxItemState::DEFAULT <= eState)
+ {
+ OUString sZoom(unicode::formatPercent(static_cast<const SfxUInt16Item*>(pState)->GetValue(),
+ Application::GetSettings().GetUILanguageTag()));
+ pBox->set_entry_text(sZoom);
+ pBox->save_value();
+ }
+}
+
+VclPtr<InterimItemWindow> SwPreviewZoomControl::CreateItemWindow( vcl::Window *pParent )
+{
+ VclPtrInstance<SwZoomBox_Impl> pRet( pParent, GetSlotId() );
+ return pRet.get();
+}
+
+namespace {
+
+class SwJumpToSpecificBox_Impl final : public InterimItemWindow
+{
+ std::unique_ptr<weld::Entry> m_xWidget;
+
+ sal_uInt16 m_nSlotId;
+
+ DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
+ DECL_LINK(SelectHdl, weld::Entry&, bool);
+public:
+ SwJumpToSpecificBox_Impl(vcl::Window* pParent, sal_uInt16 nSlot);
+ virtual void dispose() override
+ {
+ m_xWidget.reset();
+ InterimItemWindow::dispose();
+ }
+ virtual ~SwJumpToSpecificBox_Impl() override
+ {
+ disposeOnce();
+ }
+};
+
+}
+
+IMPL_LINK(SwJumpToSpecificBox_Impl, KeyInputHdl, const KeyEvent&, rKEvt, bool)
+{
+ return ChildKeyInput(rKEvt);
+}
+
+SwJumpToSpecificBox_Impl::SwJumpToSpecificBox_Impl(vcl::Window* pParent, sal_uInt16 nSlot)
+ : InterimItemWindow(pParent, "modules/swriter/ui/jumpposbox.ui", "JumpPosBox")
+ , m_xWidget(m_xBuilder->weld_entry("jumppos"))
+ , m_nSlotId(nSlot)
+{
+ InitControlBase(m_xWidget.get());
+
+ m_xWidget->connect_key_press(LINK(this, SwJumpToSpecificBox_Impl, KeyInputHdl));
+ m_xWidget->connect_activate(LINK(this, SwJumpToSpecificBox_Impl, SelectHdl));
+
+ SetSizePixel(m_xWidget->get_preferred_size());
+}
+
+IMPL_LINK_NOARG(SwJumpToSpecificBox_Impl, SelectHdl, weld::Entry&, bool)
+{
+ OUString sEntry(m_xWidget->get_text());
+ SfxUInt16Item aPageNum(m_nSlotId);
+ aPageNum.SetValue(o3tl::narrowing<sal_uInt16>(sEntry.toInt32()));
+ if (SfxObjectShell* pCurrentShell = SfxObjectShell::Current())
+ {
+ pCurrentShell->GetDispatcher()->ExecuteList(m_nSlotId, SfxCallMode::ASYNCHRON,
+ { &aPageNum });
+ }
+ return true;
+}
+
+SFX_IMPL_TOOLBOX_CONTROL( SwJumpToSpecificPageControl, SfxUInt16Item);
+
+SwJumpToSpecificPageControl::SwJumpToSpecificPageControl(
+ sal_uInt16 nSlotId,
+ ToolBoxItemId nId,
+ ToolBox& rTbx) :
+ SfxToolBoxControl( nSlotId, nId, rTbx )
+{}
+
+SwJumpToSpecificPageControl::~SwJumpToSpecificPageControl()
+{}
+
+VclPtr<InterimItemWindow> SwJumpToSpecificPageControl::CreateItemWindow( vcl::Window *pParent )
+{
+ VclPtrInstance<SwJumpToSpecificBox_Impl> pRet( pParent, GetSlotId() );
+ return pRet.get();
+}
+
+NavElementBox_Base::NavElementBox_Base(std::unique_ptr<weld::ComboBox> xComboBox,
+ uno::Reference<frame::XFrame> xFrame)
+ : m_xComboBox(std::move(xComboBox))
+ ,m_xFrame(std::move(xFrame))
+{
+ m_xComboBox->set_size_request(150, -1);
+
+ m_xComboBox->make_sorted();
+ m_xComboBox->freeze();
+ for (sal_uInt16 i = 0; i < NID_COUNT; i++)
+ m_xComboBox->append(OUString::number(aNavigationInsertIds[i]),
+ SwResId(aNavigationStrIds[i]), aNavigationImgIds[i]);
+ m_xComboBox->thaw();
+
+ m_xComboBox->connect_changed(LINK(this, NavElementBox_Base, SelectHdl));
+ m_xComboBox->connect_key_press(LINK(this, NavElementBox_Base, KeyInputHdl));
+}
+
+NavElementBox_Impl::NavElementBox_Impl(vcl::Window* pParent,
+ const uno::Reference<frame::XFrame>& xFrame)
+ : InterimItemWindow(pParent, "modules/swriter/ui/combobox.ui", "ComboBox")
+ ,NavElementBox_Base(m_xBuilder->weld_combo_box("combobox"), xFrame)
+{
+ SetSizePixel(m_xContainer->get_preferred_size());
+}
+
+void NavElementBox_Base::ReleaseFocus_Impl()
+{
+ if ( m_xFrame.is() && m_xFrame->getContainerWindow().is() )
+ m_xFrame->getContainerWindow()->setFocus();
+}
+
+IMPL_STATIC_LINK(NavElementBox_Base, SelectHdl, weld::ComboBox&, rComboBox, void)
+{
+ if (!rComboBox.changed_by_direct_pick()) // only when picked from the list
+ return;
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if (!pViewFrm)
+ return;
+ SfxUInt32Item aParam(FN_NAV_ELEMENT, rComboBox.get_active_id().toUInt32());
+ const SfxPoolItem* aArgs[2];
+ aArgs[0] = &aParam;
+ aArgs[1] = nullptr;
+ SfxDispatcher* pDispatch = pViewFrm->GetBindings().GetDispatcher();
+ pDispatch->Execute(FN_NAV_ELEMENT, SfxCallMode::SYNCHRON, aArgs);
+}
+
+void NavElementBox_Base::UpdateBox()
+{
+ sal_uInt16 nMoveType = SwView::GetMoveType();
+ for (size_t i = 0; i < SAL_N_ELEMENTS(aNavigationInsertIds); ++i)
+ {
+ if (nMoveType == aNavigationInsertIds[i])
+ {
+ m_xComboBox->set_active_text(SwResId(aNavigationStrIds[i]));
+ break;
+ }
+ }
+}
+
+IMPL_LINK(NavElementBox_Base, KeyInputHdl, const KeyEvent&, rKEvt, bool)
+{
+ return DoKeyInput(rKEvt);
+}
+
+bool NavElementBox_Base::DoKeyInput(const KeyEvent& /*rKEvt*/)
+{
+ return false;
+}
+
+bool NavElementBox_Impl::DoKeyInput(const KeyEvent& rKEvt)
+{
+ if (KEY_ESCAPE == rKEvt.GetKeyCode().GetCode())
+ {
+ ReleaseFocus_Impl();
+ return true;
+ }
+ return ChildKeyInput(rKEvt);
+}
+
+NavElementToolBoxControl::NavElementToolBoxControl( const uno::Reference< uno::XComponentContext >& rxContext )
+ : NavElementToolBoxControl_Base( rxContext,
+ uno::Reference< frame::XFrame >(),
+ ".uno:NavElement" ),
+ m_pBox( nullptr )
+{
+}
+
+// XServiceInfo
+sal_Bool SAL_CALL NavElementToolBoxControl::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService( this, ServiceName );
+}
+
+OUString SAL_CALL NavElementToolBoxControl::getImplementationName()
+{
+ return "lo.writer.NavElementToolBoxController";
+}
+
+uno::Sequence< OUString > SAL_CALL NavElementToolBoxControl::getSupportedServiceNames()
+{
+ return { "com.sun.star.frame.ToolbarController" };
+}
+
+// XComponent
+void SAL_CALL NavElementToolBoxControl::dispose()
+{
+ svt::ToolboxController::dispose();
+
+ SolarMutexGuard aSolarMutexGuard;
+ m_xVclBox.disposeAndClear();
+ m_xWeldBox.reset();
+ m_pBox = nullptr;
+}
+
+// XStatusListener
+void SAL_CALL NavElementToolBoxControl::statusChanged( const frame::FeatureStateEvent& rEvent )
+{
+ if (!m_pBox)
+ return;
+
+ SolarMutexGuard aSolarMutexGuard;
+ if ( rEvent.FeatureURL.Path != "NavElement" )
+ return;
+
+ if ( rEvent.IsEnabled )
+ {
+ m_pBox->set_sensitive(true);
+ m_pBox->UpdateBox();
+ }
+ else
+ m_pBox->set_sensitive(true);
+
+ if (SwView* pView = GetActiveView())
+ {
+ pView->GetViewFrame().GetBindings().Invalidate(FN_SCROLL_NEXT);
+ pView->GetViewFrame().GetBindings().Invalidate(FN_SCROLL_PREV);
+ }
+}
+
+// XToolbarController
+void SAL_CALL NavElementToolBoxControl::execute( sal_Int16 /*KeyModifier*/ )
+{
+}
+
+void SAL_CALL NavElementToolBoxControl::click()
+{
+}
+
+void SAL_CALL NavElementToolBoxControl::doubleClick()
+{
+}
+
+uno::Reference< awt::XWindow > SAL_CALL NavElementToolBoxControl::createPopupWindow()
+{
+ return uno::Reference< awt::XWindow >();
+}
+
+uno::Reference< awt::XWindow > SAL_CALL NavElementToolBoxControl::createItemWindow(
+ const uno::Reference< awt::XWindow >& xParent )
+{
+ uno::Reference< awt::XWindow > xItemWindow;
+
+ if (m_pBuilder)
+ {
+ SolarMutexGuard aSolarMutexGuard;
+
+ std::unique_ptr<weld::ComboBox> xWidget(m_pBuilder->weld_combo_box("NavElementWidget"));
+
+ xItemWindow = css::uno::Reference<css::awt::XWindow>(new weld::TransportAsXWindow(xWidget.get()));
+
+ m_xWeldBox.reset(new NavElementBox_Base(std::move(xWidget), m_xFrame));
+ m_pBox = m_xWeldBox.get();
+ }
+ else
+ {
+ VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow( xParent );
+ if ( pParent )
+ {
+ SolarMutexGuard aSolarMutexGuard;
+ m_xVclBox = VclPtr<NavElementBox_Impl>::Create( pParent, m_xFrame );
+ m_pBox = m_xVclBox.get();
+ xItemWindow = VCLUnoHelper::GetInterface(m_xVclBox);
+ }
+ }
+
+ return xItemWindow;
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+lo_writer_NavElementToolBoxController_get_implementation(
+ css::uno::XComponentContext *rxContext,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire( new NavElementToolBoxControl( rxContext ) );
+}
+
+namespace {
+
+typedef cppu::ImplInheritanceHelper< ::svt::ToolboxController, css::lang::XServiceInfo> PrevNextScrollToolboxController_Base;
+class PrevNextScrollToolboxController : public PrevNextScrollToolboxController_Base
+{
+public:
+ enum Type { PREVIOUS, NEXT };
+
+ PrevNextScrollToolboxController( const css::uno::Reference< css::uno::XComponentContext >& rxContext, Type eType );
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XComponent
+ virtual void SAL_CALL dispose() override;
+
+ // XStatusListener
+ virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override;
+
+private:
+ Type meType;
+};
+
+}
+
+PrevNextScrollToolboxController::PrevNextScrollToolboxController( const css::uno::Reference< css::uno::XComponentContext > & rxContext, Type eType )
+ : PrevNextScrollToolboxController_Base( rxContext,
+ css::uno::Reference< css::frame::XFrame >(),
+ (eType == PREVIOUS) ? OUString( ".uno:ScrollToPrevious" ): OUString( ".uno:ScrollToNext" ) ),
+ meType( eType )
+{
+ addStatusListener(".uno:NavElement");
+}
+
+// XServiceInfo
+OUString SAL_CALL PrevNextScrollToolboxController::getImplementationName()
+{
+ return meType == PrevNextScrollToolboxController::PREVIOUS?
+ OUString( "lo.writer.PreviousScrollToolboxController" ) :
+ OUString( "lo.writer.NextScrollToolboxController" );
+}
+
+sal_Bool SAL_CALL PrevNextScrollToolboxController::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL PrevNextScrollToolboxController::getSupportedServiceNames()
+{
+ return { "com.sun.star.frame.ToolbarController" };
+}
+
+// XComponent
+void SAL_CALL PrevNextScrollToolboxController::dispose()
+{
+ SolarMutexGuard aSolarMutexGuard;
+
+ svt::ToolboxController::dispose();
+}
+
+// XStatusListener
+void SAL_CALL PrevNextScrollToolboxController::statusChanged( const css::frame::FeatureStateEvent& rEvent )
+{
+ if (rEvent.FeatureURL.Path == "NavElement")
+ {
+ if (m_pToolbar)
+ m_pToolbar->set_item_tooltip_text(m_aCommandURL, lcl_GetScrollToolTip(meType != PrevNextScrollToolboxController::PREVIOUS));
+ else
+ {
+ ToolBox* pToolBox = nullptr;
+ ToolBoxItemId nId;
+ if (getToolboxId(nId, &pToolBox))
+ pToolBox->SetQuickHelpText(nId, lcl_GetScrollToolTip(meType != PrevNextScrollToolboxController::PREVIOUS));
+ }
+ }
+ else if (rEvent.FeatureURL.Path == "ScrollToPrevious" || rEvent.FeatureURL.Path == "ScrollToNext")
+ {
+ if (m_pToolbar)
+ m_pToolbar->set_item_sensitive(m_aCommandURL, rEvent.IsEnabled);
+ else
+ {
+ ToolBox* pToolBox = nullptr;
+ ToolBoxItemId nId;
+ if (getToolboxId(nId, &pToolBox))
+ pToolBox->EnableItem(nId, rEvent.IsEnabled);
+ }
+ }
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+lo_writer_PreviousScrollToolboxController_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire( new PrevNextScrollToolboxController( context, PrevNextScrollToolboxController::PREVIOUS ) );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+lo_writer_NextScrollToolboxController_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire( new PrevNextScrollToolboxController( context, PrevNextScrollToolboxController::NEXT ) );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/annotsh.cxx b/sw/source/uibase/shells/annotsh.cxx
new file mode 100644
index 0000000000..5c9ed82b41
--- /dev/null
+++ b/sw/source/uibase/shells/annotsh.cxx
@@ -0,0 +1,1855 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+
+#include <com/sun/star/i18n/TextConversionOption.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/linguistic2/XThesaurus.hpp>
+
+#include <i18nutil/transliteration.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/request.hxx>
+#include <editeng/editund2.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/flstitem.hxx>
+#include <editeng/spltitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/orphitem.hxx>
+#include <editeng/formatbreakitem.hxx>
+#include <editeng/widwitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/escapementitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/adjustitem.hxx>
+#include <editeng/hyphenzoneitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <svx/clipfmtitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/slstitm.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <svl/whiter.hxx>
+#include <svl/cjkoptions.hxx>
+#include <svl/ctloptions.hxx>
+#include <unotools/useroptions.hxx>
+#include <editeng/flditem.hxx>
+#include <svx/hlnkitem.hxx>
+#include <sfx2/htmlmode.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <swundo.hxx>
+#include <doc.hxx>
+#include <viewopt.hxx>
+#include <wrtsh.hxx>
+#include <chrdlgmodes.hxx>
+#include <edtwin.hxx>
+#include <SwRewriter.hxx>
+
+#include <cmdid.h>
+#include <strings.hrc>
+#include <breakit.hxx>
+#include <annotsh.hxx>
+#include <view.hxx>
+#include <PostItMgr.hxx>
+#include <AnnotationWin.hxx>
+
+#include <swtypes.hxx>
+
+#include <svx/svxdlg.hxx>
+
+#include <vcl/EnumContext.hxx>
+#include <svl/itempool.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/editview.hxx>
+#include <osl/diagnose.h>
+
+#include <svl/languageoptions.hxx>
+
+#include <svl/undo.hxx>
+#include <swabstdlg.hxx>
+
+#include <comphelper/string.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <cppuhelper/bootstrap.hxx>
+
+#include <langhelper.hxx>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::i18n;
+
+#define ShellClass_SwAnnotationShell
+
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+
+SFX_IMPL_INTERFACE(SwAnnotationShell, SfxShell)
+
+void SwAnnotationShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Text_Toolbox_Sw);
+
+ GetStaticInterface()->RegisterPopupMenu("annotation");
+}
+
+
+SfxItemPool* SwAnnotationShell::GetAnnotationPool(SwView const & rV)
+{
+ SwWrtShell &rSh = rV.GetWrtShell();
+ return rSh.GetAttrPool().GetSecondaryPool();
+}
+
+SwAnnotationShell::SwAnnotationShell( SwView& r )
+ : m_rView(r)
+{
+ SetPool(SwAnnotationShell::GetAnnotationPool(m_rView));
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Annotation));
+}
+
+SwAnnotationShell::~SwAnnotationShell()
+{
+ if (m_rView.GetWrtShell().CanInsert())
+ m_rView.ShowCursor(true);
+}
+
+SfxUndoManager* SwAnnotationShell::GetUndoManager()
+{
+ SwPostItMgr* pPostItMgr = m_rView.GetPostItMgr();
+ if ( !pPostItMgr ||
+ !pPostItMgr->HasActiveSidebarWin() )
+ {
+ OSL_ENSURE(pPostItMgr,"PostItMgr::Layout(): We are looping forever");
+ return nullptr;
+ }
+ return &pPostItMgr->GetActiveSidebarWin()->GetOutlinerView()->GetOutliner()->GetUndoManager();
+}
+
+void SwAnnotationShell::Exec( SfxRequest &rReq )
+{
+ //TODO: clean this up!!!!
+ SwPostItMgr* pPostItMgr = m_rView.GetPostItMgr();
+ if ( !pPostItMgr || !pPostItMgr->HasActiveSidebarWin() )
+ return;
+
+ OutlinerView* pOLV = pPostItMgr->GetActiveSidebarWin()->GetOutlinerView();
+ SfxItemSet aEditAttr(pOLV->GetAttribs());
+ SfxItemSet aNewAttr(*aEditAttr.GetPool(), aEditAttr.GetRanges());
+
+ sal_uInt16 nSlot = rReq.GetSlot();
+ sal_uInt16 nWhich = GetPool().GetWhich(nSlot);
+ const SfxItemSet *pNewAttrs = rReq.GetArgs();
+ sal_uInt16 nEEWhich = 0;
+ switch (nSlot)
+ {
+ case SID_PARASPACE_INCREASE:
+ case SID_PARASPACE_DECREASE:
+ {
+ SvxULSpaceItem aULSpace( aEditAttr.Get( EE_PARA_ULSPACE ) );
+ sal_uInt16 nUpper = aULSpace.GetUpper();
+ sal_uInt16 nLower = aULSpace.GetLower();
+
+ if ( nSlot == SID_PARASPACE_INCREASE )
+ {
+ nUpper = std::min< sal_uInt16 >( nUpper + 57, 5670 );
+ nLower = std::min< sal_uInt16 >( nLower + 57, 5670 );
+ }
+ else
+ {
+ nUpper = std::max< sal_Int16 >( nUpper - 57, 0 );
+ nLower = std::max< sal_Int16 >( nLower - 57, 0 );
+ }
+
+ aULSpace.SetUpper( nUpper );
+ aULSpace.SetLower( nLower );
+ aNewAttr.Put( aULSpace );
+ rReq.Done();
+ }
+ break;
+ case SID_ATTR_PARA_LRSPACE:
+ {
+ SvxLRSpaceItem aParaMargin(static_cast<const SvxLRSpaceItem&>(rReq.
+ GetArgs()->Get(nSlot)));
+ aParaMargin.SetWhich( EE_PARA_LRSPACE );
+
+ aNewAttr.Put(aParaMargin);
+ rReq.Done();
+ break;
+ }
+ case SID_ATTR_PARA_LINESPACE:
+ {
+ SvxLineSpacingItem aParaMargin = static_cast<const SvxLineSpacingItem&>(pNewAttrs->Get(
+ GetPool().GetWhich(nSlot)));
+ aParaMargin.SetWhich( EE_PARA_SBL );
+
+ aNewAttr.Put(aParaMargin);
+ rReq.Done();
+ break;
+ }
+ case SID_ATTR_PARA_ULSPACE:
+ {
+ SvxULSpaceItem aULSpace = static_cast<const SvxULSpaceItem&>(pNewAttrs->Get(
+ GetPool().GetWhich(nSlot)));
+ aULSpace.SetWhich( EE_PARA_ULSPACE );
+ aNewAttr.Put( aULSpace );
+ rReq.Done();
+ }
+ break;
+ case FN_GROW_FONT_SIZE:
+ case FN_SHRINK_FONT_SIZE:
+ {
+ const SfxObjectShell* pObjSh = SfxObjectShell::Current();
+ const SvxFontListItem* pFontListItem = static_cast<const SvxFontListItem*>
+ (pObjSh ? pObjSh->GetItem(SID_ATTR_CHAR_FONTLIST) : nullptr);
+ const FontList* pFontList = pFontListItem ? pFontListItem->GetFontList() : nullptr;
+ pOLV->GetEditView().ChangeFontSize( nSlot == FN_GROW_FONT_SIZE, pFontList );
+ }
+ break;
+
+ case SID_ATTR_CHAR_FONT:
+ case SID_ATTR_CHAR_FONTHEIGHT:
+ case SID_ATTR_CHAR_WEIGHT:
+ case SID_ATTR_CHAR_POSTURE:
+ {
+ SfxItemPool* pSecondPool = aEditAttr.GetPool()->GetSecondaryPool();
+ if( !pSecondPool )
+ pSecondPool = aEditAttr.GetPool();
+ SvxScriptSetItem aSetItem( nSlot, *pSecondPool );
+ aSetItem.PutItemForScriptType( pOLV->GetSelectedScriptType(), pNewAttrs->Get( nWhich ));
+ aNewAttr.Put( aSetItem.GetItemSet() );
+ rReq.Done();
+ break;
+ }
+ case SID_ATTR_CHAR_COLOR: nEEWhich = EE_CHAR_COLOR; break;
+ case SID_ATTR_CHAR_BACK_COLOR: nEEWhich = EE_CHAR_BKGCOLOR; break;
+ case SID_ATTR_CHAR_UNDERLINE:
+ {
+ if( rReq.GetArgs() )
+ {
+ const SvxUnderlineItem* pItem = rReq.GetArg<SvxUnderlineItem>(SID_ATTR_CHAR_UNDERLINE);
+ if (pItem)
+ {
+ aNewAttr.Put(*pItem);
+ }
+ else
+ {
+ FontLineStyle eFU = aEditAttr.Get( EE_CHAR_UNDERLINE ).GetLineStyle();
+ aNewAttr.Put( SvxUnderlineItem( eFU != LINESTYLE_NONE ?LINESTYLE_NONE : LINESTYLE_SINGLE, EE_CHAR_UNDERLINE ) );
+ }
+ }
+ break;
+ }
+ case SID_ATTR_CHAR_OVERLINE:
+ {
+ FontLineStyle eFO = aEditAttr.Get(EE_CHAR_OVERLINE).GetLineStyle();
+ aNewAttr.Put(SvxOverlineItem(eFO == LINESTYLE_SINGLE ? LINESTYLE_NONE : LINESTYLE_SINGLE, EE_CHAR_OVERLINE));
+ break;
+ }
+ case SID_ATTR_CHAR_CONTOUR: nEEWhich = EE_CHAR_OUTLINE; break;
+ case SID_ATTR_CHAR_SHADOWED: nEEWhich = EE_CHAR_SHADOW; break;
+ case SID_ATTR_CHAR_STRIKEOUT: nEEWhich = EE_CHAR_STRIKEOUT; break;
+ case SID_ATTR_CHAR_WORDLINEMODE: nEEWhich = EE_CHAR_WLM; break;
+ case SID_ATTR_CHAR_RELIEF : nEEWhich = EE_CHAR_RELIEF; break;
+ case SID_ATTR_CHAR_LANGUAGE : nEEWhich = EE_CHAR_LANGUAGE;break;
+ case SID_ATTR_CHAR_KERNING : nEEWhich = EE_CHAR_KERNING; break;
+ case SID_ATTR_CHAR_SCALEWIDTH: nEEWhich = EE_CHAR_FONTWIDTH; break;
+ case SID_ATTR_CHAR_AUTOKERN : nEEWhich = EE_CHAR_PAIRKERNING; break;
+ case SID_ATTR_CHAR_ESCAPEMENT: nEEWhich = EE_CHAR_ESCAPEMENT; break;
+ case SID_ATTR_PARA_ADJUST_LEFT:
+ aNewAttr.Put(SvxAdjustItem(SvxAdjust::Left, EE_PARA_JUST));
+ break;
+ case SID_ATTR_PARA_ADJUST_CENTER:
+ aNewAttr.Put(SvxAdjustItem(SvxAdjust::Center, EE_PARA_JUST));
+ break;
+ case SID_ATTR_PARA_ADJUST_RIGHT:
+ aNewAttr.Put(SvxAdjustItem(SvxAdjust::Right, EE_PARA_JUST));
+ break;
+ case SID_ATTR_PARA_ADJUST_BLOCK:
+ aNewAttr.Put(SvxAdjustItem(SvxAdjust::Block, EE_PARA_JUST));
+ break;
+
+ case SID_ATTR_PARA_LINESPACE_10:
+ {
+ SvxLineSpacingItem aItem(LINE_SPACE_DEFAULT_HEIGHT, EE_PARA_SBL);
+ aItem.SetPropLineSpace(100);
+ aNewAttr.Put(aItem);
+ }
+ break;
+ case SID_ATTR_PARA_LINESPACE_115:
+ {
+ SvxLineSpacingItem aItem(LINE_SPACE_DEFAULT_HEIGHT, EE_PARA_SBL);
+ aItem.SetPropLineSpace(115);
+ aNewAttr.Put(aItem);
+ }
+ break;
+ case SID_ATTR_PARA_LINESPACE_15:
+ {
+ SvxLineSpacingItem aItem(LINE_SPACE_DEFAULT_HEIGHT, EE_PARA_SBL);
+ aItem.SetPropLineSpace(150);
+ aNewAttr.Put(aItem);
+ }
+ break;
+ case SID_ATTR_PARA_LINESPACE_20:
+ {
+ SvxLineSpacingItem aItem(LINE_SPACE_DEFAULT_HEIGHT, EE_PARA_SBL);
+ aItem.SetPropLineSpace(200);
+ aNewAttr.Put(aItem);
+ }
+ break;
+ case SID_SELECTALL:
+ {
+ Outliner * pOutliner = pOLV->GetOutliner();
+ if(pOutliner)
+ {
+ sal_Int32 nParaCount = pOutliner->GetParagraphCount();
+ if (nParaCount > 0)
+ pOLV->SelectRange(0, nParaCount );
+ }
+ break;
+ }
+ case FN_FORMAT_RESET:
+ {
+ pPostItMgr->GetActiveSidebarWin()->ResetAttributes();
+ rReq.Done();
+ break;
+ }
+ case FN_SET_SUPER_SCRIPT:
+ {
+ SvxEscapementItem aItem(EE_CHAR_ESCAPEMENT);
+ SvxEscapement eEsc = static_cast<SvxEscapement>(aEditAttr.Get( EE_CHAR_ESCAPEMENT ).GetEnumValue());
+
+ if( eEsc == SvxEscapement::Superscript )
+ aItem.SetEscapement( SvxEscapement::Off );
+ else
+ aItem.SetEscapement( SvxEscapement::Superscript );
+ aNewAttr.Put( aItem );
+ }
+ break;
+ case FN_SET_SUB_SCRIPT:
+ {
+ SvxEscapementItem aItem(EE_CHAR_ESCAPEMENT);
+ SvxEscapement eEsc = static_cast<SvxEscapement>(aEditAttr.Get( EE_CHAR_ESCAPEMENT ).GetEnumValue());
+
+ if( eEsc == SvxEscapement::Subscript )
+ aItem.SetEscapement( SvxEscapement::Off );
+ else
+ aItem.SetEscapement( SvxEscapement::Subscript );
+ aNewAttr.Put( aItem );
+ }
+ break;
+ case SID_HYPERLINK_SETLINK:
+ {
+ const SfxPoolItem* pItem = nullptr;
+ if(pNewAttrs)
+ pNewAttrs->GetItemState(nSlot, false, &pItem);
+
+ if(pItem)
+ {
+ const SvxHyperlinkItem& rHLinkItem = *static_cast<const SvxHyperlinkItem *>(pItem);
+ SvxURLField aField(rHLinkItem.GetURL(), rHLinkItem.GetName(), SvxURLFormat::AppDefault);
+ aField.SetTargetFrame(rHLinkItem.GetTargetFrame());
+
+ const SvxFieldItem* pFieldItem = pOLV->GetFieldAtSelection();
+
+ if (pFieldItem && dynamic_cast<const SvxURLField *>(pFieldItem->GetField()) != nullptr)
+ {
+ // Select the field so that it will be deleted during insert
+ ESelection aSel = pOLV->GetSelection();
+ aSel.nEndPos++;
+ pOLV->SetSelection(aSel);
+ }
+ if (pPostItMgr->GetActiveSidebarWin()->GetLayoutStatus()!=SwPostItHelper::DELETED)
+ pOLV->InsertField(SvxFieldItem(aField, EE_FEATURE_FIELD));
+ }
+ break;
+ }
+ case FN_INSERT_SOFT_HYPHEN:
+ case FN_INSERT_HARDHYPHEN:
+ case FN_INSERT_HARD_SPACE:
+ case FN_INSERT_NNBSP:
+ case SID_INSERT_RLM :
+ case SID_INSERT_LRM :
+ case SID_INSERT_WJ :
+ case SID_INSERT_ZWSP:
+ {
+ sal_Unicode cIns = 0;
+ switch(rReq.GetSlot())
+ {
+ case FN_INSERT_SOFT_HYPHEN: cIns = CHAR_SOFTHYPHEN; break;
+ case FN_INSERT_HARDHYPHEN: cIns = CHAR_HARDHYPHEN; break;
+ case FN_INSERT_HARD_SPACE: cIns = CHAR_HARDBLANK; break;
+ case FN_INSERT_NNBSP: cIns = CHAR_NNBSP; break;
+ case SID_INSERT_RLM : cIns = CHAR_RLM ; break;
+ case SID_INSERT_LRM : cIns = CHAR_LRM ; break;
+ case SID_INSERT_ZWSP : cIns = CHAR_ZWSP ; break;
+ case SID_INSERT_WJ: cIns = CHAR_WJ; break;
+ }
+ pOLV->InsertText( OUString(cIns));
+ rReq.Done();
+ break;
+ }
+ case SID_CHARMAP:
+ {
+ if (pPostItMgr->GetActiveSidebarWin()->GetLayoutStatus()!=SwPostItHelper::DELETED)
+ InsertSymbol(rReq);
+ break;
+ }
+ case FN_INSERT_STRING:
+ {
+ const SfxPoolItem* pItem = nullptr;
+ if (pNewAttrs)
+ pNewAttrs->GetItemState(nSlot, false, &pItem );
+ if (pItem && pPostItMgr->GetActiveSidebarWin()->GetLayoutStatus()!=SwPostItHelper::DELETED)
+ pOLV->InsertText(static_cast<const SfxStringItem *>(pItem)->GetValue());
+ break;
+ }
+ case FN_FORMAT_FOOTNOTE_DLG:
+ {
+ m_rView.ExecFormatFootnote();
+ break;
+ }
+ case FN_NUMBERING_OUTLINE_DLG:
+ {
+ m_rView.ExecNumberingOutline(GetPool());
+ rReq.Done();
+ }
+ break;
+ case SID_OPEN_XML_FILTERSETTINGS:
+ {
+ HandleOpenXmlFilterSettings(rReq);
+ }
+ break;
+ case FN_WORDCOUNT_DIALOG:
+ {
+ m_rView.UpdateWordCount(this, nSlot);
+ break;
+ }
+ case SID_CHAR_DLG_EFFECT:
+ case SID_CHAR_DLG_POSITION:
+ case SID_CHAR_DLG:
+ {
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxStringItem* pItem = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+
+ if( !pArgs || pItem )
+ {
+ /* mod
+ SwView* pView = &GetView();
+ FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( pView) != nullptr );
+ SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, eMetric));
+ */
+ SfxItemSetFixed<XATTR_FILLSTYLE, XATTR_FILLCOLOR, EE_ITEMS_START, EE_ITEMS_END> aDlgAttr(GetPool());
+
+ // util::Language does not exist in the EditEngine! Therefore not included in the set.
+
+ aDlgAttr.Put( aEditAttr );
+ aDlgAttr.Put( SvxKerningItem(0, RES_CHRATR_KERNING) );
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateSwCharDlg(m_rView.GetFrameWeld(), m_rView, aDlgAttr, SwCharDlgMode::Ann));
+ if (nSlot == SID_CHAR_DLG_EFFECT)
+ {
+ pDlg->SetCurPageId("fonteffects");
+ }
+ if (nSlot == SID_CHAR_DLG_POSITION)
+ {
+ pDlg->SetCurPageId("position");
+ }
+ else if (pItem)
+ {
+ pDlg->SetCurPageId(pItem->GetValue());
+ }
+
+ sal_uInt16 nRet = pDlg->Execute();
+ if(RET_OK == nRet )
+ {
+ rReq.Done( *( pDlg->GetOutputItemSet() ) );
+ aNewAttr.Put(*pDlg->GetOutputItemSet());
+ }
+ if(RET_OK != nRet)
+ return ;
+ }
+ else
+ aNewAttr.Put(*pArgs);
+ break;
+ }
+ case SID_PARA_DLG:
+ {
+ const SfxItemSet* pArgs = rReq.GetArgs();
+
+ if (!pArgs)
+ {
+ /* mod todo ???
+ SwView* pView = &GetView();
+ FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( pView) != nullptr );
+ SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, eMetric));
+ */
+ SfxItemSetFixed<
+ EE_ITEMS_START, EE_ITEMS_END,
+ SID_ATTR_PARA_HYPHENZONE, SID_ATTR_PARA_WIDOWS>
+ aDlgAttr( GetPool() );
+
+ aDlgAttr.Put(aEditAttr);
+
+ aDlgAttr.Put( SvxHyphenZoneItem( false, RES_PARATR_HYPHENZONE) );
+ aDlgAttr.Put( SvxFormatBreakItem( SvxBreak::NONE, RES_BREAK ) );
+ aDlgAttr.Put( SvxFormatSplitItem( true, RES_PARATR_SPLIT ) );
+ aDlgAttr.Put( SvxWidowsItem( 0, RES_PARATR_WIDOWS ) );
+ aDlgAttr.Put( SvxOrphansItem( 0, RES_PARATR_ORPHANS ) );
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateSwParaDlg(m_rView.GetFrameWeld(), m_rView, aDlgAttr, true));
+ sal_uInt16 nRet = pDlg->Execute();
+ if(RET_OK == nRet)
+ {
+ rReq.Done( *( pDlg->GetOutputItemSet() ) );
+ aNewAttr.Put(*pDlg->GetOutputItemSet());
+ }
+ if(RET_OK != nRet)
+ return;
+ }
+ else
+ aNewAttr.Put(*pArgs);
+ break;
+ }
+
+ case SID_AUTOSPELL_CHECK:
+ {
+ m_rView.ExecuteSlot(rReq);
+ break;
+ }
+ case SID_ATTR_PARA_LEFT_TO_RIGHT:
+ case SID_ATTR_PARA_RIGHT_TO_LEFT:
+ {
+ bool bLeftToRight = nSlot == SID_ATTR_PARA_LEFT_TO_RIGHT;
+
+ const SfxPoolItem* pPoolItem;
+ if( pNewAttrs && SfxItemState::SET == pNewAttrs->GetItemState( nSlot, true, &pPoolItem ) )
+ {
+ if( !static_cast<const SfxBoolItem*>(pPoolItem)->GetValue() )
+ bLeftToRight = !bLeftToRight;
+ }
+ SfxItemSetFixed<
+ EE_PARA_WRITINGDIR, EE_PARA_WRITINGDIR,
+ EE_PARA_JUST, EE_PARA_JUST>
+ aAttr( *aNewAttr.GetPool() );
+
+ SvxAdjust nAdjust = SvxAdjust::Left;
+ if( const SvxAdjustItem* pAdjustItem = aEditAttr.GetItemIfSet(EE_PARA_JUST ) )
+ nAdjust = pAdjustItem->GetAdjust();
+
+ if( bLeftToRight )
+ {
+ aAttr.Put( SvxFrameDirectionItem( SvxFrameDirection::Horizontal_LR_TB, EE_PARA_WRITINGDIR ) );
+ if( nAdjust == SvxAdjust::Right )
+ aAttr.Put( SvxAdjustItem( SvxAdjust::Left, EE_PARA_JUST ) );
+ }
+ else
+ {
+ aAttr.Put( SvxFrameDirectionItem( SvxFrameDirection::Horizontal_RL_TB, EE_PARA_WRITINGDIR ) );
+ if( nAdjust == SvxAdjust::Left )
+ aAttr.Put( SvxAdjustItem( SvxAdjust::Right, EE_PARA_JUST ) );
+ }
+ pOLV->SetAttribs(aAttr);
+ break;
+ }
+ }
+
+ if(nEEWhich && pNewAttrs)
+ {
+ aNewAttr.Put(pNewAttrs->Get(nWhich).CloneSetWhich(nEEWhich));
+ }
+ else if (nEEWhich == EE_CHAR_COLOR)
+ {
+ m_rView.GetViewFrame().GetDispatcher()->Execute(SID_CHAR_DLG_EFFECT);
+ }
+ else if (nEEWhich == EE_CHAR_KERNING)
+ {
+ m_rView.GetViewFrame().GetDispatcher()->Execute(SID_CHAR_DLG_POSITION);
+ }
+
+
+ tools::Rectangle aOutRect = pOLV->GetOutputArea();
+ if (tools::Rectangle() != aOutRect && aNewAttr.Count())
+ pOLV->SetAttribs(aNewAttr);
+
+ m_rView.GetViewFrame().GetBindings().InvalidateAll(false);
+ if ( pOLV->GetOutliner()->IsModified() )
+ m_rView.GetWrtShell().SetModified();
+
+}
+
+void SwAnnotationShell::GetState(SfxItemSet& rSet)
+{
+ //TODO: clean this up!!!
+ // FN_SET_SUPER_SCRIPT
+ //SID_ATTR_PARA_ADJUST
+ //SID_ATTR_PARA_ADJUST_BLOCK
+
+ SwPostItMgr* pPostItMgr = m_rView.GetPostItMgr();
+ if ( !pPostItMgr || !pPostItMgr->HasActiveSidebarWin() )
+ return;
+
+ OutlinerView* pOLV = pPostItMgr->GetActiveSidebarWin()->GetOutlinerView();
+ SfxItemSet aEditAttr(pOLV->GetAttribs());
+
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while(nWhich)
+ {
+ sal_uInt16 nEEWhich = 0;
+ sal_uInt16 nSlotId = GetPool().GetSlotId( nWhich );
+ switch( nSlotId )
+ {
+ case SID_ATTR_PARA_LRSPACE:
+ case SID_ATTR_PARA_LEFTSPACE:
+ case SID_ATTR_PARA_RIGHTSPACE:
+ case SID_ATTR_PARA_FIRSTLINESPACE:
+ {
+ SfxItemState eState = aEditAttr.GetItemState( EE_PARA_LRSPACE );
+ if( eState >= SfxItemState::DEFAULT )
+ {
+ SvxLRSpaceItem aLR = aEditAttr.Get( EE_PARA_LRSPACE );
+ aLR.SetWhich(nSlotId);
+ rSet.Put(aLR);
+ }
+ else
+ rSet.InvalidateItem(nSlotId);
+ }
+ break;
+ case SID_ATTR_PARA_LINESPACE:
+ {
+ SfxItemState eState = aEditAttr.GetItemState( EE_PARA_SBL );
+ if( eState >= SfxItemState::DEFAULT )
+ {
+ const SvxLineSpacingItem& aLR = aEditAttr.Get( EE_PARA_SBL );
+ rSet.Put(aLR);
+ }
+ else
+ rSet.InvalidateItem(nSlotId);
+ }
+ break;
+ case SID_ATTR_PARA_ULSPACE:
+ case SID_ATTR_PARA_ABOVESPACE:
+ case SID_ATTR_PARA_BELOWSPACE:
+ case SID_PARASPACE_INCREASE:
+ case SID_PARASPACE_DECREASE:
+ {
+ SfxItemState eState = aEditAttr.GetItemState( EE_PARA_ULSPACE );
+ if( eState >= SfxItemState::DEFAULT )
+ {
+ SvxULSpaceItem aULSpace = aEditAttr.Get( EE_PARA_ULSPACE );
+ if ( !aULSpace.GetUpper() && !aULSpace.GetLower() )
+ rSet.DisableItem( SID_PARASPACE_DECREASE );
+ else if ( aULSpace.GetUpper() >= 5670 && aULSpace.GetLower() >= 5670 )
+ rSet.DisableItem( SID_PARASPACE_INCREASE );
+ if ( nSlotId == SID_ATTR_PARA_ULSPACE
+ || nSlotId == SID_ATTR_PARA_BELOWSPACE
+ || nSlotId == SID_ATTR_PARA_ABOVESPACE
+ )
+ {
+ aULSpace.SetWhich(nSlotId);
+ rSet.Put(aULSpace);
+ }
+ }
+ else
+ {
+ rSet.DisableItem( SID_PARASPACE_INCREASE );
+ rSet.DisableItem( SID_PARASPACE_DECREASE );
+ rSet.InvalidateItem( SID_ATTR_PARA_ULSPACE );
+ rSet.InvalidateItem( SID_ATTR_PARA_ABOVESPACE );
+ rSet.InvalidateItem( SID_ATTR_PARA_BELOWSPACE );
+ }
+ }
+ break;
+ case SID_ATTR_CHAR_FONT:
+ case SID_ATTR_CHAR_FONTHEIGHT:
+ case SID_ATTR_CHAR_WEIGHT:
+ case SID_ATTR_CHAR_POSTURE:
+ {
+ SvtScriptType nScriptType = pOLV->GetSelectedScriptType();
+ SfxItemPool* pSecondPool = aEditAttr.GetPool()->GetSecondaryPool();
+ if( !pSecondPool )
+ pSecondPool = aEditAttr.GetPool();
+ SvxScriptSetItem aSetItem( nSlotId, *pSecondPool );
+ aSetItem.GetItemSet().Put( aEditAttr, false );
+ const SfxPoolItem* pI = aSetItem.GetItemOfScript( nScriptType );
+ if( pI )
+ {
+ rSet.Put(pI->CloneSetWhich(nWhich));
+ }
+ else
+ rSet.InvalidateItem( nWhich );
+ }
+ break;
+ case SID_ATTR_CHAR_COLOR: nEEWhich = EE_CHAR_COLOR; break;
+ case SID_ATTR_CHAR_BACK_COLOR: nEEWhich = EE_CHAR_BKGCOLOR; break;
+ case SID_ATTR_CHAR_UNDERLINE: nEEWhich = EE_CHAR_UNDERLINE;break;
+ case SID_ATTR_CHAR_OVERLINE: nEEWhich = EE_CHAR_OVERLINE;break;
+ case SID_ATTR_CHAR_CONTOUR: nEEWhich = EE_CHAR_OUTLINE; break;
+ case SID_ATTR_CHAR_SHADOWED: nEEWhich = EE_CHAR_SHADOW;break;
+ case SID_ATTR_CHAR_STRIKEOUT: nEEWhich = EE_CHAR_STRIKEOUT;break;
+ case SID_ATTR_CHAR_LANGUAGE : nEEWhich = EE_CHAR_LANGUAGE;break;
+ case SID_ATTR_CHAR_ESCAPEMENT: nEEWhich = EE_CHAR_ESCAPEMENT;break;
+ case SID_ATTR_CHAR_KERNING: nEEWhich = EE_CHAR_KERNING;break;
+ case FN_SET_SUPER_SCRIPT:
+ case FN_SET_SUB_SCRIPT:
+ {
+ SvxEscapement nEsc;
+ if (nWhich==FN_SET_SUPER_SCRIPT)
+ nEsc = SvxEscapement::Superscript;
+ else
+ nEsc = SvxEscapement::Subscript;
+
+ const SfxPoolItem *pEscItem = &aEditAttr.Get( EE_CHAR_ESCAPEMENT );
+ if( nEsc == static_cast<const SvxEscapementItem*>(pEscItem)->GetEscapement() )
+ rSet.Put( SfxBoolItem( nWhich, true ));
+ else
+ rSet.InvalidateItem( nWhich );
+ break;
+ }
+ case SID_ATTR_PARA_ADJUST_LEFT:
+ case SID_ATTR_PARA_ADJUST_RIGHT:
+ case SID_ATTR_PARA_ADJUST_CENTER:
+ case SID_ATTR_PARA_ADJUST_BLOCK:
+ {
+ SvxAdjust eAdjust = SvxAdjust::Left;
+ if (nWhich==SID_ATTR_PARA_ADJUST_LEFT)
+ eAdjust = SvxAdjust::Left;
+ else if (nWhich==SID_ATTR_PARA_ADJUST_RIGHT)
+ eAdjust = SvxAdjust::Right;
+ else if (nWhich==SID_ATTR_PARA_ADJUST_CENTER)
+ eAdjust = SvxAdjust::Center;
+ else if (nWhich==SID_ATTR_PARA_ADJUST_BLOCK)
+ eAdjust = SvxAdjust::Block;
+
+ const SvxAdjustItem *pAdjust = aEditAttr.GetItemIfSet( EE_PARA_JUST, false );
+
+ if( !pAdjust || IsInvalidItem( pAdjust ))
+ {
+ rSet.InvalidateItem( nSlotId );
+ }
+ else
+ {
+ if ( eAdjust == pAdjust->GetAdjust())
+ rSet.Put( SfxBoolItem( nWhich, true ));
+ else
+ rSet.InvalidateItem( nWhich );
+ }
+ break;
+ }
+ case SID_ATTR_PARA_LINESPACE_10:
+ case SID_ATTR_PARA_LINESPACE_115:
+ case SID_ATTR_PARA_LINESPACE_15:
+ case SID_ATTR_PARA_LINESPACE_20:
+ {
+ int nLSpace = 0;
+ if (nWhich==SID_ATTR_PARA_LINESPACE_10)
+ nLSpace = 100;
+ else if (nWhich==SID_ATTR_PARA_LINESPACE_115)
+ nLSpace = 115;
+ else if (nWhich==SID_ATTR_PARA_LINESPACE_15)
+ nLSpace = 150;
+ else if (nWhich==SID_ATTR_PARA_LINESPACE_20)
+ nLSpace = 200;
+
+ const SvxLineSpacingItem *pLSpace = aEditAttr.GetItemIfSet( EE_PARA_SBL, false );
+
+ if( !pLSpace || IsInvalidItem( pLSpace ))
+ {
+ rSet.InvalidateItem( nSlotId );
+ }
+ else
+ {
+ if( nLSpace == pLSpace->GetPropLineSpace() )
+ rSet.Put( SfxBoolItem( nWhich, true ));
+ else
+ {
+ // tdf#114631 - disable non selected line spacing
+ rSet.Put(SfxBoolItem(nWhich, false));
+ }
+ }
+ break;
+ }
+ case SID_AUTOSPELL_CHECK:
+ {
+ const SfxPoolItemHolder aResult(m_rView.GetSlotState(nWhich));
+ if (nullptr != aResult.getItem())
+ rSet.Put(SfxBoolItem(nWhich, static_cast<const SfxBoolItem*>(aResult.getItem())->GetValue()));
+ else
+ rSet.DisableItem( nWhich );
+ break;
+ }
+ case SID_ATTR_PARA_LEFT_TO_RIGHT:
+ case SID_ATTR_PARA_RIGHT_TO_LEFT:
+ {
+ if ( !SvtCTLOptions::IsCTLFontEnabled() )
+ rSet.DisableItem( nWhich );
+ else
+ {
+ if(pOLV->GetOutliner() && pOLV->GetOutliner()->IsVertical())
+ rSet.DisableItem( nWhich );
+ else
+ {
+ bool bFlag = false;
+ switch( aEditAttr.Get( EE_PARA_WRITINGDIR ).GetValue() )
+ {
+ case SvxFrameDirection::Horizontal_LR_TB:
+ {
+ bFlag = nWhich == SID_ATTR_PARA_LEFT_TO_RIGHT;
+ rSet.Put( SfxBoolItem( nWhich, bFlag ));
+ break;
+ }
+ case SvxFrameDirection::Horizontal_RL_TB:
+ {
+ bFlag = nWhich != SID_ATTR_PARA_LEFT_TO_RIGHT;
+ rSet.Put( SfxBoolItem( nWhich, bFlag ));
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case SID_INSERT_RLM :
+ case SID_INSERT_LRM :
+ {
+ bool bEnabled = SvtCTLOptions::IsCTLFontEnabled();
+ m_rView.GetViewFrame().GetBindings().SetVisibleState( nWhich, bEnabled );
+ if(!bEnabled)
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ default:
+ rSet.InvalidateItem( nWhich );
+ break;
+ }
+
+ if(nEEWhich)
+ {
+ rSet.Put(aEditAttr.Get(nEEWhich).CloneSetWhich(nWhich));
+ if(nEEWhich == EE_CHAR_KERNING)
+ {
+ SfxItemState eState = aEditAttr.GetItemState( EE_CHAR_KERNING );
+ if ( eState == SfxItemState::DONTCARE )
+ {
+ rSet.InvalidateItem(EE_CHAR_KERNING);
+ }
+ }
+ }
+
+ if (pPostItMgr->GetActiveSidebarWin()->GetLayoutStatus()==SwPostItHelper::DELETED)
+ rSet.DisableItem( nWhich );
+
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwAnnotationShell::ExecSearch(SfxRequest& rReq)
+{
+ m_rView.ExecSearch(rReq);
+}
+
+void SwAnnotationShell::StateSearch(SfxItemSet &rSet)
+{
+ m_rView.StateSearch(rSet);
+}
+
+void SwAnnotationShell::ExecClpbrd(SfxRequest const &rReq)
+{
+ SwPostItMgr* pPostItMgr = m_rView.GetPostItMgr();
+ if ( !pPostItMgr || !pPostItMgr->HasActiveSidebarWin() )
+ return;
+
+ OutlinerView* pOLV = pPostItMgr->GetActiveSidebarWin()->GetOutlinerView();
+
+ tools::Long aOldHeight = pPostItMgr->GetActiveSidebarWin()->GetPostItTextHeight();
+ sal_uInt16 nSlot = rReq.GetSlot();
+ switch (nSlot)
+ {
+ case SID_CUT:
+ if ( (pPostItMgr->GetActiveSidebarWin()->GetLayoutStatus()!=SwPostItHelper::DELETED) && pOLV->HasSelection() )
+ pOLV->Cut();
+ break;
+ case SID_COPY:
+ if( pOLV->HasSelection() )
+ pOLV->Copy();
+ break;
+ case SID_PASTE:
+ if (pPostItMgr->GetActiveSidebarWin()->GetLayoutStatus()!=SwPostItHelper::DELETED)
+ pOLV->PasteSpecial();
+ break;
+ case SID_PASTE_UNFORMATTED:
+ if (pPostItMgr->GetActiveSidebarWin()->GetLayoutStatus()!=SwPostItHelper::DELETED)
+ pOLV->Paste();
+ break;
+ case SID_PASTE_SPECIAL:
+ {
+ if (pPostItMgr->GetActiveSidebarWin()->GetLayoutStatus()!=SwPostItHelper::DELETED)
+ {
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractPasteDialog> pDlg(pFact->CreatePasteDialog(m_rView.GetEditWin().GetFrameWeld()));
+
+ pDlg->Insert( SotClipboardFormatId::STRING, OUString() );
+ pDlg->Insert( SotClipboardFormatId::RTF, OUString() );
+ pDlg->Insert( SotClipboardFormatId::RICHTEXT, OUString() );
+
+ TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( &m_rView.GetEditWin() ) );
+
+ SotClipboardFormatId nFormat = pDlg->GetFormat( aDataHelper.GetTransferable() );
+
+ if (nFormat != SotClipboardFormatId::NONE)
+ {
+ if (nFormat == SotClipboardFormatId::STRING)
+ pOLV->Paste();
+ else
+ pOLV->PasteSpecial();
+ }
+ }
+ break;
+ }
+ case SID_CLIPBOARD_FORMAT_ITEMS:
+ {
+ SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
+ const SfxPoolItem* pItem;
+ if (rReq.GetArgs() && rReq.GetArgs()->GetItemState(nSlot, true, &pItem) == SfxItemState::SET)
+ {
+ if (const SfxUInt32Item* pUInt32Item = dynamic_cast<const SfxUInt32Item *>(pItem))
+ nFormat = static_cast<SotClipboardFormatId>(pUInt32Item->GetValue());
+ }
+
+ if ( nFormat != SotClipboardFormatId::NONE )
+ {
+ if (SotClipboardFormatId::STRING == nFormat)
+ pOLV->Paste();
+ else
+ pOLV->PasteSpecial();
+ }
+ break;
+ }
+ }
+ pPostItMgr->GetActiveSidebarWin()->ResizeIfNecessary(aOldHeight,pPostItMgr->GetActiveSidebarWin()->GetPostItTextHeight());
+}
+
+void SwAnnotationShell::StateClpbrd(SfxItemSet &rSet)
+{
+ SwPostItMgr* pPostItMgr = m_rView.GetPostItMgr();
+ if ( !pPostItMgr || !pPostItMgr->HasActiveSidebarWin() )
+ return;
+ OutlinerView* pOLV = pPostItMgr->GetActiveSidebarWin()->GetOutlinerView();
+
+ TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( &m_rView.GetEditWin() ) );
+ bool bPastePossible = ( aDataHelper.HasFormat( SotClipboardFormatId::STRING ) || aDataHelper.HasFormat( SotClipboardFormatId::RTF )
+ || aDataHelper.HasFormat( SotClipboardFormatId::RICHTEXT ));
+ bPastePossible = bPastePossible && (pPostItMgr->GetActiveSidebarWin()->GetLayoutStatus()!=SwPostItHelper::DELETED);
+
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while(nWhich)
+ {
+ switch(nWhich)
+ {
+ case SID_CUT:
+ {
+ if (pPostItMgr->GetActiveSidebarWin()->GetLayoutStatus() == SwPostItHelper::DELETED)
+ rSet.DisableItem( nWhich );
+ [[fallthrough]];
+ }
+ case SID_COPY:
+ {
+ SfxObjectShell* pObjectShell = GetObjectShell();
+ if (!pOLV->HasSelection() || (pObjectShell && pObjectShell->isContentExtractionLocked()) )
+ rSet.DisableItem( nWhich );
+ break;
+ }
+ case SID_PASTE:
+ case SID_PASTE_UNFORMATTED:
+ case SID_PASTE_SPECIAL:
+ {
+ if( !bPastePossible )
+ rSet.DisableItem( nWhich );
+ break;
+ }
+ case SID_CLIPBOARD_FORMAT_ITEMS:
+ {
+ if ( bPastePossible )
+ {
+ SvxClipboardFormatItem aFormats( SID_CLIPBOARD_FORMAT_ITEMS );
+ if ( aDataHelper.HasFormat( SotClipboardFormatId::RTF ) )
+ aFormats.AddClipbrdFormat( SotClipboardFormatId::RTF );
+ if ( aDataHelper.HasFormat( SotClipboardFormatId::RICHTEXT ) )
+ aFormats.AddClipbrdFormat( SotClipboardFormatId::RICHTEXT );
+ aFormats.AddClipbrdFormat( SotClipboardFormatId::STRING );
+ rSet.Put( aFormats );
+ }
+ else
+ rSet.DisableItem( nWhich );
+ break;
+ }
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwAnnotationShell::StateStatusLine(SfxItemSet &rSet)
+{
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while( nWhich )
+ {
+ switch( nWhich )
+ {
+ case FN_STAT_SELMODE:
+ {
+ rSet.Put(SfxUInt16Item(FN_STAT_SELMODE, 0));
+ rSet.DisableItem( nWhich );
+ break;
+ }
+ case FN_STAT_TEMPLATE:
+ {
+ rSet.DisableItem( nWhich );
+ break;
+ }
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwAnnotationShell::StateInsert(SfxItemSet &rSet)
+{
+ SwPostItMgr* pPostItMgr = m_rView.GetPostItMgr();
+ if ( !pPostItMgr || !pPostItMgr->HasActiveSidebarWin() )
+ return;
+
+ OutlinerView* pOLV = pPostItMgr->GetActiveSidebarWin()->GetOutlinerView();
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while(nWhich)
+ {
+ switch(nWhich)
+ {
+ case SID_HYPERLINK_GETLINK:
+ {
+ SvxHyperlinkItem aHLinkItem;
+ aHLinkItem.SetInsertMode(HLINK_FIELD);
+
+ const SvxFieldItem* pFieldItem = pOLV->GetFieldAtSelection();
+
+ if (pFieldItem)
+ {
+ if (const SvxURLField* pURLField = dynamic_cast<const SvxURLField *>(pFieldItem->GetField()))
+ {
+ aHLinkItem.SetName(pURLField->GetRepresentation());
+ aHLinkItem.SetURL(pURLField->GetURL());
+ aHLinkItem.SetTargetFrame(pURLField->GetTargetFrame());
+ }
+ }
+ else
+ {
+ OUString sSel(pOLV->GetSelected());
+ sSel = sSel.copy(0, std::min<sal_Int32>(255, sSel.getLength()));
+ aHLinkItem.SetName(comphelper::string::stripEnd(sSel, ' '));
+ }
+
+ sal_uInt16 nHtmlMode = ::GetHtmlMode(m_rView.GetDocShell());
+ aHLinkItem.SetInsertMode(static_cast<SvxLinkInsertMode>(aHLinkItem.GetInsertMode() |
+ ((nHtmlMode & HTMLMODE_ON) != 0 ? HLINK_HTMLMODE : 0)));
+
+ rSet.Put(aHLinkItem);
+ }
+ break;
+ }
+
+ if (pPostItMgr->GetActiveSidebarWin()->GetLayoutStatus()==SwPostItHelper::DELETED)
+ rSet.DisableItem( nWhich );
+
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwAnnotationShell::NoteExec(SfxRequest const &rReq)
+{
+ SwPostItMgr* pPostItMgr = m_rView.GetPostItMgr();
+ if ( !pPostItMgr )
+ return;
+
+ sal_uInt16 nSlot = rReq.GetSlot();
+ switch (nSlot)
+ {
+ case FN_REPLY:
+ case FN_POSTIT:
+ case FN_DELETE_COMMENT:
+ case FN_DELETE_COMMENT_THREAD:
+ case FN_RESOLVE_NOTE:
+ case FN_RESOLVE_NOTE_THREAD:
+ if ( pPostItMgr->HasActiveSidebarWin() )
+ pPostItMgr->GetActiveSidebarWin()->ExecuteCommand(nSlot);
+ break;
+ case FN_DELETE_ALL_NOTES:
+ pPostItMgr->Delete();
+ break;
+ case FN_FORMAT_ALL_NOTES:
+ pPostItMgr->ExecuteFormatAllDialog(m_rView);
+ break;
+ case FN_DELETE_NOTE_AUTHOR:
+ {
+ const SfxStringItem* pItem = rReq.GetArg<SfxStringItem>(nSlot);
+ if ( pItem )
+ pPostItMgr->Delete( pItem->GetValue() );
+ else if ( pPostItMgr->HasActiveSidebarWin() )
+ pPostItMgr->Delete( pPostItMgr->GetActiveSidebarWin()->GetAuthor() );
+ break;
+ }
+ case FN_HIDE_NOTE:
+ break;
+ case FN_HIDE_ALL_NOTES:
+ pPostItMgr->Hide();
+ break;
+ case FN_HIDE_NOTE_AUTHOR:
+ {
+ const SfxStringItem* pItem = rReq.GetArg<SfxStringItem>(nSlot);
+ if ( pItem )
+ pPostItMgr->Hide( pItem->GetValue() );
+ else if ( pPostItMgr->HasActiveSidebarWin() )
+ pPostItMgr->Hide( pPostItMgr->GetActiveSidebarWin()->GetAuthor() );
+ }
+ }
+}
+
+void SwAnnotationShell::GetNoteState(SfxItemSet &rSet)
+{
+ SwPostItMgr* pPostItMgr = m_rView.GetPostItMgr();
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while(nWhich)
+ {
+ sal_uInt16 nSlotId = GetPool().GetSlotId( nWhich );
+ switch( nSlotId )
+ {
+ case FN_POSTIT:
+ case FN_DELETE_ALL_NOTES:
+ case FN_FORMAT_ALL_NOTES:
+ case FN_HIDE_NOTE:
+ case FN_HIDE_ALL_NOTES:
+ case FN_DELETE_COMMENT:
+ case FN_DELETE_COMMENT_THREAD:
+ {
+ if( !pPostItMgr
+ || !pPostItMgr->HasActiveAnnotationWin() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ }
+ case FN_RESOLVE_NOTE:
+ {
+ if( !pPostItMgr
+ || !pPostItMgr->HasActiveAnnotationWin() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ else
+ {
+ SfxBoolItem aBool(nWhich, pPostItMgr->GetActiveSidebarWin()->IsResolved());
+ rSet.Put( aBool );
+ }
+ break;
+ }
+ case FN_RESOLVE_NOTE_THREAD:
+ {
+ if( !pPostItMgr
+ || !pPostItMgr->HasActiveAnnotationWin() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ else
+ {
+ SfxBoolItem aBool(nWhich, pPostItMgr->GetActiveSidebarWin()->IsThreadResolved());
+ rSet.Put( aBool );
+ }
+ break;
+ }
+ case FN_DELETE_NOTE_AUTHOR:
+ case FN_HIDE_NOTE_AUTHOR:
+ {
+ if( !pPostItMgr
+ || !pPostItMgr->HasActiveAnnotationWin() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ else
+ {
+ OUString aText( nSlotId == FN_DELETE_NOTE_AUTHOR ?
+ SwResId( STR_DELETE_NOTE_AUTHOR ) : SwResId( STR_HIDE_NOTE_AUTHOR ) );
+ SwRewriter aRewriter;
+ aRewriter.AddRule( UndoArg1, pPostItMgr->GetActiveSidebarWin()->GetAuthor() );
+ aText = aRewriter.Apply( aText );
+ SfxStringItem aItem( nSlotId, aText );
+ rSet.Put( aItem );
+ }
+ break;
+ }
+ case FN_REPLY:
+ {
+ if ( !pPostItMgr ||
+ !pPostItMgr->HasActiveAnnotationWin() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ else
+ {
+ SvtUserOptions aUserOpt;
+ OUString sAuthor;
+ if( (sAuthor = aUserOpt.GetFullName()).isEmpty() &&
+ (sAuthor = aUserOpt.GetID()).isEmpty() )
+ sAuthor = SwResId( STR_REDLINE_UNKNOWN_AUTHOR );
+ if (sAuthor == pPostItMgr->GetActiveSidebarWin()->GetAuthor())
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ }
+ default:
+ rSet.InvalidateItem( nWhich );
+ break;
+ }
+
+ if (pPostItMgr && pPostItMgr->HasActiveSidebarWin())
+ {
+ if ( (pPostItMgr->GetActiveSidebarWin()->IsReadOnlyOrProtected()) &&
+ ( (nSlotId==FN_DELETE_COMMENT) || (nSlotId==FN_REPLY) ) )
+ rSet.DisableItem( nWhich );
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwAnnotationShell::ExecLingu(SfxRequest &rReq)
+{
+ SwPostItMgr* pPostItMgr = m_rView.GetPostItMgr();
+ if ( !pPostItMgr || !pPostItMgr->HasActiveSidebarWin() )
+ return;
+
+ OutlinerView* pOLV = pPostItMgr->GetActiveSidebarWin()->GetOutlinerView();
+ sal_uInt16 nSlot = rReq.GetSlot();
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ bool bRestoreSelection = false;
+ ESelection aOldSelection;
+
+ switch (nSlot)
+ {
+ case SID_LANGUAGE_STATUS:
+ {
+ aOldSelection = pOLV->GetSelection();
+ if (!pOLV->GetEditView().HasSelection())
+ {
+ pOLV->GetEditView().SelectCurrentWord();
+ }
+
+ bRestoreSelection = SwLangHelper::SetLanguageStatus(pOLV,rReq,m_rView,rSh);
+ break;
+ }
+ case SID_THES:
+ {
+ OUString aReplaceText;
+ const SfxStringItem* pItem2 = rReq.GetArg(FN_PARAM_THES_WORD_REPLACE);
+ if (pItem2)
+ aReplaceText = pItem2->GetValue();
+ if (!aReplaceText.isEmpty())
+ ReplaceTextWithSynonym( pOLV->GetEditView(), aReplaceText );
+ break;
+ }
+ case SID_THESAURUS:
+ {
+ pOLV->StartThesaurus(rReq.GetFrameWeld());
+ break;
+ }
+ case SID_HANGUL_HANJA_CONVERSION:
+ pOLV->StartTextConversion(rReq.GetFrameWeld(), LANGUAGE_KOREAN, LANGUAGE_KOREAN, nullptr,
+ i18n::TextConversionOption::CHARACTER_BY_CHARACTER, true, false);
+ break;
+
+ case SID_CHINESE_CONVERSION:
+ {
+ //open ChineseTranslationDialog
+ Reference< XComponentContext > xContext(
+ ::cppu::defaultBootstrap_InitialComponentContext() ); //@todo get context from calc if that has one
+ if(xContext.is())
+ {
+ Reference< lang::XMultiComponentFactory > xMCF( xContext->getServiceManager() );
+ if(xMCF.is())
+ {
+ Reference< ui::dialogs::XExecutableDialog > xDialog(
+ xMCF->createInstanceWithContext(
+ "com.sun.star.linguistic2.ChineseTranslationDialog", xContext),
+ UNO_QUERY);
+ Reference< lang::XInitialization > xInit( xDialog, UNO_QUERY );
+ if( xInit.is() )
+ {
+ // initialize dialog
+ uno::Sequence<uno::Any> aSeq(comphelper::InitAnyPropertySequence(
+ {
+ {"ParentWindow", uno::Any(Reference<awt::XWindow>())}
+ }));
+ xInit->initialize( aSeq );
+
+ //execute dialog
+ sal_Int16 nDialogRet = xDialog->execute();
+ if( RET_OK == nDialogRet )
+ {
+ //get some parameters from the dialog
+ bool bToSimplified = true;
+ bool bUseVariants = true;
+ bool bCommonTerms = true;
+ Reference< beans::XPropertySet > xProp( xDialog, UNO_QUERY );
+ if( xProp.is() )
+ {
+ try
+ {
+ xProp->getPropertyValue( "IsDirectionToSimplified" ) >>= bToSimplified;
+ xProp->getPropertyValue( "IsUseCharacterVariants" ) >>= bUseVariants;
+ xProp->getPropertyValue( "IsTranslateCommonTerms" ) >>= bCommonTerms;
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+
+ //execute translation
+ LanguageType nSourceLang = bToSimplified ? LANGUAGE_CHINESE_TRADITIONAL : LANGUAGE_CHINESE_SIMPLIFIED;
+ LanguageType nTargetLang = bToSimplified ? LANGUAGE_CHINESE_SIMPLIFIED : LANGUAGE_CHINESE_TRADITIONAL;
+ sal_Int32 nOptions = bUseVariants ? i18n::TextConversionOption::USE_CHARACTER_VARIANTS : 0;
+ if( !bCommonTerms )
+ nOptions = nOptions | i18n::TextConversionOption::CHARACTER_BY_CHARACTER;
+
+ vcl::Font aTargetFont = OutputDevice::GetDefaultFont( DefaultFontType::CJK_TEXT,
+ nTargetLang, GetDefaultFontFlags::OnlyOne );
+
+ pOLV->StartTextConversion(rReq.GetFrameWeld(), nSourceLang, nTargetLang, &aTargetFont, nOptions, false, false);
+ }
+ }
+ Reference< lang::XComponent > xComponent( xDialog, UNO_QUERY );
+ if( xComponent.is() )
+ xComponent->dispose();
+ }
+ }
+ }
+ break;
+ }
+
+ if (bRestoreSelection)
+ {
+ // restore selection
+ pOLV->GetEditView().SetSelection( aOldSelection );
+ }
+}
+
+void SwAnnotationShell::GetLinguState(SfxItemSet &rSet)
+{
+ SwPostItMgr* pPostItMgr = m_rView.GetPostItMgr();
+ if ( !pPostItMgr || !pPostItMgr->HasActiveSidebarWin() )
+ return;
+
+ OutlinerView* pOLV = pPostItMgr->GetActiveSidebarWin()->GetOutlinerView();
+
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while(nWhich)
+ {
+ switch (nWhich)
+ {
+ case SID_LANGUAGE_STATUS:
+ {
+ SwLangHelper::GetLanguageStatus(pOLV,rSet);
+ break;
+ }
+
+ case SID_THES:
+ {
+ OUString aStatusVal;
+ LanguageType nLang = LANGUAGE_NONE;
+ bool bIsLookUpWord = GetStatusValueForThesaurusFromContext( aStatusVal, nLang, pOLV->GetEditView() );
+ rSet.Put( SfxStringItem( SID_THES, aStatusVal ) );
+
+ // disable "Thesaurus" context menu entry if there is nothing to look up
+ uno::Reference< linguistic2::XThesaurus > xThes( ::GetThesaurus() );
+ if (!bIsLookUpWord ||
+ !xThes.is() || nLang == LANGUAGE_NONE || !xThes->hasLocale( LanguageTag::convertToLocale( nLang ) ))
+ rSet.DisableItem( SID_THES );
+ break;
+ }
+
+ // disable "Thesaurus" if the language is not supported
+ case SID_THESAURUS:
+ {
+ TypedWhichId<SvxLanguageItem> nLangWhich = GetWhichOfScript( RES_CHRATR_LANGUAGE,
+ SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetAppLanguage() ) );
+ const SvxLanguageItem &rItem = m_rView.GetWrtShell().GetDoc()->GetDefault(nLangWhich);
+ LanguageType nLang = rItem.GetLanguage();
+ uno::Reference< linguistic2::XThesaurus > xThes( ::GetThesaurus() );
+ if (!xThes.is() || nLang == LANGUAGE_NONE ||
+ !xThes->hasLocale( LanguageTag::convertToLocale( nLang ) ))
+ rSet.DisableItem( SID_THESAURUS );
+ }
+ break;
+ case SID_HANGUL_HANJA_CONVERSION:
+ case SID_CHINESE_CONVERSION:
+ {
+ if (!SvtCJKOptions::IsAnyEnabled())
+ {
+ m_rView.GetViewFrame().GetBindings().SetVisibleState( nWhich, false );
+ rSet.DisableItem(nWhich);
+ }
+ else
+ m_rView.GetViewFrame().GetBindings().SetVisibleState( nWhich, true );
+ }
+ break;
+ }
+
+ if (pPostItMgr->GetActiveSidebarWin()->GetLayoutStatus()==SwPostItHelper::DELETED)
+ rSet.DisableItem( nWhich );
+
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwAnnotationShell::ExecTransliteration(SfxRequest const &rReq)
+{
+ SwPostItMgr* pPostItMgr = m_rView.GetPostItMgr();
+ if (!pPostItMgr || !pPostItMgr->HasActiveSidebarWin())
+ return;
+
+ OutlinerView* pOLV = pPostItMgr->GetActiveSidebarWin()->GetOutlinerView();
+
+ if (!pOLV)
+ return;
+
+ TransliterationFlags nMode = TransliterationFlags::NONE;
+
+ switch( rReq.GetSlot() )
+ {
+ case SID_TRANSLITERATE_SENTENCE_CASE:
+ nMode = TransliterationFlags::SENTENCE_CASE;
+ break;
+ case SID_TRANSLITERATE_TITLE_CASE:
+ nMode = TransliterationFlags::TITLE_CASE;
+ break;
+ case SID_TRANSLITERATE_TOGGLE_CASE:
+ nMode = TransliterationFlags::TOGGLE_CASE;
+ break;
+ case SID_TRANSLITERATE_UPPER:
+ nMode = TransliterationFlags::LOWERCASE_UPPERCASE;
+ break;
+ case SID_TRANSLITERATE_LOWER:
+ nMode = TransliterationFlags::UPPERCASE_LOWERCASE;
+ break;
+ case SID_TRANSLITERATE_HALFWIDTH:
+ nMode = TransliterationFlags::FULLWIDTH_HALFWIDTH;
+ break;
+ case SID_TRANSLITERATE_FULLWIDTH:
+ nMode = TransliterationFlags::HALFWIDTH_FULLWIDTH;
+ break;
+ case SID_TRANSLITERATE_HIRAGANA:
+ nMode = TransliterationFlags::KATAKANA_HIRAGANA;
+ break;
+ case SID_TRANSLITERATE_KATAKANA:
+ nMode = TransliterationFlags::HIRAGANA_KATAKANA;
+ break;
+
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ }
+
+ if( nMode != TransliterationFlags::NONE )
+ pOLV->TransliterateText( nMode );
+}
+
+void SwAnnotationShell::ExecRotateTransliteration( SfxRequest const & rReq )
+{
+ if( rReq.GetSlot() != SID_TRANSLITERATE_ROTATE_CASE )
+ return;
+
+ SwPostItMgr* pPostItMgr = m_rView.GetPostItMgr();
+ if (!pPostItMgr || !pPostItMgr->HasActiveSidebarWin())
+ return;
+
+ OutlinerView* pOLV = pPostItMgr->GetActiveSidebarWin()->GetOutlinerView();
+
+ if (!pOLV)
+ return;
+
+ pOLV->TransliterateText(m_aRotateCase.getNextMode());
+}
+
+void SwAnnotationShell::ExecUndo(SfxRequest &rReq)
+{
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ SfxUndoManager* pUndoManager = GetUndoManager();
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ SwUndoId nUndoId(SwUndoId::EMPTY);
+
+ // tdf#147928 get these before "undo" which may delete this SwAnnotationShell
+ SwPostItMgr* pPostItMgr = m_rView.GetPostItMgr();
+ SfxBindings& rBindings = m_rView.GetViewFrame().GetBindings();
+
+ tools::Long aOldHeight = pPostItMgr->HasActiveSidebarWin()
+ ? pPostItMgr->GetActiveSidebarWin()->GetPostItTextHeight()
+ : 0;
+
+ sal_uInt16 nId = rReq.GetSlot();
+ sal_uInt16 nCnt = 1;
+ const SfxPoolItem* pItem=nullptr;
+ if( pArgs && SfxItemState::SET == pArgs->GetItemState( nId, false, &pItem ) )
+ nCnt = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
+ switch( nId )
+ {
+ case SID_UNDO:
+ {
+ rSh.GetLastUndoInfo(nullptr, &nUndoId);
+ if (nUndoId == SwUndoId::CONFLICT)
+ {
+ rReq.SetReturnValue( SfxUInt32Item(nId, static_cast<sal_uInt32>(SID_REPAIRPACKAGE)) );
+ break;
+ }
+
+ if ( pUndoManager )
+ {
+ sal_uInt16 nCount = pUndoManager->GetUndoActionCount();
+ sal_uInt16 nSteps = nCnt;
+ if ( nCount < nCnt )
+ {
+ nCnt = nCnt - nCount;
+ nSteps = nCount;
+ }
+ else
+ nCnt = 0;
+
+ while( nSteps-- )
+ pUndoManager->Undo();
+ }
+
+ if ( nCnt )
+ rSh.Do( SwWrtShell::UNDO, nCnt );
+
+ break;
+ }
+
+ case SID_REDO:
+ {
+ (void)rSh.GetFirstRedoInfo(nullptr, &nUndoId);
+ if (nUndoId == SwUndoId::CONFLICT)
+ {
+ rReq.SetReturnValue( SfxUInt32Item(nId, static_cast<sal_uInt32>(SID_REPAIRPACKAGE)) );
+ break;
+ }
+
+ if ( pUndoManager )
+ {
+ sal_uInt16 nCount = pUndoManager->GetRedoActionCount();
+ sal_uInt16 nSteps = nCnt;
+ if ( nCount < nCnt )
+ {
+ nCnt = nCnt - nCount;
+ nSteps = nCount;
+ }
+ else
+ nCnt = 0;
+
+ while( nSteps-- )
+ pUndoManager->Redo();
+ }
+
+ if ( nCnt )
+ rSh.Do( SwWrtShell::REDO, nCnt );
+
+ break;
+ }
+ }
+
+ rBindings.InvalidateAll(false);
+
+ if (pPostItMgr->HasActiveSidebarWin())
+ pPostItMgr->GetActiveSidebarWin()->ResizeIfNecessary(aOldHeight, pPostItMgr->GetActiveSidebarWin()->GetPostItTextHeight());
+}
+
+void SwAnnotationShell::StateUndo(SfxItemSet &rSet)
+{
+ SwPostItMgr* pPostItMgr = m_rView.GetPostItMgr();
+ if ( !pPostItMgr || !pPostItMgr->HasActiveSidebarWin() )
+ return;
+
+ SfxWhichIter aIter(rSet);
+ SwUndoId nUndoId(SwUndoId::EMPTY);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ SfxUndoManager* pUndoManager = GetUndoManager();
+ SfxViewFrame& rSfxViewFrame = m_rView.GetViewFrame();
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+
+ while( nWhich )
+ {
+ switch ( nWhich )
+ {
+ case SID_UNDO:
+ {
+ sal_uInt16 nCount = pUndoManager ? pUndoManager->GetUndoActionCount() : 0;
+ if ( nCount )
+ rSfxViewFrame.GetSlotState( nWhich, rSfxViewFrame.GetInterface(), &rSet );
+ else if (rSh.GetLastUndoInfo(nullptr, &nUndoId))
+ {
+ rSet.Put( SfxStringItem( nWhich, rSh.GetDoString(SwWrtShell::UNDO)) );
+ }
+ else if (nUndoId == SwUndoId::CONFLICT)
+ {
+ rSet.Put( SfxUInt32Item(nWhich, static_cast<sal_uInt32>(SID_REPAIRPACKAGE)) );
+ }
+ else
+ rSet.DisableItem(nWhich);
+ break;
+ }
+ case SID_REDO:
+ {
+ sal_uInt16 nCount = pUndoManager ? pUndoManager->GetRedoActionCount() : 0;
+ if ( nCount )
+ rSfxViewFrame.GetSlotState( nWhich, rSfxViewFrame.GetInterface(), &rSet );
+ else if (rSh.GetFirstRedoInfo(nullptr, &nUndoId))
+ {
+ rSet.Put(SfxStringItem( nWhich, rSh.GetDoString(SwWrtShell::REDO)) );
+ }
+ else if (nUndoId == SwUndoId::CONFLICT)
+ {
+ rSet.Put( SfxUInt32Item(nWhich, static_cast<sal_uInt32>(SID_REPAIRPACKAGE)) );
+ }
+ else
+ rSet.DisableItem(nWhich);
+ break;
+ }
+ case SID_GETUNDOSTRINGS:
+ case SID_GETREDOSTRINGS:
+ {
+ if( pUndoManager )
+ {
+ OUString (SfxUndoManager::*fnGetComment)( size_t, bool const ) const;
+
+ sal_uInt16 nCount;
+ if( SID_GETUNDOSTRINGS == nWhich )
+ {
+ nCount = pUndoManager->GetUndoActionCount();
+ fnGetComment = &SfxUndoManager::GetUndoActionComment;
+ }
+ else
+ {
+ nCount = pUndoManager->GetRedoActionCount();
+ fnGetComment = &SfxUndoManager::GetRedoActionComment;
+ }
+
+ OUStringBuffer sList;
+ if( nCount )
+ {
+ for( sal_uInt16 n = 0; n < nCount; ++n )
+ sList.append( (pUndoManager->*fnGetComment)( n, SfxUndoManager::TopLevel ) + "\n");
+ }
+
+ SfxStringListItem aItem( nWhich );
+ if ((nWhich == SID_GETUNDOSTRINGS) &&
+ rSh.GetLastUndoInfo(nullptr, nullptr))
+ {
+ rSh.GetDoStrings( SwWrtShell::UNDO, aItem );
+ }
+ else if ((nWhich == SID_GETREDOSTRINGS) &&
+ (rSh.GetFirstRedoInfo(nullptr, nullptr)))
+ {
+ rSh.GetDoStrings( SwWrtShell::REDO, aItem );
+ }
+
+ sList.append(aItem.GetString());
+ aItem.SetString( sList.makeStringAndClear() );
+ rSet.Put( aItem );
+ }
+ else
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ default:
+ {
+ rSfxViewFrame.GetSlotState( nWhich, rSfxViewFrame.GetInterface(), &rSet );
+ break;
+ }
+
+ }
+
+ if (pPostItMgr->GetActiveSidebarWin()->GetLayoutStatus()==SwPostItHelper::DELETED)
+ rSet.DisableItem( nWhich );
+
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwAnnotationShell::StateDisableItems( SfxItemSet &rSet )
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while (nWhich)
+ {
+ rSet.DisableItem( nWhich );
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwAnnotationShell::InsertSymbol(SfxRequest& rReq)
+{
+ SwPostItMgr* pPostItMgr = m_rView.GetPostItMgr();
+ if ( !pPostItMgr || !pPostItMgr->HasActiveSidebarWin() )
+ return;
+
+ OutlinerView* pOLV = pPostItMgr->GetActiveSidebarWin()->GetOutlinerView();
+
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ const SfxStringItem* pCharMapItem = nullptr;
+ if( pArgs )
+ pCharMapItem = pArgs->GetItemIfSet(SID_CHARMAP, false);
+
+ OUString sSym;
+ OUString sFontName;
+ if ( pCharMapItem )
+ {
+ sSym = pCharMapItem->GetValue();
+ const SfxStringItem* pFontItem = pArgs->GetItemIfSet( SID_ATTR_SPECIALCHAR, false);
+ if (pFontItem)
+ sFontName = pFontItem->GetValue();
+ }
+
+ SfxItemSet aSet(pOLV->GetAttribs());
+ SvtScriptType nScript = pOLV->GetSelectedScriptType();
+ std::shared_ptr<SvxFontItem> aSetDlgFont(std::make_shared<SvxFontItem>(RES_CHRATR_FONT));
+ {
+ SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONT, *aSet.GetPool() );
+ aSetItem.GetItemSet().Put( aSet, false );
+ const SfxPoolItem* pI = aSetItem.GetItemOfScript( nScript );
+ if( pI )
+ {
+ aSetDlgFont.reset(static_cast<SvxFontItem*>(pI->Clone()));
+ }
+ else
+ {
+ TypedWhichId<SvxFontItem> nFontWhich =
+ GetWhichOfScript(
+ SID_ATTR_CHAR_FONT,
+ SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetAppLanguage() ) );
+ aSetDlgFont.reset(aSet.Get(nFontWhich).Clone());
+ }
+
+ if (sFontName.isEmpty())
+ sFontName = aSetDlgFont->GetFamilyName();
+ }
+
+ vcl::Font aFont(sFontName, Size(1,1));
+ if( sSym.isEmpty() )
+ {
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+
+ SfxAllItemSet aAllSet( GetPool() );
+ aAllSet.Put( SfxBoolItem( FN_PARAM_1, false ) );
+
+ SwViewOption aOpt(*m_rView.GetWrtShell().GetViewOptions());
+ const OUString& sSymbolFont = aOpt.GetSymbolFont();
+ if( !sSymbolFont.isEmpty() )
+ aAllSet.Put( SfxStringItem( SID_FONT_NAME, sSymbolFont ) );
+ else
+ aAllSet.Put( SfxStringItem( SID_FONT_NAME, aSetDlgFont->GetFamilyName() ) );
+
+ // If character is selected then it can be shown.
+ auto xFrame = m_rView.GetViewFrame().GetFrame().GetFrameInterface();
+ ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateCharMapDialog(m_rView.GetFrameWeld(), aAllSet, xFrame));
+ pDlg->Execute();
+ return;
+ }
+
+ // do not flicker
+ pOLV->HideCursor();
+ Outliner * pOutliner = pOLV->GetOutliner();
+ pOutliner->SetUpdateLayout(false);
+
+ SfxItemSet aOldSet( pOLV->GetAttribs() );
+ SfxItemSetFixed<
+ EE_CHAR_FONTINFO, EE_CHAR_FONTINFO,
+ EE_CHAR_FONTINFO_CJK, EE_CHAR_FONTINFO_CTL>
+ aFontSet( *aOldSet.GetPool() );
+ aFontSet.Set( aOldSet );
+
+ // Insert string
+ pOLV->InsertText( sSym);
+
+ // Attributing (set font)
+ SfxItemSet aSetFont( *aFontSet.GetPool(), aFontSet.GetRanges() );
+ SvxFontItem aFontItem (aFont.GetFamilyType(), aFont.GetFamilyName(),
+ aFont.GetStyleName(), aFont.GetPitch(),
+ aFont.GetCharSet(),
+ EE_CHAR_FONTINFO );
+ SvtScriptType nScriptBreak = g_pBreakIt->GetAllScriptsOfText( sSym );
+ if( SvtScriptType::LATIN & nScriptBreak )
+ aSetFont.Put( aFontItem );
+ if( SvtScriptType::ASIAN & nScriptBreak )
+ {
+ aFontItem.SetWhich(EE_CHAR_FONTINFO_CJK);
+ aSetFont.Put( aFontItem );
+ }
+ if( SvtScriptType::COMPLEX & nScriptBreak )
+ {
+ aFontItem.SetWhich(EE_CHAR_FONTINFO_CTL);
+ aSetFont.Put( aFontItem );
+ }
+ pOLV->SetAttribs(aSetFont);
+
+ // Erase selection
+ ESelection aSel(pOLV->GetSelection());
+ aSel.nStartPara = aSel.nEndPara;
+ aSel.nStartPos = aSel.nEndPos;
+ pOLV->SetSelection(aSel);
+
+ // Restore old font
+ pOLV->SetAttribs( aFontSet );
+
+ // From now on show it again
+ pOutliner->SetUpdateLayout(true);
+ pOLV->ShowCursor();
+
+ rReq.AppendItem( SfxStringItem( SID_CHARMAP, sSym ) );
+ if(!aFont.GetFamilyName().isEmpty())
+ rReq.AppendItem( SfxStringItem( SID_ATTR_SPECIALCHAR, aFont.GetFamilyName() ) );
+ rReq.Done();
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/basesh.cxx b/sw/source/uibase/shells/basesh.cxx
new file mode 100644
index 0000000000..57e7c82995
--- /dev/null
+++ b/sw/source/uibase/shells/basesh.cxx
@@ -0,0 +1,3372 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+#include <config_fuzzers.h>
+
+#include <sal/config.h>
+
+#include <hintids.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <svl/languageoptions.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <sfx2/htmlmode.hxx>
+#include <svx/imapdlg.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/request.hxx>
+#include <svl/whiter.hxx>
+#include <svl/visitem.hxx>
+#include <editeng/langitem.hxx>
+#include <svx/clipfmtitem.hxx>
+#include <svx/contdlg.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/inputctx.hxx>
+#include <svl/slstitm.hxx>
+#include <svl/ptitem.hxx>
+#include <svl/stritem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/sizeitem.hxx>
+#include <svx/flagsdef.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <sfx2/objface.hxx>
+#include <fmturl.hxx>
+#include <fmthdft.hxx>
+#include <fmtclds.hxx>
+#include <docsh.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <swmodule.hxx>
+#include <swundo.hxx>
+#include <fldbas.hxx>
+#include <uitool.hxx>
+#include <basesh.hxx>
+#include <viewopt.hxx>
+#include <fontcfg.hxx>
+#include <fmtsrnd.hxx>
+#include <fldmgr.hxx>
+#include <frmmgr.hxx>
+#include <tablemgr.hxx>
+#include <mdiexp.hxx>
+#include <swdtflvr.hxx>
+#include <pagedesc.hxx>
+#include <fmtcol.hxx>
+#include <edtwin.hxx>
+#include <tblafmt.hxx>
+#include <swwait.hxx>
+#include <cmdid.h>
+#include <strings.hrc>
+#include <unotxdoc.hxx>
+#include <doc.hxx>
+#include <drawdoc.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <ThemeColorChanger.hxx>
+#include <swabstdlg.hxx>
+#include <modcfg.hxx>
+#include <svx/fmshell.hxx>
+#include <SwRewriter.hxx>
+#include <GraphicSizeCheck.hxx>
+#include <svx/galleryitem.hxx>
+#include <svx/theme/ThemeColorPaletteManager.hxx>
+#include <sfx2/devtools/DevelopmentToolChildWindow.hxx>
+#include <com/sun/star/gallery/GalleryItemType.hpp>
+#include <com/sun/star/beans/PropertyValues.hpp>
+#include <memory>
+
+
+#include <svx/unobrushitemhelper.hxx>
+#include <svx/dialog/ThemeDialog.hxx>
+#include <comphelper/scopeguard.hxx>
+#include <comphelper/lok.hxx>
+#include <sfx2/lokhelper.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <osl/diagnose.h>
+
+#include <svx/svxdlg.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+
+#include <shellres.hxx>
+#include <UndoTable.hxx>
+
+#include <ndtxt.hxx>
+#include <UndoManager.hxx>
+#include <fmtrfmrk.hxx>
+#include <txtrfmrk.hxx>
+#include <translatehelper.hxx>
+
+FlyMode SwBaseShell::s_eFrameMode = FLY_DRAG_END;
+
+// These variables keep the state of Gallery (slot SID_GALLERY_BG_BRUSH)
+// detected by GetGalleryState() for the subsequent ExecuteGallery() call.
+
+static sal_uInt8 nParagraphPos;
+static sal_uInt8 nGraphicPos;
+static sal_uInt8 nOlePos;
+static sal_uInt8 nFramePos;
+static sal_uInt8 nTablePos;
+static sal_uInt8 nTableRowPos;
+static sal_uInt8 nTableCellPos;
+static sal_uInt8 nPagePos;
+static sal_uInt8 nHeaderPos;
+static sal_uInt8 nFooterPos;
+
+#define ShellClass_SwBaseShell
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+
+#include <AccessibilityCheck.hxx>
+
+namespace
+{
+ SvxContourDlg* GetContourDlg(SwView const &rView)
+ {
+ SfxChildWindow *pWnd = rView.GetViewFrame().GetChildWindow(SvxContourDlgChildWindow::GetChildWindowId());
+ return pWnd ? static_cast<SvxContourDlg*>(pWnd->GetController().get()) : nullptr;
+ }
+
+ SvxIMapDlg* GetIMapDlg(SwView const &rView)
+ {
+ SfxChildWindow* pWnd = rView.GetViewFrame().GetChildWindow(SvxIMapDlgChildWindow::GetChildWindowId());
+ return pWnd ? static_cast<SvxIMapDlg*>(pWnd->GetController().get()) : nullptr;
+ }
+}
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::lang;
+
+SFX_IMPL_SUPERCLASS_INTERFACE(SwBaseShell, SfxShell)
+
+void SwBaseShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterChildWindow(SvxIMapDlgChildWindow::GetChildWindowId());
+ GetStaticInterface()->RegisterChildWindow(SvxContourDlgChildWindow::GetChildWindowId());
+ GetStaticInterface()->RegisterChildWindow(DevelopmentToolChildWindow::GetChildWindowId());
+}
+
+static void lcl_UpdateIMapDlg( SwWrtShell& rSh )
+{
+ Graphic aGrf( rSh.GetIMapGraphic() );
+ GraphicType nGrfType = aGrf.GetType();
+ void* pEditObj = GraphicType::NONE != nGrfType && GraphicType::Default != nGrfType
+ ? rSh.GetIMapInventor() : nullptr;
+ TargetList aList;
+ SfxFrame::GetDefaultTargetList(aList);
+
+ SfxItemSetFixed<RES_URL, RES_URL> aSet( rSh.GetAttrPool() );
+ rSh.GetFlyFrameAttr( aSet );
+ const SwFormatURL &rURL = aSet.Get( RES_URL );
+ SvxIMapDlgChildWindow::UpdateIMapDlg(
+ aGrf, rURL.GetMap(), &aList, pEditObj );
+}
+
+static bool lcl_UpdateContourDlg( SwWrtShell &rSh, SelectionType nSel )
+{
+ Graphic aGraf( rSh.GetIMapGraphic() );
+ GraphicType nGrfType = aGraf.GetType();
+ bool bRet = GraphicType::NONE != nGrfType && GraphicType::Default != nGrfType;
+ if( bRet )
+ {
+ OUString aGrfName;
+ if ( nSel & SelectionType::Graphic )
+ rSh.GetGrfNms( &aGrfName, nullptr );
+
+ SvxContourDlg *pDlg = GetContourDlg(rSh.GetView());
+ if (pDlg)
+ {
+ pDlg->Update(aGraf, !aGrfName.isEmpty(),
+ rSh.GetGraphicPolygon(), rSh.GetIMapInventor());
+ }
+ }
+ return bRet;
+}
+
+void SwBaseShell::ExecDelete(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ SwEditWin& rTmpEditWin = GetView().GetEditWin();
+ switch(rReq.GetSlot())
+ {
+ case SID_DELETE:
+ if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ {
+ // Disallow if the cursor is at the end of a paragraph and the document model
+ // node at this position is an outline node with folded content or the next node
+ // is an outline node with folded content.
+ if (rSh.IsEndPara())
+ {
+ SwNodeIndex aIdx(rSh.GetCursor()->GetPointNode());
+ if (aIdx.GetNode().IsTextNode())
+ {
+ bool bVisible = true;
+ aIdx.GetNode().GetTextNode()->GetAttrOutlineContentVisible(bVisible);
+ if (!bVisible)
+ break;
+ ++aIdx;
+ if (aIdx.GetNode().IsTextNode())
+ {
+ bVisible = true;
+ aIdx.GetNode().GetTextNode()->GetAttrOutlineContentVisible(bVisible);
+ if (!bVisible)
+ break;
+ }
+ }
+ }
+ }
+ rSh.DelRight();
+ break;
+
+ case FN_BACKSPACE:
+ if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ {
+ // Disallow if the cursor is at the start of a paragraph and the document model
+ // node at this position is an outline node with folded content or the previous
+ // node is a content node without a layout frame.
+ if (rSh.IsSttPara())
+ {
+ SwNodeIndex aIdx(rSh.GetCursor()->GetPointNode());
+ if (aIdx.GetNode().IsTextNode())
+ {
+ bool bVisible = true;
+ aIdx.GetNode().GetTextNode()->GetAttrOutlineContentVisible(bVisible);
+ if (!bVisible)
+ break;
+ --aIdx;
+ if (aIdx.GetNode().IsContentNode() &&
+ !aIdx.GetNode().GetContentNode()->getLayoutFrame(rSh.GetLayout()))
+ break;
+ }
+ }
+ }
+ if( rSh.IsNoNum() )
+ {
+ rSh.SttCursorMove();
+ bool bLeft = rSh.Left( SwCursorSkipMode::Chars, true, 1, false );
+ if( bLeft )
+ {
+ rSh.DelLeft();
+ }
+ else
+ // JP 15.07.96: If it no longer goes forward, cancel
+ // the numbering. For example at the beginning
+ // of a doc, frame, table or an area.
+ rSh.DelNumRules();
+
+ rSh.EndCursorMove();
+ break;
+ }
+
+ [[fallthrough]]; // otherwise call DelLeft
+ case FN_SHIFT_BACKSPACE:
+ rSh.DelLeft();
+ break;
+ default:
+ OSL_FAIL("wrong Dispatcher");
+ return;
+ }
+ rReq.Done();
+
+ //#i42732# - notify the edit window that from now on we do not use the input language
+ rTmpEditWin.SetUseInputLanguage( false );
+}
+
+void SwBaseShell::ExecClpbrd(SfxRequest &rReq)
+{
+ // Attention: At risk of suicide!
+ // After paste, paste special the shell can be destroy.
+
+ SwWrtShell &rSh = GetShell();
+ sal_uInt16 nId = rReq.GetSlot();
+ bool bIgnore = false;
+ PasteTableType ePasteTable = PasteTableType::PASTE_DEFAULT;
+
+ switch( nId )
+ {
+ case SID_CUT:
+ case SID_COPY:
+ m_rView.GetEditWin().FlushInBuffer();
+ if ( rSh.HasSelection() )
+ {
+ rtl::Reference<SwTransferable> pTransfer = new SwTransferable( rSh );
+
+ if ( nId == SID_CUT && FlyProtectFlags::NONE == rSh.IsSelObjProtected(FlyProtectFlags::Content|FlyProtectFlags::Parent) )
+ pTransfer->Cut();
+ else
+ {
+ const bool bLockedView = rSh.IsViewLocked();
+ rSh.LockView( true ); //lock visible section
+ pTransfer->Copy();
+ rSh.LockView( bLockedView );
+ }
+ break;
+ }
+ return;
+
+ case FN_PASTE_NESTED_TABLE:
+ case FN_TABLE_PASTE_ROW_BEFORE:
+ case FN_TABLE_PASTE_COL_BEFORE:
+ switch ( nId )
+ {
+ case FN_PASTE_NESTED_TABLE:
+ ePasteTable = PasteTableType::PASTE_TABLE;
+ break;
+ case FN_TABLE_PASTE_ROW_BEFORE:
+ ePasteTable = PasteTableType::PASTE_ROW;
+ break;
+ case FN_TABLE_PASTE_COL_BEFORE:
+ ePasteTable = PasteTableType::PASTE_COLUMN;
+ break;
+ default:
+ ;
+ }
+ [[fallthrough]];
+ case SID_PASTE:
+ {
+ TransferableDataHelper aDataHelper(
+ TransferableDataHelper::CreateFromSystemClipboard( &rSh.GetView().GetEditWin() ) );
+ if( aDataHelper.GetXTransferable().is()
+ && SwTransferable::IsPaste( rSh, aDataHelper ) )
+ {
+ // Temporary variables, because the shell could already be
+ // destroyed after the paste.
+ SwView* pView = &m_rView;
+
+ RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA;
+ const SfxUInt16Item* pAnchorType = rReq.GetArg<SfxUInt16Item>(FN_PARAM_1);
+ if (pAnchorType)
+ nAnchorType = static_cast<RndStdIds>(pAnchorType->GetValue());
+ bool bIgnoreComments = false;
+ const SfxBoolItem* pIgnoreComments = rReq.GetArg<SfxBoolItem>(FN_PARAM_2);
+ if (pIgnoreComments)
+ bIgnoreComments = pIgnoreComments->GetValue();
+ SwTransferable::Paste(rSh, aDataHelper, nAnchorType, bIgnoreComments, ePasteTable);
+
+ if( rSh.IsFrameSelected() || rSh.IsObjSelected() )
+ rSh.EnterSelFrameMode();
+ pView->AttrChangedNotify(nullptr);
+
+ // Fold pasted outlines that have outline content visible attribute false
+ MakeAllOutlineContentTemporarilyVisible a(rSh.GetDoc());
+ }
+ else
+ return;
+ }
+ break;
+
+ case SID_CLIPBOARD_FORMAT_ITEMS:
+ {
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxPoolItem* pFormat;
+ if( pArgs && SfxItemState::SET == pArgs->GetItemState( nId, false, &pFormat ) )
+ {
+ TransferableDataHelper aDataHelper(
+ TransferableDataHelper::CreateFromSystemClipboard(
+ &rSh.GetView().GetEditWin()) );
+ if( aDataHelper.GetXTransferable().is()
+ /*&& SwTransferable::IsPaste( rSh, aDataHelper )*/ )
+ {
+ // Temporary variables, because the shell could already be
+ // destroyed after the paste.
+ SwView* pView = &m_rView;
+
+ SwTransferable::PasteFormat( rSh, aDataHelper,
+ static_cast<SotClipboardFormatId>(static_cast<const SfxUInt32Item*>(pFormat)->GetValue()) );
+
+ //Done() has to be called before the shell has been removed
+ rReq.Done();
+ bIgnore = true;
+ if( rSh.IsFrameSelected() || rSh.IsObjSelected())
+ rSh.EnterSelFrameMode();
+ pView->AttrChangedNotify(nullptr);
+
+ // Fold pasted outlines that have outline content visible attribute false
+ MakeAllOutlineContentTemporarilyVisible a(rSh.GetDoc());
+ }
+ }
+ }
+ break;
+
+ case SID_PASTE_UNFORMATTED:
+ {
+ TransferableDataHelper aDataHelper(
+ TransferableDataHelper::CreateFromSystemClipboard( &rSh.GetView().GetEditWin()) );
+ if( aDataHelper.GetXTransferable().is()
+ && SwTransferable::IsPaste( rSh, aDataHelper ) )
+ {
+ // Temporary variables, because the shell could already be
+ // destroyed after the paste.
+ SwView* pView = &m_rView;
+ rReq.Ignore();
+ bIgnore = true;
+ if(SwTransferable::PasteUnformatted( rSh, aDataHelper ))
+ {
+ SfxViewFrame& rViewFrame = pView->GetViewFrame();
+ uno::Reference< frame::XDispatchRecorder > xRecorder =
+ rViewFrame.GetBindings().GetRecorder();
+ if(xRecorder.is()) {
+ SfxRequest aReq(rViewFrame, SID_CLIPBOARD_FORMAT_ITEMS);
+ aReq.AppendItem( SfxUInt32Item( SID_CLIPBOARD_FORMAT_ITEMS, static_cast<sal_uInt32>(SotClipboardFormatId::STRING) ) );
+ aReq.Done();
+ }
+ }
+
+ if (rSh.IsFrameSelected() || rSh.IsObjSelected())
+ rSh.EnterSelFrameMode();
+ pView->AttrChangedNotify(nullptr);
+
+ // Fold pasted outlines that have outline content visible attribute false
+ MakeAllOutlineContentTemporarilyVisible a(rSh.GetDoc());
+ }
+ else
+ return;
+ }
+ break;
+
+ case SID_PASTE_SPECIAL:
+ {
+ std::shared_ptr<TransferableDataHelper> aDataHelper =
+ std::make_shared<TransferableDataHelper>(TransferableDataHelper::CreateFromSystemClipboard( &rSh.GetView().GetEditWin()));
+
+ if( aDataHelper->GetXTransferable().is()
+ && SwTransferable::IsPaste( rSh, *aDataHelper )
+ && !rSh.CursorInsideInputField() )
+ {
+ rReq.Ignore();
+ bIgnore = true;
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ VclPtr<SfxAbstractPasteDialog> pDlg(pFact->CreatePasteDialog( rReq.GetFrameWeld() ));
+
+ // Prepare the dialog
+ SwTransferable::PrePasteSpecial(rSh, *aDataHelper, pDlg);
+ pDlg->PreGetFormat(*aDataHelper);
+
+
+ pDlg->StartExecuteAsync([aDataHelper, pDlg, &rSh, this](sal_Int32 nResult){
+ if (nResult == RET_OK)
+ {
+ // Temporary variables, because the shell could already be
+ // destroyed after the paste.
+ SwView* pView = &m_rView;
+ bool bRet = false;
+ SotClipboardFormatId nFormatId = pDlg->GetFormatOnly();
+
+ if( nFormatId != SotClipboardFormatId::NONE )
+ bRet = SwTransferable::PasteFormat( rSh, *aDataHelper, nFormatId );
+
+ if (bRet)
+ {
+ SfxViewFrame& rViewFrame = pView->GetViewFrame();
+ uno::Reference< frame::XDispatchRecorder > xRecorder =
+ rViewFrame.GetBindings().GetRecorder();
+ if(xRecorder.is()) {
+ SfxRequest aReq(rViewFrame, SID_CLIPBOARD_FORMAT_ITEMS);
+ aReq.AppendItem( SfxUInt32Item( SID_CLIPBOARD_FORMAT_ITEMS, static_cast<sal_uInt32>(nFormatId) ) );
+ aReq.Done();
+ }
+ }
+
+ if (rSh.IsFrameSelected() || rSh.IsObjSelected())
+ rSh.EnterSelFrameMode();
+ pView->AttrChangedNotify(nullptr);
+
+ // Fold pasted outlines that have outline content visible attribute false
+ MakeAllOutlineContentTemporarilyVisible a(rSh.GetDoc());
+ }
+
+ pDlg->disposeOnce();
+
+ });
+ }
+ else
+ return;
+ }
+ break;
+
+ default:
+ OSL_FAIL("wrong Dispatcher");
+ return;
+ }
+ if(!bIgnore)
+ rReq.Done();
+}
+
+// ClipBoard state
+
+void SwBaseShell::StateClpbrd(SfxItemSet &rSet)
+{
+ SwWrtShell &rSh = GetShell();
+ SfxWhichIter aIter(rSet);
+
+ const bool bCopy = rSh.HasSelection();
+
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while(nWhich)
+ {
+ switch(nWhich)
+ {
+ case SID_CUT:
+ if( FlyProtectFlags::NONE != rSh.IsSelObjProtected(FlyProtectFlags::Content|FlyProtectFlags::Parent ) )
+ {
+ rSet.DisableItem( nWhich );
+ break;
+ }
+ [[fallthrough]];
+ case SID_COPY:
+ if( !bCopy || GetObjectShell()->isContentExtractionLocked())
+ rSet.DisableItem( nWhich );
+ break;
+
+ case FN_PASTE_NESTED_TABLE:
+ case FN_TABLE_PASTE_ROW_BEFORE:
+ case FN_TABLE_PASTE_COL_BEFORE:
+ if( !rSh.IsCursorInTable()
+ || !GetView().IsPasteSpecialAllowed()
+ || rSh.CursorInsideInputField()
+ // disable if not a native Writer table and not a spreadsheet format
+ || !GetView().IsPasteSpreadsheet(rSh.GetTableCopied()) )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case SID_PASTE:
+ if( !GetView().IsPasteAllowed() )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case SID_PASTE_SPECIAL:
+ if( !GetView().IsPasteSpecialAllowed()
+ || rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case SID_PASTE_UNFORMATTED:
+ if( !GetView().IsPasteSpecialAllowed() )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case SID_CLIPBOARD_FORMAT_ITEMS:
+ {
+ TransferableDataHelper aDataHelper(
+ TransferableDataHelper::CreateFromSystemClipboard(
+ &rSh.GetView().GetEditWin()) );
+
+ SvxClipboardFormatItem aFormatItem( SID_CLIPBOARD_FORMAT_ITEMS );
+ SwTransferable::FillClipFormatItem( rSh, aDataHelper, aFormatItem );
+ rSet.Put( aFormatItem );
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+// Perform undo
+
+void SwBaseShell::ExecUndo(SfxRequest &rReq)
+{
+ MakeAllOutlineContentTemporarilyVisible a(GetShell().GetDoc(), true);
+
+ SwWrtShell &rWrtShell = GetShell();
+
+ SwUndoId nUndoId(SwUndoId::EMPTY);
+ sal_uInt16 nId = rReq.GetSlot(), nCnt = 1;
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem;
+ if( pArgs && SfxItemState::SET == pArgs->GetItemState( nId, false, &pItem ))
+ nCnt = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
+
+ // Repair mode: allow undo/redo of all undo actions, even if access would
+ // be limited based on the view shell ID.
+ bool bRepair = false;
+ const SfxBoolItem* pRepairItem;
+ if (pArgs && (pRepairItem = pArgs->GetItemIfSet(SID_REPAIRPACKAGE, false)))
+ bRepair = pRepairItem->GetValue();
+
+ // #i106349#: save pointer: undo/redo may delete the shell, i.e., this!
+ SfxViewFrame& rViewFrame( GetView().GetViewFrame() );
+
+ IDocumentUndoRedo& rUndoRedo = rWrtShell.GetIDocumentUndoRedo();
+ bool bWasRepair = rUndoRedo.DoesRepair();
+ rUndoRedo.DoRepair(bRepair);
+ comphelper::ScopeGuard aGuard([&rUndoRedo, bWasRepair]()
+ {
+ rUndoRedo.DoRepair(bWasRepair);
+ });
+
+ switch( nId )
+ {
+ case SID_UNDO:
+ if (rUndoRedo.GetLastUndoInfo(nullptr, &nUndoId, &rWrtShell.GetView()))
+ {
+ for (SwViewShell& rShell : rWrtShell.GetRingContainer())
+ rShell.LockPaint(LockPaintReason::Undo);
+
+ sal_uInt16 nUndoOffset = 0;
+ if (comphelper::LibreOfficeKit::isActive() && !bRepair && nCnt == 1)
+ {
+ sw::UndoManager& rManager = rWrtShell.GetDoc()->GetUndoManager();
+ const SfxUndoAction* pAction = rManager.GetUndoAction();
+ SwView& rView = rWrtShell.GetView();
+ ViewShellId nViewShellId = rView.GetViewShellId();
+ sal_uInt16 nOffset = 0;
+ if (pAction->GetViewShellId() != nViewShellId
+ && rManager.IsViewUndoActionIndependent(&rView, nOffset))
+ {
+ // Execute the undo with an offset: don't undo the top action, but an
+ // earlier one, since it's independent and that belongs to our view.
+ nUndoOffset += nOffset;
+ }
+ }
+
+ rWrtShell.Do(SwWrtShell::UNDO, nCnt, nUndoOffset);
+
+ for (SwViewShell& rShell : rWrtShell.GetRingContainer())
+ rShell.UnlockPaint();
+
+ // tdf#141613 FIXME: Disable redoing header/footer changes for now.
+ // The proper solution would be to write a SwUndoHeaderFooter class
+ // to represent the addition of a header or footer to the current page.
+ if (nUndoId == SwUndoId::HEADER_FOOTER)
+ rUndoRedo.ClearRedo();
+ }
+ break;
+
+ case SID_REDO:
+ if (rUndoRedo.GetFirstRedoInfo(nullptr, &nUndoId, &rWrtShell.GetView()))
+ {
+ for (SwViewShell& rShell : rWrtShell.GetRingContainer())
+ rShell.LockPaint(LockPaintReason::Redo);
+ rWrtShell.Do( SwWrtShell::REDO, nCnt );
+ for (SwViewShell& rShell : rWrtShell.GetRingContainer())
+ rShell.UnlockPaint();
+ }
+ break;
+
+ case SID_REPEAT:
+ rWrtShell.Do( SwWrtShell::REPEAT );
+ break;
+ default:
+ OSL_FAIL("wrong Dispatcher");
+ }
+
+ if (nUndoId == SwUndoId::CONFLICT)
+ {
+ rReq.SetReturnValue( SfxUInt32Item(nId, static_cast<sal_uInt32>(SID_REPAIRPACKAGE)) );
+ }
+
+ rViewFrame.GetBindings().InvalidateAll(false);
+}
+
+// State of undo
+
+void SwBaseShell::StateUndo(SfxItemSet &rSet)
+{
+ SwUndoId nUndoId(SwUndoId::EMPTY);
+ SwWrtShell &rSh = GetShell();
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while(nWhich)
+ {
+ switch(nWhich)
+ {
+ case SID_UNDO:
+ {
+ if (rSh.GetLastUndoInfo(nullptr, &nUndoId, &rSh.GetView()))
+ {
+ rSet.Put( SfxStringItem(nWhich,
+ rSh.GetDoString(SwWrtShell::UNDO)));
+ }
+ else if (nUndoId == SwUndoId::CONFLICT)
+ {
+ rSet.Put( SfxUInt32Item(nWhich, static_cast<sal_uInt32>(SID_REPAIRPACKAGE)) );
+ }
+ else
+ rSet.DisableItem(nWhich);
+
+ break;
+ }
+ case SID_REDO:
+ {
+ if (rSh.GetFirstRedoInfo(nullptr, &nUndoId, &rSh.GetView()))
+ {
+ rSet.Put(SfxStringItem(nWhich,
+ rSh.GetDoString(SwWrtShell::REDO)));
+ }
+ else if (nUndoId == SwUndoId::CONFLICT)
+ {
+ rSet.Put( SfxInt32Item(nWhich, static_cast<sal_uInt32>(SID_REPAIRPACKAGE)) );
+ }
+ else
+ rSet.DisableItem(nWhich);
+ break;
+ }
+ case SID_REPEAT:
+ { // Repeat is only possible if no REDO is possible - UI-Restriction
+ if ((!rSh.GetFirstRedoInfo(nullptr, nullptr)) &&
+ !rSh.IsSelFrameMode() &&
+ (SwUndoId::EMPTY != rSh.GetRepeatInfo(nullptr)))
+ {
+ rSet.Put(SfxStringItem(nWhich, rSh.GetRepeatString()));
+ }
+ else
+ rSet.DisableItem(nWhich);
+ break;
+ }
+
+ case SID_GETUNDOSTRINGS:
+ if (rSh.GetLastUndoInfo(nullptr, nullptr))
+ {
+ SfxStringListItem aStrLst( nWhich );
+ rSh.GetDoStrings( SwWrtShell::UNDO, aStrLst );
+ rSet.Put( aStrLst );
+ }
+ else
+ rSet.DisableItem( nWhich );
+ break;
+
+ case SID_GETREDOSTRINGS:
+ if (rSh.GetFirstRedoInfo(nullptr, nullptr))
+ {
+ SfxStringListItem aStrLst( nWhich );
+ rSh.GetDoStrings( SwWrtShell::REDO, aStrLst );
+ rSet.Put( aStrLst );
+ }
+ else
+ rSet.DisableItem( nWhich );
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+namespace
+{
+/// Searches for the specified field type and field name prefix and update the matching fields to
+/// have the provided new name and content.
+bool UpdateFieldContents(SfxRequest& rReq, SwWrtShell& rWrtSh)
+{
+ const SfxStringItem* pTypeName = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if (!pTypeName || pTypeName->GetValue() != "SetRef")
+ {
+ // This is implemented so far only for reference marks.
+ return false;
+ }
+
+ const SfxStringItem* pNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
+ if (!pNamePrefix)
+ {
+ return false;
+ }
+ const OUString& rNamePrefix = pNamePrefix->GetValue();
+
+ const SfxUnoAnyItem* pFields = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_3);
+ if (!pFields)
+ {
+ return false;
+ }
+ uno::Sequence<beans::PropertyValues> aFields;
+ pFields->GetValue() >>= aFields;
+
+ SwDoc* pDoc = rWrtSh.GetDoc();
+ pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::UPDATE_FIELDS, nullptr);
+ rWrtSh.StartAction();
+
+ std::vector<const SwFormatRefMark*> aRefMarks;
+
+ for (sal_uInt16 i = 0; i < pDoc->GetRefMarks(); ++i)
+ {
+ aRefMarks.push_back(pDoc->GetRefMark(i));
+ }
+
+ std::sort(aRefMarks.begin(), aRefMarks.end(),
+ [](const SwFormatRefMark* pMark1, const SwFormatRefMark* pMark2) -> bool {
+ const SwTextRefMark* pTextRefMark1 = pMark1->GetTextRefMark();
+ const SwTextRefMark* pTextRefMark2 = pMark2->GetTextRefMark();
+ SwPosition aPos1(pTextRefMark1->GetTextNode(), pTextRefMark1->GetStart());
+ SwPosition aPos2(pTextRefMark2->GetTextNode(), pTextRefMark2->GetStart());
+ return aPos1 < aPos2;
+ });
+
+ sal_uInt16 nFieldIndex = 0;
+ for (auto& pIntermediateRefMark : aRefMarks)
+ {
+ auto pRefMark = const_cast<SwFormatRefMark*>(pIntermediateRefMark);
+ if (!pRefMark->GetRefName().startsWith(rNamePrefix))
+ {
+ continue;
+ }
+
+ if (nFieldIndex >= aFields.getLength())
+ {
+ break;
+ }
+ comphelper::SequenceAsHashMap aMap(aFields[nFieldIndex++]);
+ auto aName = aMap["Name"].get<OUString>();
+ pRefMark->GetRefName() = aName;
+
+ OUString aContent = aMap["Content"].get<OUString>();
+ auto pTextRefMark = const_cast<SwTextRefMark*>(pRefMark->GetTextRefMark());
+ pTextRefMark->UpdateFieldContent(pDoc, rWrtSh, aContent);
+ }
+
+ rWrtSh.EndAction();
+ pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::UPDATE_FIELDS, nullptr);
+ return true;
+}
+
+/// Searches for the specified field type and field name prefix under cursor and update the matching
+/// field to have the provided new name and content.
+void UpdateFieldContent(SfxRequest& rReq, SwWrtShell& rWrtSh)
+{
+ const SfxStringItem* pTypeName = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if (!pTypeName || pTypeName->GetValue() != "SetRef")
+ {
+ // This is implemented so far only for reference marks.
+ return;
+ }
+
+ const SfxStringItem* pNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
+ if (!pNamePrefix)
+ {
+ return;
+ }
+ const OUString& rNamePrefix = pNamePrefix->GetValue();
+
+ const SfxUnoAnyItem* pField = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_3);
+ if (!pField)
+ {
+ return;
+ }
+ uno::Sequence<beans::PropertyValue> aField;
+ pField->GetValue() >>= aField;
+
+ SwPosition& rCursor = *rWrtSh.GetCursor()->GetPoint();
+ SwTextNode* pTextNode = rCursor.GetNode().GetTextNode();
+ std::vector<SwTextAttr*> aAttrs
+ = pTextNode->GetTextAttrsAt(rCursor.GetContentIndex(), RES_TXTATR_REFMARK);
+ if (aAttrs.empty())
+ {
+ return;
+ }
+
+ auto& rRefmark = const_cast<SwFormatRefMark&>(aAttrs[0]->GetRefMark());
+ if (!rRefmark.GetRefName().startsWith(rNamePrefix))
+ {
+ return;
+ }
+
+ SwDoc* pDoc = rWrtSh.GetDoc();
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, rRefmark.GetRefName());
+ pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::UPDATE_FIELD, &aRewriter);
+ rWrtSh.StartAction();
+ comphelper::ScopeGuard g(
+ [&rWrtSh, &aRewriter]
+ {
+ rWrtSh.EndAction();
+ rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::UPDATE_FIELD, &aRewriter);
+ });
+
+ comphelper::SequenceAsHashMap aMap(aField);
+ auto aName = aMap["Name"].get<OUString>();
+ rRefmark.GetRefName() = aName;
+
+ OUString aContent = aMap["Content"].get<OUString>();
+ auto pTextRefMark = const_cast<SwTextRefMark*>(rRefmark.GetTextRefMark());
+ pTextRefMark->UpdateFieldContent(pDoc, rWrtSh, aContent);
+}
+}
+
+// Evaluate respectively dispatching the slot Id
+
+void SwBaseShell::Execute(SfxRequest &rReq)
+{
+ const SfxPoolItem *pItem;
+ SwWrtShell &rSh = GetShell();
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ bool bMore = false;
+
+ sal_uInt16 nSlot = rReq.GetSlot();
+ switch(nSlot)
+ {
+ case FN_REPAGINATE:
+ {
+ Reference < XModel > xModel = GetView().GetDocShell()->GetModel();
+ auto pDoc = comphelper::getFromUnoTunnel<SwXTextDocument>(xModel);
+ pDoc->NotifyRefreshListeners();
+ rSh.CalcLayout();
+ }
+ break;
+ case FN_UPDATE_FIELDS:
+ {
+ if (UpdateFieldContents(rReq, rSh))
+ {
+ // Parameters indicated that the name / content of fields has to be updated to
+ // the provided values, don't do an actual fields update.
+ break;
+ }
+
+ rSh.UpdateDocStat();
+ rSh.EndAllTableBoxEdit();
+ rSh.SwViewShell::UpdateFields(true);
+
+ if( rSh.IsCursorInTable() )
+ {
+ if( !rSh.IsTableComplexForChart() )
+ SwTableFUNC( &rSh ).UpdateChart();
+ rSh.ClearTableBoxContent();
+ rSh.SaveTableBoxContent();
+ }
+ }
+ break;
+ case FN_UPDATE_FIELD:
+ {
+ UpdateFieldContent(rReq, rSh);
+ }
+ break;
+ case FN_UPDATE_CHARTS:
+ {
+ SwWait aWait( *m_rView.GetDocShell(), true );
+ rSh.UpdateAllCharts();
+ }
+ break;
+
+ case FN_UPDATE_ALL:
+ {
+ comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer
+ = GetObjectShell()->getEmbeddedObjectContainer();
+ rEmbeddedObjectContainer.setUserAllowsLinkUpdate(true);
+
+ SwView& rTempView = GetView();
+ rSh.EnterStdMode();
+ if( !rSh.GetLinkManager().GetLinks().empty() )
+ {
+ rSh.StartAllAction();
+ rSh.GetLinkManager().UpdateAllLinks( false, true, nullptr );
+ rSh.EndAllAction();
+ }
+ SfxDispatcher &rDis = *rTempView.GetViewFrame().GetDispatcher();
+ rDis.Execute( FN_UPDATE_FIELDS );
+ rDis.Execute( FN_UPDATE_TOX );
+ rDis.Execute( FN_UPDATE_CHARTS );
+ rSh.Reformat();
+ rSh.UpdateOleObjectPreviews();
+ }
+ break;
+
+ case FN_UPDATE_INPUTFIELDS:
+ rSh.UpdateInputFields();
+ break;
+
+ case FN_PREV_BOOKMARK:
+ rReq.SetReturnValue(SfxBoolItem( nSlot, rSh.GoPrevBookmark()));
+ break;
+ case FN_NEXT_BOOKMARK:
+ rReq.SetReturnValue(SfxBoolItem( nSlot, rSh.GoNextBookmark()));
+ break;
+
+ case FN_GOTO_NEXT_MARK:
+ case FN_GOTO_PREV_MARK:
+ {
+ SwFieldMgr aFieldMgr;
+ SwFieldType* pFieldType = aFieldMgr.GetFieldType(SwFieldIds::JumpEdit);
+
+ if (pFieldType)
+ {
+ if (rSh.IsSelFrameMode())
+ {
+ rSh.UnSelectFrame();
+ rSh.LeaveSelFrameMode();
+ }
+
+ if (rSh.HasMark())
+ {
+ SwMvContext aMvContext(&rSh);
+ if (rSh.IsCursorPtAtEnd())
+ rSh.SwapPam();
+ rSh.ClearMark();
+ rSh.EndSelect();
+ }
+ bool bRet = rSh.MoveFieldType( pFieldType, nSlot == FN_GOTO_NEXT_MARK );
+ SwField* pCurField = bRet ? rSh.GetCurField() : nullptr;
+ if (pCurField)
+ rSh.ClickToField(*pCurField, /*bExecHyperlinks=*/false);
+ rReq.SetReturnValue(SfxBoolItem( nSlot, bRet));
+ }
+ }
+ break;
+
+ case FN_START_DOC_DIRECT:
+ case FN_END_DOC_DIRECT:
+ {
+ if (rSh.IsSelFrameMode())
+ {
+ rSh.UnSelectFrame();
+ rSh.LeaveSelFrameMode();
+ }
+ rSh.EnterStdMode();
+ nSlot == FN_START_DOC_DIRECT ?
+ rSh.SttEndDoc(true) :
+ rSh.SttEndDoc(false);
+ }
+ break;
+ case FN_GOTO_PREV_OBJ:
+ case FN_GOTO_NEXT_OBJ:
+ {
+ bool bSuccess = rSh.GotoObj( nSlot == FN_GOTO_NEXT_OBJ );
+ rReq.SetReturnValue(SfxBoolItem(nSlot, bSuccess));
+ if (bSuccess && !rSh.IsSelFrameMode())
+ {
+ rSh.HideCursor();
+ rSh.EnterSelFrameMode();
+ GetView().AttrChangedNotify(nullptr);
+ }
+ }
+ break;
+ case SID_GALLERY_FORMATS:
+ {
+ const SvxGalleryItem* pGalleryItem = SfxItemSet::GetItem<SvxGalleryItem>(pArgs, SID_GALLERY_FORMATS, false);
+ if ( !pGalleryItem )
+ break;
+
+ const SelectionType nSelType = rSh.GetSelectionType();
+ sal_Int8 nGalleryItemType( pGalleryItem->GetType() );
+
+ if ( (!rSh.IsSelFrameMode() || nSelType & SelectionType::Graphic) &&
+ nGalleryItemType == css::gallery::GalleryItemType::GRAPHIC )
+ {
+ SwWait aWait( *m_rView.GetDocShell(), true );
+
+ OUString aGrfName, aFltName;
+ const Graphic aGrf( pGalleryItem->GetGraphic() );
+
+ if ( nSelType & SelectionType::Graphic )
+ rSh.ReRead( aGrfName, aFltName, &aGrf );
+ else
+ rSh.InsertGraphic( aGrfName, aFltName, aGrf );
+
+ GetView().GetEditWin().GrabFocus();
+ }
+ else if(!rSh.IsSelFrameMode() &&
+ nGalleryItemType == css::gallery::GalleryItemType::MEDIA )
+ {
+ const SfxStringItem aMediaURLItem( SID_INSERT_AVMEDIA, pGalleryItem->GetURL() );
+ GetView().GetViewFrame().GetDispatcher()->ExecuteList(
+ SID_INSERT_AVMEDIA, SfxCallMode::SYNCHRON,
+ { &aMediaURLItem });
+ }
+ }
+ break;
+ case FN_PAGE_STYLE_SET_COLS:
+ {
+ if (pArgs)
+ {
+ // Determine the current PageDescriptor and fill the set with that.
+ const size_t nCurIdx = rSh.GetCurPageDesc();
+ SwPageDesc aPageDesc(rSh.GetPageDesc(nCurIdx));
+
+ SwFrameFormat &rFormat = aPageDesc.GetMaster();
+
+ SwFormatCol aFormatCol = rFormat.GetCol();
+
+ sal_uInt16 nCount;
+ if(SfxItemState::SET == pArgs->GetItemState(nSlot))
+ nCount = static_cast<const SfxUInt16Item &>(pArgs->Get(nSlot)).GetValue();
+ else
+ nCount = pArgs->Get(SID_ATTR_COLUMNS).GetValue();
+ sal_uInt16 nGutterWidth = DEF_GUTTER_WIDTH;
+
+ aFormatCol.Init(nCount ? nCount : 1, nGutterWidth, USHRT_MAX);
+ aFormatCol.SetWishWidth(USHRT_MAX);
+ aFormatCol.SetGutterWidth(nGutterWidth, USHRT_MAX);
+
+ rFormat.SetFormatAttr(aFormatCol);
+
+ rSh.ChgPageDesc(nCurIdx, aPageDesc);
+ }
+ else
+ GetView().GetViewFrame().GetDispatcher()->Execute(FN_FORMAT_PAGE_COLUMN_DLG);
+ }
+ break;
+ case FN_CONVERT_TABLE_TO_TEXT:
+ case FN_CONVERT_TEXT_TO_TABLE:
+ case FN_CONVERT_TEXT_TABLE:
+ {
+ sal_Unicode cDelim = 0;
+ bool bToTable = false;
+ if( nSlot == FN_CONVERT_TEXT_TO_TABLE ||
+ ( nSlot == FN_CONVERT_TEXT_TABLE && nullptr == rSh.GetTableFormat() ))
+ bToTable = true;
+ SwInsertTableOptions aInsTableOpts( SwInsertTableFlags::All, 1 );
+ SwTableAutoFormat const* pTAFormat = nullptr;
+ std::unique_ptr<SwTableAutoFormatTable> pAutoFormatTable;
+ bool bDeleteFormat = true;
+ if(pArgs && SfxItemState::SET == pArgs->GetItemState( FN_PARAM_1, true, &pItem))
+ {
+ aInsTableOpts.mnInsMode = SwInsertTableFlags::NONE;
+ // Delimiter
+ OUString sDelim = static_cast< const SfxStringItem* >(pItem)->GetValue();
+ if(!sDelim.isEmpty())
+ cDelim = sDelim[0];
+ // AutoFormat
+ if(SfxItemState::SET == pArgs->GetItemState( FN_PARAM_2, true, &pItem))
+ {
+ OUString sAutoFormat = static_cast< const SfxStringItem* >(pItem)->GetValue();
+
+ pAutoFormatTable.reset(new SwTableAutoFormatTable);
+ pAutoFormatTable->Load();
+
+ for( sal_uInt16 i = 0, nCount = pAutoFormatTable->size(); i < nCount; i++ )
+ {
+ SwTableAutoFormat const*const pFormat = &(*pAutoFormatTable)[ i ];
+ if( pFormat->GetName() == sAutoFormat )
+ {
+ pTAFormat = pFormat;
+ bDeleteFormat = false;
+ break;
+ }
+ }
+ }
+ //WithHeader
+ if(SfxItemState::SET == pArgs->GetItemState( FN_PARAM_3, true, &pItem) &&
+ static_cast< const SfxBoolItem* >(pItem)->GetValue())
+ aInsTableOpts.mnInsMode |= SwInsertTableFlags::Headline;
+ // RepeatHeaderLines
+ if(SfxItemState::SET == pArgs->GetItemState( FN_PARAM_4, true, &pItem))
+ aInsTableOpts.mnRowsToRepeat =
+ o3tl::narrowing<sal_uInt16>(static_cast< const SfxInt16Item* >(pItem)->GetValue());
+ //WithBorder
+ if(SfxItemState::SET == pArgs->GetItemState( FN_PARAM_5, true, &pItem) &&
+ static_cast< const SfxBoolItem* >(pItem)->GetValue())
+ aInsTableOpts.mnInsMode |= SwInsertTableFlags::DefaultBorder;
+ //DontSplitTable
+ if(SfxItemState::SET == pArgs->GetItemState( FN_PARAM_6, true, &pItem) &&
+ !static_cast< const SfxBoolItem* >(pItem)->GetValue() )
+ aInsTableOpts.mnInsMode |= SwInsertTableFlags::SplitLayout;
+ }
+ else
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractSwConvertTableDlg> pDlg(pFact->CreateSwConvertTableDlg(GetView(), bToTable));
+ if( RET_OK == pDlg->Execute() )
+ {
+ pDlg->GetValues( cDelim, aInsTableOpts, pTAFormat );
+
+ }
+ }
+
+ if( cDelim )
+ {
+ //Shell change!
+ SwView& rSaveView = m_rView;
+ bool bInserted = false;
+ //recording:
+ SfxViewFrame& rViewFrame = GetView().GetViewFrame();
+ if (SfxRequest::HasMacroRecorder(rViewFrame))
+ {
+ SfxRequest aReq(rViewFrame, nSlot);
+ aReq.AppendItem( SfxStringItem( FN_PARAM_1, OUString(cDelim) ));
+ if(bToTable)
+ {
+ if(pTAFormat)
+ aReq.AppendItem( SfxStringItem( FN_PARAM_2, pTAFormat->GetName()));
+ aReq.AppendItem( SfxBoolItem ( FN_PARAM_3, bool(aInsTableOpts.mnInsMode & SwInsertTableFlags::Headline)));
+ aReq.AppendItem( SfxInt16Item( FN_PARAM_4, static_cast<short>(aInsTableOpts.mnRowsToRepeat) ));
+ aReq.AppendItem( SfxBoolItem ( FN_PARAM_5, bool(aInsTableOpts.mnInsMode & SwInsertTableFlags::DefaultBorder) ));
+ aReq.AppendItem( SfxBoolItem ( FN_PARAM_6, !(aInsTableOpts.mnInsMode & SwInsertTableFlags::SplitLayout)));
+ }
+ aReq.Done();
+ }
+
+ if( !bToTable )
+ rSh.TableToText( cDelim );
+ else
+ {
+ bInserted = rSh.TextToTable( aInsTableOpts, cDelim, pTAFormat );
+ }
+ rSh.EnterStdMode();
+
+ if( bInserted )
+ rSaveView.AutoCaption( TABLE_CAP );
+ }
+ if(bDeleteFormat)
+ delete pTAFormat;
+ }
+ break;
+ case SID_STYLE_WATERCAN:
+ case SID_STYLE_UPDATE_BY_EXAMPLE:
+ case SID_STYLE_NEW_BY_EXAMPLE:
+ case SID_STYLE_APPLY:
+ {
+ ShellMode eMode = GetView().GetShellMode();
+ if ( ShellMode::Draw != eMode &&
+ ShellMode::DrawForm != eMode &&
+ ShellMode::DrawText != eMode &&
+ ShellMode::Bezier != eMode )
+ {
+ // oj #107754#
+ if ( SID_STYLE_WATERCAN == nSlot )
+ {
+ const bool bLockedView = rSh.IsViewLocked();
+ rSh.LockView( true ); //lock visible section
+
+ GetView().GetDocShell()->ExecStyleSheet(rReq);
+
+ rSh.LockView( bLockedView );
+ }
+ else
+ // Will be recorded from the DocShell
+ GetView().GetDocShell()->ExecStyleSheet(rReq);
+ }
+ }
+ break;
+ case SID_CLASSIFICATION_APPLY:
+ {
+ GetView().GetDocShell()->Execute(rReq);
+ }
+ break;
+ case SID_CLASSIFICATION_DIALOG:
+ {
+ GetView().GetDocShell()->Execute(rReq);
+ }
+ break;
+ case SID_PARAGRAPH_SIGN_CLASSIFY_DLG:
+ {
+ GetView().GetDocShell()->Execute(rReq);
+ }
+ break;
+ case SID_WATERMARK:
+ {
+ GetView().GetDocShell()->Execute(rReq);
+ }
+ break;
+ case FN_ESCAPE:
+ GetView().ExecuteSlot(rReq);
+ break;
+ case SID_IMAP:
+ {
+ sal_uInt16 nId = SvxIMapDlgChildWindow::GetChildWindowId();
+
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+ rVFrame.ToggleChildWindow( nId );
+ rVFrame.GetBindings().Invalidate( SID_IMAP );
+
+ if ( rVFrame.HasChildWindow( nId ) && rSh.IsFrameSelected() )
+ lcl_UpdateIMapDlg( rSh );
+ }
+ break;
+ case SID_IMAP_EXEC:
+ {
+ SvxIMapDlg* pDlg = GetIMapDlg(GetView());
+
+ // Check, if the allocation is useful or allowed at all.
+ if ( rSh.IsFrameSelected() &&
+ pDlg->GetEditingObject() == rSh.GetIMapInventor() )
+ {
+ SfxItemSetFixed<RES_URL, RES_URL> aSet( rSh.GetAttrPool() );
+ rSh.GetFlyFrameAttr( aSet );
+ SwFormatURL aURL( aSet.Get( RES_URL ) );
+ aURL.SetMap( &pDlg->GetImageMap() );
+ aSet.Put( aURL );
+ rSh.SetFlyFrameAttr( aSet );
+ }
+ }
+ break;
+ case FN_SET_TRACKED_CHANGES_IN_TEXT:
+ case FN_SET_TRACKED_DELETIONS_IN_MARGIN:
+ case FN_SET_TRACKED_INSERTIONS_IN_MARGIN:
+ {
+ SwViewOption aViewOption = *rSh.GetViewOptions();
+ bool bAllInText = FN_SET_TRACKED_CHANGES_IN_TEXT == nSlot;
+ aViewOption.SetShowChangesInMargin( !bAllInText );
+ if ( !bAllInText )
+ aViewOption.SetShowChangesInMargin2( FN_SET_TRACKED_INSERTIONS_IN_MARGIN == nSlot );
+ rSh.ApplyViewOptions( aViewOption );
+
+ // tdf#140982 restore annotation ranges stored in temporary bookmarks
+ // (only remove temporary bookmarks during file saving to avoid possible
+ // conflict with lazy deletion of the bookmarks of the moved tracked deletions)
+ if ( bAllInText || FN_SET_TRACKED_INSERTIONS_IN_MARGIN == nSlot )
+ rSh.GetDoc()->getIDocumentMarkAccess()->restoreAnnotationMarks(false);
+ }
+ break;
+ case SID_CONTOUR_DLG:
+ {
+ sal_uInt16 nId = SvxContourDlgChildWindow::GetChildWindowId();
+
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+ rVFrame.ToggleChildWindow( nId );
+ rVFrame.GetBindings().Invalidate( SID_CONTOUR_DLG );
+
+ SelectionType nSel = rSh.GetSelectionType();
+ if ( rVFrame.HasChildWindow( nId ) &&
+ (nSel & (SelectionType::Graphic|SelectionType::Ole)) )
+ {
+ lcl_UpdateContourDlg( rSh, nSel );
+ }
+ }
+ break;
+ case SID_CONTOUR_EXEC:
+ {
+ SvxContourDlg *pDlg = GetContourDlg(GetView());
+ // Check, if the allocation is useful or allowed at all.
+ SelectionType nSel = rSh.GetSelectionType();
+ if ( nSel & (SelectionType::Graphic|SelectionType::Ole) )
+ {
+ if (pDlg && pDlg->GetEditingObject() == rSh.GetIMapInventor())
+ {
+ rSh.StartAction();
+ SfxItemSetFixed<RES_SURROUND, RES_SURROUND> aSet( rSh.GetAttrPool() );
+ rSh.GetFlyFrameAttr( aSet );
+ SwFormatSurround aSur( aSet.Get( RES_SURROUND ) );
+ if ( !aSur.IsContour() )
+ {
+ aSur.SetContour( true );
+ if ( aSur.GetSurround() == css::text::WrapTextMode_NONE )
+ aSur.SetSurround( css::text::WrapTextMode_PARALLEL );
+ aSet.Put( aSur );
+ rSh.SetFlyFrameAttr( aSet );
+ }
+ const tools::PolyPolygon aPoly( pDlg->GetPolyPolygon() );
+ rSh.SetGraphicPolygon( &aPoly );
+ if ( pDlg->IsGraphicChanged() )
+ rSh.ReRead( OUString(), OUString(), &pDlg->GetGraphic());
+ rSh.EndAction();
+ }
+ }
+ }
+ break;
+ case FN_FRAME_TO_ANCHOR:
+ {
+ rSh.GotoFlyAnchor();
+ rSh.EnterStdMode();
+ rSh.CallChgLnk();
+ }
+ break;
+ case FN_TOOL_ANCHOR_PAGE:
+ case FN_TOOL_ANCHOR_PARAGRAPH:
+ case FN_TOOL_ANCHOR_CHAR:
+ case FN_TOOL_ANCHOR_AT_CHAR:
+ case FN_TOOL_ANCHOR_FRAME:
+ {
+ RndStdIds eSet = nSlot == FN_TOOL_ANCHOR_PAGE
+ ? RndStdIds::FLY_AT_PAGE
+ : nSlot == FN_TOOL_ANCHOR_PARAGRAPH
+ ? RndStdIds::FLY_AT_PARA
+ : nSlot == FN_TOOL_ANCHOR_FRAME
+ ? RndStdIds::FLY_AT_FLY
+ : nSlot == FN_TOOL_ANCHOR_CHAR
+ ? RndStdIds::FLY_AS_CHAR
+ : RndStdIds::FLY_AT_CHAR;
+ rSh.StartUndo();
+ if (rSh.IsObjSelected())
+ rSh.ChgAnchor(eSet);
+ else if (rSh.IsFrameSelected())
+ {
+ SwFormatAnchor aAnc(eSet, eSet == RndStdIds::FLY_AT_PAGE ? rSh.GetPhyPageNum() : 0);
+ SfxItemSet aSet(SwFEShell::makeItemSetFromFormatAnchor(GetPool(), aAnc));
+ rSh.SetFlyFrameAttr(aSet);
+ }
+ // if new anchor is 'as char' and it is a Math object and the usual
+ // pre-conditions are met then align the formula to the baseline of the text
+ const uno::Reference < embed::XEmbeddedObject > xObj( rSh.GetOleRef() );
+ const bool bDoMathBaselineAlignment = xObj.is() && SotExchange::IsMath( xObj->getClassID() )
+ && RndStdIds::FLY_AS_CHAR == eSet && rSh.GetDoc()->getIDocumentSettingAccess().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT );
+ if (bDoMathBaselineAlignment)
+ rSh.AlignFormulaToBaseline( xObj );
+
+ sal_uInt16 nHtmlMode = ::GetHtmlMode(GetView().GetDocShell());
+ if( nHtmlMode )
+ {
+ SfxItemSetFixed<RES_SURROUND, RES_HORI_ORIENT> aSet(GetPool());
+ rSh.GetFlyFrameAttr(aSet);
+
+ const SwFormatSurround& rSurround = aSet.Get(RES_SURROUND);
+ const SwFormatVertOrient& rVert = aSet.Get(RES_VERT_ORIENT);
+ const SwFormatHoriOrient& rHori = aSet.Get(RES_HORI_ORIENT);
+ sal_Int16 eVOrient = rVert.GetVertOrient();
+ sal_Int16 eHOrient = rHori.GetHoriOrient();
+ css::text::WrapTextMode eSurround = rSurround.GetSurround();
+
+ switch( eSet )
+ {
+ case RndStdIds::FLY_AT_FLY:
+ case RndStdIds::FLY_AT_PAGE:
+ //Wrap through, left or from left, top, from top
+ if(eSurround != css::text::WrapTextMode_THROUGH)
+ aSet.Put(SwFormatSurround(css::text::WrapTextMode_THROUGH));
+
+ if( eVOrient != text::VertOrientation::TOP && eVOrient != text::VertOrientation::NONE)
+ aSet.Put(SwFormatVertOrient(0, text::VertOrientation::TOP));
+
+ if (eHOrient != text::HoriOrientation::NONE && eHOrient != text::HoriOrientation::LEFT)
+ aSet.Put(SwFormatHoriOrient(0, text::HoriOrientation::LEFT));
+ break;
+
+ case RndStdIds::FLY_AT_PARA:
+ // left, from left, right, top, no wrap, wrap left and right
+ if (eSurround != css::text::WrapTextMode_LEFT && eSurround != css::text::WrapTextMode_RIGHT)
+ aSet.Put(SwFormatSurround(css::text::WrapTextMode_LEFT));
+
+ if( eVOrient != text::VertOrientation::TOP)
+ aSet.Put(SwFormatVertOrient(0, text::VertOrientation::TOP));
+
+ if (eHOrient != text::HoriOrientation::NONE && eHOrient != text::HoriOrientation::LEFT && eHOrient != text::HoriOrientation::RIGHT)
+ aSet.Put(SwFormatHoriOrient(0, text::HoriOrientation::LEFT));
+ break;
+
+ case RndStdIds::FLY_AT_CHAR:
+ // left, from left, right, top, wrap through
+ if(eSurround != css::text::WrapTextMode_THROUGH)
+ aSet.Put(SwFormatSurround(css::text::WrapTextMode_THROUGH));
+
+ if( eVOrient != text::VertOrientation::TOP)
+ aSet.Put(SwFormatVertOrient(0, text::VertOrientation::TOP));
+
+ if (eHOrient != text::HoriOrientation::NONE && eHOrient != text::HoriOrientation::LEFT && eHOrient != text::HoriOrientation::RIGHT)
+ aSet.Put(SwFormatHoriOrient(0, text::HoriOrientation::LEFT));
+ break;
+
+ default:
+ ;
+ }
+
+ if( aSet.Count() )
+ rSh.SetFlyFrameAttr( aSet );
+ }
+ rSh.EndUndo();
+
+ GetView().GetViewFrame().GetBindings().Invalidate( SID_ANCHOR_MENU );
+ }
+ break;
+
+ case FN_FRAME_NOWRAP:
+ case FN_FRAME_WRAP:
+ case FN_FRAME_WRAP_IDEAL:
+ case FN_FRAME_WRAPTHRU:
+ case FN_FRAME_WRAPTHRU_TRANSP:
+ case FN_FRAME_WRAPTHRU_TOGGLE:
+ case FN_FRAME_WRAP_CONTOUR:
+ case FN_WRAP_ANCHOR_ONLY:
+ case FN_FRAME_WRAP_LEFT:
+ case FN_FRAME_WRAP_RIGHT:
+ SetWrapMode( nSlot );
+ break;
+
+ case FN_UPDATE_ALL_LINKS:
+ {
+ if( !rSh.GetLinkManager().GetLinks().empty() )
+ {
+ rSh.EnterStdMode();
+ rSh.StartAllAction();
+ rSh.GetLinkManager().UpdateAllLinks( false, false, nullptr );
+ rSh.EndAllAction();
+ }
+ }
+ break;
+
+ case FN_XFORMS_DESIGN_MODE:
+ if (pArgs && pArgs->GetItemState(nSlot, true, &pItem) == SfxItemState::SET)
+ {
+ if (const SfxBoolItem* pBoolItem = dynamic_cast<const SfxBoolItem*>(pItem))
+ {
+ bool bDesignMode = pBoolItem->GetValue();
+
+ // set from design mode
+ OSL_ENSURE( GetView().GetFormShell() != nullptr, "form shell?" );
+ SfxRequest aReq(GetView().GetViewFrame(), SID_FM_DESIGN_MODE);
+ aReq.AppendItem( SfxBoolItem( SID_FM_DESIGN_MODE, bDesignMode ) );
+ GetView().GetFormShell()->Execute( aReq );
+ aReq.Done();
+
+ // also set suitable view options
+ SwViewOption aViewOption = *rSh.GetViewOptions();
+ aViewOption.SetFormView( ! bDesignMode );
+ rSh.ApplyViewOptions( aViewOption );
+ }
+ }
+ break;
+
+ default:
+ bMore = true;
+ }
+
+
+ if(!bMore || !pArgs)
+ return;
+
+ pItem = nullptr;
+ pArgs->GetItemState(GetPool().GetWhich(nSlot), false, &pItem);
+ if(!pItem)
+ return;
+
+ switch(nSlot)
+ {
+ case SID_ATTR_BRUSH:
+ case SID_ATTR_BORDER_SHADOW:
+ case RES_SHADOW:
+ {
+ rSh.StartAllAction();
+ // Table cell(s) selected?
+ if ( rSh.IsTableMode() )
+ {
+ SwFrameFormat *pFormat = rSh.GetTableFormat();
+ pFormat->SetFormatAttr( *pItem );
+ }
+ else if ( rSh.IsFrameSelected() )
+ {
+ // Set border attributes via Frame-Manager.
+ SwFlyFrameAttrMgr aMgr( false, &rSh, Frmmgr_Type::NONE, nullptr );
+ aMgr.SetAttrSet( *pArgs );
+ aMgr.UpdateFlyFrame();
+ }
+ else
+ {
+ rSh.SetAttrSet( *pArgs );
+ }
+ rSh.EndAllAction();
+ }
+ break;
+ case FN_PAGE_STYLE_SET_LR_MARGIN:
+ case FN_PAGE_STYLE_SET_UL_MARGIN:
+ case FN_PAGE_STYLE_SET_NUMBER_FORMAT:
+ case FN_PAGE_STYLE_SET_PAPER_SIZE:
+ case FN_PAGE_STYLE_SET_PAPER_BIN:
+ {
+ OSL_FAIL("not implemented");
+ }
+ break;
+
+ case SID_ATTR_BORDER_OUTER:
+ {
+ // Table cell(s) selected?
+ if ( rSh.IsTableMode() )
+ {
+ // Set border attributes Get/SetTabBorders()
+ rSh.SetTabBorders(*pArgs);
+ }
+ else if ( rSh.IsFrameSelected() )
+ {
+ // Set border attributes via Frame-Manager.
+ SwFlyFrameAttrMgr aMgr( false, &rSh, Frmmgr_Type::NONE, nullptr );
+ aMgr.SetAttrSet(*pArgs);
+ aMgr.UpdateFlyFrame();
+ }
+ else
+ {
+ // Set border attributes via shell quite normally.
+ rSh.SetAttrItem( *pItem );
+ }
+ }
+ break;
+ default:
+ OSL_FAIL("wrong Dispatcher");
+ }
+}
+
+// Here the state for SID_IMAP / SID_CONTOUR will be handled
+// until the swapping of the graphic is finished.
+
+IMPL_LINK_NOARG(SwBaseShell, GraphicArrivedHdl, SwCursorShell&, void)
+{
+ SwWrtShell &rSh = GetShell();
+ if (CNT_GRF != rSh.SwEditShell::GetCntType())
+ return;
+ GraphicType const nGrfType(rSh.GetGraphicType());
+ if (GraphicType::NONE == nGrfType || m_aGrfUpdateSlots.empty())
+ return;
+
+ bool bProtect = FlyProtectFlags::NONE != rSh.IsSelObjProtected(FlyProtectFlags::Content|FlyProtectFlags::Parent);
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+ for( const auto nSlot : m_aGrfUpdateSlots )
+ {
+ bool bSetState = false;
+ bool bState = false;
+ switch( nSlot )
+ {
+ case SID_IMAP:
+ case SID_IMAP_EXEC:
+ {
+ sal_uInt16 nId = SvxIMapDlgChildWindow::GetChildWindowId();
+ SfxChildWindow *pChildWindow = rVFrame.HasChildWindow(nId) ?
+ rVFrame.GetChildWindow(nId) : nullptr;
+ SvxIMapDlg *pDlg = pChildWindow ?
+ static_cast<SvxIMapDlg*>(pChildWindow->GetController().get()) : nullptr;
+
+ if( pDlg && ( SID_IMAP_EXEC == nSlot ||
+ ( SID_IMAP == nSlot && !bProtect)) &&
+ pDlg->GetEditingObject() != rSh.GetIMapInventor())
+ lcl_UpdateIMapDlg( rSh );
+
+ if( !bProtect && SID_IMAP == nSlot )
+ {
+ bSetState = true;
+ bState = nullptr != pDlg;
+ }
+ }
+ break;
+
+ case SID_CONTOUR_DLG:
+ if( !bProtect )
+ {
+ sal_uInt16 nId = SvxContourDlgChildWindow::GetChildWindowId();
+ SfxChildWindow *pChildWindow = rVFrame.HasChildWindow(nId) ?
+ rVFrame.GetChildWindow(nId) : nullptr;
+ SvxIMapDlg *pDlg = pChildWindow ?
+ static_cast<SvxIMapDlg*>(pChildWindow->GetController().get()) : nullptr;
+ if( pDlg && pDlg->GetEditingObject() !=
+ rSh.GetIMapInventor() )
+ lcl_UpdateContourDlg( rSh, SelectionType::Graphic );
+
+ bSetState = true;
+ bState = nullptr != pDlg;
+ }
+ break;
+
+ case FN_FRAME_WRAP_CONTOUR:
+ if( !bProtect )
+ {
+ SfxItemSetFixed<RES_SURROUND, RES_SURROUND> aSet(GetPool());
+ rSh.GetFlyFrameAttr(aSet);
+ const SwFormatSurround& rWrap = aSet.Get(RES_SURROUND);
+ bSetState = true;
+ bState = rWrap.IsContour();
+ }
+ break;
+
+ case SID_GRFFILTER:
+ case SID_GRFFILTER_INVERT:
+ case SID_GRFFILTER_SMOOTH:
+ case SID_GRFFILTER_SHARPEN:
+ case SID_GRFFILTER_REMOVENOISE:
+ case SID_GRFFILTER_SOBEL:
+ case SID_GRFFILTER_MOSAIC:
+ case SID_GRFFILTER_EMBOSS:
+ case SID_GRFFILTER_POSTER:
+ case SID_GRFFILTER_POPART:
+ case SID_GRFFILTER_SEPIA:
+ case SID_GRFFILTER_SOLARIZE:
+ bSetState = bState = GraphicType::Bitmap == nGrfType;
+ break;
+ }
+
+ if( bSetState )
+ {
+ SfxBoolItem aBool( nSlot, bState );
+ if( m_pGetStateSet )
+ m_pGetStateSet->Put( aBool );
+ else
+ rVFrame.GetBindings().SetState( aBool );
+ }
+ }
+ m_aGrfUpdateSlots.clear();
+}
+
+void SwBaseShell::GetState( SfxItemSet &rSet )
+{
+ SwWrtShell &rSh = GetShell();
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ m_pGetStateSet = &rSet;
+ while ( nWhich )
+ {
+ switch ( nWhich )
+ {
+ case SID_GALLERY_FORMATS:
+ if ( rSh.IsObjSelected() ||
+ (rSh.IsSelFrameMode() &&
+ !(rSh.GetSelectionType() & SelectionType::Graphic)) )
+ rSet.DisableItem( nWhich );
+ break;
+ case SID_GALLERY_ENABLE_ADDCOPY:
+ // #108230# allow copy from gallery in Writer AND Writer/Web!
+ rSet.Put( SfxBoolItem( SID_GALLERY_ENABLE_ADDCOPY, true ) );
+ break;
+ case FN_EDIT_REGION:
+ if( !rSh.IsAnySectionInDoc() )
+ rSet.DisableItem(nWhich);
+ break;
+
+ case FN_EDIT_CURRENT_REGION:
+ //tdf#112808 if cursor is in an index, don't show the edit section.
+ if( !rSh.GetCurrSection() ||
+ (rSh.GetCurrSection()->GetType() != SectionType::Content &&
+ rSh.GetCurrSection()->GetType() != SectionType::FileLink ))
+ {
+ rSet.DisableItem(nWhich);
+ }
+ break;
+
+ case FN_INSERT_REGION:
+ if( rSh.CursorInsideInputField()
+ || rSh.IsSelFrameMode()
+ || !rSh.IsInsRegionAvailable() )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case FN_CONVERT_TABLE_TO_TEXT:
+ {
+ FrameTypeFlags eFrameType = rSh.GetFrameType(nullptr,true);
+ if( (eFrameType & FrameTypeFlags::FOOTNOTE) ||
+ !rSh.GetTableFormat() )
+ rSet.DisableItem( nWhich );
+ }
+ break;
+ case FN_CONVERT_TEXT_TO_TABLE:
+ {
+ FrameTypeFlags eFrameType = rSh.GetFrameType(nullptr,true);
+ if( (eFrameType & FrameTypeFlags::FOOTNOTE) ||
+ !rSh.IsTextToTableAvailable() )
+ rSet.DisableItem( nWhich );
+ }
+ break;
+ case FN_CONVERT_TEXT_TABLE:
+ {
+ FrameTypeFlags eFrameType = rSh.GetFrameType(nullptr,true);
+ if( (eFrameType & FrameTypeFlags::FOOTNOTE) ||
+ (!rSh.GetTableFormat() && !rSh.IsTextToTableAvailable() ) )
+ rSet.DisableItem( nWhich );
+ }
+ break;
+ case RES_SHADOW:
+ {
+ SfxItemSetFixed<RES_SHADOW, RES_SHADOW> aSet( rSh.GetAttrPool());
+
+ // Table cell(s) selected?
+ if ( rSh.IsTableMode() )
+ {
+ SwFrameFormat *pFormat = rSh.GetTableFormat();
+ aSet.Put(pFormat->GetFormatAttr( nWhich ));
+ }
+ else if( rSh.IsFrameSelected() )
+ {
+ SwFlyFrameAttrMgr aMgr( false, &rSh, Frmmgr_Type::NONE, nullptr );
+ aSet.Put( aMgr.GetAttrSet() );
+ }
+ else
+ rSh.GetCurAttr( aSet );
+
+ const SvxShadowItem& rShItem = static_cast<const SvxShadowItem&>(aSet.Get(nWhich));
+ rSet.Put(rShItem);
+ }
+ break;
+ case SID_IMAP:
+ {
+ // #i59688#
+ // Improve efficiency:
+ // If selected object is protected, item has to disabled.
+ const bool bProtect = FlyProtectFlags::NONE != rSh.IsSelObjProtected(FlyProtectFlags::Content|FlyProtectFlags::Parent);
+ if ( bProtect )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ else
+ {
+ const sal_uInt16 nId = SvxIMapDlgChildWindow::GetChildWindowId();
+ const bool bHas = rVFrame.HasChildWindow( nId );
+ const bool bFrameSel = rSh.IsFrameSelected();
+ const bool bIsGraphicSelection =
+ rSh.GetSelectionType() == SelectionType::Graphic;
+
+ // #i59688#
+ // Avoid unnecessary loading of selected graphic.
+ // The graphic is only needed, if the dialog is open.
+ // If the swapping of the graphic is finished, the status
+ // must be determined asynchronously, until this the slot
+ // will be disabled.
+ if ( bHas && bIsGraphicSelection && rSh.IsLinkedGrfSwapOut() )
+ {
+ if( AddGrfUpdateSlot( nWhich ))
+ rSh.GetGraphic(false); // start the loading
+ }
+ else
+ {
+ if ( !bHas &&
+ ( !bFrameSel ||
+ ( bIsGraphicSelection &&
+ rSh.GetGraphicType() == GraphicType::NONE ) ) )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ else
+ {
+ SfxBoolItem aBool(nWhich, bHas);
+ if ( bHas && bFrameSel )
+ lcl_UpdateIMapDlg( rSh );
+ rSet.Put(aBool);
+ }
+ }
+ }
+ }
+ break;
+ case SID_IMAP_EXEC:
+ {
+ bool bDisable = false;
+ if( !rSh.IsFrameSelected())
+ bDisable = true;
+ sal_uInt16 nId = SvxIMapDlgChildWindow::GetChildWindowId();
+ if(!bDisable && rVFrame.HasChildWindow( nId ))
+ {
+ if(rSh.GetSelectionType() == SelectionType::Graphic
+ && rSh.IsLinkedGrfSwapOut())
+ {
+ if( AddGrfUpdateSlot( nWhich ))
+ rSh.GetGraphic(false); // start the loading
+ }
+ else
+ {
+ SvxIMapDlg *pDlg = GetIMapDlg(GetView());
+ if (pDlg && pDlg->GetEditingObject() != rSh.GetIMapInventor())
+ lcl_UpdateIMapDlg( rSh );
+ }
+ }
+ rSet.Put(SfxBoolItem(nWhich, bDisable));
+ }
+ break;
+
+ case FN_BACKSPACE:
+ case SID_DELETE:
+ if ( ( rSh.HasReadonlySel() && !rSh.CursorInsideInputField() )
+ || rSh.IsSelObjProtected( FlyProtectFlags::Content|FlyProtectFlags::Parent ) != FlyProtectFlags::NONE )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case SID_CONTOUR_DLG:
+ {
+ bool bParentCntProt = FlyProtectFlags::NONE != rSh.IsSelObjProtected(FlyProtectFlags::Content|FlyProtectFlags::Parent );
+
+ if( bParentCntProt || 0 != (HTMLMODE_ON & ::GetHtmlMode(
+ GetView().GetDocShell() )) )
+ rSet.DisableItem( nWhich );
+ else
+ {
+ sal_uInt16 nId = SvxContourDlgChildWindow::GetChildWindowId();
+ bool bHas = GetView().GetViewFrame().HasChildWindow( nId );
+ SelectionType nSel = rSh.GetSelectionType();
+ bool bOk(nSel & (SelectionType::Graphic|SelectionType::Ole));
+
+ bool bDisable = false;
+ if( !bHas && !bOk )
+ bDisable = true;
+ // #i59688#
+ // Avoid unnecessary loading of selected graphic.
+ // The graphic is only needed, if the dialog is open.
+ // If the swapping of the graphic is finished, the status
+ // must be determined asynchronously, until this the slot
+ // will be disabled.
+ else if ( bHas && (nSel & SelectionType::Graphic) &&
+ rSh.IsLinkedGrfSwapOut() )
+ {
+ if( AddGrfUpdateSlot( nWhich ))
+ rSh.GetGraphic(false); // start the loading
+ // #i75481#
+ bDisable = true;
+ }
+ else if( bHas && bOk )
+ bDisable = !lcl_UpdateContourDlg( rSh, nSel );
+ else if( bOk )
+ {
+ // #i75481#
+ // apply fix #i59688# only for selected graphics
+ if ( nSel & SelectionType::Graphic )
+ bDisable = GraphicType::NONE == rSh.GetGraphicType();
+ else
+ bDisable = GraphicType::NONE == rSh.GetIMapGraphic().GetType();
+ }
+
+ if( bDisable )
+ rSet.DisableItem( nWhich );
+ else
+ rSet.Put( SfxBoolItem(nWhich, bHas) );
+ }
+ }
+ break;
+ case SID_CONTOUR_EXEC:
+ {
+ bool bDisable = false;
+ SelectionType nSel = rSh.GetSelectionType();
+ if( !(nSel & (SelectionType::Graphic|SelectionType::Ole)) )
+ bDisable = true;
+ sal_uInt16 nId = SvxContourDlgChildWindow::GetChildWindowId();
+ if( !bDisable && GetView().GetViewFrame().HasChildWindow( nId ))
+ {
+ SvxContourDlg *pDlg = GetContourDlg(GetView());
+ if (pDlg && pDlg->GetEditingObject() != rSh.GetIMapInventor())
+ bDisable = true;
+ }
+ rSet.Put(SfxBoolItem(nWhich, bDisable));
+ }
+ break;
+
+ case SID_ANCHOR_MENU:
+ case FN_TOOL_ANCHOR_PAGE:
+ case FN_TOOL_ANCHOR_PARAGRAPH:
+ case FN_TOOL_ANCHOR_CHAR:
+ case FN_TOOL_ANCHOR_AT_CHAR:
+ case FN_TOOL_ANCHOR_FRAME:
+ {
+ bool bObj = 0 != rSh.IsObjSelected();
+ bool bParentCntProt = rSh.IsSelObjProtected( FlyProtectFlags::Content|FlyProtectFlags::Parent ) != FlyProtectFlags::NONE;
+
+ if( !bParentCntProt && (bObj || rSh.IsFrameSelected()))
+ {
+ SfxItemSetFixed<RES_ANCHOR, RES_ANCHOR> aSet(GetPool());
+ if(bObj)
+ rSh.GetObjAttr(aSet);
+ else
+ rSh.GetFlyFrameAttr(aSet);
+ RndStdIds eSet = aSet.Get(RES_ANCHOR).GetAnchorId();
+ const bool bSet =
+ ((nWhich == FN_TOOL_ANCHOR_PAGE) &&
+ (eSet == RndStdIds::FLY_AT_PAGE))
+ || ((nWhich == FN_TOOL_ANCHOR_PARAGRAPH) &&
+ (eSet == RndStdIds::FLY_AT_PARA))
+ || ((nWhich == FN_TOOL_ANCHOR_FRAME) &&
+ (eSet == RndStdIds::FLY_AT_FLY))
+ || ((nWhich == FN_TOOL_ANCHOR_AT_CHAR) &&
+ (eSet == RndStdIds::FLY_AT_CHAR))
+ || ((nWhich == FN_TOOL_ANCHOR_CHAR) &&
+ (eSet == RndStdIds::FLY_AS_CHAR));
+
+ if( nWhich == FN_TOOL_ANCHOR_FRAME && !rSh.IsFlyInFly() )
+ rSet.DisableItem(nWhich);
+ else if(nWhich != SID_ANCHOR_MENU)
+ rSet.Put(SfxBoolItem(nWhich, bSet));
+
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ if (nWhich == FN_TOOL_ANCHOR_PAGE || nWhich == FN_TOOL_ANCHOR_FRAME)
+ {
+ rSet.DisableItem(nWhich);
+ }
+ }
+ }
+ else
+ rSet.DisableItem( nWhich );
+ }
+ break;
+ case FN_FRAME_NOWRAP:
+ case FN_FRAME_WRAP:
+ case FN_FRAME_WRAP_IDEAL:
+ case FN_FRAME_WRAPTHRU:
+ case FN_FRAME_WRAPTHRU_TRANSP:
+ case FN_FRAME_WRAPTHRU_TOGGLE:
+ case FN_FRAME_WRAP_CONTOUR:
+ case FN_WRAP_ANCHOR_ONLY:
+ case FN_FRAME_WRAP_LEFT:
+ case FN_FRAME_WRAP_RIGHT:
+ {
+ bool bObj = 0 != rSh.IsObjSelected();
+ bool bParentCntProt = rSh.IsSelObjProtected( FlyProtectFlags::Content|FlyProtectFlags::Parent ) != FlyProtectFlags::NONE;
+
+ if( !bParentCntProt && (bObj || rSh.IsFrameSelected()))
+ {
+ SfxItemSetFixed<RES_OPAQUE, RES_ANCHOR> aSet(GetPool());
+ RndStdIds nAnchorType;
+ if(bObj)
+ {
+ rSh.GetObjAttr(aSet);
+ nAnchorType = rSh.GetAnchorId();
+ }
+ else
+ {
+ rSh.GetFlyFrameAttr(aSet);
+ nAnchorType = aSet.Get(RES_ANCHOR).GetAnchorId();
+ }
+ const SwFormatSurround& rWrap = aSet.Get(RES_SURROUND);
+
+ const SvxOpaqueItem& rOpaque = aSet.Get(RES_OPAQUE);
+ bool bOpaque = rOpaque.GetValue();
+ css::text::WrapTextMode nSurround = rWrap.GetSurround();
+ bool bSet = false;
+
+ bool bDisable =
+ (nAnchorType == RndStdIds::UNKNOWN) || (nAnchorType == RndStdIds::FLY_AS_CHAR);
+ const bool bHtmlMode =
+ 0 != ::GetHtmlMode(GetView().GetDocShell());
+
+ switch( nWhich )
+ {
+ case FN_FRAME_NOWRAP:
+ bDisable |=
+ ( (nAnchorType != RndStdIds::FLY_AT_PARA)
+ && (nAnchorType != RndStdIds::FLY_AT_CHAR)
+ && (nAnchorType != RndStdIds::FLY_AT_PAGE));
+ bSet = nSurround == css::text::WrapTextMode_NONE;
+ break;
+ case FN_FRAME_WRAP:
+ bDisable |= bHtmlMode;
+ bSet = nSurround == css::text::WrapTextMode_PARALLEL;
+ break;
+ case FN_FRAME_WRAP_IDEAL:
+ bDisable |= bHtmlMode;
+ bSet = nSurround == css::text::WrapTextMode_DYNAMIC;
+ break;
+ case FN_FRAME_WRAPTHRU:
+ bDisable |= (bHtmlMode ||
+ ( (nAnchorType != RndStdIds::FLY_AT_PARA)
+ && (nAnchorType != RndStdIds::FLY_AT_CHAR)
+ && (nAnchorType != RndStdIds::FLY_AT_PAGE)));
+ if(bObj)
+ bSet = nSurround == css::text::WrapTextMode_THROUGH && rSh.GetLayerId();
+ else
+ bSet = nSurround == css::text::WrapTextMode_THROUGH && bOpaque;
+ break;
+ case FN_FRAME_WRAPTHRU_TRANSP:
+ case FN_FRAME_WRAPTHRU_TOGGLE:
+ bDisable |= bHtmlMode;
+ if(bObj)
+ bSet = nSurround == css::text::WrapTextMode_THROUGH && !rSh.GetLayerId();
+ else
+ bSet = nSurround == css::text::WrapTextMode_THROUGH && !bOpaque;
+ break;
+ case FN_FRAME_WRAP_CONTOUR:
+ bDisable |= bHtmlMode;
+ //no contour available when no wrap or wrap through is set
+ bDisable |= (nSurround == css::text::WrapTextMode_NONE || nSurround == css::text::WrapTextMode_THROUGH);
+ if( !bDisable )
+ {
+ SelectionType nSel = rSh.GetSelectionType();
+ if( (nSel & SelectionType::Graphic) &&
+ rSh.IsLinkedGrfSwapOut())
+ {
+ if( AddGrfUpdateSlot( nWhich ))
+ rSh.GetGraphic(false); // start the loading
+ }
+ else if( rSh.IsFrameSelected() )
+ {
+ // #i102253# applied patch from OD (see task)
+ bDisable =
+ nSel & SelectionType::Frame ||
+ GraphicType::NONE == rSh.GetIMapGraphic().GetType();
+ }
+ }
+ bSet = !bDisable && rWrap.IsContour();
+
+ break;
+ case FN_WRAP_ANCHOR_ONLY:
+ bDisable |= (bHtmlMode ||
+ (nAnchorType != RndStdIds::FLY_AT_PARA));
+ bSet = rWrap.IsAnchorOnly();
+ break;
+ case FN_FRAME_WRAP_LEFT:
+ bSet = nSurround == css::text::WrapTextMode_LEFT;
+ break;
+ case FN_FRAME_WRAP_RIGHT:
+ bSet = nSurround == css::text::WrapTextMode_RIGHT;
+ break;
+ }
+
+ if(bDisable)
+ rSet.DisableItem(nWhich);
+ else
+ rSet.Put(SfxBoolItem(nWhich, bSet));
+ }
+ else
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case FN_UPDATE_CHARTS:
+ if( !rSh.HasCharts() )
+ rSet.DisableItem( nWhich );
+ break;
+ case FN_UPDATE_ALL_LINKS:
+ if ( rSh.GetLinkManager().GetLinks().empty() )
+ rSet.DisableItem(nWhich);
+ break;
+ case FN_XFORMS_DESIGN_MODE:
+ // enable if in XForms document
+ if( rSh.GetDoc()->isXForms() )
+ {
+ // determine current state from view options
+ bool bValue = ! rSh.GetViewOptions()->IsFormView();
+ rSet.Put( SfxBoolItem( nWhich, bValue ) );
+ }
+ else
+ rSet.Put( SfxVisibilityItem( nWhich, false ) );
+ break;
+ case SID_GRAPHIC_SIZE_CHECK:
+ {
+ sal_Int32 nDPI = rSh.GetDoc()->getIDocumentSettingAccess().getImagePreferredDPI();
+ if (nDPI <= 0)
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_THEME_DIALOG:
+ {
+ bool bDisable = true;
+ auto* pDocument = rSh.GetDoc();
+ auto* pDocumentShell = pDocument->GetDocShell();
+ if (pDocumentShell)
+ {
+ SdrModel* pModel = pDocument->getIDocumentDrawModelAccess().GetDrawModel();
+ if (pModel)
+ {
+ auto const& pTheme = pModel->getTheme();
+ if (pTheme)
+ bDisable = false;
+ }
+ }
+ if (bDisable)
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+ m_pGetStateSet = nullptr;
+}
+
+// Disable the slots with this status method
+
+void SwBaseShell::StateDisableItems( SfxItemSet &rSet )
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while (nWhich)
+ {
+ rSet.DisableItem( nWhich );
+ nWhich = aIter.NextWhich();
+ }
+}
+
+// Disable the slots with this status method
+
+void SwBaseShell::StateStyle( SfxItemSet &rSet )
+{
+ bool bParentCntProt = GetShell().IsSelObjProtected( FlyProtectFlags::Content|FlyProtectFlags::Parent ) != FlyProtectFlags::NONE;
+ ShellMode eMode = GetView().GetShellMode();
+
+ if ( bParentCntProt ||
+ ShellMode::Draw == eMode ||
+ ShellMode::DrawForm == eMode ||
+ ShellMode::DrawText == eMode ||
+ ShellMode::Bezier == eMode )
+ {
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while ( nWhich )
+ {
+ rSet.DisableItem( nWhich );
+ nWhich = aIter.NextWhich();
+ }
+ }
+ else
+ GetView().GetDocShell()->StateStyleSheet(rSet, &GetShell());
+}
+
+void SwBaseShell::SetWrapMode( sal_uInt16 nSlot )
+{
+ SwWrtShell &rSh = GetShell();
+ bool bObj = 0 != rSh.IsObjSelected();
+ if( !bObj && !rSh.IsFrameSelected())
+ return;
+
+ SfxItemSetFixed<RES_OPAQUE, RES_SURROUND> aSet(GetPool());
+ if(bObj)
+ rSh.GetObjAttr(aSet);
+ else
+ rSh.GetFlyFrameAttr(aSet);
+ SwFormatSurround aWrap( aSet.Get(RES_SURROUND) );
+ css::text::WrapTextMode nOldSurround(aWrap.GetSurround());
+ css::text::WrapTextMode nSurround = css::text::WrapTextMode_PARALLEL;
+
+ switch (nSlot)
+ {
+ case FN_FRAME_NOWRAP:
+ nSurround = css::text::WrapTextMode_NONE;
+ if (aWrap.IsContour())
+ aWrap.SetContour(false);
+ break;
+ case FN_FRAME_WRAP_IDEAL:
+ nSurround = css::text::WrapTextMode_DYNAMIC;
+ break;
+ case FN_WRAP_ANCHOR_ONLY:
+ aWrap.SetAnchorOnly(!aWrap.IsAnchorOnly());
+
+ // keep previous wrapping
+
+ // switch to wrap css::text::WrapTextMode_PARALLEL, if previous wrap is css::text::WrapTextMode_NONE
+ if ( nOldSurround != css::text::WrapTextMode_NONE )
+ {
+ nSurround = nOldSurround;
+ }
+ break;
+ case FN_FRAME_WRAP_CONTOUR:
+ aWrap.SetContour(!aWrap.IsContour());
+ // Contour is meaningless in no-wrap or wrap-through context. Otherwise keep existing wrap.
+ if ( !aWrap.IsContour() ||
+ ( nOldSurround != css::text::WrapTextMode_NONE &&
+ nOldSurround != css::text::WrapTextMode_THROUGH ) )
+ {
+ nSurround = nOldSurround;
+ }
+ break;
+ case FN_FRAME_WRAPTHRU_TRANSP:
+ case FN_FRAME_WRAPTHRU_TOGGLE:
+ if (aWrap.IsContour())
+ aWrap.SetContour(false);
+ [[fallthrough]];
+ case FN_FRAME_WRAPTHRU:
+ nSurround = css::text::WrapTextMode_THROUGH;
+ break;
+
+ case FN_FRAME_WRAP_LEFT:
+ nSurround = css::text::WrapTextMode_LEFT;
+ break;
+
+ case FN_FRAME_WRAP_RIGHT:
+ nSurround = css::text::WrapTextMode_RIGHT;
+ break;
+
+ default:
+ break;
+ }
+ aWrap.SetSurround(nSurround);
+
+ if (nSlot != FN_FRAME_WRAP_CONTOUR)
+ {
+ // Defaulting the contour wrap on draw objects.
+ if (bObj && nOldSurround != nSurround &&
+ (nOldSurround == css::text::WrapTextMode_NONE || nOldSurround == css::text::WrapTextMode_THROUGH))
+ {
+ aWrap.SetContour(true);
+ }
+ }
+
+ aSet.Put( aWrap );
+
+ bool bOpaque = nSlot != FN_FRAME_WRAPTHRU_TRANSP && nSlot != FN_FRAME_WRAPTHRU_TOGGLE;
+ if( nSlot == FN_FRAME_WRAPTHRU_TOGGLE )
+ {
+ if( bObj )
+ bOpaque = !rSh.GetLayerId();
+ else
+ {
+ const SvxOpaqueItem& aOpaque( aSet.Get(RES_OPAQUE) );
+ bOpaque = !aOpaque.GetValue();
+ }
+ }
+ aSet.Put(SvxOpaqueItem(RES_OPAQUE, bOpaque ));
+
+ if(bObj)
+ {
+ rSh.SetObjAttr(aSet);
+ if ( bOpaque )
+ rSh.SelectionToHeaven();
+ else
+ rSh.SelectionToHell();
+ }
+ else
+ rSh.SetFlyFrameAttr(aSet);
+
+}
+
+//Force update of the status line
+
+void SwBaseShell::SetFrameMode(FlyMode eMode, SwWrtShell *pSh )
+{
+ s_eFrameMode = eMode;
+ SfxBindings &rBnd = pSh->GetView().GetViewFrame().GetBindings();
+
+ if( eMode == FLY_DRAG || pSh->IsFrameSelected() || pSh->IsObjSelected() )
+ {
+ const SfxPointItem aTmp1( SID_ATTR_POSITION, pSh->GetAnchorObjDiff());
+ const SvxSizeItem aTmp2( SID_ATTR_SIZE, pSh->GetObjSize());
+ rBnd.SetState( aTmp1 );
+ rBnd.SetState( aTmp2 );
+ }
+ else if( eMode == FLY_DRAG_END )
+ {
+ static sal_uInt16 aInval[] =
+ {
+ SID_ATTR_POSITION, SID_ATTR_SIZE, 0
+ };
+ rBnd.Invalidate(aInval);
+ }
+}
+
+SwBaseShell::SwBaseShell(SwView& rVw) :
+ SfxShell( &rVw ),
+ m_rView(rVw),
+ m_pGetStateSet(nullptr)
+{
+ SwWrtShell& rWrtSh = m_rView.GetWrtShell();
+
+ SetPool(&rWrtSh.GetAttrPool());
+ SetName("Base");
+ rWrtSh.SetGrfArrivedLnk( LINK( this, SwBaseShell, GraphicArrivedHdl));
+}
+
+SwBaseShell::~SwBaseShell()
+{
+ if( m_rView.GetCurShell() == this )
+ m_rView.ResetSubShell();
+
+ Link<SwCursorShell&,void> aTmp( LINK( this, SwBaseShell, GraphicArrivedHdl));
+ if( aTmp == m_rView.GetWrtShell().GetGrfArrivedLnk() )
+ m_rView.GetWrtShell().SetGrfArrivedLnk( Link<SwCursorShell&,void>() );
+}
+
+void SwBaseShell::ExecTextCtrl( SfxRequest& rReq )
+{
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ const sal_uInt16 nSlot = rReq.GetSlot();
+
+ if( pArgs)
+ {
+ SwWrtShell &rSh = GetShell();
+ std::unique_ptr<SvxScriptSetItem> pSSetItem;
+ SfxItemPool& rPool = rSh.GetAttrPool();
+ sal_uInt16 nWhich = rPool.GetWhich( nSlot );
+ SvtScriptType nScripts = SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX;
+ SfxItemSetFixed<RES_CHRATR_FONTSIZE, RES_CHRATR_FONTSIZE,
+ RES_CHRATR_CJK_FONTSIZE, RES_CHRATR_CJK_FONTSIZE,
+ RES_CHRATR_CTL_FONTSIZE, RES_CHRATR_CTL_FONTSIZE>
+ aHeightSet( GetPool() );
+
+ switch( nSlot )
+ {
+ case SID_ATTR_CHAR_FONT:
+ {
+ nScripts = rSh.GetScriptType();
+ // #i42732# input language should be preferred over
+ // current cursor position to detect script type
+ if(!rSh.HasSelection())
+ {
+ LanguageType nInputLang = GetView().GetEditWin().GetInputLanguage();
+ if(nInputLang != LANGUAGE_DONTKNOW && nInputLang != LANGUAGE_SYSTEM)
+ nScripts = SvtLanguageOptions::GetScriptTypeOfLanguage( nInputLang );
+ }
+ [[fallthrough]];
+ }
+ case SID_ATTR_CHAR_POSTURE:
+ case SID_ATTR_CHAR_WEIGHT:
+ {
+ pSSetItem.reset(new SvxScriptSetItem( nSlot, rPool ));
+ pSSetItem->PutItemForScriptType( nScripts, pArgs->Get( nWhich ));
+ pArgs = &pSSetItem->GetItemSet();
+ }
+ break;
+ case SID_ATTR_CHAR_FONTHEIGHT:
+ {
+ if(rSh.HasSelection())
+ {
+ pSSetItem.reset(new SvxScriptSetItem( nSlot, rPool ));
+ pSSetItem->PutItemForScriptType( nScripts, pArgs->Get( nWhich ));
+ pArgs = &pSSetItem->GetItemSet();
+ }
+ else
+ {
+ nScripts = rSh.GetScriptType();
+ LanguageType nInputLang = GetView().GetEditWin().GetInputLanguage();
+ if(nInputLang != LANGUAGE_DONTKNOW && nInputLang != LANGUAGE_SYSTEM)
+ nScripts = SvtLanguageOptions::GetScriptTypeOfLanguage( nInputLang );
+ sal_uInt32 nHeight = static_cast< const SvxFontHeightItem& >(pArgs->Get( nWhich )).GetHeight();
+ SwStdFontConfig* pStdFont = SW_MOD()->GetStdFontConfig();
+
+ SfxItemSetFixed<RES_CHRATR_LANGUAGE, RES_CHRATR_LANGUAGE,
+ RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_LANGUAGE,
+ RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_LANGUAGE>
+ aLangSet( GetPool() );
+ rSh.GetCurAttr( aLangSet );
+
+ sal_Int32 nWesternSize =
+ pStdFont->GetFontHeight(FONT_STANDARD, FONT_GROUP_DEFAULT,
+ aLangSet.Get( RES_CHRATR_LANGUAGE).GetLanguage());
+ sal_Int32 nCJKSize =
+ pStdFont->GetFontHeight(FONT_STANDARD, FONT_GROUP_CJK,
+ aLangSet.Get( RES_CHRATR_CJK_LANGUAGE).GetLanguage());
+ sal_Int32 nCTLSize =
+ pStdFont->GetFontHeight(FONT_STANDARD, FONT_GROUP_CTL,
+ aLangSet.Get( RES_CHRATR_CTL_LANGUAGE).GetLanguage());
+
+ switch(nScripts)
+ {
+ case SvtScriptType::LATIN:
+ nCJKSize = nHeight * nCJKSize / nWesternSize;
+ nCTLSize = nHeight * nCTLSize / nWesternSize;
+ nWesternSize = static_cast<sal_Int32>(nHeight);
+ break;
+ case SvtScriptType::ASIAN:
+ nCTLSize = nHeight* nCTLSize / nCJKSize;
+ nWesternSize = nHeight * nWesternSize / nCJKSize;
+ nCJKSize = static_cast<sal_Int32>(nHeight);
+ break;
+ case SvtScriptType::COMPLEX:
+ nCJKSize = nHeight * nCJKSize / nCTLSize;
+ nWesternSize = nHeight * nWesternSize / nCTLSize;
+ nCTLSize = static_cast<sal_Int32>(nHeight);
+ break;
+ default: break;
+ }
+ aHeightSet.Put( SvxFontHeightItem( static_cast<sal_uInt32>(nWesternSize), 100, RES_CHRATR_FONTSIZE ));
+ aHeightSet.Put( SvxFontHeightItem( static_cast<sal_uInt32>(nCJKSize), 100, RES_CHRATR_CJK_FONTSIZE ));
+ aHeightSet.Put( SvxFontHeightItem( static_cast<sal_uInt32>(nCTLSize), 100, RES_CHRATR_CTL_FONTSIZE ));
+ pArgs = &aHeightSet;
+ }
+ }
+ break;
+ }
+
+ if( pArgs )
+ {
+ bool bAuto = false;
+ if ( !isCHRATR(nWhich) ||
+ ( rSh.HasSelection() && rSh.IsSelFullPara() ) )
+ {
+ SwTextFormatColl * pColl = rSh.GetCurTextFormatColl();
+ if ( pColl && pColl->IsAutoUpdateOnDirectFormat() )
+ {
+ rSh.AutoUpdatePara( pColl, *pArgs );
+ bAuto = true;
+ }
+ }
+
+ if (!bAuto)
+ {
+ rSh.SetAttrSet( *pArgs );
+ }
+ }
+ }
+ else
+ {
+ if (nSlot == SID_ATTR_CHAR_KERNING)
+ GetView().GetViewFrame().GetDispatcher()->Execute(SID_CHAR_DLG_POSITION);
+ else if (nSlot == SID_ATTR_CHAR_COLOR)
+ GetView().GetViewFrame().GetDispatcher()->Execute(SID_CHAR_DLG_EFFECT);
+ else
+ GetView().GetViewFrame().GetDispatcher()->Execute(SID_CHAR_DLG);
+ }
+ rReq.Done();
+}
+
+void SwBaseShell::GetTextCtrlState( SfxItemSet& rSet )
+{
+ SwWrtShell &rSh = GetShell();
+ rSh.GetCurAttr( rSet );
+}
+
+void SwBaseShell::GetTextFontCtrlState( SfxItemSet& rSet )
+{
+ SwWrtShell &rSh = GetShell();
+ bool bFirst = true;
+ std::optional<SfxItemSet> pFntCoreSet;
+ SvtScriptType nScriptType = SvtScriptType::LATIN;
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while( nWhich )
+ {
+ switch( nWhich )
+ {
+ case RES_CHRATR_FONT:
+ case RES_CHRATR_FONTSIZE:
+ case RES_CHRATR_WEIGHT:
+ case RES_CHRATR_POSTURE:
+ {
+ if( !pFntCoreSet )
+ {
+ pFntCoreSet.emplace( *rSet.GetPool(),
+ svl::Items<RES_CHRATR_BEGIN, RES_CHRATR_END-1> );
+ rSh.GetCurAttr( *pFntCoreSet );
+ nScriptType = rSh.GetScriptType();
+ // #i42732# input language should be preferred over
+ // current cursor position to detect script type
+ SwEditWin& rEditWin = GetView().GetEditWin();
+ if( rEditWin.IsUseInputLanguage() )
+ {
+ if(!rSh.HasSelection() && (
+ nWhich == RES_CHRATR_FONT ||
+ nWhich == RES_CHRATR_FONTSIZE ))
+ {
+ LanguageType nInputLang = rEditWin.GetInputLanguage();
+ if(nInputLang != LANGUAGE_DONTKNOW && nInputLang != LANGUAGE_SYSTEM)
+ nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( nInputLang );
+ }
+ }
+ }
+ SfxItemPool& rPool = *rSet.GetPool();
+ SvxScriptSetItem aSetItem( rPool.GetSlotId( nWhich ), rPool );
+ aSetItem.GetItemSet().Put( *pFntCoreSet, false );
+ const SfxPoolItem* pI = aSetItem.GetItemOfScript( nScriptType );
+ if( pI )
+ {
+ rSet.Put( pI->CloneSetWhich(nWhich) );
+ }
+ else
+ rSet.InvalidateItem( nWhich );
+ // Set input context of the SwEditWin according to the selected font and script type
+ if(RES_CHRATR_FONT == nWhich)
+ {
+ vcl::Font aFont;
+ if (const SvxFontItem* pFontItem = dynamic_cast<const SvxFontItem*>(pI))
+ {
+ aFont.SetFamilyName(pFontItem->GetFamilyName());
+ aFont.SetStyleName(pFontItem->GetStyleName());
+ aFont.SetFamily(pFontItem->GetFamily());
+ aFont.SetPitch(pFontItem->GetPitch());
+ aFont.SetCharSet(pFontItem->GetCharSet());
+ }
+
+ bool bVertical = rSh.IsInVerticalText();
+ aFont.SetOrientation(Degree10(bVertical ? 2700 : 0));
+ aFont.SetVertical(bVertical);
+ GetView().GetEditWin().SetInputContext( InputContext( aFont, InputContextFlags::Text |
+ InputContextFlags::ExtText ) );
+ }
+ }
+ break;
+
+ default:
+ if( bFirst )
+ {
+ rSh.GetCurAttr( rSet );
+ bFirst = false;
+ }
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwBaseShell::GetBckColState(SfxItemSet &rSet)
+{
+ SwWrtShell &rSh = GetShell();
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich(aIter.FirstWhich());
+ SelectionType nSelType(rSh.GetSelectionType());
+ std::unique_ptr<SvxBrushItem> aBrushItem(std::make_unique<SvxBrushItem>(RES_BACKGROUND));
+
+ if( nWhich == SID_TABLE_CELL_BACKGROUND_COLOR )
+ {
+ rSh.GetBoxBackground( aBrushItem );
+ }
+ else
+ {
+ // Adapt to new DrawingLayer FillStyle; use a parent which has XFILL_NONE set
+ SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> aCoreSet(GetPool());
+
+ aCoreSet.SetParent(&GetView().GetDocShell()->GetDoc()->GetDfltFrameFormat()->GetAttrSet());
+
+ if(nSelType & SelectionType::Graphic || SelectionType::Frame & nSelType)
+ {
+ rSh.GetFlyFrameAttr(aCoreSet);
+ }
+ else
+ {
+ rSh.GetCurAttr(aCoreSet);
+ }
+
+ aBrushItem = getSvxBrushItemFromSourceSet(aCoreSet, RES_BACKGROUND);
+ }
+
+ while(nWhich)
+ {
+ switch(nWhich)
+ {
+ case SID_BACKGROUND_COLOR:
+ case SID_TABLE_CELL_BACKGROUND_COLOR:
+ {
+ SvxColorItem aColorItem(aBrushItem->GetColor(), aBrushItem->getComplexColor(), nWhich);
+ rSet.Put(aColorItem);
+ break;
+ }
+ case SID_ATTR_BRUSH:
+ case RES_BACKGROUND:
+ {
+ // if this was intended to have a independent copy of the Item to be set
+ // this is not needed due to the ItemSet/Pool cloning Items which get set anyways.
+ // Keeping code as reference - it may have had other reasons I do notz see (?!?)
+ // std::unique_ptr<SfxPoolItem> pNewItem(aBrushItem.CloneSetWhich(GetPool().GetWhich(nWhich)));
+ rSet.Put(*aBrushItem);
+ break;
+ }
+ }
+
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwBaseShell::ExecBckCol(SfxRequest& rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ SelectionType nSelType(rSh.GetSelectionType());
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ sal_uInt16 nSlot(rReq.GetSlot());
+
+ if (!pArgs && nSlot != SID_BACKGROUND_COLOR && nSlot != SID_TABLE_CELL_BACKGROUND_COLOR)
+ {
+ return;
+ }
+
+ std::unique_ptr<SvxBrushItem> aBrushItem(std::make_unique<SvxBrushItem>(RES_BACKGROUND));
+
+ if ( nSlot == SID_TABLE_CELL_BACKGROUND_COLOR )
+ {
+ rSh.GetBoxBackground( aBrushItem );
+ }
+ else
+ {
+ // Adapt to new DrawingLayer FillStyle; use a parent which has XFILL_NONE set
+ SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> aCoreSet(GetPool());
+
+ aCoreSet.SetParent(&GetView().GetDocShell()->GetDoc()->GetDfltFrameFormat()->GetAttrSet());
+
+ if((SelectionType::Frame & nSelType) || (SelectionType::Graphic & nSelType))
+ {
+ rSh.GetFlyFrameAttr(aCoreSet);
+ }
+ else
+ {
+ rSh.GetCurAttr(aCoreSet);
+ }
+
+ aBrushItem = getSvxBrushItemFromSourceSet(aCoreSet, RES_BACKGROUND);
+ }
+
+ switch(nSlot)
+ {
+ case SID_BACKGROUND_COLOR:
+ case SID_TABLE_CELL_BACKGROUND_COLOR:
+ {
+ bool bIsTransparent = false;
+
+ aBrushItem->SetGraphicPos(GPOS_NONE);
+
+ sal_uInt16 nSlotId = (nSlot == SID_BACKGROUND_COLOR) ? SID_BACKGROUND_COLOR : SID_TABLE_CELL_BACKGROUND_COLOR;
+ if (pArgs)
+ {
+ const SvxColorItem& rNewColorItem = static_cast<const SvxColorItem&>(pArgs->Get(nSlotId));
+ aBrushItem->SetColor(rNewColorItem.GetValue());
+ aBrushItem->setComplexColor(rNewColorItem.getComplexColor());
+ GetView().GetViewFrame().GetBindings().SetState(rNewColorItem);
+ }
+ else
+ {
+ bIsTransparent = true;
+ }
+
+ if (bIsTransparent)
+ {
+ aBrushItem->SetColor(COL_TRANSPARENT);
+ rReq.AppendItem(SvxColorItem(COL_TRANSPARENT,nSlot));
+ }
+ break;
+ }
+
+ case SID_ATTR_BRUSH:
+ case RES_BACKGROUND:
+ {
+ assert(pArgs && "only SID_BACKGROUND_COLOR can have !pArgs, checked at entry");
+ aBrushItem.reset(static_cast<SvxBrushItem*>(pArgs->Get(GetPool().GetWhich(nSlot)).Clone()));
+ break;
+ }
+ default:
+ {
+ rReq.Ignore();
+ OSL_FAIL("unknown message in ExecuteAttr!" );
+ return;
+ }
+ }
+
+ if ( nSlot == SID_TABLE_CELL_BACKGROUND_COLOR )
+ {
+ rSh.SetBoxBackground( *aBrushItem );
+ }
+ else
+ {
+ // Adapt to new DrawingLayer FillStyle; use a parent which has XFILL_NONE set
+ SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> aCoreSet(GetPool());
+
+ aCoreSet.SetParent(&GetView().GetDocShell()->GetDoc()->GetDfltFrameFormat()->GetAttrSet());
+ setSvxBrushItemAsFillAttributesToTargetSet(*aBrushItem, aCoreSet);
+
+ if((SelectionType::Frame & nSelType) || (SelectionType::Graphic & nSelType))
+ {
+ // Template autoupdate
+ SwFrameFormat* pFormat = rSh.GetSelectedFrameFormat();
+
+ if(pFormat && pFormat->IsAutoUpdateOnDirectFormat())
+ {
+ rSh.AutoUpdateFrame(pFormat, aCoreSet);
+ }
+ else
+ {
+ rSh.SetFlyFrameAttr(aCoreSet);
+ }
+ }
+ else
+ {
+ SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
+
+ if(pColl && pColl->IsAutoUpdateOnDirectFormat())
+ {
+ rSh.AutoUpdatePara(pColl, aCoreSet);
+ }
+ else
+ {
+ rSh.SetAttrSet(aCoreSet);
+ }
+ }
+ }
+
+ rReq.Done();
+}
+
+void SwBaseShell::GetBorderState(SfxItemSet &rSet)
+{
+ SwWrtShell &rSh = GetShell();
+ // Table cell(s) selected?
+ bool bPrepare = true;
+ bool bTableMode = rSh.IsTableMode();
+ if ( bTableMode )
+ {
+ SfxItemSetFixed<RES_BOX, RES_BOX,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER> aCoreSet( GetPool() );
+ SvxBoxInfoItem aBoxInfo( SID_ATTR_BORDER_INNER );
+ aCoreSet.Put( aBoxInfo );
+ rSh.GetTabBorders( aCoreSet );
+ rSet.Put( aCoreSet );
+ }
+ else if ( rSh.IsFrameSelected() )
+ {
+ SwFlyFrameAttrMgr aMgr( false, &rSh, Frmmgr_Type::NONE, nullptr );
+ rSet.Put( aMgr.GetAttrSet() );
+ bPrepare = false;
+ }
+ else
+ // Get border attributes via shell quite normal
+ rSh.GetCurAttr( rSet );
+ if ( bPrepare )
+ ::PrepareBoxInfo( rSet, rSh );
+ // Switch the border toolbox controller mode
+ rSet.Put( SfxBoolItem( SID_BORDER_REDUCED_MODE, !bTableMode ));
+}
+
+void SwBaseShell::ExecDlg(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ weld::Window* pMDI = GetView().GetFrameWeld();
+ // So that from the basic no dialogues for the background views are called:
+ bool bBackground = (&GetView() != GetActiveView());
+ const SfxPoolItem* pItem = nullptr;
+ const SfxItemSet* pArgs = rReq.GetArgs();
+
+ sal_uInt16 nSlot = rReq.GetSlot();
+ const SfxItemSet* pOutSet = nullptr;
+ bool bDone = false;
+ if(pArgs)
+ pArgs->GetItemState( GetPool().GetWhich(nSlot), false, &pItem );
+
+ switch ( nSlot )
+ {
+ case FN_FORMAT_TITLEPAGE_DLG:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateTitlePageDlg(pMDI));
+ VclAbstractDialog::AsyncContext aContext;
+ aContext.maEndDialogFn = [](sal_Int32){};
+ pDlg->StartExecuteAsync(aContext);
+ }
+ break;
+ case FN_FORMAT_PAGE_DLG:
+ case FN_FORMAT_PAGE_COLUMN_DLG:
+ case FN_FORMAT_PAGE_SETTING_DLG:
+ case FN_FORMAT_PAGE_AREA_DLG:
+ {
+ if( !bBackground )
+ {
+ const size_t nCurIdx = rSh.GetCurPageDesc();
+ const SwPageDesc& rPageDesc = rSh.GetPageDesc( nCurIdx );
+ // Temporary view, because the shell does not need to be valid after the dialog
+ // for example disable header
+ SwView& rTempView = GetView();
+
+ OUString sPageId;
+ switch (nSlot)
+ {
+ case FN_FORMAT_PAGE_COLUMN_DLG:
+ sPageId = "columns";
+ break;
+ case FN_FORMAT_PAGE_SETTING_DLG:
+ sPageId = "page";
+ break;
+ case FN_FORMAT_PAGE_AREA_DLG:
+ sPageId = "area";
+ break;
+ case FN_FORMAT_PAGE_DLG:
+ if (pItem)
+ sPageId = static_cast<const SfxStringItem*>(pItem)->GetValue();
+ break;
+ }
+ rTempView.GetDocShell()->FormatPage(rReq.GetFrameWeld(), rPageDesc.GetName(), sPageId, rSh, &rReq);
+ rTempView.InvalidateRulerPos();
+
+ bDone = true; // FormatPage() takes care of calling Done()
+ }
+ }
+ break;
+ case FN_FORMAT_BORDER_DLG:
+ {
+ SfxItemSetFixed<RES_BOX , RES_SHADOW,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER> aSet( rSh.GetAttrPool() );
+ ScopedVclPtr<SfxAbstractDialog> pDlg;
+ // Table cell(s) selected?
+ if ( rSh.IsTableMode() )
+ {
+ // Set border attributes Get/SetTabBorders()
+ ::PrepareBoxInfo( aSet, rSh );
+ rSh.GetTabBorders( aSet );
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ pDlg.disposeAndReset(pFact->CreateSwBorderDlg(pMDI, aSet, SwBorderModes::TABLE));
+ if ( pDlg->Execute() == RET_OK )
+ {
+ rSh.SetTabBorders( *pDlg->GetOutputItemSet() );
+ pOutSet = pDlg->GetOutputItemSet();
+ }
+ }
+ else if ( rSh.IsFrameSelected() )
+ {
+ // Set border attributes via Frame-Manager
+ SwFlyFrameAttrMgr aMgr( false, &rSh, Frmmgr_Type::NONE, nullptr );
+ aSet.Put( aMgr.GetAttrSet() );
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ pDlg.disposeAndReset(pFact->CreateSwBorderDlg(pMDI, aSet, SwBorderModes::FRAME));
+ if ( pDlg->Execute() == RET_OK )
+ {
+ aMgr.SetAttrSet( *pDlg->GetOutputItemSet() );
+ aMgr.UpdateFlyFrame();
+ pOutSet = pDlg->GetOutputItemSet();
+ }
+ }
+ else
+ {
+ // Set border attributes via Shell quite normal
+ rSh.GetCurAttr( aSet );
+ ::PrepareBoxInfo( aSet, rSh );
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ pDlg.disposeAndReset(pFact->CreateSwBorderDlg(pMDI, aSet, SwBorderModes::PARA));
+ if ( pDlg->Execute() == RET_OK )
+ {
+ rSh.SetAttrSet( *pDlg->GetOutputItemSet() );
+ pOutSet = pDlg->GetOutputItemSet();
+ }
+ }
+ if(pOutSet)
+ {
+ rReq.Done(*pOutSet);
+ bDone = true;
+ }
+ }
+ break;
+ case FN_FORMAT_BACKGROUND_DLG:
+ {
+ SfxItemSetFixed<RES_BACKGROUND, RES_BACKGROUND,
+ XATTR_FILL_FIRST, XATTR_FILL_LAST> aSet( rSh.GetAttrPool() );
+
+ ScopedVclPtr<SfxAbstractDialog> pDlg;
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+
+ // Table cell(s) selected?
+ if ( rSh.IsTableMode() )
+ {
+ // Get background attributes of the table and put it in the set
+ // tdf#144843 calling GetBoxBackground *requires* an incarnation to be handed over
+ std::unique_ptr<SvxBrushItem> aBrush(std::make_unique<SvxBrushItem>(RES_BACKGROUND));
+ rSh.GetBoxBackground( aBrush );
+ pDlg.disposeAndReset(pFact->CreateSwBackgroundDialog(pMDI, aSet));
+ aSet.Put( std::move(aBrush) );
+ if ( pDlg->Execute() == RET_OK )
+ {
+
+ rSh.SetBoxBackground( pDlg->GetOutputItemSet()->Get( RES_BACKGROUND ) );
+ pOutSet = pDlg->GetOutputItemSet();
+ }
+ }
+ else if ( rSh.IsFrameSelected() )
+ {
+
+ rSh.GetFlyFrameAttr( aSet );
+
+ pDlg.disposeAndReset(pFact->CreateSwBackgroundDialog(pMDI, aSet));
+ if ( pDlg->Execute() == RET_OK )
+ {
+ rSh.SetFlyFrameAttr(const_cast<SfxItemSet &>(*pDlg->GetOutputItemSet()) );
+ pOutSet = pDlg->GetOutputItemSet();
+ }
+ }
+ else
+ {
+ // Set border attributes Umrandungsattribute with the shell quite normal.
+ rSh.GetCurAttr( aSet );
+
+ pDlg.disposeAndReset(pFact->CreateSwBackgroundDialog(pMDI, aSet));
+ if ( pDlg->Execute() == RET_OK )
+ {
+ rSh.SetAttrSet( *pDlg->GetOutputItemSet() );
+ pOutSet = pDlg->GetOutputItemSet();
+ }
+ }
+ if(pOutSet)
+ {
+ rReq.Done(*pOutSet);
+ bDone = true;
+ }
+ }
+ break;
+
+ case SID_GRAPHIC_SIZE_CHECK:
+ {
+ sw::GraphicSizeCheckGUIResult aResult(rSh.GetDoc());
+ svx::GenericCheckDialog aDialog(pMDI, aResult);
+ aDialog.run();
+ }
+ break;
+
+ case SID_THEME_DIALOG:
+ {
+ auto* pDocument = rSh.GetDoc();
+ auto* pDocumentShell = pDocument->GetDocShell();
+ if (pDocumentShell)
+ {
+ SdrModel* pModel = pDocument->getIDocumentDrawModelAccess().GetDrawModel();
+ auto const& pTheme = pModel->getTheme();
+ if (pTheme)
+ {
+ std::shared_ptr<svx::IThemeColorChanger> pChanger(new sw::ThemeColorChanger(pDocumentShell));
+ auto pDialog = std::make_shared<svx::ThemeDialog>(pMDI, pTheme.get());
+ weld::DialogController::runAsync(pDialog, [pDialog, pChanger](sal_uInt32 nResult) {
+ if (RET_OK != nResult)
+ return;
+
+ auto pColorSet = pDialog->getCurrentColorSet();
+ if (pColorSet)
+ {
+ pChanger->apply(pColorSet);
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ svx::ThemeColorPaletteManager aManager(pColorSet);
+ SfxLokHelper::notifyAllViews(LOK_CALLBACK_COLOR_PALETTES, aManager.generateJSON());
+ }
+ }
+ });
+ }
+ }
+ }
+ break;
+
+ default:OSL_FAIL("wrong Dispatcher (basesh.cxx)");
+ }
+ if(!bDone)
+ rReq.Done();
+}
+
+SwWrtShell& SwBaseShell::GetShell()
+{
+ return m_rView.GetWrtShell();
+}
+
+SwWrtShell* SwBaseShell::GetShellPtr()
+{
+ return m_rView.GetWrtShellPtr();
+}
+
+static void EndUndo(SwWrtShell& rSh)
+{
+ SwRewriter aRewriter;
+
+ if (rSh.GetTableFormat())
+ {
+ aRewriter.AddRule(UndoArg1, SwResId(STR_START_QUOTE));
+ aRewriter.AddRule(UndoArg2, rSh.GetTableFormat()->GetName());
+ aRewriter.AddRule(UndoArg3, SwResId(STR_END_QUOTE));
+
+ }
+ rSh.EndUndo(SwUndoId::INSTABLE, &aRewriter); // If possible change the Shell
+}
+
+static void InsertTableImpl(SwWrtShell& rSh,
+ SwView &rTempView,
+ const OUString& aTableName,
+ sal_uInt16 nRows,
+ sal_uInt16 nCols,
+ SwInsertTableOptions aInsTableOpts,
+ const OUString& aAutoName,
+ const std::unique_ptr<SwTableAutoFormat>& pTAFormat)
+{
+ rSh.StartUndo(SwUndoId::INSTABLE);
+
+ rSh.StartAllAction();
+ if( rSh.HasSelection() )
+ rSh.DelRight();
+
+ rSh.InsertTable( aInsTableOpts, nRows, nCols, pTAFormat.get() );
+ rSh.MoveTable( GotoPrevTable, fnTableStart );
+
+ if( !aTableName.isEmpty() && !rSh.GetTableStyle( aTableName ) )
+ rSh.GetTableFormat()->SetFormatName( aTableName );
+
+ if( pTAFormat != nullptr && !aAutoName.isEmpty()
+ && aAutoName != SwViewShell::GetShellRes()->aStrNone )
+ {
+ SwTableNode* pTableNode = const_cast<SwTableNode*>( rSh.IsCursorInTable() );
+ if ( pTableNode )
+ {
+ pTableNode->GetTable().SetTableStyleName( aAutoName );
+ SwUndoTableAutoFormat* pUndo = new SwUndoTableAutoFormat( *pTableNode, *pTAFormat );
+ if ( pUndo )
+ rSh.GetIDocumentUndoRedo().AppendUndo( std::unique_ptr<SwUndo>(pUndo) );
+ }
+ }
+
+ rSh.EndAllAction();
+ rTempView.AutoCaption(TABLE_CAP);
+}
+
+void SwBaseShell::InsertTable( SfxRequest& _rRequest )
+{
+ const SfxItemSet* pArgs = _rRequest.GetArgs();
+ SwWrtShell& rSh = GetShell();
+
+ if ( rSh.GetFrameType( nullptr, true ) & FrameTypeFlags::FOOTNOTE )
+ return;
+
+ SwView &rTempView = GetView(); // Because GetView() does not work after the shell exchange
+ bool bHTMLMode = 0 != (::GetHtmlMode(rTempView.GetDocShell())&HTMLMODE_ON);
+ bool bCallEndUndo = false;
+
+ if( !pArgs && rSh.IsSelection() && !rSh.IsInClickToEdit() &&
+ !rSh.IsTableMode() )
+ {
+ const SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig();
+ SwInsertTableOptions aInsTableOpts = pModOpt->GetInsTableFlags(bHTMLMode);
+
+ rSh.StartUndo(SwUndoId::INSTABLE);
+ bCallEndUndo = true;
+
+ bool bInserted = rSh.TextToTable( aInsTableOpts, '\t' );
+ rSh.EnterStdMode();
+ if (bInserted)
+ rTempView.AutoCaption(TABLE_CAP);
+ _rRequest.Done();
+ }
+ else
+ {
+ sal_uInt16 nColsIn = 0;
+ sal_uInt16 nRowsIn = 0;
+ SwInsertTableOptions aInsTableOptsIn( SwInsertTableFlags::All, 1 );
+ OUString aTableNameIn;
+ OUString aAutoNameIn;
+ std::unique_ptr<SwTableAutoFormat> pTAFormatIn;
+
+ if( pArgs && pArgs->Count() >= 2 )
+ {
+ const SfxStringItem* pName = _rRequest.GetArg<SfxStringItem>(FN_INSERT_TABLE);
+ const SfxUInt16Item* pCols = _rRequest.GetArg<SfxUInt16Item>(SID_ATTR_TABLE_COLUMN);
+ const SfxUInt16Item* pRows = _rRequest.GetArg<SfxUInt16Item>(SID_ATTR_TABLE_ROW);
+ const SfxInt32Item* pFlags = _rRequest.GetArg<SfxInt32Item>(FN_PARAM_1);
+ const SfxStringItem* pAuto = _rRequest.GetArg<SfxStringItem>(FN_PARAM_2);
+
+ if ( pName )
+ aTableNameIn = pName->GetValue();
+ if ( pCols )
+ nColsIn = pCols->GetValue();
+ if ( pRows )
+ nRowsIn = pRows->GetValue();
+ if ( pAuto )
+ {
+ aAutoNameIn = pAuto->GetValue();
+ if ( !aAutoNameIn.isEmpty() )
+ {
+ SwTableAutoFormatTable aTableTable;
+ aTableTable.Load();
+ for ( size_t n=0; n<aTableTable.size(); n++ )
+ {
+ if ( aTableTable[n].GetName() == aAutoNameIn )
+ {
+ pTAFormatIn.reset(new SwTableAutoFormat( aTableTable[n] ));
+ break;
+ }
+ }
+ }
+ }
+
+ if ( pFlags )
+ aInsTableOptsIn.mnInsMode = static_cast<SwInsertTableFlags>(pFlags->GetValue());
+ else
+ {
+ const SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig();
+ aInsTableOptsIn = pModOpt->GetInsTableFlags(bHTMLMode);
+ }
+ }
+
+ if( !nColsIn || !nRowsIn )
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ std::shared_ptr<AbstractInsTableDlg> pAbstractDialog(pFact->CreateInsTableDlg(rTempView));
+ std::shared_ptr<weld::DialogController> pDialogController(pAbstractDialog->getDialogController());
+
+ weld::DialogController::runAsync(pDialogController,
+ [pAbstractDialog, &rSh, &rTempView, aTableNameIn, nRowsIn, nColsIn, aInsTableOptsIn, aAutoNameIn] (sal_Int32 nResult) {
+ if( RET_OK == nResult )
+ {
+ sal_uInt16 nCols = nColsIn;
+ sal_uInt16 nRows = nRowsIn;
+ SwInsertTableOptions aInsTableOpts = aInsTableOptsIn;
+ OUString aTableName = aTableNameIn;
+ OUString aAutoName = aAutoNameIn;
+ std::unique_ptr<SwTableAutoFormat> pTAFormat;
+
+ pAbstractDialog->GetValues( aTableName, nRows, nCols, aInsTableOpts, aAutoName, pTAFormat );
+
+ if( nCols && nRows )
+ {
+ InsertTableImpl( rSh, rTempView, aTableName, nRows, nCols, aInsTableOpts, aAutoName, pTAFormat );
+ EndUndo(rSh);
+ }
+ }
+ }
+ );
+ }
+ else
+ {
+ // record before shell change
+ _rRequest.AppendItem( SfxStringItem( FN_INSERT_TABLE, aTableNameIn ) );
+ if ( !aAutoNameIn.isEmpty() )
+ _rRequest.AppendItem( SfxStringItem( FN_PARAM_2, aAutoNameIn ) );
+ _rRequest.AppendItem( SfxUInt16Item( SID_ATTR_TABLE_COLUMN, nColsIn ) );
+ _rRequest.AppendItem( SfxUInt16Item( SID_ATTR_TABLE_ROW, nRowsIn ) );
+ _rRequest.AppendItem( SfxInt32Item( FN_PARAM_1, static_cast<sal_Int32>(aInsTableOptsIn.mnInsMode) ) );
+ _rRequest.Done();
+
+ InsertTableImpl( rSh, rTempView, aTableNameIn, nRowsIn, nColsIn, aInsTableOptsIn, aAutoNameIn, pTAFormatIn );
+
+ bCallEndUndo = true;
+ }
+ }
+
+ if( bCallEndUndo )
+ EndUndo(rSh);
+}
+
+void SwBaseShell::GetGalleryState( SfxItemSet &rSet )
+{
+ SwWrtShell &rSh = GetShell();
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ switch ( nWhich )
+ {
+ case SID_GALLERY_BG_BRUSH:
+ {
+ SelectionType nSel = rSh.GetSelectionType();
+ SfxStringListItem aLst( nWhich );
+ std::vector<OUString> &rLst = aLst.GetList();
+ nParagraphPos = nGraphicPos = nOlePos = nFramePos = nTablePos =
+ nTableRowPos = nTableCellPos = nPagePos =
+ nHeaderPos = nFooterPos = 0;
+ sal_uInt8 nPos = 1;
+ rLst.push_back( SwResId( STR_SWBG_PAGE ) );
+ nPagePos = nPos++;
+ sal_uInt16 nHtmlMode = ::GetHtmlMode(GetView().GetDocShell());
+ bool bHtmlMode = 0 != (nHtmlMode & HTMLMODE_ON);
+
+ if ( (!bHtmlMode || (nHtmlMode & HTMLMODE_FULL_STYLES)) &&
+ (nSel & SelectionType::Text) )
+ {
+ rLst.push_back( SwResId( STR_SWBG_PARAGRAPH ) );
+ nParagraphPos = nPos++;
+ }
+ if ( (!bHtmlMode || (nHtmlMode & HTMLMODE_SOME_STYLES)) &&
+ nSel & (SelectionType::Table|SelectionType::TableCell) )
+ {
+ rLst.push_back( SwResId( STR_SWBG_TABLE ) );
+ nTablePos = nPos++;
+
+ if(!bHtmlMode)
+ {
+ rLst.push_back( SwResId( STR_SWBG_TABLE_ROW ) );
+ nTableRowPos = nPos++;
+ }
+
+ rLst.push_back( SwResId( STR_SWBG_TABLE_CELL) );
+ nTableCellPos = nPos++;
+ }
+ if(!bHtmlMode)
+ {
+ if ( nSel & SelectionType::Frame )
+ {
+ rLst.push_back( SwResId( STR_SWBG_FRAME ) );
+ nFramePos = nPos++;
+ }
+ if ( nSel & SelectionType::Graphic )
+ {
+ rLst.push_back( SwResId( STR_SWBG_GRAPHIC ) );
+ nGraphicPos = nPos++;
+ }
+ if ( nSel & SelectionType::Ole )
+ {
+ rLst.push_back( SwResId( STR_SWBG_OLE ) );
+ nOlePos = nPos++;
+ }
+ const FrameTypeFlags nType = rSh.GetFrameType(nullptr,true);
+ if ( nType & FrameTypeFlags::HEADER )
+ {
+ rLst.push_back( SwResId( STR_SWBG_HEADER ) );
+ nHeaderPos = nPos++;
+ }
+ if ( nType & FrameTypeFlags::FOOTER )
+ {
+ rLst.push_back( SwResId( STR_SWBG_FOOTER ) );
+ nFooterPos = nPos;
+ }
+ }
+ if ( rLst.empty() )
+ rSet.DisableItem( nWhich );
+ else
+ rSet.Put( aLst );
+ break;
+ }
+ }
+}
+
+void SwBaseShell::ExecuteGallery(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ rSh.StartAction();
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ sal_uInt16 nSlot = rReq.GetSlot();
+ switch(nSlot)
+ {
+ case SID_GALLERY_BG_BRUSH:
+ {
+ if ( !pArgs )
+ break;
+
+ SelectionType nSel = rSh.GetSelectionType();
+ if ( nSel & SelectionType::DrawObjectEditMode )
+ break;
+
+ const SfxUInt16Item* pPos = rReq.GetArg<SfxUInt16Item>(SID_GALLERY_BG_POS);
+ const SvxBrushItem* pBrush = rReq.GetArg<SvxBrushItem>(SID_GALLERY_BG_BRUSH);
+ if ( !pPos || !pBrush )
+ break;
+
+ sal_uInt8 nPos = pPos->GetValue();
+ ++nPos;
+
+ SvxBrushItem aBrush( *pBrush );
+ aBrush.SetWhich( RES_BACKGROUND );
+ if ( nPos == nParagraphPos )
+ rSh.SetAttrItem( aBrush );
+ else if ( nPos == nTablePos )
+ rSh.SetTabBackground( aBrush );
+ else if ( nPos == nTableRowPos )
+ rSh.SetRowBackground( aBrush );
+ else if ( nPos == nTableCellPos )
+ rSh.SetBoxBackground( aBrush );
+ else if ( nPos == nFramePos || nPos == nGraphicPos || nPos == nOlePos )
+ {
+ SfxItemSetFixed<RES_BACKGROUND, RES_BACKGROUND> aCoreSet(GetPool());
+ aCoreSet.Put( aBrush );
+ rSh.SetFlyFrameAttr( aCoreSet );
+ }
+ else if ( nPos == nPagePos || nPos == nHeaderPos || nPos == nFooterPos )
+ {
+ sal_uInt16 nDesc = rSh.GetCurPageDesc();
+ SwPageDesc aDesc( rSh.GetPageDesc( nDesc ) );
+ if ( nPos == nPagePos )
+ aDesc.GetMaster().SetFormatAttr( aBrush );
+ else if ( nPos == nHeaderPos )
+ {
+ SwFormatHeader aHead( aDesc.GetMaster().GetHeader() );
+ aHead.GetHeaderFormat()->SetFormatAttr( aBrush );
+ aDesc.GetMaster().SetFormatAttr( aHead );
+ }
+ else if ( nPos == nFooterPos )
+ {
+ SwFormatFooter aFoot( aDesc.GetMaster().GetFooter() );
+ aFoot.GetFooterFormat()->SetFormatAttr( aBrush );
+ aDesc.GetMaster().SetFormatAttr( aFoot );
+ }
+ rSh.ChgPageDesc( nDesc, aDesc );
+ }
+ break;
+ }
+ }
+ rSh.EndAction();
+ rReq.Done();
+}
+
+void SwBaseShell::ExecField( SfxRequest const & rReq )
+{
+ sal_uInt16 nSlot = rReq.GetSlot();
+ switch( nSlot )
+ {
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+ case FN_CHANGE_DBFIELD:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateSwChangeDBDlg(GetView()));
+ pDlg->Execute();
+ }
+ break;
+#endif
+ default:
+ OSL_FAIL("wrong dispatcher");
+ }
+}
+
+std::shared_ptr<std::vector<std::unique_ptr<SwPaM>>> SwBaseShell::CopyPaMRing(SwPaM& rOrig)
+{
+ auto vCursors = std::make_shared<std::vector<std::unique_ptr<SwPaM>>>();
+ vCursors->emplace_back(std::make_unique<SwPaM>(rOrig, nullptr));
+ for (auto& rCursor : rOrig.GetRingContainer())
+ {
+ if (&rCursor != &rOrig)
+ vCursors->emplace_back(std::make_unique<SwPaM>(rCursor, vCursors->front().get()));
+ }
+ return vCursors;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/beziersh.cxx b/sw/source/uibase/shells/beziersh.cxx
new file mode 100644
index 0000000000..2c4510fd7a
--- /dev/null
+++ b/sw/source/uibase/shells/beziersh.cxx
@@ -0,0 +1,325 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cmdid.h>
+#include <svx/svdview.hxx>
+#include <svl/eitem.hxx>
+#include <svl/whiter.hxx>
+#include <svx/svdopath.hxx>
+#include <vcl/EnumContext.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/viewfrm.hxx>
+
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <edtwin.hxx>
+#include <drawbase.hxx>
+#include <beziersh.hxx>
+#define ShellClass_SwBezierShell
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+
+SFX_IMPL_INTERFACE(SwBezierShell, SwBaseShell)
+
+void SwBezierShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("draw");
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Bezier_Toolbox_Sw);
+}
+
+
+SwBezierShell::SwBezierShell(SwView &_rView):
+ SwBaseShell( _rView )
+{
+ SetName("Bezier");
+
+ SwWrtShell *pSh = &GetShell();
+ SdrView* pSdrView = pSh->GetDrawView();
+ pSdrView->SetEliminatePolyPointLimitAngle(1500_deg100);
+
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Draw));
+}
+
+void SwBezierShell::Execute(SfxRequest const &rReq)
+{
+ SwWrtShell *pSh = &GetShell();
+ SdrView* pSdrView = pSh->GetDrawView();
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ sal_uInt16 nSlotId = rReq.GetSlot();
+ bool bChanged = pSdrView->GetModel().IsChanged();
+ pSdrView->GetModel().SetChanged(false);
+ const SfxPoolItem* pItem;
+ if(pArgs)
+ pArgs->GetItemState(nSlotId, false, &pItem);
+
+ switch (nSlotId)
+ {
+ case SID_DELETE:
+ case FN_BACKSPACE:
+ if (pSh->IsObjSelected())
+ {
+ if (pSdrView->HasMarkedPoints())
+ pSh->GetView().GetViewFrame().GetDispatcher()->Execute(SID_BEZIER_DELETE);
+ else
+ {
+ pSh->DelSelectedObj();
+ if (pSh->IsSelFrameMode())
+ {
+ pSh->LeaveSelFrameMode();
+ pSh->NoEdit();
+ }
+ GetView().AttrChangedNotify(nullptr); // Shell change if applicable...
+ }
+ }
+ break;
+
+ case FN_ESCAPE:
+ if (pSdrView->HasMarkedPoints())
+ pSdrView->UnmarkAllPoints();
+ else
+ {
+ if ( pSh->IsDrawCreate() )
+ {
+ GetView().GetDrawFuncPtr()->BreakCreate();
+ GetView().AttrChangedNotify(nullptr); // Shell change if applicable...
+ }
+ else if ( pSh->HasSelection() || GetView().IsDrawMode() )
+ {
+ GetView().LeaveDrawCreate();
+ pSh->EnterStdMode();
+ GetView().AttrChangedNotify(nullptr); // Shell change if applicable...
+ }
+ }
+ break;
+
+ case SID_BEZIER_MOVE:
+ case SID_BEZIER_INSERT:
+ {
+ GetView().GetEditWin().SetBezierMode(nSlotId);
+ static sal_uInt16 aInva[] =
+ {
+ SID_BEZIER_INSERT,
+ SID_BEZIER_MOVE,
+ 0
+ };
+ GetView().GetViewFrame().GetBindings().Invalidate(aInva);
+ }
+ break;
+
+ case SID_BEZIER_DELETE:
+ case SID_BEZIER_CUTLINE:
+ case SID_BEZIER_CONVERT:
+ case SID_BEZIER_EDGE:
+ case SID_BEZIER_SMOOTH:
+ case SID_BEZIER_SYMMTR:
+ case SID_BEZIER_CLOSE:
+ case SID_BEZIER_ELIMINATE_POINTS:
+ {
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+
+ if (rMarkList.GetMark(0) && !pSdrView->IsAction())
+ {
+ switch (nSlotId)
+ {
+ case SID_BEZIER_DELETE:
+ pSdrView->DeleteMarkedPoints();
+ break;
+
+ case SID_BEZIER_CUTLINE:
+ {
+ pSdrView->RipUpAtMarkedPoints();
+ pSh->CheckUnboundObjects();
+ }
+ break;
+
+ case SID_BEZIER_CONVERT:
+ {
+ pSdrView->SetMarkedSegmentsKind(SdrPathSegmentKind::Toggle);
+ break;
+ }
+
+ case SID_BEZIER_EDGE:
+ case SID_BEZIER_SMOOTH:
+ case SID_BEZIER_SYMMTR:
+ {
+ SdrPathSmoothKind eKind = SdrPathSmoothKind::Asymmetric;
+
+ switch (nSlotId)
+ {
+ case SID_BEZIER_EDGE: eKind = SdrPathSmoothKind::Angular; break;
+ case SID_BEZIER_SMOOTH: eKind = SdrPathSmoothKind::Asymmetric; break;
+ case SID_BEZIER_SYMMTR: eKind = SdrPathSmoothKind::Symmetric; break;
+ }
+
+ SdrPathSmoothKind eSmooth = pSdrView->GetMarkedPointsSmooth();
+ if (eKind != eSmooth)
+ {
+ pSdrView->SetMarkedPointsSmooth(eKind);
+
+ static sal_uInt16 aInva[] =
+ {
+ SID_BEZIER_SMOOTH,
+ SID_BEZIER_EDGE,
+ SID_BEZIER_SYMMTR,
+ 0
+ };
+ GetView().GetViewFrame().GetBindings().Invalidate(aInva);
+ }
+ break;
+ }
+
+ case SID_BEZIER_CLOSE:
+ {
+ SdrPathObj* pPathObj = static_cast<SdrPathObj*>( rMarkList.GetMark(0)->GetMarkedSdrObj() );
+ pSdrView->UnmarkAllPoints();
+ // Size aDist(GetView().GetEditWin().PixelToLogic(Size(8,8)));
+ pPathObj->ToggleClosed(); // aDist.Width());
+ break;
+ }
+
+ case SID_BEZIER_ELIMINATE_POINTS:
+ pSdrView->SetEliminatePolyPoints(!pSdrView->IsEliminatePolyPoints());
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (pSdrView->GetModel().IsChanged())
+ GetShell().SetModified();
+ else if (bChanged)
+ pSdrView->GetModel().SetChanged();
+}
+
+void SwBezierShell::GetState(SfxItemSet &rSet)
+{
+ SdrView* pSdrView = GetShell().GetDrawView();
+
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while( nWhich )
+ {
+ switch( nWhich )
+ {
+ case SID_BEZIER_MOVE:
+ case SID_BEZIER_INSERT:
+ {
+ sal_uInt16 nEditMode = GetView().GetEditWin().GetBezierMode();
+
+ rSet.Put(SfxBoolItem(nWhich, nEditMode == nWhich));
+ }
+ break;
+
+ case SID_BEZIER_CUTLINE:
+ if (!pSdrView->IsRipUpAtMarkedPointsPossible())
+ {
+ rSet.DisableItem(SID_BEZIER_CUTLINE);
+ }
+ break;
+
+ case SID_BEZIER_DELETE:
+ if (!pSdrView->IsDeleteMarkedPointsPossible())
+ {
+ rSet.DisableItem(SID_BEZIER_DELETE);
+ }
+ break;
+
+ case SID_BEZIER_CONVERT:
+ if (!pSdrView->IsSetMarkedSegmentsKindPossible())
+ {
+ rSet.DisableItem(SID_BEZIER_CONVERT);
+ }
+ else
+ {
+ SdrPathSegmentKind eSegm = pSdrView->GetMarkedSegmentsKind();
+ switch (eSegm)
+ {
+ case SdrPathSegmentKind::DontCare: rSet.InvalidateItem(SID_BEZIER_CONVERT); break;
+ case SdrPathSegmentKind::Line : rSet.Put(SfxBoolItem(SID_BEZIER_CONVERT,false)); break; // Button pressed = curve
+ case SdrPathSegmentKind::Curve : rSet.Put(SfxBoolItem(SID_BEZIER_CONVERT,true)); break;
+ default:; //prevent warning
+ }
+ }
+ break;
+
+ case SID_BEZIER_EDGE:
+ case SID_BEZIER_SMOOTH:
+ case SID_BEZIER_SYMMTR:
+ if (!pSdrView->IsSetMarkedPointsSmoothPossible())
+ rSet.DisableItem(nWhich);
+ else
+ {
+ SdrPathSmoothKind eSmooth = pSdrView->GetMarkedPointsSmooth();
+ bool bEnable = false;
+ switch (eSmooth)
+ {
+ case SdrPathSmoothKind::DontCare :
+ break;
+ case SdrPathSmoothKind::Angular :
+ bEnable = nWhich == SID_BEZIER_EDGE;
+ break;
+ case SdrPathSmoothKind::Asymmetric:
+ bEnable = nWhich == SID_BEZIER_SMOOTH;
+ break;
+ case SdrPathSmoothKind::Symmetric :
+ bEnable = nWhich == SID_BEZIER_SYMMTR;
+ break;
+ }
+ rSet.Put(SfxBoolItem(nWhich, bEnable));
+ }
+ break;
+
+ case SID_BEZIER_CLOSE:
+ if (!pSdrView->IsOpenCloseMarkedObjectsPossible())
+ {
+ rSet.DisableItem(SID_BEZIER_CLOSE);
+ }
+ else
+ {
+ SdrObjClosedKind eClose = pSdrView->GetMarkedObjectsClosedState();
+ switch (eClose)
+ {
+ case SdrObjClosedKind::DontCare: rSet.InvalidateItem(SID_BEZIER_CLOSE); break;
+ case SdrObjClosedKind::Open : rSet.Put(SfxBoolItem(SID_BEZIER_CLOSE,false)); break;
+ case SdrObjClosedKind::Closed : rSet.Put(SfxBoolItem(SID_BEZIER_CLOSE,true)); break;
+ default:; //prevent warning
+ }
+ }
+ break;
+
+ case SID_BEZIER_ELIMINATE_POINTS:
+ rSet.Put(SfxBoolItem(SID_BEZIER_ELIMINATE_POINTS, pSdrView->IsEliminatePolyPoints()));
+ break;
+
+ default:
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/drawdlg.cxx b/sw/source/uibase/shells/drawdlg.cxx
new file mode 100644
index 0000000000..ec93f35029
--- /dev/null
+++ b/sw/source/uibase/shells/drawdlg.cxx
@@ -0,0 +1,368 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/request.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svx/svdview.hxx>
+
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <cmdid.h>
+
+#include <drawsh.hxx>
+#include <svx/svxdlg.hxx>
+#include <svx/dialogs.hrc>
+#include <memory>
+#include <svl/stritem.hxx>
+#include <svx/xlnclit.hxx>
+#include <svx/xflclit.hxx>
+#include <svx/chrtitem.hxx>
+#include <svx/xlnwtit.hxx>
+#include <svx/xflgrit.hxx>
+#include <svx/xflftrit.hxx>
+#include <svx/xfltrit.hxx>
+#include <comphelper/lok.hxx>
+#include <textboxhelper.hxx>
+
+using namespace com::sun::star::drawing;
+
+void SwDrawShell::ExecDrawDlg(SfxRequest& rReq)
+{
+ SwWrtShell* pSh = &GetShell();
+ SdrView* pView = pSh->GetDrawView();
+ SdrModel& rModel = pView->GetModel();
+ bool bChanged = rModel.IsChanged();
+ rModel.SetChanged(false);
+
+ SfxItemSet aNewAttr(rModel.GetItemPool());
+ pView->GetAttributes( aNewAttr );
+
+ GetView().NoRotate();
+
+ switch (rReq.GetSlot())
+ {
+ case FN_DRAWTEXT_ATTR_DLG:
+ {
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateTextTabDialog(rReq.GetFrameWeld(), &aNewAttr, pView));
+ sal_uInt16 nResult = pDlg->Execute();
+
+ if (nResult == RET_OK)
+ {
+ if (pView->AreObjectsMarked())
+ {
+ pSh->StartAction();
+ pView->SetAttributes(*pDlg->GetOutputItemSet());
+ auto vMarkedObjs = pView->GetMarkedObjects();
+ for (auto pObj : vMarkedObjs)
+ {
+ // If the shape has textframe, set its params as well.
+ if (SwTextBoxHelper::hasTextFrame(pObj))
+ SwTextBoxHelper::updateTextBoxMargin(pObj);
+ }
+ rReq.Done(*(pDlg->GetOutputItemSet()));
+ pSh->EndAction();
+ }
+ }
+ }
+ break;
+
+ case SID_MEASURE_DLG:
+ {
+ bool bHasMarked = pView->AreObjectsMarked();
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateSfxDialog(rReq.GetFrameWeld(),
+ aNewAttr, pView, RID_SVXPAGE_MEASURE));
+ if (pDlg->Execute() == RET_OK)
+ {
+ pSh->StartAction();
+ if (bHasMarked)
+ pView->SetAttrToMarked(*pDlg->GetOutputItemSet(), false);
+ else
+ pView->SetDefaultAttr(*pDlg->GetOutputItemSet(), false);
+ pSh->EndAction();
+ }
+ }
+ break;
+
+ case SID_ATTRIBUTES_AREA:
+ {
+ bool bHasMarked = pView->AreObjectsMarked();
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ VclPtr<AbstractSvxAreaTabDialog> pDlg(pFact->CreateSvxAreaTabDialog(rReq.GetFrameWeld(),
+ &aNewAttr,
+ &rModel,
+ true,
+ false));
+
+ pDlg->StartExecuteAsync([bChanged, bHasMarked, &rModel, pDlg, pSh, pView, this](
+ sal_Int32 nResult){
+ rModel.SetChanged(false);
+
+ if (nResult == RET_OK)
+ {
+ pSh->StartAction();
+ if (bHasMarked)
+ pView->SetAttributes(*pDlg->GetOutputItemSet());
+ else
+ pView->SetDefaultAttr(*pDlg->GetOutputItemSet(), false);
+ pSh->EndAction();
+
+ static sal_uInt16 aInval[] =
+ {
+ SID_ATTR_FILL_STYLE,
+ SID_ATTR_FILL_COLOR,
+ SID_ATTR_FILL_TRANSPARENCE,
+ SID_ATTR_FILL_FLOATTRANSPARENCE,
+ 0
+ };
+ SfxBindings &rBnd = GetView().GetViewFrame().GetBindings();
+ rBnd.Invalidate(aInval);
+ rBnd.Update(SID_ATTR_FILL_STYLE);
+ rBnd.Update(SID_ATTR_FILL_COLOR);
+ rBnd.Update(SID_ATTR_FILL_TRANSPARENCE);
+ rBnd.Update(SID_ATTR_FILL_FLOATTRANSPARENCE);
+ }
+
+ if (rModel.IsChanged())
+ GetShell().SetModified();
+ else if (bChanged)
+ rModel.SetChanged();
+
+ pDlg->disposeOnce();
+ });
+ }
+ break;
+
+ case SID_ATTRIBUTES_LINE:
+ {
+ bool bHasMarked = pView->AreObjectsMarked();
+
+ const SdrObject* pObj = nullptr;
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if( rMarkList.GetMarkCount() == 1 )
+ pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateSvxLineTabDialog(rReq.GetFrameWeld(),
+ &aNewAttr,
+ &rModel,
+ pObj,
+ bHasMarked));
+
+ pDlg->StartExecuteAsync([bChanged, bHasMarked, &rModel, pDlg, pSh, pView, this](
+ sal_Int32 nResult){
+ rModel.SetChanged(false);
+
+ if (nResult == RET_OK)
+ {
+ pSh->StartAction();
+ if(bHasMarked)
+ pView->SetAttrToMarked(*pDlg->GetOutputItemSet(), false);
+ else
+ pView->SetDefaultAttr(*pDlg->GetOutputItemSet(), false);
+ pSh->EndAction();
+
+ static sal_uInt16 aInval[] =
+ {
+ SID_ATTR_LINE_STYLE, // ( SID_SVX_START + 169 )
+ SID_ATTR_LINE_DASH, // ( SID_SVX_START + 170 )
+ SID_ATTR_LINE_WIDTH, // ( SID_SVX_START + 171 )
+ SID_ATTR_LINE_COLOR, // ( SID_SVX_START + 172 )
+ SID_ATTR_LINE_START, // ( SID_SVX_START + 173 )
+ SID_ATTR_LINE_END, // ( SID_SVX_START + 174 )
+ SID_ATTR_LINE_TRANSPARENCE, // (SID_SVX_START+1107)
+ SID_ATTR_LINE_JOINT, // (SID_SVX_START+1110)
+ SID_ATTR_LINE_CAP, // (SID_SVX_START+1111)
+ 0
+ };
+
+ GetView().GetViewFrame().GetBindings().Invalidate(aInval);
+ }
+
+ if (rModel.IsChanged())
+ GetShell().SetModified();
+ else if (bChanged)
+ rModel.SetChanged();
+
+ pDlg->disposeOnce();
+ });
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (rModel.IsChanged())
+ GetShell().SetModified();
+ else if (bChanged)
+ rModel.SetChanged();
+}
+
+namespace
+{
+ void lcl_convertStringArguments(const std::unique_ptr<SfxItemSet>& pArgs)
+ {
+ if (const SvxDoubleItem* pWidthItem = pArgs->GetItemIfSet(SID_ATTR_LINE_WIDTH_ARG, false))
+ {
+ double fValue = pWidthItem->GetValue();
+ // FIXME: different units...
+ int nPow = 100;
+ int nValue = fValue * nPow;
+
+ XLineWidthItem aItem(nValue);
+ pArgs->Put(aItem);
+ }
+ if (const SfxStringItem* pJSON = pArgs->GetItemIfSet(SID_FILL_GRADIENT_JSON, false))
+ {
+ basegfx::BGradient aGradient = basegfx::BGradient::fromJSON(pJSON->GetValue());
+ XFillGradientItem aItem(aGradient);
+ pArgs->Put(aItem);
+ }
+ }
+}
+
+void SwDrawShell::ExecDrawAttrArgs(SfxRequest const & rReq)
+{
+ SwWrtShell* pSh = &GetShell();
+ SdrView* pView = pSh->GetDrawView();
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ bool bChanged = pView->GetModel().IsChanged();
+ pView->GetModel().SetChanged(false);
+
+ GetView().NoRotate();
+
+ if (pArgs)
+ {
+ if(pView->AreObjectsMarked())
+ {
+ std::unique_ptr<SfxItemSet> pNewArgs = pArgs->Clone();
+ lcl_convertStringArguments(pNewArgs);
+ pView->SetAttrToMarked(*pNewArgs, false);
+ }
+ else
+ pView->SetDefaultAttr(*rReq.GetArgs(), false);
+ }
+ else
+ {
+ SfxDispatcher* pDis = pSh->GetView().GetViewFrame().GetDispatcher();
+ switch (rReq.GetSlot())
+ {
+ case SID_ATTR_FILL_STYLE:
+ case SID_ATTR_FILL_COLOR:
+ case SID_ATTR_FILL_GRADIENT:
+ case SID_ATTR_FILL_HATCH:
+ case SID_ATTR_FILL_BITMAP:
+ case SID_ATTR_FILL_TRANSPARENCE:
+ case SID_ATTR_FILL_FLOATTRANSPARENCE:
+ pDis->Execute(SID_ATTRIBUTES_AREA);
+ break;
+ case SID_ATTR_LINE_STYLE:
+ case SID_ATTR_LINE_DASH:
+ case SID_ATTR_LINE_WIDTH:
+ case SID_ATTR_LINE_COLOR:
+ case SID_ATTR_LINE_TRANSPARENCE:
+ case SID_ATTR_LINE_JOINT:
+ case SID_ATTR_LINE_CAP:
+ pDis->Execute(SID_ATTRIBUTES_LINE);
+ break;
+ }
+ }
+ if (pView->GetModel().IsChanged())
+ GetShell().SetModified();
+ else
+ if (bChanged)
+ pView->GetModel().SetChanged();
+}
+
+static void lcl_unifyFillTransparencyItems(const SfxItemSet& rSet)
+{
+ // Transparent fill options are None, Solid, Linear, Axial, Radial, Elliptical, Square, Rectangular.
+ // But this is represented across two items namely XFillTransparenceItem (for None and Solid)
+ // and XFillFloatTransparenceItem (for the rest). To simplify the representation in LOKit case let's
+ // use XFillFloatTransparenceItem to carry the information of XFillTransparenceItem when gradients
+ // are disabled. When gradient transparency is disabled, all fields of XFillFloatTransparenceItem are invalid
+ // and not used. So convert XFillTransparenceItem's constant transparency percentage as an intensity
+ // and assign this to the XFillFloatTransparenceItem's start-intensity and end-intensity fields.
+ // Now the LOK clients need only listen to statechange messages of XFillFloatTransparenceItem
+ // to get fill-transparency settings instead of listening to two separate items.
+
+ XFillFloatTransparenceItem* pFillFloatTranspItem =
+ const_cast<XFillFloatTransparenceItem*>
+ (rSet.GetItem<XFillFloatTransparenceItem>(XATTR_FILLFLOATTRANSPARENCE));
+ if (!pFillFloatTranspItem || pFillFloatTranspItem->IsEnabled())
+ return;
+
+ const XFillTransparenceItem* pFillTranspItem =
+ rSet.GetItem<XFillTransparenceItem>(XATTR_FILLTRANSPARENCE);
+
+ if (!pFillTranspItem)
+ return;
+
+ basegfx::BGradient aTmpGradient = pFillFloatTranspItem->GetGradientValue();
+ sal_uInt16 nTranspPercent = pFillTranspItem->GetValue();
+ // Encode transparency percentage as intensity
+ sal_uInt16 nIntensity = 100 - std::min<sal_uInt16>
+ (std::max<sal_uInt16>(nTranspPercent, 0), 100);
+ aTmpGradient.SetStartIntens(nIntensity);
+ aTmpGradient.SetEndIntens(nIntensity);
+ pFillFloatTranspItem->SetGradientValue(aTmpGradient);
+}
+
+void SwDrawShell::GetDrawAttrState(SfxItemSet& rSet)
+{
+ SdrView* pSdrView = GetShell().GetDrawView();
+
+ if (pSdrView->AreObjectsMarked())
+ {
+ bool bDisable = Disable( rSet );
+
+ if( !bDisable )
+ {
+ SfxItemSet aSet(rSet);
+ aSet.MergeRange(SDRATTR_TEXTCOLUMNS_NUMBER, SDRATTR_TEXTCOLUMNS_SPACING);
+ pSdrView->GetAttributes(aSet);
+ if (const SfxPoolItem* pItem = nullptr;
+ aSet.GetItemState(SDRATTR_TEXTCOLUMNS_NUMBER, false, &pItem)
+ >= SfxItemState::DEFAULT
+ && pItem)
+ {
+ aSet.Put(pItem->CloneSetWhich(SID_ATTR_TEXTCOLUMNS_NUMBER));
+ }
+ if (const SfxPoolItem* pItem = nullptr;
+ aSet.GetItemState(SDRATTR_TEXTCOLUMNS_SPACING, false, &pItem)
+ >= SfxItemState::DEFAULT
+ && pItem)
+ {
+ aSet.Put(pItem->CloneSetWhich(SID_ATTR_TEXTCOLUMNS_SPACING));
+ }
+ rSet.Put(aSet, false);
+ if (comphelper::LibreOfficeKit::isActive())
+ lcl_unifyFillTransparencyItems(rSet);
+ }
+ }
+ else
+ rSet.Put(pSdrView->GetDefaultAttr());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/drawsh.cxx b/sw/source/uibase/shells/drawsh.cxx
new file mode 100644
index 0000000000..23c4dd6187
--- /dev/null
+++ b/sw/source/uibase/shells/drawsh.cxx
@@ -0,0 +1,629 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svdview.hxx>
+#include <svx/svdotext.hxx>
+#include <svl/whiter.hxx>
+#include <svx/fontwork.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svx/extrusionbar.hxx>
+#include <svx/fontworkbar.hxx>
+#include <uitool.hxx>
+#include <dcontact.hxx>
+#include <textboxhelper.hxx>
+#include <wview.hxx>
+#include <swmodule.hxx>
+
+#include <svx/svdoashp.hxx>
+#include <svx/xfillit0.hxx>
+#include <vcl/EnumContext.hxx>
+#include <svx/svdoole2.hxx>
+#include <sfx2/opengrf.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/svdundo.hxx>
+#include <svx/xbtmpit.hxx>
+#include <svx/sdasitm.hxx>
+#include <osl/diagnose.h>
+
+#include <swundo.hxx>
+#include <wrtsh.hxx>
+#include <cmdid.h>
+#include <strings.hrc>
+#include <drwbassh.hxx>
+#include <drawsh.hxx>
+
+#define ShellClass_SwDrawShell
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+SFX_IMPL_INTERFACE(SwDrawShell, SwDrawBaseShell)
+
+void SwDrawShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("draw");
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Draw_Toolbox_Sw);
+
+ GetStaticInterface()->RegisterChildWindow(SvxFontWorkChildWindow::GetChildWindowId());
+}
+
+
+// #i123922# check as the name implies
+SdrObject* SwDrawShell::IsSingleFillableNonOLESelected()
+{
+ SwWrtShell &rSh = GetShell();
+ SdrView* pSdrView = rSh.GetDrawView();
+
+ if(!pSdrView)
+ {
+ return nullptr;
+ }
+
+ if(1 != pSdrView->GetMarkedObjectCount())
+ {
+ return nullptr;
+ }
+
+ SdrObject* pPickObj = pSdrView->GetMarkedObjectByIndex(0);
+
+ if(!pPickObj)
+ {
+ return nullptr;
+ }
+
+ if(!pPickObj->IsClosedObj())
+ {
+ return nullptr;
+ }
+
+ if(dynamic_cast< SdrOle2Obj* >(pPickObj))
+ {
+ return nullptr;
+ }
+
+ return pPickObj;
+}
+
+// #i123922# insert given graphic data dependent of the object type in focus
+void SwDrawShell::InsertPictureFromFile(SdrObject& rObject)
+{
+ SwWrtShell &rSh = GetShell();
+ SdrView* pSdrView = rSh.GetDrawView();
+
+ if(!pSdrView)
+ return;
+
+ SvxOpenGraphicDialog aDlg(SwResId(STR_INSERT_GRAPHIC), GetView().GetFrameWeld());
+
+ if (ERRCODE_NONE != aDlg.Execute())
+ return;
+
+ Graphic aGraphic;
+ ErrCode nError = aDlg.GetGraphic(aGraphic);
+
+ if(ERRCODE_NONE != nError)
+ return;
+
+ const bool bAsLink(aDlg.IsAsLink());
+ SdrObject* pResult = &rObject;
+
+ rSh.StartUndo(SwUndoId::PASTE_CLIPBOARD);
+
+ if (SdrGrafObj* pSdrGrafObj = dynamic_cast<SdrGrafObj*>(&rObject))
+ {
+ rtl::Reference<SdrGrafObj> pNewGrafObj = SdrObject::Clone(*pSdrGrafObj, pSdrGrafObj->getSdrModelFromSdrObject());
+
+ pNewGrafObj->SetGraphic(aGraphic);
+
+ // #i123922# for handling MasterObject and virtual ones correctly, SW
+ // wants us to call ReplaceObject at the page, but that also
+ // triggers the same assertion (I tried it), so stay at the view method
+ pSdrView->ReplaceObjectAtView(&rObject, *pSdrView->GetSdrPageView(), pNewGrafObj.get());
+
+ // set in all cases - the Clone() will have copied an existing link (!)
+ pNewGrafObj->SetGraphicLink(
+ bAsLink ? aDlg.GetPath() : OUString());
+
+ pResult = pNewGrafObj.get();
+ }
+ else // if(rObject.IsClosedObj() && !dynamic_cast< SdrOle2Obj* >(&rObject))
+ {
+ pSdrView->AddUndo(std::make_unique<SdrUndoAttrObj>(rObject));
+
+ SfxItemSetFixed<XATTR_FILLSTYLE, XATTR_FILLBITMAP> aSet(pSdrView->GetModel().GetItemPool());
+
+ aSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP));
+ aSet.Put(XFillBitmapItem(OUString(), std::move(aGraphic)));
+ rObject.SetMergedItemSetAndBroadcast(aSet);
+ }
+
+ rSh.EndUndo( SwUndoId::END );
+
+ if(pResult)
+ {
+ // we are done; mark the modified/new object
+ pSdrView->MarkObj(pResult, pSdrView->GetSdrPageView());
+ }
+}
+
+void SwDrawShell::Execute(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ SdrView *pSdrView = rSh.GetDrawView();
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ SfxBindings &rBnd = GetView().GetViewFrame().GetBindings();
+ sal_uInt16 nSlotId = rReq.GetSlot();
+ bool bChanged = pSdrView->GetModel().IsChanged();
+
+ pSdrView->GetModel().SetChanged(false);
+
+ const SfxPoolItem* pItem;
+ if(pArgs)
+ pArgs->GetItemState(nSlotId, false, &pItem);
+
+ bool bMirror = true;
+
+ switch (nSlotId)
+ {
+ case SID_OBJECT_ROTATE:
+ if (rSh.IsObjSelected() && pSdrView->IsRotateAllowed())
+ {
+ if (GetView().IsDrawRotate())
+ rSh.SetDragMode(SdrDragMode::Move);
+ else
+ rSh.SetDragMode(SdrDragMode::Rotate);
+
+ GetView().FlipDrawRotate();
+ }
+ break;
+ case SID_MOVE_SHAPE_HANDLE:
+ {
+ if (pArgs && pArgs->Count() >= 3)
+ {
+ const SfxUInt32Item* handleNumItem = rReq.GetArg<SfxUInt32Item>(FN_PARAM_1);
+ const SfxUInt32Item* newPosXTwips = rReq.GetArg<SfxUInt32Item>(FN_PARAM_2);
+ const SfxUInt32Item* newPosYTwips = rReq.GetArg<SfxUInt32Item>(FN_PARAM_3);
+ const SfxInt32Item* OrdNum = rReq.GetArg<SfxInt32Item>(FN_PARAM_4);
+
+ const sal_uLong handleNum = handleNumItem->GetValue();
+ const sal_uLong newPosX = newPosXTwips->GetValue();
+ const sal_uLong newPosY = newPosYTwips->GetValue();
+ const Point mPoint(newPosX, newPosY);
+ const SdrHdl* handle = pSdrView->GetHdlList().GetHdl(handleNum);
+ if (!handle)
+ {
+ break;
+ }
+
+ if (handle->GetKind() == SdrHdlKind::Anchor || handle->GetKind() == SdrHdlKind::Anchor_TR)
+ {
+ rSh.FindAnchorPos(mPoint, /*bMoveIt=*/true);
+ pSdrView->ModelHasChanged();
+ }
+ else
+ pSdrView->MoveShapeHandle(handleNum, mPoint, OrdNum ? OrdNum->GetValue() : -1);
+ }
+ }
+ break;
+ case SID_BEZIER_EDIT:
+ if (GetView().IsDrawRotate())
+ {
+ rSh.SetDragMode(SdrDragMode::Move);
+ GetView().FlipDrawRotate();
+ }
+ GetView().FlipDrawSelMode();
+ pSdrView->SetFrameDragSingles(GetView().IsDrawSelMode());
+ GetView().AttrChangedNotify(nullptr); // Shell switch
+ break;
+
+ case SID_OBJECT_HELL:
+ if (rSh.IsObjSelected())
+ {
+ rSh.StartUndo( SwUndoId::START );
+ SetWrapMode(FN_FRAME_WRAPTHRU_TRANSP);
+ rSh.SelectionToHell();
+ rSh.EndUndo( SwUndoId::END );
+ rBnd.Invalidate(SID_OBJECT_HEAVEN);
+ }
+ break;
+
+ case SID_OBJECT_HEAVEN:
+ if (rSh.IsObjSelected())
+ {
+ rSh.StartUndo( SwUndoId::START );
+ SetWrapMode(FN_FRAME_WRAPTHRU);
+ rSh.SelectionToHeaven();
+ rSh.EndUndo( SwUndoId::END );
+ rBnd.Invalidate(SID_OBJECT_HELL);
+ }
+ break;
+
+ case FN_TOOL_HIERARCHIE:
+ if (rSh.IsObjSelected())
+ {
+ rSh.StartUndo( SwUndoId::START );
+ if (rSh.GetLayerId() == SdrLayerID(0))
+ {
+ SetWrapMode(FN_FRAME_WRAPTHRU);
+ rSh.SelectionToHeaven();
+ }
+ else
+ {
+ SetWrapMode(FN_FRAME_WRAPTHRU_TRANSP);
+ rSh.SelectionToHell();
+ }
+ rSh.EndUndo( SwUndoId::END );
+ rBnd.Invalidate( SID_OBJECT_HELL );
+ rBnd.Invalidate( SID_OBJECT_HEAVEN );
+ }
+ break;
+
+ case SID_FLIP_VERTICAL:
+ bMirror = false;
+ [[fallthrough]];
+ case SID_FLIP_HORIZONTAL:
+ rSh.MirrorSelection( bMirror );
+ break;
+
+ case SID_FONTWORK:
+ {
+ FieldUnit eMetric = ::GetDfltMetric( dynamic_cast<SwWebView*>( &rSh.GetView()) != nullptr );
+ SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)) );
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+ if (pArgs)
+ {
+ rVFrame.SetChildWindow(SvxFontWorkChildWindow::GetChildWindowId(),
+ static_cast<const SfxBoolItem&>((pArgs->Get(SID_FONTWORK))).GetValue());
+ }
+ else
+ rVFrame.ToggleChildWindow( SvxFontWorkChildWindow::GetChildWindowId() );
+ rVFrame.GetBindings().Invalidate(SID_FONTWORK);
+ }
+ break;
+ case FN_FORMAT_FOOTNOTE_DLG:
+ {
+ GetView().ExecFormatFootnote();
+ break;
+ }
+ case FN_NUMBERING_OUTLINE_DLG:
+ {
+ GetView().ExecNumberingOutline(GetPool());
+ rReq.Done();
+ }
+ break;
+ case SID_OPEN_XML_FILTERSETTINGS:
+ {
+ HandleOpenXmlFilterSettings(rReq);
+ }
+ break;
+ case FN_WORDCOUNT_DIALOG:
+ {
+ GetView().UpdateWordCount(this, nSlotId);
+ }
+ break;
+ case SID_EXTRUSION_TOGGLE:
+ case SID_EXTRUSION_TILT_DOWN:
+ case SID_EXTRUSION_TILT_UP:
+ case SID_EXTRUSION_TILT_LEFT:
+ case SID_EXTRUSION_TILT_RIGHT:
+ case SID_EXTRUSION_3D_COLOR:
+ case SID_EXTRUSION_DEPTH:
+ case SID_EXTRUSION_DIRECTION:
+ case SID_EXTRUSION_PROJECTION:
+ case SID_EXTRUSION_LIGHTING_DIRECTION:
+ case SID_EXTRUSION_LIGHTING_INTENSITY:
+ case SID_EXTRUSION_SURFACE:
+ case SID_EXTRUSION_DEPTH_FLOATER:
+ case SID_EXTRUSION_DIRECTION_FLOATER:
+ case SID_EXTRUSION_LIGHTING_FLOATER:
+ case SID_EXTRUSION_SURFACE_FLOATER:
+ case SID_EXTRUSION_DEPTH_DIALOG:
+ svx::ExtrusionBar::execute( pSdrView, rReq, rBnd );
+ rReq.Ignore ();
+ break;
+
+ case SID_FONTWORK_SHAPE:
+ case SID_FONTWORK_SHAPE_TYPE:
+ case SID_FONTWORK_ALIGNMENT:
+ case SID_FONTWORK_SAME_LETTER_HEIGHTS:
+ case SID_FONTWORK_CHARACTER_SPACING:
+ case SID_FONTWORK_KERN_CHARACTER_PAIRS:
+ case SID_FONTWORK_CHARACTER_SPACING_FLOATER:
+ case SID_FONTWORK_ALIGNMENT_FLOATER:
+ case SID_FONTWORK_CHARACTER_SPACING_DIALOG:
+ svx::FontworkBar::execute(*pSdrView, rReq, rBnd);
+ rReq.Ignore ();
+ break;
+
+ case SID_INSERT_GRAPHIC:
+ {
+ // #i123922# check if we can do something
+ SdrObject* pObj = IsSingleFillableNonOLESelected();
+
+ if(pObj)
+ {
+ // ...and if yes, do something
+ InsertPictureFromFile(*pObj);
+ }
+
+ break;
+ }
+
+ case FN_ADD_TEXT_BOX:
+ {
+ if (SdrObject* pObj = IsSingleFillableNonOLESelected())
+ {
+ SwFrameFormat* pFrameFormat = ::FindFrameFormat(pObj);
+ if (pFrameFormat)
+ SwTextBoxHelper::create(pFrameFormat, pObj, pObj->HasText());
+ }
+ break;
+ }
+ case FN_REMOVE_TEXT_BOX:
+ {
+ if (SdrObject* pObj = IsSingleFillableNonOLESelected())
+ {
+ SwFrameFormat* pFrameFormat = ::FindFrameFormat(pObj);
+ if (pFrameFormat)
+ SwTextBoxHelper::destroy(pFrameFormat, pObj);
+ }
+ break;
+ }
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ return;
+ }
+ if (pSdrView->GetModel().IsChanged())
+ rSh.SetModified();
+ else if (bChanged)
+ pSdrView->GetModel().SetChanged();
+}
+
+void SwDrawShell::GetState(SfxItemSet& rSet)
+{
+ SwWrtShell &rSh = GetShell();
+ SdrView* pSdrView = rSh.GetDrawViewWithValidMarkList();
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ bool bProtected = rSh.IsSelObjProtected(FlyProtectFlags::Content) != FlyProtectFlags::NONE;
+
+ if (!bProtected) // Check the parent
+ bProtected |= rSh.IsSelObjProtected( FlyProtectFlags::Content|FlyProtectFlags::Parent ) != FlyProtectFlags::NONE;
+
+ while( nWhich )
+ {
+ switch( nWhich )
+ {
+ case SID_OBJECT_HELL:
+ if ( !rSh.IsObjSelected() || rSh.GetLayerId() == SdrLayerID(0) || bProtected )
+ rSet.DisableItem( nWhich );
+ break;
+
+ case SID_OBJECT_HEAVEN:
+ if ( !rSh.IsObjSelected() || rSh.GetLayerId() == SdrLayerID(1) || bProtected )
+ rSet.DisableItem( nWhich );
+ break;
+
+ case FN_TOOL_HIERARCHIE:
+ if ( !rSh.IsObjSelected() || bProtected )
+ rSet.DisableItem( nWhich );
+ break;
+
+ case SID_OBJECT_ROTATE:
+ {
+ const bool bIsRotate = GetView().IsDrawRotate();
+ if ( (!bIsRotate && !pSdrView->IsRotateAllowed()) || bProtected )
+ rSet.DisableItem( nWhich );
+ else
+ rSet.Put( SfxBoolItem( nWhich, bIsRotate ) );
+ }
+ break;
+
+ case SID_BEZIER_EDIT:
+ if (!Disable(rSet, nWhich))
+ rSet.Put( SfxBoolItem( nWhich, !GetView().IsDrawSelMode()));
+ break;
+
+ case SID_FLIP_VERTICAL:
+ if ( !pSdrView->IsMirrorAllowed() || bProtected )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ else
+ {
+ // TTTT - needs to be adapted in aw080:
+ // state is not kept for drawing objects --> provide not flipped state
+ rSet.Put( SfxBoolItem( nWhich, false ) );
+ }
+ break;
+
+ case SID_FLIP_HORIZONTAL:
+ if ( !pSdrView->IsMirrorAllowed() || bProtected )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ else
+ {
+ // TTTT - needs to be adapted in aw080:
+ // state is not kept for drawing objects --> provide not flipped state
+ rSet.Put( SfxBoolItem( nWhich, false ) );
+ }
+ break;
+
+ case SID_FONTWORK:
+ {
+ if (bProtected)
+ rSet.DisableItem( nWhich );
+ else
+ {
+ const sal_uInt16 nId = SvxFontWorkChildWindow::GetChildWindowId();
+ rSet.Put(SfxBoolItem( nWhich , GetView().GetViewFrame().HasChildWindow(nId)));
+ }
+ }
+ break;
+
+ case SID_INSERT_GRAPHIC:
+ {
+ // #i123922# check if we can do something
+ SdrObject* pObj = IsSingleFillableNonOLESelected();
+
+ if(!pObj)
+ {
+ rSet.DisableItem(nWhich);
+ }
+
+ break;
+ }
+ case FN_ADD_TEXT_BOX:
+ {
+ bool bDisable = true;
+ if (SdrObject* pObj = IsSingleFillableNonOLESelected())
+ {
+ SwFrameFormat* pFrameFormat = ::FindFrameFormat(pObj);
+ // Allow creating a TextBox only in case this is a draw format without a TextBox so far.
+ if (pFrameFormat && pFrameFormat->Which() == RES_DRAWFRMFMT && !SwTextBoxHelper::isTextBox(pFrameFormat, RES_DRAWFRMFMT, pObj))
+ {
+ if (SdrObjCustomShape* pCustomShape = dynamic_cast<SdrObjCustomShape*>( pObj) )
+ {
+ const SdrCustomShapeGeometryItem& rGeometryItem = pCustomShape->GetMergedItem(SDRATTR_CUSTOMSHAPE_GEOMETRY);
+ if (const uno::Any* pAny = rGeometryItem.GetPropertyValueByName("Type"))
+ // But still disallow fontwork shapes.
+ bDisable = pAny->get<OUString>().startsWith("fontwork-");
+ }
+ }
+ }
+
+ if (bDisable)
+ rSet.DisableItem(nWhich);
+ break;
+ }
+ case FN_REMOVE_TEXT_BOX:
+ {
+ bool bDisable = true;
+ if (SdrObject* pObj = IsSingleFillableNonOLESelected())
+ {
+ SwFrameFormat* pFrameFormat = ::FindFrameFormat(pObj);
+ // Allow removing a TextBox only in case it has one.
+ if (pFrameFormat && SwTextBoxHelper::isTextBox(pFrameFormat, RES_DRAWFRMFMT, pObj))
+ bDisable = false;
+ }
+
+ if (bDisable)
+ rSet.DisableItem(nWhich);
+ break;
+ }
+ }
+ nWhich = aIter.NextWhich();
+ }
+ svx::ExtrusionBar::getState( pSdrView, rSet );
+ svx::FontworkBar::getState( pSdrView, rSet );
+}
+
+SwDrawShell::SwDrawShell(SwView &_rView) :
+ SwDrawBaseShell(_rView)
+{
+ SetName("Draw");
+
+ vcl::EnumContext::Context eContext = vcl::EnumContext::Context::Draw;
+
+ SwWrtShell &rSh = GetShell();
+ SdrView* pDrView = rSh.GetDrawView();
+
+ if (pDrView && svx::checkForSelectedFontWork(pDrView))
+ eContext = vcl::EnumContext::Context::DrawFontwork;
+
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(eContext));
+}
+
+// Edit SfxRequests for FontWork
+
+void SwDrawShell::ExecFormText(SfxRequest const & rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ SdrView* pDrView = rSh.GetDrawView();
+ bool bChanged = pDrView->GetModel().IsChanged();
+ pDrView->GetModel().SetChanged(false);
+
+ const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
+
+ if ( rMarkList.GetMarkCount() == 1 && rReq.GetArgs() )
+ {
+ const SfxItemSet& rSet = *rReq.GetArgs();
+
+ if ( pDrView->IsTextEdit() )
+ {
+ pDrView->SdrEndTextEdit( true );
+ GetView().AttrChangedNotify(nullptr);
+ }
+
+ pDrView->SetAttributes(rSet);
+ }
+ if (pDrView->GetModel().IsChanged())
+ rSh.SetModified();
+ else
+ if (bChanged)
+ pDrView->GetModel().SetChanged();
+}
+
+//Return status values for FontWork
+
+void SwDrawShell::GetFormTextState(SfxItemSet& rSet)
+{
+ SwWrtShell &rSh = GetShell();
+ SdrView* pDrView = rSh.GetDrawView();
+ const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
+ const SdrObject* pObj = nullptr;
+
+ if ( rMarkList.GetMarkCount() == 1 )
+ pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+
+ const SdrTextObj* pTextObj = DynCastSdrTextObj(pObj);
+ const bool bDeactivate(
+ !pObj ||
+ !pTextObj ||
+ !pTextObj->HasText() ||
+ dynamic_cast< const SdrObjCustomShape* >(pObj)); // #121538# no FontWork for CustomShapes
+
+ if(bDeactivate)
+ {
+ rSet.DisableItem(XATTR_FORMTXTSTYLE);
+ rSet.DisableItem(XATTR_FORMTXTADJUST);
+ rSet.DisableItem(XATTR_FORMTXTDISTANCE);
+ rSet.DisableItem(XATTR_FORMTXTSTART);
+ rSet.DisableItem(XATTR_FORMTXTMIRROR);
+ rSet.DisableItem(XATTR_FORMTXTHIDEFORM);
+ rSet.DisableItem(XATTR_FORMTXTOUTLINE);
+ rSet.DisableItem(XATTR_FORMTXTSHADOW);
+ rSet.DisableItem(XATTR_FORMTXTSHDWCOLOR);
+ rSet.DisableItem(XATTR_FORMTXTSHDWXVAL);
+ rSet.DisableItem(XATTR_FORMTXTSHDWYVAL);
+ }
+ else
+ {
+ pDrView->GetAttributes( rSet );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/drformsh.cxx b/sw/source/uibase/shells/drformsh.cxx
new file mode 100644
index 0000000000..fcf2eab803
--- /dev/null
+++ b/sw/source/uibase/shells/drformsh.cxx
@@ -0,0 +1,251 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/hlnkitem.hxx>
+#include <svx/svdview.hxx>
+#include <svl/whiter.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/dispatch.hxx>
+#include <vcl/EnumContext.hxx>
+#include <svx/svdouno.hxx>
+#include <com/sun/star/form/FormButtonType.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <sfx2/htmlmode.hxx>
+#include <tools/urlobj.hxx>
+#include <osl/diagnose.h>
+
+#include <viewopt.hxx>
+#include <wrtsh.hxx>
+#include <cmdid.h>
+#include <drwbassh.hxx>
+#include <drformsh.hxx>
+#include <svl/urihelper.hxx>
+#include <view.hxx>
+#include <sfx2/docfile.hxx>
+#include <docsh.hxx>
+
+#define ShellClass_SwDrawFormShell
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+
+using namespace ::com::sun::star;
+
+SFX_IMPL_INTERFACE(SwDrawFormShell, SwDrawBaseShell)
+
+void SwDrawFormShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("form");
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Text_Toolbox_Sw);
+}
+
+
+void SwDrawFormShell::Execute(SfxRequest const &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ const SfxPoolItem* pItem = nullptr;
+ const SfxItemSet *pArgs = rReq.GetArgs();
+
+ switch ( rReq.GetSlot() )
+ {
+ case SID_HYPERLINK_SETLINK:
+ {
+ if(pArgs)
+ pArgs->GetItemState(SID_HYPERLINK_SETLINK, false, &pItem);
+ if(pItem)
+ {
+ SdrView *pSdrView = rSh.GetDrawView();
+ const SvxHyperlinkItem& rHLinkItem = *static_cast<const SvxHyperlinkItem *>(pItem);
+ bool bConvertToText = rHLinkItem.GetInsertMode() == HLINK_DEFAULT ||
+ rHLinkItem.GetInsertMode() == HLINK_FIELD;
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ if (rMarkList.GetMark(0))
+ {
+ SdrUnoObj* pUnoCtrl = dynamic_cast<SdrUnoObj*>( rMarkList.GetMark(0)->GetMarkedSdrObj() );
+ if (pUnoCtrl && SdrInventor::FmForm == pUnoCtrl->GetObjInventor())
+ {
+ if(bConvertToText)
+ {
+ //remove object -> results in destruction of this!
+ SwView& rTempView = GetView();
+ rTempView.GetViewFrame().GetDispatcher()->Execute(SID_DELETE, SfxCallMode::SYNCHRON );
+ rTempView.StopShellTimer();
+ //issue a new command to insert the link
+ rTempView.GetViewFrame().GetDispatcher()->ExecuteList(
+ SID_HYPERLINK_SETLINK, SfxCallMode::ASYNCHRON,
+ { &rHLinkItem });
+ }
+ else
+ {
+ const uno::Reference< awt::XControlModel >& xControlModel = pUnoCtrl->GetUnoControlModel();
+
+ OSL_ENSURE( xControlModel.is(), "UNO-Control without Model" );
+ if( !xControlModel.is() )
+ return;
+
+ uno::Reference< beans::XPropertySet > xPropSet(xControlModel, uno::UNO_QUERY);
+
+ // Can we set a URL to the object?
+ OUString sTargetURL( "TargetURL" );
+ uno::Reference< beans::XPropertySetInfo > xPropInfoSet = xPropSet->getPropertySetInfo();
+ if( xPropInfoSet->hasPropertyByName( sTargetURL ))
+ {
+ beans::Property aProp = xPropInfoSet->getPropertyByName( sTargetURL );
+ if( !aProp.Name.isEmpty() )
+ {
+ uno::Any aTmp;
+ // Yes!
+ OUString sLabel("Label");
+ if( xPropInfoSet->hasPropertyByName(sLabel) )
+ {
+ aTmp <<= rHLinkItem.GetName();
+ xPropSet->setPropertyValue(sLabel, aTmp );
+ }
+
+ SfxMedium* pMedium = GetView().GetDocShell()->GetMedium();
+ INetURLObject aAbs;
+ if( pMedium )
+ aAbs = pMedium->GetURLObject();
+ aTmp <<= URIHelper::SmartRel2Abs(aAbs, rHLinkItem.GetURL());
+ xPropSet->setPropertyValue( sTargetURL, aTmp );
+
+ if( !rHLinkItem.GetTargetFrame().isEmpty() )
+ {
+ aTmp <<= rHLinkItem.GetTargetFrame();
+ xPropSet->setPropertyValue( "TargetFrame", aTmp );
+ }
+
+ aTmp <<= form::FormButtonType_URL;
+ xPropSet->setPropertyValue( "ButtonType", aTmp );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ return;
+ }
+}
+
+void SwDrawFormShell::GetState(SfxItemSet& rSet)
+{
+ SwWrtShell &rSh = GetShell();
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while( nWhich )
+ {
+ switch( nWhich )
+ {
+ case SID_HYPERLINK_GETLINK:
+ {
+ SdrView* pSdrView = rSh.GetDrawViewWithValidMarkList();
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ SvxHyperlinkItem aHLinkItem;
+ if (rMarkList.GetMark(0))
+ {
+ SdrUnoObj* pUnoCtrl = dynamic_cast<SdrUnoObj*>( rMarkList.GetMark(0)->GetMarkedSdrObj() );
+ if (pUnoCtrl && SdrInventor::FmForm == pUnoCtrl->GetObjInventor())
+ {
+ const uno::Reference< awt::XControlModel >& xControlModel = pUnoCtrl->GetUnoControlModel();
+
+ OSL_ENSURE( xControlModel.is(), "UNO-Control without Model" );
+ if( !xControlModel.is() )
+ return;
+
+ uno::Reference< beans::XPropertySet > xPropSet(xControlModel, uno::UNO_QUERY);
+
+ uno::Any aTmp;
+ uno::Reference< beans::XPropertySetInfo > xInfo = xPropSet->getPropertySetInfo();
+ if(xInfo->hasPropertyByName( "ButtonType" ))
+ {
+ form::FormButtonType eButtonType = form::FormButtonType_URL;
+ aTmp = xPropSet->getPropertyValue( "ButtonType" );
+ if( aTmp >>= eButtonType )
+ {
+ // Label
+ if(xInfo->hasPropertyByName( "Label" ))
+ {
+ aTmp = xPropSet->getPropertyValue( "Label" );
+ OUString sTmp;
+ if( (aTmp >>= sTmp) && !sTmp.isEmpty())
+ {
+ aHLinkItem.SetName(sTmp);
+ }
+ }
+
+ // URL
+ if(xInfo->hasPropertyByName( "TargetURL" ))
+ {
+ aTmp = xPropSet->getPropertyValue( "TargetURL" );
+ OUString sTmp;
+ if( (aTmp >>= sTmp) && !sTmp.isEmpty())
+ {
+ aHLinkItem.SetURL(sTmp);
+ }
+ }
+
+ // Target
+ if(xInfo->hasPropertyByName( "TargetFrame" ))
+ {
+ aTmp = xPropSet->getPropertyValue( "TargetFrame" );
+ OUString sTmp;
+ if( (aTmp >>= sTmp) && !sTmp.isEmpty())
+ {
+ aHLinkItem.SetTargetFrame(sTmp);
+ }
+ }
+ aHLinkItem.SetInsertMode(HLINK_BUTTON);
+ }
+ }
+ }
+ }
+ sal_uInt16 nHtmlMode = ::GetHtmlMode(GetView().GetDocShell());
+ aHLinkItem.SetInsertMode(static_cast<SvxLinkInsertMode>(aHLinkItem.GetInsertMode() |
+ ((nHtmlMode & HTMLMODE_ON) != 0 ? HLINK_HTMLMODE : 0)));
+
+ rSet.Put(aHLinkItem);
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+SwDrawFormShell::SwDrawFormShell(SwView &_rView) :
+ SwDrawBaseShell(_rView)
+{
+ GetShell().NoEdit();
+ SetName("DrawForm");
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Form));
+}
+
+SwDrawFormShell::~SwDrawFormShell()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/drwbassh.cxx b/sw/source/uibase/shells/drwbassh.cxx
new file mode 100644
index 0000000000..a5a63a6634
--- /dev/null
+++ b/sw/source/uibase/shells/drwbassh.cxx
@@ -0,0 +1,1245 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+#include <swtypes.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svx/svdview.hxx>
+#include <svl/whiter.hxx>
+#include <svx/swframevalidation.hxx>
+#include <svx/anchorid.hxx>
+#include <svx/hlnkitem.hxx>
+#include <osl/diagnose.h>
+#include <drawdoc.hxx>
+#include <uitool.hxx>
+#include <fmtornt.hxx>
+#include <cmdid.h>
+#include <swmodule.hxx>
+#include <wrtsh.hxx>
+#include <wview.hxx>
+#include <edtwin.hxx>
+#include <viewopt.hxx>
+#include <dcontact.hxx>
+#include <frmfmt.hxx>
+#include <drawbase.hxx>
+#include <drwbassh.hxx>
+#include <swdtflvr.hxx>
+#include <svx/svditer.hxx>
+#define ShellClass_SwDrawBaseShell
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+#include <svx/svxdlg.hxx>
+#include <svx/svdogrp.hxx>
+#include <vcl/unohelp2.hxx>
+#include <swabstdlg.hxx>
+#include <swundo.hxx>
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <com/sun/star/text/RelOrientation.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <fmtfollowtextflow.hxx>
+#include <textboxhelper.hxx>
+#include <svx/diagram/IDiagramHelper.hxx>
+
+using namespace ::com::sun::star;
+using namespace css::beans;
+using namespace css::drawing;
+using namespace css::uno;
+
+SFX_IMPL_SUPERCLASS_INTERFACE(SwDrawBaseShell, SwBaseShell)
+
+void SwDrawBaseShell::InitInterface_Impl()
+{
+}
+
+
+SwDrawBaseShell::SwDrawBaseShell(SwView &_rView)
+ : SwBaseShell(_rView)
+{
+ GetShell().NoEdit();
+
+ SwEditWin& rWin = GetView().GetEditWin();
+
+ rWin.SetBezierMode(SID_BEZIER_MOVE);
+
+ if ( !_rView.GetDrawFuncPtr() )
+ _rView.GetEditWin().StdDrawMode( SdrObjKind::NONE, true );
+
+ SwTransferable::CreateSelection( GetShell() );
+}
+
+SwDrawBaseShell::~SwDrawBaseShell()
+{
+ GetView().ExitDraw();
+ GetShell().Edit();
+ SwTransferable::ClearSelection( GetShell() );
+}
+
+void SwDrawBaseShell::Execute(SfxRequest const &rReq)
+{
+ SwWrtShell *pSh = &GetShell();
+ SdrView* pSdrView = pSh->GetDrawView();
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ sal_uInt16 nSlotId = rReq.GetSlot();
+ bool bChanged = pSdrView->GetModel().IsChanged();
+ pSdrView->GetModel().SetChanged(false);
+ const SfxPoolItem* pItem = nullptr;
+ if(pArgs)
+ pArgs->GetItemState(nSlotId, false, &pItem);
+
+ bool bAlignPossible = pSh->IsAlignPossible();
+
+ bool bTopParam = true, bBottomParam = true;
+ bool bDone = false;
+ SfxBindings& rBind = GetView().GetViewFrame().GetBindings();
+
+ switch (nSlotId)
+ {
+ case FN_DRAW_WRAP_DLG:
+ {
+ if(pSdrView->AreObjectsMarked())
+ {
+ if(!pArgs)
+ {
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ if( rMarkList.GetMark(0) != nullptr )
+ {
+ SfxItemSetFixed<
+ RES_LR_SPACE, RES_UL_SPACE,
+ RES_SURROUND, RES_SURROUND,
+ RES_ANCHOR, RES_ANCHOR,
+ RES_WRAP_INFLUENCE_ON_OBJPOS, RES_WRAP_INFLUENCE_ON_OBJPOS,
+ SID_HTML_MODE, SID_HTML_MODE,
+ FN_DRAW_WRAP_DLG, FN_DRAW_WRAP_DLG>
+ aSet( GetPool() );
+
+ aSet.Put(SfxBoolItem(SID_HTML_MODE,
+ 0 != ::GetHtmlMode(pSh->GetView().GetDocShell())));
+
+ aSet.Put(SfxInt16Item(FN_DRAW_WRAP_DLG, pSh->GetLayerId().get()));
+
+ pSh->GetObjAttr(aSet);
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateSwWrapDlg(GetView().GetFrameWeld(), aSet, pSh));
+
+ if (pDlg->Execute() == RET_OK)
+ {
+ const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
+ if(const SfxInt16Item* pWrapItem = pOutSet->GetItemIfSet(FN_DRAW_WRAP_DLG, false))
+ {
+ short nLayer = pWrapItem->GetValue();
+ if (nLayer == 1)
+ pSh->SelectionToHeaven();
+ else
+ pSh->SelectionToHell();
+ }
+
+ pSh->SetObjAttr(*pOutSet);
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case SID_ATTR_TRANSFORM:
+ {
+ if(pSdrView->AreObjectsMarked())
+ {
+ if(!pArgs)
+ {
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ if( rMarkList.GetMark(0) != nullptr )
+ {
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ VclPtr<SfxAbstractTabDialog> pDlg;
+ bool bCaption = false;
+
+ // Allowed anchorages:
+ RndStdIds nAnchor = pSh->GetAnchorId();
+ SvxAnchorIds nAllowedAnchors = SvxAnchorIds::Paragraph | SvxAnchorIds::Character | SvxAnchorIds::Page;
+ sal_uInt16 nHtmlMode = ::GetHtmlMode(pSh->GetView().GetDocShell());
+
+ if ( pSh->IsFlyInFly() )
+ nAllowedAnchors |= SvxAnchorIds::Fly;
+
+ if (pObj->GetObjIdentifier() == SdrObjKind::Caption )
+ bCaption = true;
+
+ if (bCaption)
+ {
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ VclPtr<AbstractSvxCaptionDialog> pCaptionDlg =
+ pFact->CreateCaptionDialog( rReq.GetFrameWeld(), pSdrView, nAllowedAnchors );
+ pDlg.reset(pCaptionDlg);
+ pCaptionDlg->SetValidateFramePosLink( LINK(this, SwDrawBaseShell, ValidatePosition) );
+ }
+ else
+ {
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ VclPtr<AbstractSvxTransformTabDialog> pTransform =
+ pFact->CreateSvxTransformTabDialog(rReq.GetFrameWeld(), nullptr, pSdrView, nAllowedAnchors);
+ pDlg.reset(pTransform);
+ pTransform->SetValidateFramePosLink( LINK(this, SwDrawBaseShell, ValidatePosition) );
+ }
+ SfxItemSet aNewAttr(pSdrView->GetGeoAttrFromMarked());
+
+ const WhichRangesContainer& pRange = pDlg->GetInputRanges( *aNewAttr.GetPool() );
+ SfxItemSet aSet( *aNewAttr.GetPool(), pRange );
+ FieldUnit eMetric = ::GetDfltMetric( dynamic_cast<SwWebView*>(&GetView()) != nullptr );
+ SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)) );
+
+ aSet.Put( aNewAttr, false );
+
+ if (bCaption)
+ pSdrView->GetAttributes( aSet );
+
+ aSet.Put(SfxInt16Item(SID_ATTR_TRANSFORM_ANCHOR, static_cast<sal_Int16>(nAnchor)));
+ bool bRTL;
+ bool bVertL2R;
+ aSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_IN_VERTICAL_TEXT, pSh->IsFrameVertical(true, bRTL, bVertL2R)));
+ aSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_IN_RTL_TEXT, bRTL));
+
+ SwFrameFormat* pFrameFormat = FindFrameFormat( pObj );
+
+ aSet.Put( pFrameFormat->GetFormatAttr(RES_FOLLOW_TEXT_FLOW) );
+
+ SwFormatVertOrient aVOrient(pFrameFormat->GetFormatAttr(RES_VERT_ORIENT));
+ aSet.Put(SfxInt16Item(SID_ATTR_TRANSFORM_VERT_ORIENT, aVOrient.GetVertOrient()));
+ aSet.Put(SfxInt16Item(SID_ATTR_TRANSFORM_VERT_RELATION, aVOrient.GetRelationOrient() ));
+ aSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_VERT_POSITION, aVOrient.GetPos()));
+
+ SwFormatHoriOrient aHOrient(pFrameFormat->GetFormatAttr(RES_HORI_ORIENT));
+ aSet.Put(SfxInt16Item(SID_ATTR_TRANSFORM_HORI_ORIENT, aHOrient.GetHoriOrient()));
+ aSet.Put(SfxInt16Item(SID_ATTR_TRANSFORM_HORI_RELATION, aHOrient.GetRelationOrient() ));
+ aSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_HORI_MIRROR, aHOrient.IsPosToggle()));
+ aSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_HORI_POSITION, aHOrient.GetPos()));
+
+ aSet.Put(SfxUInt16Item(SID_HTML_MODE, nHtmlMode));
+
+ pDlg->SetInputSet( &aSet );
+
+ pDlg->StartExecuteAsync([bCaption, bChanged, pDlg, pFrameFormat, pSdrView,
+ pSh, &rMarkList, this](
+ sal_Int32 nResult){
+ pSdrView->GetModel().SetChanged(false);
+
+ if (nResult == RET_OK)
+ {
+ SwFormatVertOrient aVOrientFinal(pFrameFormat->GetFormatAttr(RES_VERT_ORIENT));
+ SwFormatHoriOrient aHOrientFinal(pFrameFormat->GetFormatAttr(RES_HORI_ORIENT));
+
+ const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
+ pSh->StartAllAction();
+
+ // #i30451#
+ pSh->StartUndo(SwUndoId::INSFMTATTR);
+
+ pSdrView->SetGeoAttrToMarked(*pOutSet);
+
+ if (bCaption)
+ pSdrView->SetAttributes(*pOutSet);
+
+ bool bPosCorr =
+ SfxItemState::SET != pOutSet->GetItemState(
+ SID_ATTR_TRANSFORM_POS_X, false ) &&
+ SfxItemState::SET != pOutSet->GetItemState(
+ SID_ATTR_TRANSFORM_POS_Y, false );
+
+ SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END - 1> aFrameAttrSet(GetPool());
+
+ bool bSingleSelection = rMarkList.GetMarkCount() == 1;
+
+ if(const SfxInt16Item* pAnchorItem = pOutSet->GetItemIfSet(
+ SID_ATTR_TRANSFORM_ANCHOR, false))
+ {
+ if(!bSingleSelection)
+ pSh->ChgAnchor(static_cast<RndStdIds>(pAnchorItem
+ ->GetValue()), false, bPosCorr );
+ else
+ {
+ SwFormatAnchor aAnchor(pFrameFormat->GetAnchor());
+ aAnchor.SetType(static_cast<RndStdIds>(pAnchorItem->GetValue()));
+ aFrameAttrSet.Put( aAnchor );
+ }
+ }
+ const SfxInt16Item* pHoriOrient =
+ pOutSet->GetItemIfSet(SID_ATTR_TRANSFORM_HORI_ORIENT, false);
+ const SfxInt16Item* pHoriRelation =
+ pOutSet->GetItemIfSet(SID_ATTR_TRANSFORM_HORI_RELATION, false);
+ const SfxInt32Item* pHoriPosition =
+ pOutSet->GetItemIfSet(SID_ATTR_TRANSFORM_HORI_POSITION, false);
+ const SfxBoolItem* pHoriMirror =
+ pOutSet->GetItemIfSet(SID_ATTR_TRANSFORM_HORI_MIRROR, false);
+ if(pHoriOrient || pHoriRelation || pHoriPosition || pHoriMirror)
+ {
+ if(pHoriOrient)
+ aHOrientFinal.SetHoriOrient(pHoriOrient->GetValue());
+ if(pHoriRelation)
+ aHOrientFinal.SetRelationOrient(pHoriRelation->GetValue());
+ if(pHoriPosition)
+ aHOrientFinal.SetPos( pHoriPosition->GetValue());
+ if(pHoriMirror)
+ aHOrientFinal.SetPosToggle( pHoriMirror->GetValue());
+ aFrameAttrSet.Put(aHOrientFinal);
+ }
+
+ const SfxInt16Item* pVertOrient =
+ pOutSet->GetItemIfSet(SID_ATTR_TRANSFORM_VERT_ORIENT, false);
+ const SfxInt16Item* pVertRelation =
+ pOutSet->GetItemIfSet(SID_ATTR_TRANSFORM_VERT_RELATION, false);
+ const SfxInt32Item* pVertPosition =
+ pOutSet->GetItemIfSet(SID_ATTR_TRANSFORM_VERT_POSITION, false);
+ if(pVertOrient || pVertRelation || pVertPosition )
+ {
+ if(pVertOrient)
+ aVOrientFinal.SetVertOrient(pVertOrient->GetValue());
+ if(pVertRelation)
+ aVOrientFinal.SetRelationOrient(pVertRelation->GetValue());
+ if(pVertPosition)
+ aVOrientFinal.SetPos( pVertPosition->GetValue());
+ aFrameAttrSet.Put( aVOrientFinal );
+ }
+ const SwFormatFollowTextFlow* pFollowItem =
+ pOutSet->GetItemIfSet(RES_FOLLOW_TEXT_FLOW, false);
+ if(pFollowItem)
+ aFrameAttrSet.Put(*pFollowItem);
+
+ if(aFrameAttrSet.Count())
+ pSh->SetDrawingAttr(aFrameAttrSet);
+
+ GetView().GetViewFrame().GetBindings().InvalidateAll(false);
+
+ // #i30451#
+ pSh->EndUndo( SwUndoId::INSFMTATTR );
+
+ pSh->EndAllAction();
+ }
+
+ if (pSdrView->GetModel().IsChanged())
+ pSh->SetModified();
+ else if (bChanged)
+ pSdrView->GetModel().SetChanged();
+
+ pDlg->disposeOnce();
+ });
+ }
+ }
+ else
+ {
+ pSh->StartAllAction();
+ pSdrView->SetGeoAttrToMarked( *pArgs );
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ if (pObj)
+ {
+ SwFrameFormat* pFrameFormat = FindFrameFormat(pObj);
+ if (pFrameFormat)
+ {
+ const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
+ // Don't change shape position / size, just update the anchor doc model
+ // position.
+ pSh->ChgAnchor(rAnchor.GetAnchorId(), /*bSameOnly=*/true);
+ }
+ }
+ pSh->EndAllAction();
+ }
+ }
+ }
+ break;
+
+ case SID_DELETE:
+ case FN_BACKSPACE:
+ if (pSh->IsObjSelected() && !pSdrView->IsTextEdit())
+ {
+ bDone = true;
+
+ const Point aPt = pSh->GetObjRect().TopLeft(); // tdf#150589
+
+ if( GetView().IsDrawRotate() )
+ {
+ pSh->SetDragMode( SdrDragMode::Move );
+ GetView().FlipDrawRotate();
+ }
+
+ pSh->SetModified();
+ pSh->DelSelectedObj();
+
+ if (rReq.IsAPI() ||
+ GetView().GetEditWin().IsObjectSelect() )
+ {
+ // If basic call, then back to the text shell, because the
+ // Basic otherwise has no possibility to return.
+ if (GetView().GetDrawFuncPtr())
+ {
+ GetView().GetDrawFuncPtr()->Deactivate();
+ GetView().SetDrawFuncPtr(nullptr);
+ }
+ GetView().LeaveDrawCreate(); // Switch to selection mode
+ }
+
+ if (pSh->IsSelFrameMode())
+ {
+ pSh->LeaveSelFrameMode();
+ // #105852# FME <- perhaps fixed by tdf#150589
+ static_cast<SwEditShell*>(pSh)->SetCursor(aPt);
+ }
+
+ }
+ break;
+
+ case SID_GROUP:
+ if (pSh->IsObjSelected() > 1 && pSh->IsGroupAllowed())
+ {
+ pSh->GroupSelection();
+ rBind.Invalidate(SID_UNGROUP);
+ }
+ break;
+
+ case SID_UNGROUP:
+ if (pSh->IsGroupSelected(true) && pSh->IsUnGroupAllowed())
+ {
+ pSh->UnGroupSelection();
+ rBind.Invalidate(SID_GROUP);
+ }
+ break;
+
+ case SID_ENTER_GROUP:
+ if (pSh->IsGroupSelected(false))
+ {
+ pSdrView->EnterMarkedGroup();
+ rBind.InvalidateAll(false);
+ }
+ break;
+
+ case SID_LEAVE_GROUP:
+ if (pSdrView->IsGroupEntered())
+ {
+ pSdrView->LeaveOneGroup();
+ rBind.Invalidate(SID_ENTER_GROUP);
+ rBind.Invalidate(SID_UNGROUP);
+ }
+ break;
+
+ case SID_REGENERATE_DIAGRAM:
+ case SID_EDIT_DIAGRAM:
+ {
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+
+ if (1 == rMarkList.GetMarkCount())
+ {
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+
+ // Support advanced DiagramHelper
+ if(nullptr != pObj && pObj->isDiagram())
+ {
+ if(SID_REGENERATE_DIAGRAM == nSlotId)
+ {
+ pSdrView->UnmarkAll();
+ pObj->getDiagramHelper()->reLayout(*static_cast<SdrObjGroup*>(pObj));
+ pSdrView->MarkObj(pObj, pSdrView->GetSdrPageView());
+ }
+ else // SID_EDIT_DIAGRAM
+ {
+ VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg = pFact->CreateDiagramDialog(
+ GetView().GetFrameWeld(),
+ *static_cast<SdrObjGroup*>(pObj));
+ pDlg->Execute();
+ }
+ }
+ }
+ }
+ break;
+
+ case SID_OBJECT_ALIGN_LEFT:
+ case SID_OBJECT_ALIGN_CENTER:
+ case SID_OBJECT_ALIGN_RIGHT:
+ case SID_OBJECT_ALIGN_UP:
+ case SID_OBJECT_ALIGN_MIDDLE:
+ case SID_OBJECT_ALIGN_DOWN:
+ {
+ if ( bAlignPossible )
+ {
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ if (rMarkList.GetMarkCount() == 1
+ && !SwTextBoxHelper::hasTextFrame(rMarkList.GetMark(0)->GetMarkedSdrObj()))
+ {
+ sal_Int16 nHorizOrient = -1, nVertOrient = -1;
+
+ switch (nSlotId)
+ {
+ case SID_OBJECT_ALIGN_LEFT:
+ nHorizOrient = text::HoriOrientation::LEFT;
+ break;
+ case SID_OBJECT_ALIGN_CENTER:
+ nHorizOrient = text::HoriOrientation::CENTER;
+ break;
+ case SID_OBJECT_ALIGN_RIGHT:
+ nHorizOrient = text::HoriOrientation::RIGHT;
+ break;
+ case SID_OBJECT_ALIGN_UP:
+ nVertOrient = text::VertOrientation::TOP;
+ break;
+ case SID_OBJECT_ALIGN_MIDDLE:
+ nVertOrient = text::VertOrientation::CENTER;
+ break;
+ case SID_OBJECT_ALIGN_DOWN:
+ nVertOrient = text::VertOrientation::BOTTOM;
+ break;
+ default:
+ break;
+ }
+
+ if (nHorizOrient != -1)
+ {
+ pSh->StartAction();
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ SwFrameFormat* pFrameFormat = FindFrameFormat( pObj );
+ SwFormatHoriOrient aHOrient(pFrameFormat->GetFormatAttr(RES_HORI_ORIENT));
+ aHOrient.SetHoriOrient( nHorizOrient );
+ pFrameFormat->SetFormatAttr(aHOrient);
+ pSh->EndAction();
+ }
+
+ if (nVertOrient != -1)
+ {
+ pSh->StartAction();
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ SwFrameFormat* pFrameFormat = FindFrameFormat( pObj );
+ SwFormatVertOrient aVOrient(pFrameFormat->GetFormatAttr(RES_VERT_ORIENT));
+ aVOrient.SetVertOrient( nVertOrient );
+ pFrameFormat->SetFormatAttr(aVOrient);
+ pSh->EndAction();
+ }
+
+ break;
+ }
+
+ pSh->StartAction();
+ switch (nSlotId)
+ {
+ case SID_OBJECT_ALIGN_LEFT:
+ pSdrView->AlignMarkedObjects(SdrHorAlign::Left, SdrVertAlign::NONE);
+ break;
+ case SID_OBJECT_ALIGN_CENTER:
+ pSdrView->AlignMarkedObjects(SdrHorAlign::Center, SdrVertAlign::NONE);
+ break;
+ case SID_OBJECT_ALIGN_RIGHT:
+ pSdrView->AlignMarkedObjects(SdrHorAlign::Right, SdrVertAlign::NONE);
+ break;
+ case SID_OBJECT_ALIGN_UP:
+ pSdrView->AlignMarkedObjects(SdrHorAlign::NONE, SdrVertAlign::Top);
+ break;
+ case SID_OBJECT_ALIGN_MIDDLE:
+ pSdrView->AlignMarkedObjects(SdrHorAlign::NONE, SdrVertAlign::Center);
+ break;
+ case SID_OBJECT_ALIGN_DOWN:
+ pSdrView->AlignMarkedObjects(SdrHorAlign::NONE, SdrVertAlign::Bottom);
+ break;
+ }
+ pSh->EndAction();
+ }
+ }
+ break;
+
+ case FN_FRAME_UP:
+ bTopParam = false;
+ [[fallthrough]];
+ case SID_FRAME_TO_TOP:
+ pSh->SelectionToTop( bTopParam );
+ break;
+
+ case FN_FRAME_DOWN:
+ bBottomParam = false;
+ [[fallthrough]];
+ case SID_FRAME_TO_BOTTOM:
+ pSh->SelectionToBottom( bBottomParam );
+ break;
+
+ case FN_NAME_SHAPE:
+ {
+ bDone = true;
+
+ if(1 == pSdrView->GetMarkedObjectCount())
+ {
+ // #i68101#
+ SdrObject* pSelected = pSdrView->GetMarkedObjectByIndex(0);
+ OSL_ENSURE(pSelected, "DrawViewShell::FuTemp03: nMarkCount, but no object (!)");
+ OUString aName(pSelected->GetName());
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractSvxObjectNameDialog> pDlg(pFact->CreateSvxObjectNameDialog(GetView().GetFrameWeld(), aName));
+
+ pDlg->SetCheckNameHdl(LINK(this, SwDrawBaseShell, CheckGroupShapeNameHdl));
+
+ if(RET_OK == pDlg->Execute())
+ {
+ const OUString aOrigName = aName;
+ pDlg->GetName(aName);
+ pSelected->SetName(aName);
+ pSh->SetModified();
+
+ // update accessibility sidebar object name if we modify the object name on the navigator bar
+ if (!aName.isEmpty() && aOrigName != aName)
+ {
+ if (SwNode* pSwNode = FindFrameFormat(pSelected)->GetAnchor().GetAnchorNode())
+ pSwNode->resetAndQueueAccessibilityCheck(true);
+ }
+ }
+ }
+
+ break;
+ }
+
+ // #i68101#
+ case FN_TITLE_DESCRIPTION_SHAPE:
+ {
+ bDone = true;
+
+ if(1 == pSdrView->GetMarkedObjectCount())
+ {
+ SdrObject* pSelected = pSdrView->GetMarkedObjectByIndex(0);
+ OSL_ENSURE(pSelected, "DrawViewShell::FuTemp03: nMarkCount, but no object (!)");
+ OUString aTitle(pSelected->GetTitle());
+ OUString aDescription(pSelected->GetDescription());
+ bool isDecorative(pSelected->IsDecorative());
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractSvxObjectTitleDescDialog> pDlg(pFact->CreateSvxObjectTitleDescDialog(GetView().GetFrameWeld(),
+ aTitle, aDescription, isDecorative));
+
+ if(RET_OK == pDlg->Execute())
+ {
+ pDlg->GetTitle(aTitle);
+ pDlg->GetDescription(aDescription);
+ pDlg->IsDecorative(isDecorative);
+
+ pSelected->SetTitle(aTitle);
+ pSelected->SetDescription(aDescription);
+ pSelected->SetDecorative(isDecorative);
+
+ pSh->SetModified();
+ }
+ }
+
+ break;
+ }
+
+ case SID_OPEN_HYPERLINK:
+ {
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ LoadURL(GetShell(), pObj->getHyperlink(), LoadUrlFlags::NewView,
+ /*rTargetFrameName=*/OUString());
+ break;
+ }
+
+ case SID_EDIT_HYPERLINK:
+ case SID_HYPERLINK_DIALOG:
+ {
+ GetView().GetViewFrame().SetChildWindow(SID_HYPERLINK_DIALOG, true);
+ break;
+ }
+
+ case SID_HYPERLINK_SETLINK:
+ {
+ if(pItem)
+ {
+ const SvxHyperlinkItem& rHLinkItem = *static_cast<const SvxHyperlinkItem *>(pItem);
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ pObj->setHyperlink(rHLinkItem.GetURL());
+ }
+ break;
+ }
+
+ case SID_REMOVE_HYPERLINK:
+ {
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ pObj->setHyperlink(OUString());
+ break;
+ }
+
+ case SID_COPY_HYPERLINK_LOCATION:
+ {
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ uno::Reference<datatransfer::clipboard::XClipboard> xClipboard
+ = GetView().GetEditWin().GetClipboard();
+ vcl::unohelper::TextDataObject::CopyStringTo(pObj->getHyperlink(), xClipboard);
+ break;
+ }
+
+ default:
+ OSL_ENSURE(false, "wrong Dispatcher");
+ return;
+ }
+ if(!bDone)
+ {
+ if(nSlotId >= SID_OBJECT_ALIGN_LEFT && nSlotId <= SID_OBJECT_ALIGN_DOWN)
+ rBind.Invalidate(SID_ATTR_LONG_LRSPACE);
+ if (pSdrView->GetModel().IsChanged())
+ pSh->SetModified();
+ else if (bChanged)
+ pSdrView->GetModel().SetChanged();
+ }
+}
+
+// Checks whether a given name is allowed for a group shape
+
+IMPL_LINK( SwDrawBaseShell, CheckGroupShapeNameHdl, AbstractSvxObjectNameDialog&, rNameDialog, bool )
+{
+ SwWrtShell &rSh = GetShell();
+ SdrView *pSdrView = rSh.GetDrawView();
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ OSL_ENSURE(rMarkList.GetMarkCount() == 1, "wrong draw selection");
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ const OUString sCurrentName = pObj->GetName();
+ OUString sNewName;
+ rNameDialog.GetName(sNewName);
+ bool bRet = false;
+ if (sNewName.isEmpty() || sCurrentName == sNewName)
+ bRet = true;
+ else
+ {
+ bRet = true;
+ SwDrawModel* pModel = rSh.getIDocumentDrawModelAccess().GetDrawModel();
+ SdrObjListIter aIter( pModel->GetPage(0), SdrIterMode::DeepWithGroups );
+ while( aIter.IsMore() )
+ {
+ SdrObject* pTempObj = aIter.Next();
+ if ( pObj != pTempObj && pTempObj->GetName() == sNewName )
+ {
+ bRet = false;
+ break;
+ }
+ }
+ }
+ return bRet;
+}
+
+void SwDrawBaseShell::GetState(SfxItemSet& rSet)
+{
+ SwWrtShell &rSh = GetShell();
+ SdrView* pSdrView = rSh.GetDrawViewWithValidMarkList();
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ bool bProtected = rSh.IsSelObjProtected(FlyProtectFlags::Content) != FlyProtectFlags::NONE;
+
+ if (!bProtected) // Look in the parent
+ bProtected |= rSh.IsSelObjProtected( FlyProtectFlags::Content|FlyProtectFlags::Parent ) != FlyProtectFlags::NONE;
+
+ while( nWhich )
+ {
+ switch( nWhich )
+ {
+ case FN_DRAW_WRAP_DLG:
+ case SID_ATTR_TRANSFORM:
+ case SID_FRAME_TO_TOP:
+ case SID_FRAME_TO_BOTTOM:
+ case FN_FRAME_UP:
+ case FN_FRAME_DOWN:
+ case SID_DELETE:
+ case FN_BACKSPACE:
+ if( bProtected || !rSh.IsObjSelected() )
+ rSet.DisableItem( nWhich );
+ break;
+ case SID_GROUP:
+ if ( rSh.IsObjSelected() < 2 || bProtected || !rSh.IsGroupAllowed() )
+ rSet.DisableItem( nWhich );
+ break;
+ case SID_UNGROUP:
+ if ( !rSh.IsGroupSelected(true) || bProtected || !rSh.IsUnGroupAllowed() )
+ rSet.DisableItem( nWhich );
+ break;
+ case SID_ENTER_GROUP:
+ if ( !rSh.IsGroupSelected(false) )
+ rSet.DisableItem( nWhich );
+ break;
+ case SID_LEAVE_GROUP:
+ if ( !pSdrView->IsGroupEntered() )
+ rSet.DisableItem( nWhich );
+ break;
+ case SID_OBJECT_ALIGN_LEFT:
+ case SID_OBJECT_ALIGN_CENTER:
+ case SID_OBJECT_ALIGN_RIGHT:
+ case SID_OBJECT_ALIGN_UP:
+ case SID_OBJECT_ALIGN_MIDDLE:
+ case SID_OBJECT_ALIGN_DOWN:
+ case SID_OBJECT_ALIGN:
+ {
+ bool bDisableThis = false;
+ bool bDisableHoriz = false;
+ bool bHoriz = (nWhich == SID_OBJECT_ALIGN_LEFT || nWhich == SID_OBJECT_ALIGN_CENTER ||
+ nWhich == SID_OBJECT_ALIGN_RIGHT);
+ bool bVert = (nWhich == SID_OBJECT_ALIGN_UP || nWhich == SID_OBJECT_ALIGN_MIDDLE ||
+ nWhich == SID_OBJECT_ALIGN_DOWN);
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ if ( !rSh.IsAlignPossible() || bProtected )
+ {
+ bDisableThis = true;
+ rSet.DisableItem( nWhich );
+ }
+ else if ( rSh.GetAnchorId() == RndStdIds::FLY_AS_CHAR )
+ {
+ //if only one object is selected it can only be vertically
+ // aligned because it is character bound
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ bDisableHoriz = true;
+ rSet.DisableItem(SID_OBJECT_ALIGN_LEFT);
+ rSet.DisableItem(SID_OBJECT_ALIGN_CENTER);
+ rSet.DisableItem(SID_OBJECT_ALIGN_RIGHT);
+ }
+ }
+
+ if (bHoriz && !bDisableThis && !bDisableHoriz &&
+ rMarkList.GetMarkCount() == 1)
+ {
+ sal_Int16 nHoriOrient = -1;
+ switch(nWhich)
+ {
+ case SID_OBJECT_ALIGN_LEFT:
+ nHoriOrient = text::HoriOrientation::LEFT;
+ break;
+ case SID_OBJECT_ALIGN_CENTER:
+ nHoriOrient = text::HoriOrientation::CENTER;
+ break;
+ case SID_OBJECT_ALIGN_RIGHT:
+ nHoriOrient = text::HoriOrientation::RIGHT;
+ break;
+ default:
+ break;
+ }
+
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ SwFrameFormat* pFrameFormat = FindFrameFormat(pObj);
+ SwFormatHoriOrient aHOrient(pFrameFormat->GetFormatAttr(RES_HORI_ORIENT));
+ rSet.Put(SfxBoolItem(nWhich, aHOrient.GetHoriOrient() == nHoriOrient));
+ }
+
+ if (bVert && !bDisableThis && rMarkList.GetMarkCount() == 1)
+ {
+ sal_Int16 nVertOrient = -1;
+ switch(nWhich)
+ {
+ case SID_OBJECT_ALIGN_UP:
+ nVertOrient = text::VertOrientation::TOP;
+ break;
+ case SID_OBJECT_ALIGN_MIDDLE:
+ nVertOrient = text::VertOrientation::CENTER;
+ break;
+ case SID_OBJECT_ALIGN_DOWN:
+ nVertOrient = text::VertOrientation::BOTTOM;
+ break;
+ default:
+ break;
+ }
+
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ SwFrameFormat* pFrameFormat = FindFrameFormat(pObj);
+ SwFormatVertOrient aVOrient(pFrameFormat->GetFormatAttr(RES_VERT_ORIENT));
+ rSet.Put(SfxBoolItem(nWhich, aVOrient.GetVertOrient() == nVertOrient));
+ }
+ }
+ break;
+
+ case FN_NAME_SHAPE :
+ {
+ if(1 != pSdrView->GetMarkedObjectCount())
+ {
+ rSet.DisableItem( nWhich );
+ }
+ }
+ break;
+
+ // #i68101#
+ case FN_TITLE_DESCRIPTION_SHAPE:
+ {
+ const bool bIsWebView(nullptr != dynamic_cast<SwWebView*>(&GetView()));
+
+ if(!bIsWebView && 1 != pSdrView->GetMarkedObjectCount())
+ {
+ rSet.DisableItem( nWhich );
+ }
+ }
+ break;
+
+ case SID_OPEN_HYPERLINK:
+ case SID_EDIT_HYPERLINK:
+ case SID_HYPERLINK_DIALOG:
+ case SID_REMOVE_HYPERLINK:
+ case SID_COPY_HYPERLINK_LOCATION:
+ {
+ if (pSdrView->GetMarkedObjectCount() != 1)
+ {
+ rSet.DisableItem(nWhich);
+ break;
+ }
+
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ SdrObjKind nObjType = pObj->GetObjIdentifier();
+
+ // Only enable hyperlink for the following types
+ switch (nObjType)
+ {
+ case SdrObjKind::PathFill:
+ case SdrObjKind::CircleSection:
+ case SdrObjKind::Line:
+ case SdrObjKind::CustomShape:
+ case SdrObjKind::Text:
+ case SdrObjKind::Rectangle:
+ case SdrObjKind::Caption:
+ case SdrObjKind::Polygon:
+ case SdrObjKind::PolyLine:
+ case SdrObjKind::E3D_Scene:
+ case SdrObjKind::Measure:
+ case SdrObjKind::Edge:
+ break;
+ default:
+ rSet.DisableItem(nWhich);
+ break;
+ }
+
+ if (nWhich == SID_OPEN_HYPERLINK || nWhich == SID_REMOVE_HYPERLINK
+ || nWhich == SID_EDIT_HYPERLINK || nWhich == SID_COPY_HYPERLINK_LOCATION)
+ {
+ if (pObj->getHyperlink().isEmpty())
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+
+ case SID_HYPERLINK_GETLINK:
+ {
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ if (rMarkList.GetMark(0) != nullptr)
+ {
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ OUString sHyperLink = pObj->getHyperlink();
+ SvxHyperlinkItem aHLinkItem;
+ aHLinkItem.SetURL(sHyperLink);
+ rSet.Put(aHLinkItem);
+ }
+ }
+ break;
+
+ case SID_REGENERATE_DIAGRAM:
+ case SID_EDIT_DIAGRAM:
+ {
+ bool bDisable(true);
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ if (nullptr != rMarkList.GetMark(0))
+ {
+ SdrObject* pObj(rMarkList.GetMark(0)->GetMarkedSdrObj());
+
+ if(nullptr != pObj && pObj->isDiagram())
+ {
+ bDisable = false;
+ }
+ }
+
+ if(bDisable)
+ {
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+
+
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwDrawBaseShell::GetDrawAttrStateForIFBX( SfxItemSet& rSet )
+{
+ SwWrtShell *pSh = &GetShell();
+ SdrView* pSdrView = pSh->GetDrawView();
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ if( rMarkList.GetMark(0) != nullptr )
+ {
+ SfxItemSet aNewAttr(pSdrView->GetGeoAttrFromMarked());
+ rSet.Put(aNewAttr,false);
+ }
+}
+
+bool SwDrawBaseShell::Disable(SfxItemSet& rSet, sal_uInt16 nWhich)
+{
+ bool bDisable = GetShell().IsSelObjProtected(FlyProtectFlags::Content) != FlyProtectFlags::NONE;
+
+ if (bDisable)
+ {
+ if (nWhich)
+ rSet.DisableItem( nWhich );
+ else
+ {
+ SfxWhichIter aIter( rSet );
+ nWhich = aIter.FirstWhich();
+ while (nWhich)
+ {
+ rSet.DisableItem( nWhich );
+ nWhich = aIter.NextWhich();
+ }
+ }
+ }
+
+ return bDisable;
+}
+
+void SwDrawBaseShell::DisableState( SfxItemSet& rSet )
+{
+ SwWrtShell *pSh = &GetShell();
+ SdrView* pSdrView = pSh->GetDrawView();
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ const size_t nMarkCount = rMarkList.GetMarkCount();
+ bool bShowArea = true, bShowMeasure = true;
+
+ for (size_t i = 0; i < nMarkCount && i < 50; ++i)
+ {
+ SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
+ SdrObjKind nObjType = pObj->GetObjIdentifier();
+
+ if ( nObjType != SdrObjKind::Measure )
+ bShowMeasure = false;
+
+ // If marked object is 2D, disable format area command.
+ if ( nObjType == SdrObjKind::PolyLine ||
+ nObjType == SdrObjKind::Line ||
+ nObjType == SdrObjKind::PathLine ||
+ nObjType == SdrObjKind::FreehandLine ||
+ nObjType == SdrObjKind::Edge ||
+ nObjType == SdrObjKind::CircleArc ||
+ bShowMeasure )
+ bShowArea = false;
+
+ if (!bShowArea && !bShowMeasure)
+ break;
+ }
+
+ if (!bShowArea)
+ rSet.DisableItem(SID_ATTRIBUTES_AREA);
+
+ if (!bShowMeasure)
+ rSet.DisableItem(SID_MEASURE_DLG);
+
+ Disable(rSet);
+
+}
+
+// Validate of drawing positions
+
+IMPL_LINK(SwDrawBaseShell, ValidatePosition, SvxSwFrameValidation&, rValidation, void )
+{
+ SwWrtShell *pSh = &GetShell();
+ rValidation.nMinHeight = MINFLY;
+ rValidation.nMinWidth = MINFLY;
+
+ SwRect aBoundRect;
+
+ // OD 18.09.2003 #i18732# - adjustment for allowing vertical position
+ // aligned to page for fly frame anchored to paragraph or to character.
+ const RndStdIds eAnchorType = rValidation.nAnchorType;
+ const SwFormatAnchor* pAnchor = nullptr;
+ SdrView* pSdrView = pSh->GetDrawView();
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ SwFrameFormat* pFrameFormat = FindFrameFormat( pObj );
+ pAnchor = &pFrameFormat->GetAnchor();
+ }
+
+ pSh->CalcBoundRect( aBoundRect, eAnchorType,
+ rValidation.nHRelOrient,
+ rValidation.nVRelOrient,
+ pAnchor,
+ rValidation.bFollowTextFlow,
+ rValidation.bMirror, nullptr, &rValidation.aPercentSize);
+
+ bool bIsInVertical( false );
+ {
+ bool bRTL;
+ bool bVertL2R;
+ bIsInVertical = pSh->IsFrameVertical(true, bRTL, bVertL2R);
+ }
+ if(bIsInVertical)
+ {
+ Point aPos(aBoundRect.Pos());
+ tools::Long nTmp = aPos.X();
+ aPos.setX( aPos.Y() );
+ aPos.setY( nTmp );
+ Size aSize(aBoundRect.SSize());
+ nTmp = aSize.Width();
+ aSize.setWidth( aSize.Height() );
+ aSize.setHeight( nTmp );
+ aBoundRect.Chg( aPos, aSize );
+ //exchange width/height to enable correct values
+ nTmp = rValidation.nWidth;
+ rValidation.nWidth = rValidation.nHeight;
+ rValidation.nHeight = nTmp;
+ }
+ if ((eAnchorType == RndStdIds::FLY_AT_PAGE) || (eAnchorType == RndStdIds::FLY_AT_FLY))
+ {
+ // MinimalPosition
+ rValidation.nMinHPos = aBoundRect.Left();
+ rValidation.nMinVPos = aBoundRect.Top();
+ SwTwips nH = rValidation.nHPos;
+ SwTwips nV = rValidation.nVPos;
+
+ if (rValidation.nHPos + rValidation.nWidth > aBoundRect.Right())
+ {
+ if (rValidation.nHoriOrient == text::HoriOrientation::NONE)
+ {
+ rValidation.nHPos -= ((rValidation.nHPos + rValidation.nWidth) - aBoundRect.Right());
+ nH = rValidation.nHPos;
+ }
+ else
+ rValidation.nWidth = aBoundRect.Right() - rValidation.nHPos;
+ }
+
+ if (rValidation.nHPos + rValidation.nWidth > aBoundRect.Right())
+ rValidation.nWidth = aBoundRect.Right() - rValidation.nHPos;
+
+ if (rValidation.nVPos + rValidation.nHeight > aBoundRect.Bottom())
+ {
+ if (rValidation.nVertOrient == text::VertOrientation::NONE)
+ {
+ rValidation.nVPos -= ((rValidation.nVPos + rValidation.nHeight) - aBoundRect.Bottom());
+ nV = rValidation.nVPos;
+ }
+ else
+ rValidation.nHeight = aBoundRect.Bottom() - rValidation.nVPos;
+ }
+
+ if (rValidation.nVPos + rValidation.nHeight > aBoundRect.Bottom())
+ rValidation.nHeight = aBoundRect.Bottom() - rValidation.nVPos;
+
+ if ( rValidation.nVertOrient != text::VertOrientation::NONE )
+ nV = aBoundRect.Top();
+
+ if ( rValidation.nHoriOrient != text::HoriOrientation::NONE )
+ nH = aBoundRect.Left();
+
+ rValidation.nMaxHPos = aBoundRect.Right() - rValidation.nWidth;
+ rValidation.nMaxHeight = aBoundRect.Bottom() - nV;
+
+ rValidation.nMaxVPos = aBoundRect.Bottom() - rValidation.nHeight;
+ rValidation.nMaxWidth = aBoundRect.Right() - nH;
+ }
+ else if ((eAnchorType == RndStdIds::FLY_AT_PARA) || (eAnchorType == RndStdIds::FLY_AT_CHAR))
+ {
+ if (rValidation.nHPos + rValidation.nWidth > aBoundRect.Right())
+ {
+ if (rValidation.nHoriOrient == text::HoriOrientation::NONE)
+ {
+ rValidation.nHPos -= ((rValidation.nHPos + rValidation.nWidth) - aBoundRect.Right());
+ }
+ else
+ rValidation.nWidth = aBoundRect.Right() - rValidation.nHPos;
+ }
+
+ // OD 29.09.2003 #i17567#, #i18732# - consider following the text flow
+ // and alignment at page areas.
+ const bool bMaxVPosAtBottom = !rValidation.bFollowTextFlow ||
+ rValidation.nVRelOrient == text::RelOrientation::PAGE_FRAME ||
+ rValidation.nVRelOrient == text::RelOrientation::PAGE_PRINT_AREA ||
+ rValidation.nVRelOrient == text::RelOrientation::PAGE_PRINT_AREA_BOTTOM;
+ {
+ SwTwips nTmpMaxVPos = ( bMaxVPosAtBottom
+ ? aBoundRect.Bottom()
+ : aBoundRect.Height() ) -
+ rValidation.nHeight;
+ if ( rValidation.nVPos > nTmpMaxVPos )
+ {
+ if (rValidation.nVertOrient == text::VertOrientation::NONE)
+ {
+ rValidation.nVPos = nTmpMaxVPos;
+ }
+ else
+ {
+ rValidation.nHeight = ( bMaxVPosAtBottom
+ ? aBoundRect.Bottom()
+ : aBoundRect.Height() ) - rValidation.nVPos;
+ }
+ }
+ }
+
+ rValidation.nMinHPos = aBoundRect.Left();
+ rValidation.nMaxHPos = aBoundRect.Right() - rValidation.nWidth;
+
+ rValidation.nMinVPos = aBoundRect.Top();
+ // OD 26.09.2003 #i17567#, #i18732# - determine maximum vertical position
+ if ( bMaxVPosAtBottom )
+ {
+ rValidation.nMaxVPos = aBoundRect.Bottom() - rValidation.nHeight;
+ }
+ else
+ {
+ rValidation.nMaxVPos = aBoundRect.Height() - rValidation.nHeight;
+ }
+
+ // Maximum width height
+ const SwTwips nH = ( rValidation.nHoriOrient != text::HoriOrientation::NONE )
+ ? aBoundRect.Left()
+ : rValidation.nHPos;
+ const SwTwips nV = ( rValidation.nVertOrient != text::VertOrientation::NONE )
+ ? aBoundRect.Top()
+ : rValidation.nVPos;
+ rValidation.nMaxHeight = rValidation.nMaxVPos + rValidation.nHeight - nV;
+ rValidation.nMaxWidth = rValidation.nMaxHPos + rValidation.nWidth - nH;
+ }
+ else if (eAnchorType == RndStdIds::FLY_AS_CHAR)
+ {
+ rValidation.nMinHPos = 0;
+ rValidation.nMaxHPos = 0;
+
+ rValidation.nMaxHeight = aBoundRect.Height();
+ rValidation.nMaxWidth = aBoundRect.Width();
+
+ rValidation.nMaxVPos = aBoundRect.Height();
+ rValidation.nMinVPos = -aBoundRect.Height() + rValidation.nHeight;
+ if (rValidation.nMaxVPos < rValidation.nMinVPos)
+ {
+ rValidation.nMinVPos = rValidation.nMaxVPos;
+ rValidation.nMaxVPos = -aBoundRect.Height();
+ }
+ }
+ if(bIsInVertical)
+ {
+ //restore width/height exchange
+ tools::Long nTmp = rValidation.nWidth;
+ rValidation.nWidth = rValidation.nHeight;
+ rValidation.nHeight = nTmp;
+ }
+
+ if (rValidation.nMaxWidth < rValidation.nWidth)
+ rValidation.nWidth = rValidation.nMaxWidth;
+ if (rValidation.nMaxHeight < rValidation.nHeight)
+ rValidation.nHeight = rValidation.nMaxHeight;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/drwtxtex.cxx b/sw/source/uibase/shells/drwtxtex.cxx
new file mode 100644
index 0000000000..4d8dd6304e
--- /dev/null
+++ b/sw/source/uibase/shells/drwtxtex.cxx
@@ -0,0 +1,1241 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <com/sun/star/linguistic2/XThesaurus.hpp>
+
+#include <comphelper/string.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/request.hxx>
+#include <svx/svdview.hxx>
+#include <editeng/spltitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/orphitem.hxx>
+#include <editeng/formatbreakitem.hxx>
+#include <editeng/widwitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/escapementitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/flstitem.hxx>
+#include <editeng/adjustitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/urlfieldhelper.hxx>
+#include <svx/svdoutl.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/stritem.hxx>
+#include <svl/whiter.hxx>
+#include <svl/cjkoptions.hxx>
+#include <svl/ctloptions.hxx>
+#include <svl/languageoptions.hxx>
+#include <editeng/flditem.hxx>
+#include <editeng/editstat.hxx>
+#include <svx/clipfmtitem.hxx>
+#include <svx/hlnkitem.hxx>
+#include <svx/svxdlg.hxx>
+#include <sfx2/htmlmode.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <editeng/writingmodeitem.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/editdata.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/editview.hxx>
+#include <vcl/unohelp2.hxx>
+#include <editeng/hyphenzoneitem.hxx>
+#include <osl/diagnose.h>
+
+#include <cmdid.h>
+#include <doc.hxx>
+#include <drwtxtsh.hxx>
+#include <edtwin.hxx>
+#include <hintids.hxx>
+#include <langhelper.hxx>
+#include <chrdlgmodes.hxx>
+#include <swmodule.hxx>
+#include <uitool.hxx>
+#include <viewopt.hxx>
+#include <wrtsh.hxx>
+#include <wview.hxx>
+
+#include <swabstdlg.hxx>
+
+using namespace ::com::sun::star;
+
+void SwDrawTextShell::Execute( SfxRequest &rReq )
+{
+ SwWrtShell &rSh = GetShell();
+ OutlinerView* pOLV = m_pSdrView->GetTextEditOutlinerView();
+ SfxItemSet aEditAttr(pOLV->GetAttribs());
+ SfxItemSet aNewAttr(*aEditAttr.GetPool(), aEditAttr.GetRanges());
+
+ const sal_uInt16 nSlot = rReq.GetSlot();
+
+ const sal_uInt16 nWhich = GetPool().GetWhich(nSlot);
+ std::unique_ptr<SfxItemSet> pNewAttrs(rReq.GetArgs() ? rReq.GetArgs()->Clone() : nullptr);
+
+ bool bRestoreSelection = false;
+ ESelection aOldSelection;
+
+ sal_uInt16 nEEWhich = 0;
+ switch (nSlot)
+ {
+ case SID_LANGUAGE_STATUS:
+ {
+ aOldSelection = pOLV->GetSelection();
+ if (!pOLV->GetEditView().HasSelection())
+ {
+ pOLV->GetEditView().SelectCurrentWord();
+ }
+
+ bRestoreSelection = SwLangHelper::SetLanguageStatus(pOLV,rReq,GetView(),rSh);
+ break;
+ }
+
+ case SID_THES:
+ {
+ OUString aReplaceText;
+ const SfxStringItem* pItem2 = rReq.GetArg(FN_PARAM_THES_WORD_REPLACE);
+ if (pItem2)
+ aReplaceText = pItem2->GetValue();
+ if (!aReplaceText.isEmpty())
+ ReplaceTextWithSynonym( pOLV->GetEditView(), aReplaceText );
+ break;
+ }
+
+ case SID_ATTR_CHAR_FONT:
+ case SID_ATTR_CHAR_FONTHEIGHT:
+ case SID_ATTR_CHAR_WEIGHT:
+ case SID_ATTR_CHAR_POSTURE:
+ {
+ SfxItemPool* pPool2 = aEditAttr.GetPool()->GetSecondaryPool();
+ if( !pPool2 )
+ pPool2 = aEditAttr.GetPool();
+ SvxScriptSetItem aSetItem( nSlot, *pPool2 );
+
+ // #i78017 establish the same behaviour as in Writer
+ SvtScriptType nScriptTypes = SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX;
+ if (nSlot == SID_ATTR_CHAR_FONT)
+ nScriptTypes = pOLV->GetSelectedScriptType();
+
+ if (pNewAttrs)
+ {
+ aSetItem.PutItemForScriptType( nScriptTypes, pNewAttrs->Get( nWhich ) );
+ aNewAttr.Put( aSetItem.GetItemSet() );
+ }
+ }
+ break;
+
+ case SID_ATTR_CHAR_COLOR: nEEWhich = EE_CHAR_COLOR; break;
+ case SID_ATTR_CHAR_BACK_COLOR: nEEWhich = EE_CHAR_BKGCOLOR; break;
+
+ case SID_ATTR_CHAR_UNDERLINE:
+ {
+ if ( pNewAttrs )
+ {
+ const SvxTextLineItem& rTextLineItem = static_cast< const SvxTextLineItem& >( pNewAttrs->Get( pNewAttrs->GetPool()->GetWhich(nSlot) ) );
+ aNewAttr.Put( SvxUnderlineItem( rTextLineItem.GetLineStyle(), EE_CHAR_UNDERLINE ) );
+ }
+ else
+ {
+ FontLineStyle eFU = aEditAttr.Get(EE_CHAR_UNDERLINE).GetLineStyle();
+ aNewAttr.Put( SvxUnderlineItem(eFU == LINESTYLE_SINGLE ? LINESTYLE_NONE : LINESTYLE_SINGLE, EE_CHAR_UNDERLINE) );
+ }
+ }
+ break;
+
+ case SID_ATTR_CHAR_OVERLINE:
+ {
+ FontLineStyle eFO = aEditAttr.Get(EE_CHAR_OVERLINE).GetLineStyle();
+ aNewAttr.Put(SvxOverlineItem(eFO == LINESTYLE_SINGLE ? LINESTYLE_NONE : LINESTYLE_SINGLE, EE_CHAR_OVERLINE));
+ }
+ break;
+
+ case SID_ATTR_CHAR_CONTOUR: nEEWhich = EE_CHAR_OUTLINE; break;
+ case SID_ATTR_CHAR_SHADOWED: nEEWhich = EE_CHAR_SHADOW; break;
+ case SID_ATTR_CHAR_STRIKEOUT: nEEWhich = EE_CHAR_STRIKEOUT; break;
+ case SID_ATTR_CHAR_WORDLINEMODE: nEEWhich = EE_CHAR_WLM; break;
+ case SID_ATTR_CHAR_RELIEF : nEEWhich = EE_CHAR_RELIEF; break;
+ case SID_ATTR_CHAR_LANGUAGE : nEEWhich = EE_CHAR_LANGUAGE;break;
+ case SID_ATTR_CHAR_KERNING : nEEWhich = EE_CHAR_KERNING; break;
+ case SID_ATTR_CHAR_SCALEWIDTH: nEEWhich = EE_CHAR_FONTWIDTH; break;
+ case SID_ATTR_CHAR_AUTOKERN : nEEWhich = EE_CHAR_PAIRKERNING; break;
+ case SID_ATTR_CHAR_ESCAPEMENT: nEEWhich = EE_CHAR_ESCAPEMENT; break;
+ case SID_ATTR_PARA_ADJUST_LEFT:
+ aNewAttr.Put(SvxAdjustItem(SvxAdjust::Left, EE_PARA_JUST));
+ break;
+ case SID_ATTR_PARA_ADJUST_CENTER:
+ aNewAttr.Put(SvxAdjustItem(SvxAdjust::Center, EE_PARA_JUST));
+ break;
+ case SID_ATTR_PARA_ADJUST_RIGHT:
+ aNewAttr.Put(SvxAdjustItem(SvxAdjust::Right, EE_PARA_JUST));
+ break;
+ case SID_ATTR_PARA_ADJUST_BLOCK:
+ aNewAttr.Put(SvxAdjustItem(SvxAdjust::Block, EE_PARA_JUST));
+ break;
+ case SID_ATTR_PARA_LRSPACE:
+ {
+ SvxLRSpaceItem aParaMargin(static_cast<const SvxLRSpaceItem&>(rReq.
+ GetArgs()->Get(nSlot)));
+ aParaMargin.SetWhich( EE_PARA_LRSPACE );
+ aNewAttr.Put(aParaMargin);
+ rReq.Done();
+ }
+ break;
+ case SID_HANGING_INDENT:
+ {
+ SfxItemState eState = aEditAttr.GetItemState( EE_PARA_LRSPACE );
+ if( eState >= SfxItemState::DEFAULT )
+ {
+ SvxLRSpaceItem aParaMargin = aEditAttr.Get( EE_PARA_LRSPACE );
+ aParaMargin.SetWhich( EE_PARA_LRSPACE );
+ short int nFirstLineOffset = aParaMargin.GetTextFirstLineOffset();
+ aParaMargin.SetTextLeft( aParaMargin.GetTextLeft() + nFirstLineOffset );
+ aParaMargin.SetRight( aParaMargin.GetRight() );
+ aParaMargin.SetTextFirstLineOffset( nFirstLineOffset * -1 );
+ aNewAttr.Put(aParaMargin);
+ rReq.Done();
+ }
+ }
+ break;
+ case SID_ATTR_PARA_LINESPACE:
+ if (pNewAttrs)
+ {
+ SvxLineSpacingItem aLineSpace = static_cast<const SvxLineSpacingItem&>(pNewAttrs->Get(
+ GetPool().GetWhich(nSlot)));
+ aLineSpace.SetWhich( EE_PARA_SBL );
+ aNewAttr.Put( aLineSpace );
+ rReq.Done();
+ }
+ break;
+ case SID_ATTR_PARA_ULSPACE:
+ if (pNewAttrs)
+ {
+ SvxULSpaceItem aULSpace = static_cast<const SvxULSpaceItem&>(pNewAttrs->Get(
+ GetPool().GetWhich(nSlot)));
+ aULSpace.SetWhich( EE_PARA_ULSPACE );
+ aNewAttr.Put( aULSpace );
+ rReq.Done();
+ }
+ break;
+ case SID_PARASPACE_INCREASE:
+ case SID_PARASPACE_DECREASE:
+ {
+ SvxULSpaceItem aULSpace( aEditAttr.Get( EE_PARA_ULSPACE ) );
+ sal_uInt16 nUpper = aULSpace.GetUpper();
+ sal_uInt16 nLower = aULSpace.GetLower();
+
+ if ( nSlot == SID_PARASPACE_INCREASE )
+ {
+ nUpper = std::min< sal_uInt16 >( nUpper + 57, 5670 );
+ nLower = std::min< sal_uInt16 >( nLower + 57, 5670 );
+ }
+ else
+ {
+ nUpper = std::max< sal_Int16 >( nUpper - 57, 0 );
+ nLower = std::max< sal_Int16 >( nLower - 57, 0 );
+ }
+
+ aULSpace.SetUpper( nUpper );
+ aULSpace.SetLower( nLower );
+ aNewAttr.Put( aULSpace );
+ rReq.Done();
+ }
+ break;
+ case SID_ATTR_PARA_LINESPACE_10:
+ {
+ SvxLineSpacingItem aItem(LINE_SPACE_DEFAULT_HEIGHT, EE_PARA_SBL);
+ aItem.SetPropLineSpace(100);
+ aNewAttr.Put(aItem);
+ }
+ break;
+ case SID_ATTR_PARA_LINESPACE_115:
+ {
+ SvxLineSpacingItem aItem(LINE_SPACE_DEFAULT_HEIGHT, EE_PARA_SBL);
+ aItem.SetPropLineSpace(115);
+ aNewAttr.Put(aItem);
+ }
+ break;
+ case SID_ATTR_PARA_LINESPACE_15:
+ {
+ SvxLineSpacingItem aItem(LINE_SPACE_DEFAULT_HEIGHT, EE_PARA_SBL);
+ aItem.SetPropLineSpace(150);
+ aNewAttr.Put(aItem);
+ }
+ break;
+ case SID_ATTR_PARA_LINESPACE_20:
+ {
+ SvxLineSpacingItem aItem(LINE_SPACE_DEFAULT_HEIGHT, EE_PARA_SBL);
+ aItem.SetPropLineSpace(200);
+ aNewAttr.Put(aItem);
+ }
+ break;
+
+ case FN_SET_SUPER_SCRIPT:
+ {
+ SvxEscapementItem aItem(EE_CHAR_ESCAPEMENT);
+ SvxEscapement eEsc = static_cast<SvxEscapement>(aEditAttr.Get( EE_CHAR_ESCAPEMENT ).GetEnumValue());
+
+ if( eEsc == SvxEscapement::Superscript )
+ aItem.SetEscapement( SvxEscapement::Off );
+ else
+ aItem.SetEscapement( SvxEscapement::Superscript );
+ aNewAttr.Put( aItem );
+ }
+ break;
+ case FN_SET_SUB_SCRIPT:
+ {
+ SvxEscapementItem aItem(EE_CHAR_ESCAPEMENT);
+ SvxEscapement eEsc = static_cast<SvxEscapement>(aEditAttr.Get( EE_CHAR_ESCAPEMENT ).GetEnumValue());
+
+ if( eEsc == SvxEscapement::Subscript )
+ aItem.SetEscapement( SvxEscapement::Off );
+ else
+ aItem.SetEscapement( SvxEscapement::Subscript );
+ aNewAttr.Put( aItem );
+ }
+ break;
+
+ case SID_CHAR_DLG_EFFECT:
+ case SID_CHAR_DLG_POSITION:
+ case SID_CHAR_DLG:
+ case SID_CHAR_DLG_FOR_PARAGRAPH:
+ {
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxStringItem* pItem = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+
+ if( !pArgs || pItem )
+ {
+ aOldSelection = pOLV->GetSelection();
+ if (nSlot == SID_CHAR_DLG_FOR_PARAGRAPH)
+ {
+ // select current paragraph (and restore selection later on...)
+ EditView & rEditView = pOLV->GetEditView();
+ SwLangHelper::SelectPara( rEditView, rEditView.GetSelection() );
+ bRestoreSelection = true;
+ }
+
+ SwView* pView = &GetView();
+ FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( pView) != nullptr );
+ SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)) );
+ SfxItemSetFixed<XATTR_FILLSTYLE, XATTR_FILLCOLOR, EE_ITEMS_START, EE_ITEMS_END> aDlgAttr(GetPool());
+
+ // util::Language does not exists in the EditEngine! That is why not in set.
+
+ aDlgAttr.Put( aEditAttr );
+ aDlgAttr.Put( SvxKerningItem(0, RES_CHRATR_KERNING) );
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateSwCharDlg(pView->GetFrameWeld(), *pView, aDlgAttr, SwCharDlgMode::Draw));
+ if (nSlot == SID_CHAR_DLG_EFFECT)
+ {
+ pDlg->SetCurPageId("fonteffects");
+ }
+ else if (nSlot == SID_CHAR_DLG_POSITION)
+ {
+ pDlg->SetCurPageId("position");
+ }
+ else if (nSlot == SID_CHAR_DLG_FOR_PARAGRAPH)
+ {
+ pDlg->SetCurPageId("font");
+ }
+ else if (pItem)
+ {
+ pDlg->SetCurPageId(pItem->GetValue());
+ }
+
+ sal_uInt16 nRet = pDlg->Execute();
+ if(RET_OK == nRet )
+ {
+ rReq.Done( *( pDlg->GetOutputItemSet() ) );
+ aNewAttr.Put(*pDlg->GetOutputItemSet());
+ }
+ if(RET_OK != nRet)
+ return ;
+ }
+ else
+ aNewAttr.Put(*pArgs);
+ }
+ break;
+ case FN_FORMAT_FOOTNOTE_DLG:
+ {
+ GetView().ExecFormatFootnote();
+ break;
+ }
+ case FN_NUMBERING_OUTLINE_DLG:
+ {
+ GetView().ExecNumberingOutline(GetPool());
+ rReq.Done();
+ }
+ break;
+ case SID_OPEN_XML_FILTERSETTINGS:
+ {
+ HandleOpenXmlFilterSettings(rReq);
+ }
+ break;
+ case FN_WORDCOUNT_DIALOG:
+ {
+ GetView().UpdateWordCount(this, nSlot);
+ }
+ break;
+ case SID_PARA_DLG:
+ {
+ const SfxItemSet* pArgs = rReq.GetArgs();
+
+ if (!pArgs)
+ {
+ SwView* pView = &GetView();
+ FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( pView) != nullptr );
+ SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)) );
+ SfxItemSetFixed<
+ EE_ITEMS_START, EE_ITEMS_END,
+ SID_ATTR_PARA_HYPHENZONE, SID_ATTR_PARA_WIDOWS> aDlgAttr( GetPool() );
+
+ aDlgAttr.Put(aEditAttr);
+
+ aDlgAttr.Put( SvxHyphenZoneItem( false, RES_PARATR_HYPHENZONE) );
+ aDlgAttr.Put( SvxFormatBreakItem( SvxBreak::NONE, RES_BREAK ) );
+ aDlgAttr.Put( SvxFormatSplitItem( true, RES_PARATR_SPLIT ) );
+ aDlgAttr.Put( SvxWidowsItem( 0, RES_PARATR_WIDOWS ) );
+ aDlgAttr.Put( SvxOrphansItem( 0, RES_PARATR_ORPHANS ) );
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateSwParaDlg(GetView().GetFrameWeld(), GetView(), aDlgAttr, true));
+ sal_uInt16 nRet = pDlg->Execute();
+ if(RET_OK == nRet)
+ {
+ rReq.Done( *( pDlg->GetOutputItemSet() ) );
+ aNewAttr.Put(*pDlg->GetOutputItemSet());
+ }
+ if(RET_OK != nRet)
+ return;
+ }
+ else
+ aNewAttr.Put(*pArgs);
+ }
+ break;
+ case SID_AUTOSPELL_CHECK:
+ {
+//!! JP 16.03.2001: why?? pSdrView = rSh.GetDrawView();
+//!! JP 16.03.2001: why?? pOutliner = pSdrView->GetTextEditOutliner();
+ SdrOutliner * pOutliner = m_pSdrView->GetTextEditOutliner();
+ EEControlBits nCtrl = pOutliner->GetControlWord();
+
+ bool bSet = static_cast<const SfxBoolItem&>(rReq.GetArgs()->Get(
+ nSlot)).GetValue();
+ if(bSet)
+ nCtrl |= EEControlBits::ONLINESPELLING|EEControlBits::ALLOWBIGOBJS;
+ else
+ nCtrl &= ~EEControlBits::ONLINESPELLING;
+ pOutliner->SetControlWord(nCtrl);
+
+ m_rView.ExecuteSlot(rReq);
+ }
+ break;
+ case SID_HYPERLINK_SETLINK:
+ {
+ const SfxPoolItem* pItem = nullptr;
+ if(pNewAttrs)
+ pNewAttrs->GetItemState(nSlot, false, &pItem);
+
+ if(pItem)
+ {
+ const SvxHyperlinkItem& rHLinkItem = *static_cast<const SvxHyperlinkItem *>(pItem);
+ SvxURLField aField(rHLinkItem.GetURL(), rHLinkItem.GetName(), SvxURLFormat::AppDefault);
+ aField.SetTargetFrame(rHLinkItem.GetTargetFrame());
+
+ const SvxFieldItem* pFieldItem = pOLV->GetFieldAtSelection();
+
+ if (pFieldItem && dynamic_cast< const SvxURLField *>( pFieldItem->GetField() ) != nullptr )
+ {
+ // Select field so that it will be deleted during insert
+ ESelection aSel = pOLV->GetSelection();
+ aSel.nEndPos++;
+ pOLV->SetSelection(aSel);
+ }
+ pOLV->InsertField(SvxFieldItem(aField, EE_FEATURE_FIELD));
+ }
+ }
+ break;
+
+ case SID_EDIT_HYPERLINK:
+ {
+ // Ensure the field is selected first
+ pOLV->SelectFieldAtCursor();
+ GetView().GetViewFrame().GetDispatcher()->Execute(SID_HYPERLINK_DIALOG);
+ }
+ break;
+
+ case SID_REMOVE_HYPERLINK:
+ {
+ URLFieldHelper::RemoveURLField(pOLV->GetEditView());
+ }
+ break;
+
+ case SID_OPEN_HYPERLINK:
+ {
+ const SvxFieldItem* pFieldItem
+ = pOLV->GetFieldAtSelection(/*AlsoCheckBeforeCursor=*/true);
+ const SvxFieldData* pField = pFieldItem ? pFieldItem->GetField() : nullptr;
+ if (const SvxURLField* pURLField = dynamic_cast<const SvxURLField*>(pField))
+ {
+ ::LoadURL(GetShell(), pURLField->GetURL(), LoadUrlFlags::NONE,
+ pURLField->GetTargetFrame());
+ }
+ }
+ break;
+
+ case SID_COPY_HYPERLINK_LOCATION:
+ {
+ const SvxFieldItem* pFieldItem
+ = pOLV->GetFieldAtSelection(/*AlsoCheckBeforeCursor=*/true);
+ const SvxFieldData* pField = pFieldItem ? pFieldItem->GetField() : nullptr;
+ if (const SvxURLField* pURLField = dynamic_cast<const SvxURLField*>(pField))
+ {
+ uno::Reference<datatransfer::clipboard::XClipboard> xClipboard
+ = GetView().GetEditWin().GetClipboard();
+ vcl::unohelper::TextDataObject::CopyStringTo(pURLField->GetURL(), xClipboard);
+ }
+ }
+ break;
+
+ case SID_TEXTDIRECTION_LEFT_TO_RIGHT:
+ case SID_TEXTDIRECTION_TOP_TO_BOTTOM:
+ // Shell switch!
+ {
+ SdrObject* pTmpObj = m_pSdrView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
+ SdrPageView* pTmpPV = m_pSdrView->GetSdrPageView();
+ SdrView* pTmpView = m_pSdrView;
+
+ m_pSdrView->SdrEndTextEdit(true);
+
+ SfxItemSetFixed<SDRATTR_TEXTDIRECTION,
+ SDRATTR_TEXTDIRECTION> aAttr( *aNewAttr.GetPool() );
+
+ aAttr.Put( SvxWritingModeItem(
+ nSlot == SID_TEXTDIRECTION_LEFT_TO_RIGHT ?
+ text::WritingMode_LR_TB
+ : text::WritingMode_TB_RL, SDRATTR_TEXTDIRECTION ) );
+ pTmpView->SetAttributes( aAttr );
+
+ rSh.GetView().BeginTextEdit( pTmpObj, pTmpPV, &rSh.GetView().GetEditWin());
+ rSh.GetView().AttrChangedNotify(nullptr);
+ }
+ return;
+
+ case SID_ATTR_PARA_LEFT_TO_RIGHT:
+ case SID_ATTR_PARA_RIGHT_TO_LEFT:
+ {
+ SdrObject* pTmpObj = m_pSdrView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
+ SdrPageView* pTmpPV = m_pSdrView->GetSdrPageView();
+ SdrView* pTmpView = m_pSdrView;
+
+ m_pSdrView->SdrEndTextEdit(true);
+ bool bLeftToRight = nSlot == SID_ATTR_PARA_LEFT_TO_RIGHT;
+
+ const SfxPoolItem* pPoolItem;
+ if( pNewAttrs && SfxItemState::SET == pNewAttrs->GetItemState( nSlot, true, &pPoolItem ) )
+ {
+ if( !static_cast<const SfxBoolItem*>(pPoolItem)->GetValue() )
+ bLeftToRight = !bLeftToRight;
+ }
+ SfxItemSetFixed<
+ EE_PARA_WRITINGDIR, EE_PARA_WRITINGDIR,
+ EE_PARA_JUST, EE_PARA_JUST> aAttr( *aNewAttr.GetPool() );
+
+ SvxAdjust nAdjust = SvxAdjust::Left;
+ if( const SvxAdjustItem* pAdjustItem = aEditAttr.GetItemIfSet(EE_PARA_JUST) )
+ nAdjust = pAdjustItem->GetAdjust();
+
+ if( bLeftToRight )
+ {
+ aAttr.Put( SvxFrameDirectionItem( SvxFrameDirection::Horizontal_LR_TB, EE_PARA_WRITINGDIR ) );
+ if( nAdjust == SvxAdjust::Right )
+ aAttr.Put( SvxAdjustItem( SvxAdjust::Left, EE_PARA_JUST ) );
+ }
+ else
+ {
+ aAttr.Put( SvxFrameDirectionItem( SvxFrameDirection::Horizontal_RL_TB, EE_PARA_WRITINGDIR ) );
+ if( nAdjust == SvxAdjust::Left )
+ aAttr.Put( SvxAdjustItem( SvxAdjust::Right, EE_PARA_JUST ) );
+ }
+ pTmpView->SetAttributes( aAttr );
+ rSh.GetView().BeginTextEdit( pTmpObj, pTmpPV, &rSh.GetView().GetEditWin() );
+ rSh.GetView().AttrChangedNotify(nullptr);
+ }
+ return;
+
+ case FN_GROW_FONT_SIZE:
+ case FN_SHRINK_FONT_SIZE:
+ {
+ const SfxObjectShell* pObjSh = SfxObjectShell::Current();
+ const SvxFontListItem* pFontListItem = static_cast< const SvxFontListItem* >
+ (pObjSh ? pObjSh->GetItem(SID_ATTR_CHAR_FONTLIST) : nullptr);
+ const FontList* pFontList = pFontListItem ? pFontListItem->GetFontList() : nullptr;
+ pOLV->GetEditView().ChangeFontSize( nSlot == FN_GROW_FONT_SIZE, pFontList );
+ }
+ break;
+
+ default:
+ assert(false && "wrong dispatcher");
+ return;
+ }
+ if (nEEWhich && pNewAttrs)
+ {
+ aNewAttr.Put(pNewAttrs->Get(nWhich).CloneSetWhich(nEEWhich));
+ }
+ else if (nEEWhich == EE_CHAR_COLOR)
+ {
+ GetView().GetViewFrame().GetDispatcher()->Execute(SID_CHAR_DLG_EFFECT);
+ }
+ else if (nEEWhich == EE_CHAR_KERNING)
+ {
+ GetView().GetViewFrame().GetDispatcher()->Execute(SID_CHAR_DLG_POSITION);
+ }
+
+
+ SetAttrToMarked(aNewAttr);
+
+ GetView().GetViewFrame().GetBindings().InvalidateAll(false);
+
+ if (IsTextEdit() && pOLV->GetOutliner()->IsModified())
+ rSh.SetModified();
+
+ if (bRestoreSelection)
+ {
+ // restore selection
+ pOLV->GetEditView().SetSelection( aOldSelection );
+ }
+}
+
+void SwDrawTextShell::GetState(SfxItemSet& rSet)
+{
+ if (!IsTextEdit()) // Otherwise sometimes crash!
+ return;
+
+ OutlinerView* pOLV = m_pSdrView->GetTextEditOutlinerView();
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ SfxItemSet aEditAttr(pOLV->GetAttribs());
+ const SvxAdjustItem *pAdjust = nullptr;
+ const SvxLineSpacingItem *pLSpace = nullptr;
+ const SfxPoolItem *pEscItem = nullptr;
+ SvxAdjust eAdjust;
+ int nLSpace;
+ SvxEscapement nEsc;
+
+ while (nWhich)
+ {
+ sal_uInt16 nSlotId = GetPool().GetSlotId(nWhich);
+ bool bFlag = false;
+ switch (nSlotId)
+ {
+ case SID_LANGUAGE_STATUS: //20412:
+ {
+ SwLangHelper::GetLanguageStatus(pOLV, rSet);
+ nSlotId = 0;
+ break;
+ }
+
+ case SID_THES:
+ {
+ OUString aStatusVal;
+ LanguageType nLang = LANGUAGE_NONE;
+ bool bIsLookUpWord
+ = GetStatusValueForThesaurusFromContext(aStatusVal, nLang, pOLV->GetEditView());
+ rSet.Put(SfxStringItem(SID_THES, aStatusVal));
+
+ // disable "Thesaurus" context menu entry if there is nothing to look up
+ uno::Reference<linguistic2::XThesaurus> xThes(::GetThesaurus());
+ if (!bIsLookUpWord || !xThes.is() || nLang == LANGUAGE_NONE
+ || !xThes->hasLocale(LanguageTag::convertToLocale(nLang)))
+ rSet.DisableItem(SID_THES);
+
+ //! avoid putting the same item as SfxBoolItem at the end of this function
+ nSlotId = 0;
+ break;
+ }
+
+ case SID_ATTR_PARA_ADJUST_LEFT:
+ eAdjust = SvxAdjust::Left;
+ goto ASK_ADJUST;
+ case SID_ATTR_PARA_ADJUST_RIGHT:
+ eAdjust = SvxAdjust::Right;
+ goto ASK_ADJUST;
+ case SID_ATTR_PARA_ADJUST_CENTER:
+ eAdjust = SvxAdjust::Center;
+ goto ASK_ADJUST;
+ case SID_ATTR_PARA_ADJUST_BLOCK:
+ eAdjust = SvxAdjust::Block;
+ goto ASK_ADJUST;
+ ASK_ADJUST:
+ {
+ if (!pAdjust)
+ pAdjust = aEditAttr.GetItemIfSet(EE_PARA_JUST, false);
+
+ if (!pAdjust || IsInvalidItem(pAdjust))
+ {
+ rSet.InvalidateItem(nSlotId);
+ nSlotId = 0;
+ }
+ else
+ bFlag = eAdjust == pAdjust->GetAdjust();
+ }
+ break;
+
+ case SID_ATTR_PARA_LRSPACE:
+ case SID_ATTR_PARA_LEFTSPACE:
+ case SID_ATTR_PARA_RIGHTSPACE:
+ case SID_ATTR_PARA_FIRSTLINESPACE:
+ {
+ SfxItemState eState = aEditAttr.GetItemState(EE_PARA_LRSPACE);
+ if (eState >= SfxItemState::DEFAULT)
+ {
+ SvxLRSpaceItem aLR = aEditAttr.Get(EE_PARA_LRSPACE);
+ aLR.SetWhich(SID_ATTR_PARA_LRSPACE);
+ rSet.Put(aLR);
+ }
+ else
+ rSet.InvalidateItem(nSlotId);
+ nSlotId = 0;
+ }
+ break;
+ case SID_ATTR_PARA_LINESPACE:
+ {
+ SfxItemState eState = aEditAttr.GetItemState(EE_PARA_SBL);
+ if (eState >= SfxItemState::DEFAULT)
+ {
+ const SvxLineSpacingItem& aLR = aEditAttr.Get(EE_PARA_SBL);
+ rSet.Put(aLR);
+ }
+ else
+ rSet.InvalidateItem(nSlotId);
+ nSlotId = 0;
+ }
+ break;
+ case SID_ATTR_PARA_ULSPACE:
+ case SID_ATTR_PARA_BELOWSPACE:
+ case SID_ATTR_PARA_ABOVESPACE:
+ case SID_PARASPACE_INCREASE:
+ case SID_PARASPACE_DECREASE:
+ {
+ SfxItemState eState = aEditAttr.GetItemState(EE_PARA_ULSPACE);
+ if (eState >= SfxItemState::DEFAULT)
+ {
+ SvxULSpaceItem aULSpace = aEditAttr.Get(EE_PARA_ULSPACE);
+ if (!aULSpace.GetUpper() && !aULSpace.GetLower())
+ rSet.DisableItem(SID_PARASPACE_DECREASE);
+ else if (aULSpace.GetUpper() >= 5670 && aULSpace.GetLower() >= 5670)
+ rSet.DisableItem(SID_PARASPACE_INCREASE);
+ if (nSlotId == SID_ATTR_PARA_ULSPACE || nSlotId == SID_ATTR_PARA_ABOVESPACE
+ || nSlotId == SID_ATTR_PARA_BELOWSPACE)
+ {
+ aULSpace.SetWhich(nSlotId);
+ rSet.Put(aULSpace);
+ }
+ }
+ else
+ {
+ rSet.DisableItem(SID_PARASPACE_INCREASE);
+ rSet.DisableItem(SID_PARASPACE_DECREASE);
+ rSet.InvalidateItem(SID_ATTR_PARA_ULSPACE);
+ rSet.InvalidateItem(SID_ATTR_PARA_ABOVESPACE);
+ rSet.InvalidateItem(SID_ATTR_PARA_BELOWSPACE);
+ }
+ nSlotId = 0;
+ }
+ break;
+
+ case SID_ATTR_PARA_LINESPACE_10:
+ nLSpace = 100;
+ goto ASK_LINESPACE;
+ case SID_ATTR_PARA_LINESPACE_115:
+ nLSpace = 115;
+ goto ASK_LINESPACE;
+ case SID_ATTR_PARA_LINESPACE_15:
+ nLSpace = 150;
+ goto ASK_LINESPACE;
+ case SID_ATTR_PARA_LINESPACE_20:
+ nLSpace = 200;
+ goto ASK_LINESPACE;
+ ASK_LINESPACE:
+ {
+ if (!pLSpace)
+ pLSpace = aEditAttr.GetItemIfSet(EE_PARA_SBL, false);
+
+ if (!pLSpace || IsInvalidItem(pLSpace))
+ {
+ rSet.InvalidateItem(nSlotId);
+ nSlotId = 0;
+ }
+ else if (nLSpace
+ == pLSpace->GetPropLineSpace())
+ bFlag = true;
+ else
+ {
+ // tdf#114631 - disable non selected line spacing
+ rSet.Put(SfxBoolItem(nWhich, false));
+ nSlotId = 0;
+ }
+ }
+ break;
+
+ case FN_SET_SUPER_SCRIPT:
+ nEsc = SvxEscapement::Superscript;
+ goto ASK_ESCAPE;
+ case FN_SET_SUB_SCRIPT:
+ nEsc = SvxEscapement::Subscript;
+ goto ASK_ESCAPE;
+ ASK_ESCAPE:
+ {
+ if (!pEscItem)
+ pEscItem = &aEditAttr.Get(EE_CHAR_ESCAPEMENT);
+
+ if (nEsc == static_cast<const SvxEscapementItem*>(pEscItem)->GetEscapement())
+ bFlag = true;
+ else
+ nSlotId = 0;
+ }
+ break;
+
+ case SID_THESAURUS:
+ {
+ // disable "Thesaurus" if the language is not supported
+ TypedWhichId<SvxLanguageItem> nLangWhich = GetWhichOfScript(
+ RES_CHRATR_LANGUAGE,
+ SvtLanguageOptions::GetI18NScriptTypeOfLanguage(GetAppLanguage()));
+ const SvxLanguageItem& rItem = GetShell().GetDoc()->GetDefault(nLangWhich);
+ LanguageType nLang = rItem.GetLanguage();
+
+ uno::Reference<linguistic2::XThesaurus> xThes(::GetThesaurus());
+ if (!xThes.is() || nLang == LANGUAGE_NONE
+ || !xThes->hasLocale(LanguageTag::convertToLocale(nLang)))
+ rSet.DisableItem(SID_THESAURUS);
+ nSlotId = 0;
+ }
+ break;
+ case SID_HANGUL_HANJA_CONVERSION:
+ case SID_CHINESE_CONVERSION:
+ {
+ if (!SvtCJKOptions::IsAnyEnabled())
+ {
+ GetView().GetViewFrame().GetBindings().SetVisibleState(nWhich, false);
+ rSet.DisableItem(nWhich);
+ }
+ else
+ GetView().GetViewFrame().GetBindings().SetVisibleState(nWhich, true);
+ }
+ break;
+
+ case SID_TEXTDIRECTION_LEFT_TO_RIGHT:
+ case SID_TEXTDIRECTION_TOP_TO_BOTTOM:
+ if (!SvtCJKOptions::IsVerticalTextEnabled())
+ {
+ rSet.DisableItem(nSlotId);
+ nSlotId = 0;
+ }
+ else
+ {
+ SdrOutliner* pOutliner = m_pSdrView->GetTextEditOutliner();
+ if (pOutliner)
+ bFlag = pOutliner->IsVertical()
+ == (SID_TEXTDIRECTION_TOP_TO_BOTTOM == nSlotId);
+ else
+ {
+ text::WritingMode eMode = aEditAttr.Get(SDRATTR_TEXTDIRECTION).GetValue();
+
+ if (nSlotId == SID_TEXTDIRECTION_LEFT_TO_RIGHT)
+ {
+ bFlag = eMode == text::WritingMode_LR_TB;
+ }
+ else
+ {
+ bFlag = eMode != text::WritingMode_TB_RL;
+ }
+ }
+ }
+ break;
+ case SID_ATTR_PARA_LEFT_TO_RIGHT:
+ case SID_ATTR_PARA_RIGHT_TO_LEFT:
+ {
+ if (!SvtCTLOptions::IsCTLFontEnabled())
+ {
+ rSet.DisableItem(nWhich);
+ nSlotId = 0;
+ }
+ else
+ {
+ SdrOutliner* pOutliner = m_pSdrView->GetTextEditOutliner();
+ if (pOutliner && pOutliner->IsVertical())
+ {
+ rSet.DisableItem(nWhich);
+ nSlotId = 0;
+ }
+ else
+ {
+ switch (aEditAttr.Get(EE_PARA_WRITINGDIR).GetValue())
+ {
+ case SvxFrameDirection::Horizontal_LR_TB:
+ bFlag = nWhich == SID_ATTR_PARA_LEFT_TO_RIGHT;
+ break;
+
+ case SvxFrameDirection::Horizontal_RL_TB:
+ bFlag = nWhich != SID_ATTR_PARA_LEFT_TO_RIGHT;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case SID_TRANSLITERATE_HALFWIDTH:
+ case SID_TRANSLITERATE_FULLWIDTH:
+ case SID_TRANSLITERATE_HIRAGANA:
+ case SID_TRANSLITERATE_KATAKANA:
+ {
+ if (!SvtCJKOptions::IsChangeCaseMapEnabled())
+ {
+ rSet.DisableItem(nWhich);
+ GetView().GetViewFrame().GetBindings().SetVisibleState(nWhich, false);
+ }
+ else
+ GetView().GetViewFrame().GetBindings().SetVisibleState(nWhich, true);
+ }
+ break;
+ case SID_INSERT_RLM:
+ case SID_INSERT_LRM:
+ {
+ bool bEnabled = SvtCTLOptions::IsCTLFontEnabled();
+ GetView().GetViewFrame().GetBindings().SetVisibleState(nWhich, bEnabled);
+ if (!bEnabled)
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_REMOVE_HYPERLINK:
+ case SID_EDIT_HYPERLINK:
+ case SID_OPEN_HYPERLINK:
+ case SID_COPY_HYPERLINK_LOCATION:
+ {
+ if (!URLFieldHelper::IsCursorAtURLField(pOLV, /*AlsoCheckBeforeCursor=*/true))
+ rSet.DisableItem(nWhich);
+ nSlotId = 0;
+ }
+ break;
+ default:
+ nSlotId = 0; // don't know this slot
+ break;
+ }
+
+ if (nSlotId)
+ rSet.Put(SfxBoolItem(nWhich, bFlag));
+
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwDrawTextShell::GetDrawTextCtrlState(SfxItemSet& rSet)
+{
+ if (!IsTextEdit()) // Otherwise crash!
+ return;
+
+ OutlinerView* pOLV = m_pSdrView->GetTextEditOutlinerView();
+ SfxItemSet aEditAttr(pOLV->GetAttribs());
+
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ SvtScriptType nScriptType = pOLV->GetSelectedScriptType();
+ while(nWhich)
+ {
+ sal_uInt16 nEEWhich = 0;
+ sal_uInt16 nSlotId = GetPool().GetSlotId( nWhich );
+ switch( nSlotId )
+ {
+ case SID_ATTR_CHAR_FONT:
+ case SID_ATTR_CHAR_FONTHEIGHT:
+ case SID_ATTR_CHAR_WEIGHT:
+ case SID_ATTR_CHAR_POSTURE:
+ {
+ SfxItemPool* pEditPool = aEditAttr.GetPool()->GetSecondaryPool();
+ if( !pEditPool )
+ pEditPool = aEditAttr.GetPool();
+ SvxScriptSetItem aSetItem( nSlotId, *pEditPool );
+ aSetItem.GetItemSet().Put( aEditAttr, false );
+ const SfxPoolItem* pI = aSetItem.GetItemOfScript( nScriptType );
+ if( pI )
+ {
+ rSet.Put(pI->CloneSetWhich(nWhich));
+ }
+ else
+ rSet.InvalidateItem( nWhich );
+ }
+ break;
+ case SID_ATTR_CHAR_COLOR: nEEWhich = EE_CHAR_COLOR; break;
+ case SID_ATTR_CHAR_BACK_COLOR: nEEWhich = EE_CHAR_BKGCOLOR; break;
+ case SID_ATTR_CHAR_UNDERLINE: nEEWhich = EE_CHAR_UNDERLINE;break;
+ case SID_ATTR_CHAR_OVERLINE: nEEWhich = EE_CHAR_OVERLINE;break;
+ case SID_ATTR_CHAR_CONTOUR: nEEWhich = EE_CHAR_OUTLINE; break;
+ case SID_ATTR_CHAR_SHADOWED: nEEWhich = EE_CHAR_SHADOW;break;
+ case SID_ATTR_CHAR_STRIKEOUT: nEEWhich = EE_CHAR_STRIKEOUT;break;
+ case SID_AUTOSPELL_CHECK:
+ {
+ const SfxPoolItemHolder aResult(m_rView.GetSlotState(nWhich));
+ if (nullptr != aResult.getItem())
+ rSet.Put(SfxBoolItem(nWhich, static_cast<const SfxBoolItem*>(aResult.getItem())->GetValue()));
+ else
+ rSet.DisableItem( nWhich );
+ break;
+ }
+ case SID_ATTR_CHAR_WORDLINEMODE: nEEWhich = EE_CHAR_WLM; break;
+ case SID_ATTR_CHAR_RELIEF : nEEWhich = EE_CHAR_RELIEF; break;
+ case SID_ATTR_CHAR_LANGUAGE : nEEWhich = EE_CHAR_LANGUAGE;break;
+ case SID_ATTR_CHAR_KERNING : nEEWhich = EE_CHAR_KERNING; break;
+ case SID_ATTR_CHAR_SCALEWIDTH: nEEWhich = EE_CHAR_FONTWIDTH;break;
+ case SID_ATTR_CHAR_AUTOKERN : nEEWhich = EE_CHAR_PAIRKERNING; break;
+ case SID_ATTR_CHAR_ESCAPEMENT: nEEWhich = EE_CHAR_ESCAPEMENT; break;
+ case FN_GROW_FONT_SIZE:
+ case FN_SHRINK_FONT_SIZE:
+ {
+ SfxItemPool* pEditPool = aEditAttr.GetPool()->GetSecondaryPool();
+ if( !pEditPool )
+ pEditPool = aEditAttr.GetPool();
+
+ SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONTHEIGHT, *pEditPool );
+ aSetItem.GetItemSet().Put( aEditAttr, false );
+ const SvxFontHeightItem* pSize( static_cast<const SvxFontHeightItem*>( aSetItem.GetItemOfScript( nScriptType ) ) );
+
+ if( pSize )
+ {
+ sal_uInt32 nSize = pSize->GetHeight();
+ if( nSize >= 19998 )
+ rSet.DisableItem( FN_GROW_FONT_SIZE );
+ else if( nSize <= 40 )
+ rSet.DisableItem( FN_SHRINK_FONT_SIZE );
+ }
+ }
+ }
+ if(nEEWhich)
+ {
+ rSet.Put(aEditAttr.Get(nEEWhich).CloneSetWhich(nWhich));
+ }
+
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwDrawTextShell::ExecClpbrd(SfxRequest const &rReq)
+{
+ if (!IsTextEdit()) // Otherwise crash!
+ return;
+
+ OutlinerView* pOLV = m_pSdrView->GetTextEditOutlinerView();
+
+ ESelection aSel(pOLV->GetSelection());
+ const bool bCopy = (aSel.nStartPara != aSel.nEndPara) || (aSel.nStartPos != aSel.nEndPos);
+ sal_uInt16 nId = rReq.GetSlot();
+ switch( nId )
+ {
+ case SID_CUT:
+ if (bCopy)
+ pOLV->Cut();
+ return;
+
+ case SID_COPY:
+ if (bCopy)
+ pOLV->Copy();
+ return;
+
+ case SID_PASTE:
+ pOLV->PasteSpecial();
+ break;
+
+ case SID_PASTE_UNFORMATTED:
+ pOLV->Paste();
+ break;
+
+ case SID_PASTE_SPECIAL:
+ {
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractPasteDialog> pDlg(pFact->CreatePasteDialog(GetView().GetEditWin().GetFrameWeld()));
+
+ pDlg->Insert(SotClipboardFormatId::STRING, OUString());
+ pDlg->Insert(SotClipboardFormatId::RTF, OUString());
+ pDlg->Insert(SotClipboardFormatId::RICHTEXT, OUString());
+ pDlg->Insert(SotClipboardFormatId::HTML_SIMPLE, OUString());
+
+ TransferableDataHelper aDataHelper(TransferableDataHelper::CreateFromSystemClipboard(&GetView().GetEditWin()));
+ SotClipboardFormatId nFormat = pDlg->GetFormat(aDataHelper.GetTransferable());
+
+ if (nFormat != SotClipboardFormatId::NONE)
+ {
+ if (nFormat == SotClipboardFormatId::STRING)
+ pOLV->Paste();
+ else
+ pOLV->PasteSpecial(nFormat);
+ }
+
+ break;
+ }
+
+ case SID_CLIPBOARD_FORMAT_ITEMS:
+ {
+ SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
+ const SfxPoolItem* pItem;
+ if (rReq.GetArgs() && rReq.GetArgs()->GetItemState(nId, true, &pItem) == SfxItemState::SET)
+ {
+ if (const SfxUInt32Item* pUInt32Item = dynamic_cast<const SfxUInt32Item *>(pItem))
+ nFormat = static_cast<SotClipboardFormatId>(pUInt32Item->GetValue());
+ }
+
+ if (nFormat != SotClipboardFormatId::NONE)
+ {
+ if (nFormat == SotClipboardFormatId::STRING)
+ pOLV->Paste();
+ else
+ pOLV->PasteSpecial(nFormat);
+ }
+
+ break;
+ }
+
+ default:
+ OSL_FAIL("wrong dispatcher");
+ return;
+ }
+}
+
+void SwDrawTextShell::StateClpbrd(SfxItemSet &rSet)
+{
+ if (!IsTextEdit()) // Otherwise crash!
+ return;
+
+ OutlinerView* pOLV = m_pSdrView->GetTextEditOutlinerView();
+ ESelection aSel(pOLV->GetSelection());
+ const bool bCopy = (aSel.nStartPara != aSel.nEndPara) ||
+ (aSel.nStartPos != aSel.nEndPos);
+
+ TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( &GetView().GetEditWin() ) );
+ const bool bPaste = aDataHelper.HasFormat( SotClipboardFormatId::STRING ) ||
+ aDataHelper.HasFormat( SotClipboardFormatId::RTF ) ||
+ aDataHelper.HasFormat( SotClipboardFormatId::RICHTEXT ) ||
+ aDataHelper.HasFormat( SotClipboardFormatId::HTML_SIMPLE);
+
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while(nWhich)
+ {
+ switch(nWhich)
+ {
+ case SID_CUT:
+ case SID_COPY:
+ if( !bCopy || GetObjectShell()->isContentExtractionLocked())
+ rSet.DisableItem( nWhich );
+ break;
+
+ case SID_PASTE:
+ case SID_PASTE_UNFORMATTED:
+ case SID_PASTE_SPECIAL:
+ if( !bPaste )
+ rSet.DisableItem( nWhich );
+ break;
+
+ case SID_CLIPBOARD_FORMAT_ITEMS:
+ if( bPaste )
+ {
+ SvxClipboardFormatItem aFormats( SID_CLIPBOARD_FORMAT_ITEMS );
+
+ if ( aDataHelper.HasFormat( SotClipboardFormatId::STRING ) )
+ aFormats.AddClipbrdFormat( SotClipboardFormatId::STRING );
+ if ( aDataHelper.HasFormat( SotClipboardFormatId::RTF ) )
+ aFormats.AddClipbrdFormat( SotClipboardFormatId::RTF );
+ if ( aDataHelper.HasFormat( SotClipboardFormatId::RICHTEXT ) )
+ aFormats.AddClipbrdFormat( SotClipboardFormatId::RICHTEXT );
+ if (aDataHelper.HasFormat(SotClipboardFormatId::HTML_SIMPLE))
+ aFormats.AddClipbrdFormat(SotClipboardFormatId::HTML_SIMPLE);
+
+ rSet.Put( aFormats );
+ }
+ else
+ rSet.DisableItem( nWhich );
+ break;
+ }
+
+ nWhich = aIter.NextWhich();
+ }
+}
+
+// Hyperlink status
+
+void SwDrawTextShell::StateInsert(SfxItemSet &rSet)
+{
+ if (!IsTextEdit()) // Otherwise crash!
+ return;
+
+ OutlinerView* pOLV = m_pSdrView->GetTextEditOutlinerView();
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while(nWhich)
+ {
+ switch(nWhich)
+ {
+ case SID_HYPERLINK_GETLINK:
+ {
+ SvxHyperlinkItem aHLinkItem;
+ aHLinkItem.SetInsertMode(HLINK_FIELD);
+
+ const SvxFieldItem* pFieldItem = pOLV->GetFieldAtSelection();
+
+ if (pFieldItem)
+ {
+ const SvxURLField* pURLField = dynamic_cast<const SvxURLField*>(pFieldItem->GetField());
+
+ if (pURLField)
+ {
+ aHLinkItem.SetName(pURLField->GetRepresentation());
+ aHLinkItem.SetURL(pURLField->GetURL());
+ aHLinkItem.SetTargetFrame(pURLField->GetTargetFrame());
+ }
+ }
+ else
+ {
+ OUString sSel(pOLV->GetSelected());
+ sSel = sSel.copy(0, std::min<sal_Int32>(255, sSel.getLength()));
+ aHLinkItem.SetName(comphelper::string::stripEnd(sSel, ' '));
+ }
+
+ sal_uInt16 nHtmlMode = ::GetHtmlMode(GetView().GetDocShell());
+ aHLinkItem.SetInsertMode(static_cast<SvxLinkInsertMode>(aHLinkItem.GetInsertMode() |
+ ((nHtmlMode & HTMLMODE_ON) != 0 ? HLINK_HTMLMODE : 0)));
+
+ rSet.Put(aHLinkItem);
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/drwtxtsh.cxx b/sw/source/uibase/shells/drwtxtsh.cxx
new file mode 100644
index 0000000000..4d9a181730
--- /dev/null
+++ b/sw/source/uibase/shells/drwtxtsh.cxx
@@ -0,0 +1,849 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+#include <i18nlangtag/lang.h>
+#include <i18nutil/transliteration.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <svl/slstitm.hxx>
+#include <svl/stritem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/editund2.hxx>
+#include <svx/svdview.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/objface.hxx>
+#include <svx/svdotext.hxx>
+#include <svx/sdooitm.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <sfx2/bindings.hxx>
+#include <svx/fontwork.hxx>
+#include <sfx2/request.hxx>
+#include <vcl/EnumContext.hxx>
+#include <svl/whiter.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/editstat.hxx>
+#include <svx/svdoutl.hxx>
+#include <com/sun/star/i18n/TextConversionOption.hpp>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/propertysequence.hxx>
+#include <osl/diagnose.h>
+#include <swtypes.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <viewopt.hxx>
+#include <drwtxtsh.hxx>
+#include <breakit.hxx>
+
+#include <cmdid.h>
+
+#define ShellClass_SwDrawTextShell
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+#include <uitool.hxx>
+#include <wview.hxx>
+#include <swmodule.hxx>
+#include <svx/svdoashp.hxx>
+#include <svx/svxdlg.hxx>
+#include <comphelper/processfactory.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <memory>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::i18n;
+
+SFX_IMPL_INTERFACE(SwDrawTextShell, SfxShell)
+
+void SwDrawTextShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("drawtext");
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Draw_Text_Toolbox_Sw);
+
+ GetStaticInterface()->RegisterChildWindow(SvxFontWorkChildWindow::GetChildWindowId());
+}
+
+
+void SwDrawTextShell::Init()
+{
+ SwWrtShell &rSh = GetShell();
+ m_pSdrView = rSh.GetDrawView();
+ SdrOutliner * pOutliner = m_pSdrView->GetTextEditOutliner();
+ //#97471# mouse click _and_ key input at the same time
+ if( !pOutliner )
+ return ;
+ OutlinerView* pOLV = m_pSdrView->GetTextEditOutlinerView();
+ EEControlBits nCtrl = pOutliner->GetControlWord();
+ nCtrl |= EEControlBits::AUTOCORRECT;
+
+ SetUndoManager(&pOutliner->GetUndoManager());
+
+ // Now let's try an AutoSpell.
+
+ const SwViewOption* pVOpt = rSh.GetViewOptions();
+ if(pVOpt->IsOnlineSpell())
+ {
+ nCtrl |= EEControlBits::ONLINESPELLING|EEControlBits::ALLOWBIGOBJS;
+ }
+ else
+ nCtrl &= ~EEControlBits::ONLINESPELLING;
+
+ pOutliner->SetControlWord(nCtrl);
+ pOLV->ShowCursor();
+}
+
+SwDrawTextShell::SwDrawTextShell(SwView &rV) :
+ SfxShell(&rV),
+ m_rView(rV)
+{
+ SwWrtShell &rSh = GetShell();
+ SetPool(rSh.GetAttrPool().GetSecondaryPool());
+
+ // Initialize and show cursor to start editing.
+ Init();
+
+ SetName("ObjectText");
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::DrawText));
+}
+
+SwDrawTextShell::~SwDrawTextShell()
+{
+ if ( GetView().GetCurShell() == this )
+ m_rView.ResetSubShell();
+}
+
+SwWrtShell& SwDrawTextShell::GetShell()
+{
+ return m_rView.GetWrtShell();
+}
+
+// Disable slots with this status method
+
+void SwDrawTextShell::StateDisableItems( SfxItemSet &rSet )
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while (nWhich)
+ {
+ rSet.DisableItem( nWhich );
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwDrawTextShell::SetAttrToMarked(const SfxItemSet& rAttr)
+{
+ OutlinerView* pOLV = m_pSdrView->GetTextEditOutlinerView();
+ tools::Rectangle aOutRect = pOLV->GetOutputArea();
+
+ if (tools::Rectangle() != aOutRect)
+ {
+ GetShell().GetDrawView()->SetAttributes(rAttr);
+ }
+}
+
+bool SwDrawTextShell::IsTextEdit() const
+{
+ return m_pSdrView->IsTextEdit();
+}
+
+void SwDrawTextShell::ExecFontWork(SfxRequest const & rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ FieldUnit eMetric = ::GetDfltMetric( dynamic_cast<SwWebView*>( &rSh.GetView()) != nullptr );
+ SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)) );
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+ if ( rReq.GetArgs() )
+ {
+ rVFrame.SetChildWindow(SvxFontWorkChildWindow::GetChildWindowId(),
+ static_cast<const SfxBoolItem&>( (rReq.GetArgs()->
+ Get(SID_FONTWORK))).GetValue());
+ }
+ else
+ rVFrame.ToggleChildWindow(SvxFontWorkChildWindow::GetChildWindowId());
+
+ rVFrame.GetBindings().Invalidate(SID_FONTWORK);
+}
+
+void SwDrawTextShell::StateFontWork(SfxItemSet& rSet)
+{
+ const sal_uInt16 nId = SvxFontWorkChildWindow::GetChildWindowId();
+ rSet.Put(SfxBoolItem(SID_FONTWORK, GetView().GetViewFrame().HasChildWindow(nId)));
+}
+
+// Edit SfxRequests for FontWork
+
+void SwDrawTextShell::ExecFormText(SfxRequest const & rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ SdrView* pDrView = rSh.GetDrawView();
+
+ const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
+
+ if ( !(rMarkList.GetMarkCount() == 1 && rReq.GetArgs()) )
+ return;
+
+ const SfxItemSet& rSet = *rReq.GetArgs();
+
+ if ( pDrView->IsTextEdit() )
+ {
+ //#111733# Sometimes SdrEndTextEdit() initiates the change in selection and
+ // 'this' is not valid anymore
+ SwView& rTempView = GetView();
+ pDrView->SdrEndTextEdit(true);
+ //this removes the current shell from the dispatcher stack!!
+ rTempView.AttrChangedNotify(nullptr);
+ }
+
+ pDrView->SetAttributes(rSet);
+
+}
+
+// Return Status values back to FontWork
+
+void SwDrawTextShell::GetFormTextState(SfxItemSet& rSet)
+{
+ SwWrtShell &rSh = GetShell();
+ SdrView* pDrView = rSh.GetDrawView();
+ const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
+ const SdrObject* pObj = nullptr;
+
+ if ( rMarkList.GetMarkCount() == 1 )
+ pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+
+ const SdrTextObj* pTextObj = DynCastSdrTextObj(pObj);
+ const bool bDeactivate(
+ !pObj ||
+ !pTextObj ||
+ !pTextObj->HasText() ||
+ dynamic_cast< const SdrObjCustomShape* >(pObj)); // #121538# no FontWork for CustomShapes
+
+ if (bDeactivate)
+ {
+ rSet.DisableItem(XATTR_FORMTXTSTYLE);
+ rSet.DisableItem(XATTR_FORMTXTADJUST);
+ rSet.DisableItem(XATTR_FORMTXTDISTANCE);
+ rSet.DisableItem(XATTR_FORMTXTSTART);
+ rSet.DisableItem(XATTR_FORMTXTMIRROR);
+ rSet.DisableItem(XATTR_FORMTXTHIDEFORM);
+ rSet.DisableItem(XATTR_FORMTXTOUTLINE);
+ rSet.DisableItem(XATTR_FORMTXTSHADOW);
+ rSet.DisableItem(XATTR_FORMTXTSHDWCOLOR);
+ rSet.DisableItem(XATTR_FORMTXTSHDWXVAL);
+ rSet.DisableItem(XATTR_FORMTXTSHDWYVAL);
+ }
+ else
+ {
+ pDrView->GetAttributes( rSet );
+ }
+}
+
+void SwDrawTextShell::ExecDrawLingu(SfxRequest const &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ OutlinerView* pOutlinerView = m_pSdrView->GetTextEditOutlinerView();
+ if( !rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() )
+ return;
+
+ switch(rReq.GetSlot())
+ {
+ case SID_THESAURUS:
+ pOutlinerView->StartThesaurus(rReq.GetFrameWeld());
+ break;
+
+ case SID_HANGUL_HANJA_CONVERSION:
+ pOutlinerView->StartTextConversion(rReq.GetFrameWeld(),
+ LANGUAGE_KOREAN, LANGUAGE_KOREAN, nullptr,
+ i18n::TextConversionOption::CHARACTER_BY_CHARACTER, true, false);
+ break;
+
+ case SID_CHINESE_CONVERSION:
+ {
+ //open ChineseTranslationDialog
+ Reference<XComponentContext> xContext = comphelper::getProcessComponentContext();
+ if (!xContext.is())
+ return;
+
+ Reference<lang::XMultiComponentFactory> xMCF(xContext->getServiceManager());
+ if (!xMCF.is())
+ return;
+
+ Reference<ui::dialogs::XExecutableDialog> xDialog(
+ xMCF->createInstanceWithContext("com.sun.star.linguistic2.ChineseTranslationDialog", xContext), UNO_QUERY);
+
+ Reference<lang::XInitialization> xInit(xDialog, UNO_QUERY);
+
+ if (!xInit.is())
+ return;
+
+ // initialize dialog
+ uno::Sequence<uno::Any> aSequence(comphelper::InitAnyPropertySequence(
+ {
+ {"ParentWindow", uno::Any(Reference<awt::XWindow>())}
+ }));
+ xInit->initialize( aSequence );
+
+ //execute dialog
+ sal_Int16 nDialogRet = xDialog->execute();
+ if(RET_OK == nDialogRet)
+ {
+ //get some parameters from the dialog
+ bool bToSimplified = true;
+ bool bUseVariants = true;
+ bool bCommonTerms = true;
+ Reference<beans::XPropertySet> xPropertySet(xDialog, UNO_QUERY);
+ if (xPropertySet.is())
+ {
+ try
+ {
+ xPropertySet->getPropertyValue("IsDirectionToSimplified") >>= bToSimplified;
+ xPropertySet->getPropertyValue("IsUseCharacterVariants") >>= bUseVariants;
+ xPropertySet->getPropertyValue("IsTranslateCommonTerms") >>= bCommonTerms;
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+
+ //execute translation
+ LanguageType nSourceLang = bToSimplified ? LANGUAGE_CHINESE_TRADITIONAL : LANGUAGE_CHINESE_SIMPLIFIED;
+ LanguageType nTargetLang = bToSimplified ? LANGUAGE_CHINESE_SIMPLIFIED : LANGUAGE_CHINESE_TRADITIONAL;
+ sal_Int32 nOptions = bUseVariants ? i18n::TextConversionOption::USE_CHARACTER_VARIANTS : 0;
+ if(!bCommonTerms)
+ nOptions = nOptions | i18n::TextConversionOption::CHARACTER_BY_CHARACTER;
+
+ vcl::Font aTargetFont = OutputDevice::GetDefaultFont(DefaultFontType::CJK_TEXT, nTargetLang, GetDefaultFontFlags::OnlyOne);
+
+ pOutlinerView->StartTextConversion(rReq.GetFrameWeld(), nSourceLang, nTargetLang, &aTargetFont, nOptions, false, false);
+ }
+
+ Reference<lang::XComponent> xComponent(xDialog, UNO_QUERY);
+ if (xComponent.is())
+ xComponent->dispose();
+ }
+ break;
+
+ default:
+ OSL_ENSURE(false, "unexpected slot-id");
+ }
+}
+
+void SwDrawTextShell::ExecDraw(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ m_pSdrView = rSh.GetDrawView();
+ OutlinerView* pOLV = m_pSdrView->GetTextEditOutlinerView();
+
+ switch (rReq.GetSlot())
+ {
+ case FN_INSERT_SOFT_HYPHEN:
+ case FN_INSERT_HARDHYPHEN:
+ case FN_INSERT_HARD_SPACE:
+ case FN_INSERT_NNBSP:
+ case SID_INSERT_RLM :
+ case SID_INSERT_LRM :
+ case SID_INSERT_WJ :
+ case SID_INSERT_ZWSP:
+ {
+ sal_Unicode cIns = 0;
+ switch(rReq.GetSlot())
+ {
+ case FN_INSERT_SOFT_HYPHEN: cIns = CHAR_SOFTHYPHEN; break;
+ case FN_INSERT_HARDHYPHEN: cIns = CHAR_HARDHYPHEN; break;
+ case FN_INSERT_HARD_SPACE: cIns = CHAR_HARDBLANK; break;
+ case FN_INSERT_NNBSP: cIns = CHAR_NNBSP; break;
+ case SID_INSERT_RLM : cIns = CHAR_RLM ; break;
+ case SID_INSERT_LRM : cIns = CHAR_LRM ; break;
+ case SID_INSERT_ZWSP : cIns = CHAR_ZWSP ; break;
+ case SID_INSERT_WJ: cIns = CHAR_WJ; break;
+ }
+ pOLV->InsertText( OUString(cIns));
+ rReq.Done();
+ }
+ break;
+ case SID_CHARMAP:
+ { // Insert special character
+ InsertSymbol(rReq);
+ break;
+ }
+ case FN_INSERT_STRING:
+ {
+ const SfxItemSet *pNewAttrs = rReq.GetArgs();
+ sal_uInt16 nSlot = rReq.GetSlot();
+ const SfxPoolItem* pItem = nullptr;
+ if(pNewAttrs)
+ {
+ pNewAttrs->GetItemState(nSlot, false, &pItem );
+ pOLV->InsertText(static_cast<const SfxStringItem *>(pItem)->GetValue());
+ }
+ break;
+ }
+
+ case SID_SELECTALL:
+ {
+ SdrOutliner * pOutliner = m_pSdrView->GetTextEditOutliner();
+ if(pOutliner)
+ {
+ sal_Int32 nParaCount = pOutliner->GetParagraphCount();
+ if (nParaCount > 0)
+ pOLV->SelectRange(0, nParaCount );
+ }
+ }
+ break;
+
+ case FN_FORMAT_RESET: // delete hard text attributes
+ {
+ pOLV->RemoveAttribsKeepLanguages( true );
+ pOLV->GetEditView().GetEditEngine()->RemoveFields();
+ rReq.Done();
+ }
+ break;
+
+ case FN_ESCAPE:
+ if (m_pSdrView->IsTextEdit())
+ {
+ // Shell switch!
+ rSh.EndTextEdit();
+ SwView& rTempView = rSh.GetView();
+ rTempView.ExitDraw();
+ rSh.Edit();
+ return;
+ }
+ break;
+ case FN_DRAWTEXT_ATTR_DLG:
+ {
+ SfxItemSet aNewAttr(m_pSdrView->GetModel().GetItemPool());
+ m_pSdrView->GetAttributes( aNewAttr );
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateTextTabDialog(
+ GetView().GetFrameWeld(),
+ &aNewAttr, m_pSdrView ));
+ sal_uInt16 nResult = pDlg->Execute();
+
+ if (nResult == RET_OK)
+ {
+ if (m_pSdrView->AreObjectsMarked())
+ {
+ m_pSdrView->SetAttributes(*pDlg->GetOutputItemSet());
+ rReq.Done(*(pDlg->GetOutputItemSet()));
+ }
+ }
+ }
+ break;
+ case SID_TABLE_VERT_NONE:
+ case SID_TABLE_VERT_CENTER:
+ case SID_TABLE_VERT_BOTTOM:
+ {
+ sal_uInt16 nSId = rReq.GetSlot();
+ if (m_pSdrView->AreObjectsMarked())
+ {
+ SdrTextVertAdjust eTVA = SDRTEXTVERTADJUST_TOP;
+ if (nSId == SID_TABLE_VERT_CENTER)
+ eTVA = SDRTEXTVERTADJUST_CENTER;
+ else if (nSId == SID_TABLE_VERT_BOTTOM)
+ eTVA = SDRTEXTVERTADJUST_BOTTOM;
+
+ SfxItemSet aNewAttr(m_pSdrView->GetModel().GetItemPool());
+ m_pSdrView->GetAttributes( aNewAttr );
+ aNewAttr.Put(SdrTextVertAdjustItem(eTVA));
+ m_pSdrView->SetAttributes(aNewAttr);
+ rReq.Done();
+ }
+
+ }
+ break;
+
+ default:
+ OSL_ENSURE(false, "unexpected slot-id");
+ return;
+ }
+
+ GetView().GetViewFrame().GetBindings().InvalidateAll(false);
+
+ if (IsTextEdit() && pOLV->GetOutliner()->IsModified())
+ rSh.SetModified();
+}
+
+// Execute undo
+
+void SwDrawTextShell::ExecUndo(SfxRequest &rReq)
+{
+ if( !IsTextEdit() )
+ return;
+
+ bool bCallBase = true;
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ if( pArgs )
+ {
+ sal_uInt16 nId = rReq.GetSlot(), nCnt = 1;
+ const SfxPoolItem* pItem;
+ switch( nId )
+ {
+ case SID_UNDO:
+ case SID_REDO:
+ if( SfxItemState::SET == pArgs->GetItemState( nId, false, &pItem ) &&
+ 1 < (nCnt = static_cast<const SfxUInt16Item*>(pItem)->GetValue()) )
+ {
+ // then we make by ourself.
+ SfxUndoManager* pUndoManager = GetUndoManager();
+ if( pUndoManager )
+ {
+ if( SID_UNDO == nId )
+ while( nCnt-- )
+ pUndoManager->Undo();
+ else
+ while( nCnt-- )
+ pUndoManager->Redo();
+ }
+ bCallBase = false;
+ GetView().GetViewFrame().GetBindings().InvalidateAll(false);
+ }
+ break;
+ }
+ }
+ if( bCallBase )
+ {
+ SfxViewFrame& rSfxViewFrame = GetView().GetViewFrame();
+ rSfxViewFrame.ExecuteSlot(rReq, rSfxViewFrame.GetInterface());
+ }
+}
+
+// State of undo
+
+void SwDrawTextShell::StateUndo(SfxItemSet &rSet)
+{
+ if ( !IsTextEdit() )
+ return;
+
+ SfxViewFrame& rSfxViewFrame = GetView().GetViewFrame();
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while( nWhich )
+ {
+ switch ( nWhich )
+ {
+ case SID_GETUNDOSTRINGS:
+ case SID_GETREDOSTRINGS:
+ {
+ SfxUndoManager* pUndoManager = GetUndoManager();
+ if( pUndoManager )
+ {
+ OUString (SfxUndoManager::*fnGetComment)( size_t, bool const ) const;
+
+ sal_uInt16 nCount;
+ if( SID_GETUNDOSTRINGS == nWhich )
+ {
+ nCount = pUndoManager->GetUndoActionCount();
+ fnGetComment = &SfxUndoManager::GetUndoActionComment;
+ }
+ else
+ {
+ nCount = pUndoManager->GetRedoActionCount();
+ fnGetComment = &SfxUndoManager::GetRedoActionComment;
+ }
+ if( nCount )
+ {
+ OUStringBuffer sList;
+ for( sal_uInt16 n = 0; n < nCount; ++n )
+ sList.append( (pUndoManager->*fnGetComment)( n, SfxUndoManager::TopLevel ) + "\n");
+
+ SfxStringListItem aItem( nWhich );
+ aItem.SetString( sList.makeStringAndClear() );
+ rSet.Put( aItem );
+ }
+ }
+ else
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ default:
+ {
+ auto* pUndoManager = dynamic_cast<IDocumentUndoRedo*>(GetUndoManager());
+ if (pUndoManager)
+ pUndoManager->SetView(&GetView());
+ rSfxViewFrame.GetSlotState(nWhich, rSfxViewFrame.GetInterface(), &rSet);
+ if (pUndoManager)
+ pUndoManager->SetView(nullptr);
+ }
+ }
+
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwDrawTextShell::ExecTransliteration( SfxRequest const & rReq )
+{
+ if (!m_pSdrView)
+ return;
+
+ using namespace i18n;
+
+ TransliterationFlags nMode = TransliterationFlags::NONE;
+
+ switch( rReq.GetSlot() )
+ {
+ case SID_TRANSLITERATE_SENTENCE_CASE:
+ nMode = TransliterationFlags::SENTENCE_CASE;
+ break;
+ case SID_TRANSLITERATE_TITLE_CASE:
+ nMode = TransliterationFlags::TITLE_CASE;
+ break;
+ case SID_TRANSLITERATE_TOGGLE_CASE:
+ nMode = TransliterationFlags::TOGGLE_CASE;
+ break;
+ case SID_TRANSLITERATE_UPPER:
+ nMode = TransliterationFlags::LOWERCASE_UPPERCASE;
+ break;
+ case SID_TRANSLITERATE_LOWER:
+ nMode = TransliterationFlags::UPPERCASE_LOWERCASE;
+ break;
+
+ case SID_TRANSLITERATE_HALFWIDTH:
+ nMode = TransliterationFlags::FULLWIDTH_HALFWIDTH;
+ break;
+ case SID_TRANSLITERATE_FULLWIDTH:
+ nMode = TransliterationFlags::HALFWIDTH_FULLWIDTH;
+ break;
+
+ case SID_TRANSLITERATE_HIRAGANA:
+ nMode = TransliterationFlags::KATAKANA_HIRAGANA;
+ break;
+ case SID_TRANSLITERATE_KATAKANA:
+ nMode = TransliterationFlags::HIRAGANA_KATAKANA;
+ break;
+
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ }
+
+ if( nMode != TransliterationFlags::NONE )
+ {
+ OutlinerView* pOLV = m_pSdrView->GetTextEditOutlinerView();
+
+ if (!pOLV)
+ return;
+
+ pOLV->TransliterateText( nMode );
+ }
+}
+
+void SwDrawTextShell::ExecRotateTransliteration( SfxRequest const & rReq )
+{
+ if( rReq.GetSlot() == SID_TRANSLITERATE_ROTATE_CASE )
+ {
+ if (!m_pSdrView)
+ return;
+
+ OutlinerView* pOLV = m_pSdrView->GetTextEditOutlinerView();
+
+ if (!pOLV)
+ return;
+
+ pOLV->TransliterateText( m_aRotateCase.getNextMode() );
+ }
+}
+
+// Insert special character (see SDraw: FUBULLET.CXX)
+
+void SwDrawTextShell::InsertSymbol(SfxRequest& rReq)
+{
+ OutlinerView* pOLV = m_pSdrView->GetTextEditOutlinerView();
+ if(!pOLV)
+ return;
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ const SfxStringItem* pItem = nullptr;
+ if( pArgs )
+ pItem = pArgs->GetItemIfSet(SID_CHARMAP, false);
+
+ OUString sSym;
+ OUString sFontName;
+ if ( pItem )
+ {
+ sSym = pItem->GetValue();
+ const SfxStringItem* pFontItem = pArgs->GetItemIfSet( SID_ATTR_SPECIALCHAR, false);
+ if ( pFontItem )
+ sFontName = pFontItem->GetValue();
+ }
+
+ SfxItemSet aSet(pOLV->GetAttribs());
+ SvtScriptType nScript = pOLV->GetSelectedScriptType();
+ std::shared_ptr<SvxFontItem> aSetDlgFont(std::make_shared<SvxFontItem>(RES_CHRATR_FONT));
+ {
+ SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONT, *aSet.GetPool() );
+ aSetItem.GetItemSet().Put( aSet, false );
+ const SfxPoolItem* pI = aSetItem.GetItemOfScript( nScript );
+ if( pI )
+ aSetDlgFont.reset(static_cast<SvxFontItem*>(pI->Clone()));
+ else
+ {
+ TypedWhichId<SvxFontItem> nFontWhich =
+ GetWhichOfScript(
+ SID_ATTR_CHAR_FONT,
+ SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetAppLanguage() ) );
+ aSetDlgFont.reset(aSet.Get( nFontWhich ).Clone());
+ }
+ if (sFontName.isEmpty())
+ sFontName = aSetDlgFont->GetFamilyName();
+ }
+
+ vcl::Font aFont(sFontName, Size(1,1));
+ if(sSym.isEmpty())
+ {
+ SfxAllItemSet aAllSet( GetPool() );
+ aAllSet.Put( SfxBoolItem( FN_PARAM_1, false ) );
+
+ SwViewOption aOpt(*m_rView.GetWrtShell().GetViewOptions());
+ const OUString& sSymbolFont = aOpt.GetSymbolFont();
+ if( !sSymbolFont.isEmpty() )
+ aAllSet.Put( SfxStringItem( SID_FONT_NAME, sSymbolFont ) );
+ else
+ aAllSet.Put( SfxStringItem( SID_FONT_NAME, aSetDlgFont->GetFamilyName() ) );
+
+ // If character is selected, it can be shown
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ auto xFrame = m_rView.GetViewFrame().GetFrame().GetFrameInterface();
+ ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateCharMapDialog(m_rView.GetFrameWeld(), aAllSet, xFrame));
+ pDlg->Execute();
+ return;
+ }
+
+ // do not flicker
+ pOLV->HideCursor();
+ SdrOutliner * pOutliner = m_pSdrView->GetTextEditOutliner();
+ pOutliner->SetUpdateLayout(false);
+
+ SfxItemSet aOldSet( pOLV->GetAttribs() );
+ SfxItemSetFixed<
+ EE_CHAR_FONTINFO, EE_CHAR_FONTINFO,
+ EE_CHAR_FONTINFO_CJK, EE_CHAR_FONTINFO_CTL> aFontSet( *aOldSet.GetPool() );
+ aFontSet.Set( aOldSet );
+
+ // Insert string
+ pOLV->InsertText( sSym );
+
+ // assign attributes (Set font)
+ SfxItemSet aFontAttribSet( *aFontSet.GetPool(), aFontSet.GetRanges() );
+ SvxFontItem aFontItem (aFont.GetFamilyType(), aFont.GetFamilyName(),
+ aFont.GetStyleName(), aFont.GetPitch(),
+ aFont.GetCharSet(),
+ EE_CHAR_FONTINFO );
+ nScript = g_pBreakIt->GetAllScriptsOfText( sSym );
+ if( SvtScriptType::LATIN & nScript )
+ aFontAttribSet.Put( aFontItem );
+ if( SvtScriptType::ASIAN & nScript )
+ {
+ aFontItem.SetWhich(EE_CHAR_FONTINFO_CJK);
+ aFontAttribSet.Put( aFontItem );
+ }
+ if( SvtScriptType::COMPLEX & nScript )
+ {
+ aFontItem.SetWhich(EE_CHAR_FONTINFO_CTL);
+ aFontAttribSet.Put( aFontItem );
+ }
+ pOLV->SetAttribs(aFontAttribSet);
+
+ // Remove selection
+ ESelection aSel(pOLV->GetSelection());
+ aSel.nStartPara = aSel.nEndPara;
+ aSel.nStartPos = aSel.nEndPos;
+ pOLV->SetSelection(aSel);
+
+ // Restore old font
+ pOLV->SetAttribs( aFontSet );
+
+ // From now on show again
+ pOutliner->SetUpdateLayout(true);
+ pOLV->ShowCursor();
+
+ rReq.AppendItem( SfxStringItem( SID_CHARMAP, sSym ) );
+ if(!aFont.GetFamilyName().isEmpty())
+ rReq.AppendItem( SfxStringItem( SID_ATTR_SPECIALCHAR, aFont.GetFamilyName() ) );
+ rReq.Done();
+
+}
+
+SfxUndoManager* SwDrawTextShell::GetUndoManager()
+{
+ SwWrtShell &rSh = GetShell();
+ m_pSdrView = rSh.GetDrawView();
+ SdrOutliner * pOutliner = m_pSdrView->GetTextEditOutliner();
+ return &pOutliner->GetUndoManager();
+}
+
+void SwDrawTextShell::GetStatePropPanelAttr(SfxItemSet &rSet)
+{
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ SwWrtShell &rSh = GetShell();
+ m_pSdrView = rSh.GetDrawView();
+
+ SfxItemSet aAttrs(m_pSdrView->GetModel().GetItemPool());
+ m_pSdrView->GetAttributes( aAttrs );
+
+ while ( nWhich )
+ {
+ sal_uInt16 nSlotId = SfxItemPool::IsWhich(nWhich)
+ ? GetPool().GetSlotId(nWhich)
+ : nWhich;
+ switch ( nSlotId )
+ {
+ case SID_TABLE_VERT_NONE:
+ case SID_TABLE_VERT_CENTER:
+ case SID_TABLE_VERT_BOTTOM:
+ bool bContour = false;
+ SfxItemState eConState = aAttrs.GetItemState( SDRATTR_TEXT_CONTOURFRAME );
+ if( eConState != SfxItemState::DONTCARE )
+ {
+ bContour = aAttrs.Get( SDRATTR_TEXT_CONTOURFRAME ).GetValue();
+ }
+ if (bContour) break;
+
+ SfxItemState eVState = aAttrs.GetItemState( SDRATTR_TEXT_VERTADJUST );
+ //SfxItemState eHState = aAttrs.GetItemState( SDRATTR_TEXT_HORZADJUST );
+
+ //if(SfxItemState::DONTCARE != eVState && SfxItemState::DONTCARE != eHState)
+ if(SfxItemState::DONTCARE != eVState)
+ {
+ SdrTextVertAdjust eTVA = aAttrs.Get(SDRATTR_TEXT_VERTADJUST).GetValue();
+ bool bSet = (nSlotId == SID_TABLE_VERT_NONE && eTVA == SDRTEXTVERTADJUST_TOP) ||
+ (nSlotId == SID_TABLE_VERT_CENTER && eTVA == SDRTEXTVERTADJUST_CENTER) ||
+ (nSlotId == SID_TABLE_VERT_BOTTOM && eTVA == SDRTEXTVERTADJUST_BOTTOM);
+ rSet.Put(SfxBoolItem(nSlotId, bSet));
+ }
+ else
+ {
+ rSet.Put(SfxBoolItem(nSlotId, false));
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/frmsh.cxx b/sw/source/uibase/shells/frmsh.cxx
new file mode 100644
index 0000000000..ac5ee0d808
--- /dev/null
+++ b/sw/source/uibase/shells/frmsh.cxx
@@ -0,0 +1,1463 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+
+#include <hintids.hxx>
+#include <svl/whiter.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <basic/sbstar.hxx>
+#include <svl/ptitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/eitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/lineitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/objface.hxx>
+#include <vcl/EnumContext.hxx>
+#include <svx/hlnkitem.hxx>
+#include <svx/svdview.hxx>
+#include <svx/sdangitm.hxx>
+#include <vcl/commandinfoprovider.hxx>
+#include <sal/log.hxx>
+
+#include <doc.hxx>
+#include <drawdoc.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <fmturl.hxx>
+#include <fmtclds.hxx>
+#include <fmtcnct.hxx>
+#include <swmodule.hxx>
+#include <wrtsh.hxx>
+#include <wview.hxx>
+#include <uitool.hxx>
+#include <frmfmt.hxx>
+#include <frmsh.hxx>
+#include <frmmgr.hxx>
+#include <edtwin.hxx>
+#include <swdtflvr.hxx>
+#include <viewopt.hxx>
+
+#include <cmdid.h>
+#include <strings.hrc>
+#include <swabstdlg.hxx>
+
+#include <svx/svxdlg.hxx>
+
+#include <docsh.hxx>
+#include <svx/drawitem.hxx>
+#include <memory>
+
+#define ShellClass_SwFrameShell
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+#include <grfatr.hxx>
+#include <fldmgr.hxx>
+#include <flyfrm.hxx>
+
+using ::editeng::SvxBorderLine;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+// Prototypes
+static void lcl_FrameGetMaxLineWidth(const SvxBorderLine* pBorderLine, SvxBorderLine& rBorderLine);
+static const SwFrameFormat* lcl_GetFrameFormatByName(SwWrtShell const & rSh, std::u16string_view rName)
+{
+ const size_t nCount = rSh.GetFlyCount(FLYCNTTYPE_FRM);
+ for( size_t i = 0; i < nCount; ++i )
+ {
+ const SwFrameFormat* pFormat = rSh.GetFlyNum(i, FLYCNTTYPE_FRM);
+ if(pFormat->GetName() == rName)
+ return pFormat;
+ }
+ return nullptr;
+}
+
+SFX_IMPL_INTERFACE(SwFrameShell, SwBaseShell)
+
+void SwFrameShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("frame");
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Frame_Toolbox);
+}
+
+void SwFrameShell::ExecMove(SfxRequest& rReq)
+{
+ SwWrtShell& rSh = GetShell();
+ sal_uInt16 nSlot = rReq.GetSlot();
+ switch (nSlot)
+ {
+ case SID_SELECTALL:
+ rSh.SelAll();
+ rReq.Done();
+ break;
+ }
+}
+
+void SwFrameShell::ExecField(const SfxRequest& rReq)
+{
+ SwWrtShell& rSh = GetShell();
+ sal_uInt16 nSlot = rReq.GetSlot();
+ switch (nSlot)
+ {
+ case FN_POSTIT:
+ SwFieldMgr aFieldMgr(&rSh);
+ rSh.InsertPostIt(aFieldMgr, rReq);
+ break;
+ }
+}
+
+void SwFrameShell::Execute(SfxRequest &rReq)
+{
+ //First those who do not need FrameMgr.
+ SwWrtShell &rSh = GetShell();
+ bool bMore = false;
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem;
+ sal_uInt16 nSlot = rReq.GetSlot();
+
+ switch ( nSlot )
+ {
+ case FN_FRAME_TO_ANCHOR:
+ if ( rSh.IsFrameSelected() )
+ {
+ rSh.GotoFlyAnchor();
+ rSh.EnterStdMode();
+ rSh.CallChgLnk();
+ }
+ break;
+ case SID_FRAME_TO_TOP:
+ rSh.SelectionToTop();
+ break;
+
+ case SID_FRAME_TO_BOTTOM:
+ rSh.SelectionToBottom();
+ break;
+
+ case FN_FRAME_UP:
+ rSh.SelectionToTop( false );
+ break;
+
+ case FN_FRAME_DOWN:
+ rSh.SelectionToBottom( false );
+ break;
+ case FN_INSERT_FRAME:
+ if (!pArgs)
+ {
+ // Frame already exists, open frame dialog for editing.
+ SfxStringItem aDefPage(FN_FORMAT_FRAME_DLG, "columns");
+ rSh.GetView().GetViewFrame().GetDispatcher()->ExecuteList(
+ FN_FORMAT_FRAME_DLG,
+ SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
+ { &aDefPage });
+
+ }
+ else
+ {
+ // Frame already exists, only the number of columns will be changed.
+ sal_uInt16 nCols = 1;
+ if(const SfxUInt16Item* pColsItem = pArgs->GetItemIfSet(SID_ATTR_COLUMNS, false))
+ nCols = pColsItem->GetValue();
+
+ SfxItemSetFixed<RES_COL,RES_COL> aSet(GetPool());
+ rSh.GetFlyFrameAttr( aSet );
+ SwFormatCol aCol(aSet.Get(RES_COL));
+ // GutterWidth will not always passed, hence get firstly
+ // (see view2: Execute on this slot)
+ sal_uInt16 nGutterWidth = aCol.GetGutterWidth();
+ if(!nCols )
+ nCols++;
+ aCol.Init(nCols, nGutterWidth, aCol.GetWishWidth());
+ aSet.Put(aCol);
+ // Template AutoUpdate
+ SwFrameFormat* pFormat = rSh.GetSelectedFrameFormat();
+ if(pFormat && pFormat->IsAutoUpdateOnDirectFormat())
+ {
+ rSh.AutoUpdateFrame(pFormat, aSet);
+ }
+ else
+ {
+ rSh.StartAllAction();
+ rSh.SetFlyFrameAttr( aSet );
+ rSh.SetModified();
+ rSh.EndAllAction();
+ }
+
+ }
+ return;
+
+ case SID_HYPERLINK_SETLINK:
+ {
+ if(pArgs && SfxItemState::SET == pArgs->GetItemState(SID_HYPERLINK_SETLINK, false, &pItem))
+ {
+ const SvxHyperlinkItem& rHLinkItem = *static_cast<const SvxHyperlinkItem *>(pItem);
+ const OUString& rURL = rHLinkItem.GetURL();
+ const OUString& rTarget = rHLinkItem.GetTargetFrame();
+
+ SfxItemSetFixed<RES_URL, RES_URL> aSet( rSh.GetAttrPool() );
+ rSh.GetFlyFrameAttr( aSet );
+ SwFormatURL aURL( aSet.Get( RES_URL ) );
+
+ OUString sOldName(rHLinkItem.GetName().toAsciiUpperCase());
+ OUString sFlyName(rSh.GetFlyName().toAsciiUpperCase());
+ if (sOldName != sFlyName)
+ {
+ OUString sName(sOldName);
+ sal_uInt16 i = 1;
+ while (rSh.FindFlyByName(sName))
+ {
+ sName = sOldName + "_" + OUString::number(i++);
+ }
+ rSh.SetFlyName(sName);
+ }
+ aURL.SetURL( rURL, false );
+ aURL.SetTargetFrameName(rTarget);
+
+ aSet.Put( aURL );
+ rSh.SetFlyFrameAttr( aSet );
+ }
+ }
+ break;
+
+ case FN_FRAME_CHAIN:
+ rSh.GetView().GetEditWin().SetChainMode( !rSh.GetView().GetEditWin().IsChainMode() );
+ break;
+
+ case FN_FRAME_UNCHAIN:
+ rSh.Unchain( *rSh.GetFlyFrameFormat() );
+ GetView().GetViewFrame().GetBindings().Invalidate(FN_FRAME_CHAIN);
+ break;
+ case FN_FORMAT_FOOTNOTE_DLG:
+ {
+ GetView().ExecFormatFootnote();
+ break;
+ }
+ case FN_NUMBERING_OUTLINE_DLG:
+ {
+ GetView().ExecNumberingOutline(GetPool());
+ rReq.Done();
+ break;
+ }
+ case SID_OPEN_XML_FILTERSETTINGS:
+ {
+ HandleOpenXmlFilterSettings(rReq);
+ }
+ break;
+ case FN_WORDCOUNT_DIALOG:
+ {
+ GetView().UpdateWordCount(this, nSlot);
+ break;
+ }
+ case FN_UNFLOAT_FRAME:
+ {
+ rSh.UnfloatFlyFrame();
+ rReq.Done();
+ break;
+ }
+ default: bMore = true;
+ }
+
+ if ( !bMore )
+ {
+ return;
+ }
+
+ SwFlyFrameAttrMgr aMgr( false, &rSh, Frmmgr_Type::NONE, nullptr );
+ bool bUpdateMgr = true;
+ bool bCopyToFormat = false;
+ switch ( nSlot )
+ {
+ case SID_OBJECT_ALIGN_MIDDLE:
+ case FN_FRAME_ALIGN_VERT_CENTER:
+ aMgr.SetVertOrientation( text::VertOrientation::CENTER );
+ break;
+ case SID_OBJECT_ALIGN_DOWN :
+ case FN_FRAME_ALIGN_VERT_BOTTOM:
+ aMgr.SetVertOrientation( text::VertOrientation::BOTTOM );
+ break;
+ case SID_OBJECT_ALIGN_UP :
+ case FN_FRAME_ALIGN_VERT_TOP:
+ aMgr.SetVertOrientation( text::VertOrientation::TOP );
+ break;
+
+ case FN_FRAME_ALIGN_VERT_CHAR_CENTER:
+ aMgr.SetVertOrientation( text::VertOrientation::CHAR_CENTER );
+ break;
+
+ case FN_FRAME_ALIGN_VERT_CHAR_BOTTOM:
+ aMgr.SetVertOrientation( text::VertOrientation::CHAR_BOTTOM );
+ break;
+
+ case FN_FRAME_ALIGN_VERT_CHAR_TOP:
+ aMgr.SetVertOrientation( text::VertOrientation::CHAR_TOP );
+ break;
+
+ case FN_FRAME_ALIGN_VERT_ROW_CENTER:
+ aMgr.SetVertOrientation( text::VertOrientation::LINE_CENTER );
+ break;
+
+ case FN_FRAME_ALIGN_VERT_ROW_BOTTOM:
+ aMgr.SetVertOrientation( text::VertOrientation::LINE_BOTTOM );
+ break;
+
+ case FN_FRAME_ALIGN_VERT_ROW_TOP:
+ aMgr.SetVertOrientation( text::VertOrientation::LINE_TOP );
+ break;
+ case SID_OBJECT_ALIGN_CENTER :
+ case FN_FRAME_ALIGN_HORZ_CENTER:
+ aMgr.SetHorzOrientation( text::HoriOrientation::CENTER );
+ break;
+ case SID_OBJECT_ALIGN_RIGHT:
+ case FN_FRAME_ALIGN_HORZ_RIGHT:
+ aMgr.SetHorzOrientation( text::HoriOrientation::RIGHT );
+ break;
+ case SID_OBJECT_ALIGN_LEFT:
+ case FN_FRAME_ALIGN_HORZ_LEFT:
+ aMgr.SetHorzOrientation( text::HoriOrientation::LEFT );
+ break;
+
+ case FN_SET_FRM_POSITION:
+ {
+ aMgr.SetAbsPos(static_cast<const SfxPointItem &>(pArgs->Get
+ (FN_SET_FRM_POSITION)).GetValue());
+ }
+ break;
+ case SID_ATTR_BRUSH:
+ {
+ if(pArgs)
+ {
+ aMgr.SetAttrSet( *pArgs );
+ bCopyToFormat = true;
+ }
+ }
+ break;
+ case SID_ATTR_ULSPACE:
+ case SID_ATTR_LRSPACE:
+ {
+ if(pArgs && SfxItemState::SET == pArgs->GetItemState(GetPool().GetWhich(nSlot), false, &pItem))
+ {
+ aMgr.SetAttrSet( *pArgs );
+ bCopyToFormat = true;
+ }
+ }
+ break;
+
+ case SID_ATTR_TRANSFORM:
+ {
+ bool bApplyNewPos = false;
+ bool bApplyNewSize = false;
+
+ Point aNewPos = aMgr.GetPos();
+ if (pArgs)
+ {
+ if (const SfxInt32Item* pXItem = pArgs->GetItemIfSet(SID_ATTR_TRANSFORM_POS_X, false))
+ {
+ aNewPos.setX( pXItem->GetValue() );
+ bApplyNewPos = true;
+ }
+ if (const SfxInt32Item* pYItem = pArgs->GetItemIfSet(SID_ATTR_TRANSFORM_POS_Y, false))
+ {
+ aNewPos.setY( pYItem->GetValue() );
+ bApplyNewPos = true;
+ }
+ }
+
+ Size aNewSize = aMgr.GetSize();
+ if (pArgs)
+ {
+ if (const SfxUInt32Item* pWidthItem = pArgs->GetItemIfSet(SID_ATTR_TRANSFORM_WIDTH, false))
+ {
+ aNewSize.setWidth( pWidthItem->GetValue() );
+ bApplyNewSize = true;
+ }
+ if (const SfxUInt32Item* pHeightItem = pArgs->GetItemIfSet(SID_ATTR_TRANSFORM_HEIGHT, false))
+ {
+ aNewSize.setHeight( pHeightItem->GetValue() );
+ bApplyNewSize = true;
+ }
+ }
+
+ if (pArgs && (pArgs->HasItem(SID_ATTR_TRANSFORM_ANGLE) || pArgs->HasItem(SID_ATTR_TRANSFORM_DELTA_ANGLE)))
+ {
+ SfxItemSetFixed<RES_GRFATR_ROTATION, RES_GRFATR_ROTATION> aSet(rSh.GetAttrPool() );
+ rSh.GetCurAttr(aSet);
+ const SwRotationGrf& rRotation = aSet.Get(RES_GRFATR_ROTATION);
+ const Degree10 nOldRot(rRotation.GetValue());
+
+ if (const SdrAngleItem* pAngleItem = pArgs->GetItemIfSet(SID_ATTR_TRANSFORM_DELTA_ANGLE, false))
+ {
+ const Degree10 nDeltaRot = to<Degree10>(pAngleItem->GetValue());
+ aMgr.SetRotation(nOldRot, nOldRot + nDeltaRot, rRotation.GetUnrotatedSize());
+ }
+
+ // RotGrfFlyFrame: Get Value and disable is in SwGrfShell::GetAttrStateForRotation, but the
+ // value setter uses SID_ATTR_TRANSFORM and a group of three values. Rotation is
+ // added now, so use it in this central place. Do no forget to convert angle from
+ // 100th degrees in SID_ATTR_TRANSFORM_ANGLE to 10th degrees in RES_GRFATR_ROTATION
+ if (const SdrAngleItem* pTransformItem = pArgs->GetItemIfSet(SID_ATTR_TRANSFORM_ANGLE, false))
+ {
+ const Degree10 nNewRot = to<Degree10>(pTransformItem->GetValue());
+
+ // RotGrfFlyFrame: Rotation change here, SwFlyFrameAttrMgr aMgr is available
+ aMgr.SetRotation(nOldRot, nNewRot, rRotation.GetUnrotatedSize());
+ }
+ }
+
+ if (bApplyNewPos)
+ {
+ aMgr.SetAbsPos(aNewPos);
+ }
+ if ( bApplyNewSize )
+ {
+ aMgr.SetSize( aNewSize );
+ }
+ if (!bApplyNewPos && !bApplyNewSize)
+ {
+ bUpdateMgr = false;
+ }
+
+ }
+ break;
+
+ case FN_FORMAT_FRAME_DLG:
+ case FN_DRAW_WRAP_DLG:
+ {
+ const SelectionType nSel = rSh.GetSelectionType();
+ if (nSel & SelectionType::Graphic)
+ {
+ rSh.GetView().GetViewFrame().GetDispatcher()->Execute(FN_FORMAT_GRAFIC_DLG);
+ bUpdateMgr = false;
+ }
+ else
+ {
+ SfxItemSetFixed<
+ RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
+ // FillAttribute support:
+ XATTR_FILL_FIRST, XATTR_FILL_LAST,
+ SID_DOCFRAME, SID_DOCFRAME,
+ SID_ATTR_BRUSH, SID_ATTR_BRUSH,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
+ SID_ATTR_LRSPACE, SID_ATTR_ULSPACE,
+ SID_ATTR_PAGE_SIZE, SID_ATTR_PAGE_SIZE,
+ // Items to hand over XPropertyList things like
+ // XColorList, XHatchList, XGradientList, and
+ // XBitmapList to the Area TabPage
+ SID_COLOR_TABLE, SID_PATTERN_LIST,
+ SID_HTML_MODE, SID_HTML_MODE,
+ FN_GET_PRINT_AREA, FN_GET_PRINT_AREA,
+ FN_SURROUND, FN_KEEP_ASPECT_RATIO,
+ FN_SET_FRM_ALT_NAME, FN_SET_FRM_ALT_NAME,
+ FN_UNO_DESCRIPTION, FN_UNO_DESCRIPTION,
+ FN_OLE_IS_MATH, FN_MATH_BASELINE_ALIGNMENT,
+ FN_PARAM_CHAIN_PREVIOUS, FN_PARAM_CHAIN_NEXT> aSet( GetPool() );
+
+ // create needed items for XPropertyList entries from the DrawModel so that
+ // the Area TabPage can access them
+ const SwDrawModel* pDrawModel = rSh.GetView().GetDocShell()->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
+ pDrawModel->PutAreaListItems(aSet);
+
+ const SwViewOption* pVOpt = rSh.GetViewOptions();
+ if(nSel & SelectionType::Ole)
+ aSet.Put( SfxBoolItem(FN_KEEP_ASPECT_RATIO, pVOpt->IsKeepRatio()) );
+ aSet.Put(SfxUInt16Item(SID_HTML_MODE, ::GetHtmlMode(GetView().GetDocShell())));
+ aSet.Put(SfxStringItem(FN_SET_FRM_NAME, rSh.GetFlyName()));
+ aSet.Put(SfxStringItem(FN_UNO_DESCRIPTION, rSh.GetObjDescription()));
+ if( nSel & SelectionType::Ole )
+ {
+ // #i73249#
+ aSet.Put( SfxStringItem( FN_SET_FRM_ALT_NAME, rSh.GetObjTitle() ) );
+ }
+
+ const SwRect &rPg = rSh.GetAnyCurRect(CurRectType::Page);
+ SwFormatFrameSize aFrameSize(SwFrameSize::Variable, rPg.Width(), rPg.Height());
+ aFrameSize.SetWhich(GetPool().GetWhich(SID_ATTR_PAGE_SIZE));
+ aSet.Put(aFrameSize);
+
+ const SwRect &rPr = rSh.GetAnyCurRect(CurRectType::PagePrt);
+ SwFormatFrameSize aPrtSize(SwFrameSize::Variable, rPr.Width(), rPr.Height());
+ aPrtSize.SetWhich(GetPool().GetWhich(FN_GET_PRINT_AREA));
+ aSet.Put(aPrtSize);
+
+ aSet.Put(aMgr.GetAttrSet());
+ aSet.SetParent( aMgr.GetAttrSet().GetParent() );
+
+ // On % values initialize size
+ SwFormatFrameSize& rSize = const_cast<SwFormatFrameSize&>(aSet.Get(RES_FRM_SIZE));
+ if (rSize.GetWidthPercent() && rSize.GetWidthPercent() != SwFormatFrameSize::SYNCED)
+ rSize.SetWidth(rSh.GetAnyCurRect(CurRectType::FlyEmbedded).Width());
+ if (rSize.GetHeightPercent() && rSize.GetHeightPercent() != SwFormatFrameSize::SYNCED)
+ rSize.SetHeight(rSh.GetAnyCurRect(CurRectType::FlyEmbedded).Height());
+
+ // disable vertical positioning for Math Objects anchored 'as char' if baseline alignment is activated
+ aSet.Put( SfxBoolItem( FN_MATH_BASELINE_ALIGNMENT,
+ rSh.GetDoc()->getIDocumentSettingAccess().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT ) ) );
+ const uno::Reference < embed::XEmbeddedObject > xObj( rSh.GetOleRef() );
+ aSet.Put( SfxBoolItem( FN_OLE_IS_MATH, xObj.is() && SotExchange::IsMath( xObj->getClassID() ) ) );
+
+ OUString sDefPage;
+ const SfxStringItem* pDlgItem;
+ if(pArgs && (pDlgItem = pArgs->GetItemIfSet(FN_FORMAT_FRAME_DLG, false)))
+ sDefPage = pDlgItem->GetValue();
+
+ aSet.Put(SfxFrameItem( SID_DOCFRAME, &GetView().GetViewFrame().GetFrame()));
+ FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( &GetView()) != nullptr );
+ SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric) ));
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateFrameTabDialog(
+ nSel & SelectionType::Graphic ? OUString("PictureDialog") :
+ nSel & SelectionType::Ole ? OUString("ObjectDialog"):
+ OUString("FrameDialog"),
+ GetView().GetViewFrame(),
+ GetView().GetFrameWeld(),
+ aSet,
+ false,
+ sDefPage));
+
+ if ( nSlot == FN_DRAW_WRAP_DLG )
+ {
+ pDlg->SetCurPageId("wrap");
+ }
+
+ if ( pDlg->Execute() )
+ {
+ const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
+ if(pOutSet)
+ {
+ rReq.Done(*pOutSet);
+ const SfxBoolItem* pRatioItem = nullptr;
+ if(nSel & SelectionType::Ole &&
+ (pRatioItem = pOutSet->GetItemIfSet(FN_KEEP_ASPECT_RATIO)))
+ {
+ SwViewOption aUsrPref( *pVOpt );
+ aUsrPref.SetKeepRatio(pRatioItem->GetValue());
+ SW_MOD()->ApplyUsrPref(aUsrPref, &GetView());
+ }
+ if (const SfxStringItem* pAltNameItem = pOutSet->GetItemIfSet(FN_SET_FRM_ALT_NAME))
+ {
+ // #i73249#
+ rSh.SetObjTitle(pAltNameItem->GetValue());
+ }
+ if (const SfxStringItem* pDescripItem = pOutSet->GetItemIfSet(FN_UNO_DESCRIPTION))
+ rSh.SetObjDescription(pDescripItem->GetValue());
+
+ // Template AutoUpdate
+ SwFrameFormat* pFormat = rSh.GetSelectedFrameFormat();
+ if(pFormat && pFormat->IsAutoUpdateOnDirectFormat())
+ {
+ rSh.AutoUpdateFrame(pFormat, *pOutSet);
+ // Anything which is not supported by the format must be set hard.
+ if(const SfxStringItem* pFrameName = pOutSet->GetItemIfSet(FN_SET_FRM_NAME, false))
+ rSh.SetFlyName(pFrameName->GetValue());
+ SfxItemSetFixed<
+ RES_FRM_SIZE, RES_FRM_SIZE,
+ RES_SURROUND, RES_ANCHOR> aShellSet( GetPool() );
+ aShellSet.Put(*pOutSet);
+ aMgr.SetAttrSet(aShellSet);
+ if(const SfxStringItem* pFrameName = pOutSet->GetItemIfSet(FN_SET_FRM_NAME, false))
+ rSh.SetFlyName(pFrameName->GetValue());
+ }
+ else
+ aMgr.SetAttrSet( *pOutSet );
+
+ const SwFrameFormat* pCurrFlyFormat = rSh.GetFlyFrameFormat();
+ if(const SfxStringItem* pPreviousItem =
+ pOutSet->GetItemIfSet(FN_PARAM_CHAIN_PREVIOUS, false))
+ {
+ rSh.HideChainMarker();
+
+ OUString sPrevName = pPreviousItem->GetValue();
+ const SwFormatChain &rChain = pCurrFlyFormat->GetChain();
+ //needs cast - no non-const method available
+ SwFlyFrameFormat* pFlyFormat =
+ rChain.GetPrev();
+ if(pFlyFormat)
+ {
+ if (pFlyFormat->GetName() != sPrevName)
+ {
+ rSh.Unchain(*pFlyFormat);
+ }
+ else
+ sPrevName.clear();
+ }
+
+ if (!sPrevName.isEmpty())
+ {
+ //needs cast - no non-const method available
+ SwFrameFormat* pPrevFormat = const_cast<SwFrameFormat*>(
+ lcl_GetFrameFormatByName(rSh, sPrevName));
+ SAL_WARN_IF(!pPrevFormat, "sw.ui", "No frame found!");
+ if(pPrevFormat)
+ {
+ rSh.Chain(*pPrevFormat, *pCurrFlyFormat);
+ }
+ }
+ rSh.SetChainMarker();
+ }
+ if(const SfxStringItem* pChainNextItem =
+ pOutSet->GetItemIfSet(FN_PARAM_CHAIN_NEXT, false))
+ {
+ rSh.HideChainMarker();
+ OUString sNextName = pChainNextItem->GetValue();
+ const SwFormatChain &rChain = pCurrFlyFormat->GetChain();
+ //needs cast - no non-const method available
+ SwFlyFrameFormat* pFlyFormat =
+ rChain.GetNext();
+ if(pFlyFormat)
+ {
+ if (pFlyFormat->GetName() != sNextName)
+ {
+ rSh.Unchain(*const_cast<SwFlyFrameFormat*>(static_cast<const SwFlyFrameFormat*>( pCurrFlyFormat)));
+ }
+ else
+ sNextName.clear();
+ }
+
+ if (!sNextName.isEmpty())
+ {
+ //needs cast - no non-const method available
+ SwFrameFormat* pNextFormat = const_cast<SwFrameFormat*>(
+ lcl_GetFrameFormatByName(rSh, sNextName));
+ SAL_WARN_IF(!pNextFormat, "sw.ui", "No frame found!");
+ if(pNextFormat)
+ {
+ rSh.Chain(*const_cast<SwFrameFormat*>(
+ pCurrFlyFormat), *pNextFormat);
+ }
+ }
+ rSh.SetChainMarker();
+ }
+ }
+ }
+ else
+ bUpdateMgr = false;
+ }
+ }
+ break;
+ case FN_FRAME_MIRROR_ON_EVEN_PAGES:
+ {
+ SwFormatHoriOrient aHori(aMgr.GetHoriOrient());
+ bool bMirror = !aHori.IsPosToggle();
+ aHori.SetPosToggle(bMirror);
+ SfxItemSetFixed<RES_HORI_ORIENT, RES_HORI_ORIENT> aSet(GetPool());
+ aSet.Put(aHori);
+ aMgr.SetAttrSet(aSet);
+ bCopyToFormat = true;
+ rReq.SetReturnValue(SfxBoolItem(nSlot, bMirror));
+ }
+ break;
+ case FN_NAME_SHAPE:
+ {
+ bUpdateMgr = false;
+ SdrView* pSdrView = rSh.GetDrawViewWithValidMarkList();
+ if ( pSdrView &&
+ pSdrView->GetMarkedObjectCount() == 1 )
+ {
+ OUString aName(rSh.GetFlyName());
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractSvxObjectNameDialog> pDlg(
+ pFact->CreateSvxObjectNameDialog(GetView().GetFrameWeld(), aName));
+
+ if ( pDlg->Execute() == RET_OK )
+ {
+ pDlg->GetName(aName);
+ rSh.SetFlyName(aName);
+ }
+ }
+ }
+ break;
+ // #i73249#
+ case FN_TITLE_DESCRIPTION_SHAPE:
+ {
+ bUpdateMgr = false;
+ SdrView* pSdrView = rSh.GetDrawViewWithValidMarkList();
+ if ( pSdrView &&
+ pSdrView->GetMarkedObjectCount() == 1 )
+ {
+ OUString aDescription(rSh.GetObjDescription());
+ OUString aTitle(rSh.GetObjTitle());
+ bool isDecorative(rSh.IsObjDecorative());
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractSvxObjectTitleDescDialog> pDlg(
+ pFact->CreateSvxObjectTitleDescDialog(GetView().GetFrameWeld(),
+ aTitle, aDescription, isDecorative));
+
+ if ( pDlg->Execute() == RET_OK )
+ {
+ pDlg->GetDescription(aDescription);
+ pDlg->GetTitle(aTitle);
+ pDlg->IsDecorative(isDecorative);
+
+ rSh.SetObjDescription(aDescription);
+ rSh.SetObjTitle(aTitle);
+ rSh.SetObjDecorative(isDecorative);
+ }
+ }
+ }
+ break;
+ default:
+ assert(!"wrong dispatcher");
+ return;
+ }
+ if ( bUpdateMgr )
+ {
+ SwFrameFormat* pFormat = rSh.GetSelectedFrameFormat();
+ if ( bCopyToFormat && pFormat && pFormat->IsAutoUpdateOnDirectFormat() )
+ {
+ rSh.AutoUpdateFrame(pFormat, aMgr.GetAttrSet());
+ }
+ else
+ {
+ aMgr.UpdateFlyFrame();
+ }
+ }
+
+}
+
+void SwFrameShell::GetState(SfxItemSet& rSet)
+{
+ SwWrtShell &rSh = GetShell();
+ bool bHtmlMode = 0 != ::GetHtmlMode(rSh.GetView().GetDocShell());
+ if (!rSh.IsFrameSelected())
+ return;
+
+ SfxItemSetFixed<
+ RES_LR_SPACE, RES_UL_SPACE,
+ RES_PRINT, RES_HORI_ORIENT> aSet(rSh.GetAttrPool() );
+ rSh.GetFlyFrameAttr( aSet );
+
+ bool bProtect = rSh.IsSelObjProtected(FlyProtectFlags::Pos) != FlyProtectFlags::NONE;
+ bool bParentCntProt = rSh.IsSelObjProtected( FlyProtectFlags::Content|FlyProtectFlags::Parent ) != FlyProtectFlags::NONE;
+
+ bProtect |= bParentCntProt;
+
+ const FrameTypeFlags eFrameType = rSh.GetFrameType(nullptr,true);
+ SwFlyFrameAttrMgr aMgr( false, &rSh, Frmmgr_Type::NONE, nullptr );
+
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while ( nWhich )
+ {
+ switch ( nWhich )
+ {
+ case RES_FRM_SIZE:
+ {
+ const SwFormatFrameSize& aSz(aMgr.GetFrameSize());
+ rSet.Put(aSz);
+ }
+ break;
+ case RES_VERT_ORIENT:
+ case RES_HORI_ORIENT:
+ case SID_ATTR_ULSPACE:
+ case SID_ATTR_LRSPACE:
+ case RES_LR_SPACE:
+ case RES_UL_SPACE:
+ case RES_PROTECT:
+ case RES_OPAQUE:
+ case RES_PRINT:
+ case RES_SURROUND:
+ {
+ rSet.Put(aSet.Get(GetPool().GetWhich(nWhich)));
+ }
+ break;
+ case SID_OBJECT_ALIGN:
+ {
+ if ( bProtect )
+ rSet.DisableItem( nWhich );
+ }
+ break;
+ case SID_OBJECT_ALIGN_LEFT :
+ case SID_OBJECT_ALIGN_CENTER :
+ case SID_OBJECT_ALIGN_RIGHT :
+ case FN_FRAME_ALIGN_HORZ_CENTER:
+ case FN_FRAME_ALIGN_HORZ_RIGHT:
+ case FN_FRAME_ALIGN_HORZ_LEFT:
+ if ( (eFrameType & FrameTypeFlags::FLY_INCNT) ||
+ bProtect ||
+ ((nWhich == FN_FRAME_ALIGN_HORZ_CENTER || nWhich == SID_OBJECT_ALIGN_CENTER) &&
+ bHtmlMode ))
+ {
+ rSet.DisableItem( nWhich );
+ }
+ else
+ {
+ sal_Int16 nHoriOrient = -1;
+ switch(nWhich)
+ {
+ case SID_OBJECT_ALIGN_LEFT:
+ nHoriOrient = text::HoriOrientation::LEFT;
+ break;
+ case SID_OBJECT_ALIGN_CENTER:
+ nHoriOrient = text::HoriOrientation::CENTER;
+ break;
+ case SID_OBJECT_ALIGN_RIGHT:
+ nHoriOrient = text::HoriOrientation::RIGHT;
+ break;
+ default:
+ break;
+ }
+ SwFormatHoriOrient aHOrient(aMgr.GetHoriOrient());
+ if (nHoriOrient != -1)
+ rSet.Put(SfxBoolItem(nWhich, nHoriOrient == aHOrient.GetHoriOrient()));
+ }
+ break;
+ case FN_FRAME_ALIGN_VERT_ROW_TOP:
+ case FN_FRAME_ALIGN_VERT_ROW_CENTER:
+ case FN_FRAME_ALIGN_VERT_ROW_BOTTOM:
+ case FN_FRAME_ALIGN_VERT_CHAR_TOP:
+ case FN_FRAME_ALIGN_VERT_CHAR_CENTER:
+ case FN_FRAME_ALIGN_VERT_CHAR_BOTTOM:
+ if ( !(eFrameType & FrameTypeFlags::FLY_INCNT) || bProtect
+ || (bHtmlMode && FN_FRAME_ALIGN_VERT_CHAR_BOTTOM == nWhich) )
+ rSet.DisableItem( nWhich );
+ break;
+
+ case SID_OBJECT_ALIGN_UP :
+ case SID_OBJECT_ALIGN_MIDDLE :
+ case SID_OBJECT_ALIGN_DOWN :
+
+ case FN_FRAME_ALIGN_VERT_TOP:
+ case FN_FRAME_ALIGN_VERT_CENTER:
+ case FN_FRAME_ALIGN_VERT_BOTTOM:
+ if ( bProtect || (bHtmlMode && eFrameType & FrameTypeFlags::FLY_ATCNT))
+ rSet.DisableItem( nWhich );
+ else
+ {
+ // These slots need different labels depending on whether they are anchored in a character
+ // or on a paragraph/page etc.
+ OUString sNewLabel;
+ if (eFrameType & FrameTypeFlags::FLY_INCNT)
+ {
+ switch (nWhich)
+ {
+ case SID_OBJECT_ALIGN_UP :
+ case FN_FRAME_ALIGN_VERT_TOP:
+ sNewLabel = SwResId(STR_FRMUI_TOP_BASE);
+ break;
+ case SID_OBJECT_ALIGN_MIDDLE :
+ case FN_FRAME_ALIGN_VERT_CENTER:
+ sNewLabel = SwResId(STR_FRMUI_CENTER_BASE);
+ break;
+ case SID_OBJECT_ALIGN_DOWN :
+ case FN_FRAME_ALIGN_VERT_BOTTOM:
+ if(!bHtmlMode)
+ sNewLabel = SwResId(STR_FRMUI_BOTTOM_BASE);
+ else
+ rSet.DisableItem( nWhich );
+ break;
+ }
+ }
+ else
+ {
+ if (nWhich != FN_FRAME_ALIGN_VERT_TOP &&
+ nWhich != SID_OBJECT_ALIGN_UP )
+ {
+ if (aMgr.GetAnchor() == RndStdIds::FLY_AT_FLY)
+ {
+ const SwFrameFormat* pFormat = rSh.IsFlyInFly();
+ if (pFormat)
+ {
+ const SwFormatFrameSize& rFrameSz = pFormat->GetFrameSize();
+ if (rFrameSz.GetHeightSizeType() != SwFrameSize::Fixed)
+ {
+ rSet.DisableItem( nWhich );
+ break;
+ }
+ }
+ }
+ }
+ OUString aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(GetFrame()->GetFrame().GetFrameInterface()));
+ switch (nWhich)
+ {
+ case SID_OBJECT_ALIGN_UP :
+ case FN_FRAME_ALIGN_VERT_TOP:
+ {
+ auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(".uno:AlignTop", aModuleName);
+ sNewLabel = vcl::CommandInfoProvider::GetLabelForCommand(aProperties);
+ break;
+ }
+ case SID_OBJECT_ALIGN_MIDDLE:
+ case FN_FRAME_ALIGN_VERT_CENTER:
+ {
+ auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(".uno:AlignVerticalCenter", aModuleName);
+ sNewLabel = vcl::CommandInfoProvider::GetLabelForCommand(aProperties);
+ break;
+ }
+ case SID_OBJECT_ALIGN_DOWN:
+ case FN_FRAME_ALIGN_VERT_BOTTOM:
+ {
+ auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(".uno:AlignBottom", aModuleName);
+ sNewLabel = vcl::CommandInfoProvider::GetLabelForCommand(aProperties);
+ break;
+ }
+ }
+ }
+ if ( !sNewLabel.isEmpty() )
+ rSet.Put( SfxStringItem( nWhich, sNewLabel ));
+ }
+ break;
+ case SID_HYPERLINK_GETLINK:
+ {
+ SvxHyperlinkItem aHLinkItem;
+
+ SfxItemSetFixed<RES_URL, RES_URL> aURLSet(GetPool());
+ rSh.GetFlyFrameAttr( aURLSet );
+
+ if(const SwFormatURL* pFormatURL = aURLSet.GetItemIfSet(RES_URL))
+ {
+ aHLinkItem.SetURL(pFormatURL->GetURL());
+ aHLinkItem.SetTargetFrame(pFormatURL->GetTargetFrameName());
+ aHLinkItem.SetName(rSh.GetFlyName());
+ }
+
+ aHLinkItem.SetInsertMode(static_cast<SvxLinkInsertMode>(aHLinkItem.GetInsertMode() |
+ (bHtmlMode ? HLINK_HTMLMODE : 0)));
+
+ rSet.Put(aHLinkItem);
+ }
+ break;
+
+ case FN_FRAME_CHAIN:
+ {
+ const SelectionType nSel = rSh.GetSelectionType();
+ if (nSel & SelectionType::Graphic || nSel & SelectionType::Ole)
+ rSet.DisableItem( FN_FRAME_CHAIN );
+ else
+ {
+ const SwFrameFormat *pFormat = rSh.GetFlyFrameFormat();
+ if ( bParentCntProt || rSh.GetView().GetEditWin().GetApplyTemplate() ||
+ !pFormat || pFormat->GetChain().GetNext() )
+ {
+ rSet.DisableItem( FN_FRAME_CHAIN );
+ }
+ else
+ {
+ bool bChainMode = rSh.GetView().GetEditWin().IsChainMode();
+ rSet.Put( SfxBoolItem( FN_FRAME_CHAIN, bChainMode ) );
+ }
+ }
+ }
+ break;
+ case FN_FRAME_UNCHAIN:
+ {
+ const SelectionType nSel = rSh.GetSelectionType();
+ if (nSel & SelectionType::Graphic || nSel & SelectionType::Ole)
+ rSet.DisableItem( FN_FRAME_UNCHAIN );
+ else
+ {
+ const SwFrameFormat *pFormat = rSh.GetFlyFrameFormat();
+ if ( bParentCntProt || rSh.GetView().GetEditWin().GetApplyTemplate() ||
+ !pFormat || !pFormat->GetChain().GetNext() )
+ {
+ rSet.DisableItem( FN_FRAME_UNCHAIN );
+ }
+ }
+ }
+ break;
+ case SID_FRAME_TO_TOP:
+ case SID_FRAME_TO_BOTTOM:
+ case FN_FRAME_UP:
+ case FN_FRAME_DOWN:
+ if ( bParentCntProt )
+ rSet.DisableItem( nWhich );
+ break;
+
+ case SID_ATTR_TRANSFORM:
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case SID_ATTR_TRANSFORM_PROTECT_SIZE:
+ {
+ const FlyProtectFlags eProtection = rSh.IsSelObjProtected( FlyProtectFlags::Size );
+ if ( ( eProtection & FlyProtectFlags::Content ) ||
+ ( eProtection & FlyProtectFlags::Size ) )
+ {
+ rSet.Put( SfxBoolItem( SID_ATTR_TRANSFORM_PROTECT_SIZE, true ) );
+ }
+ else
+ {
+ rSet.Put( SfxBoolItem( SID_ATTR_TRANSFORM_PROTECT_SIZE, false ) );
+ }
+ }
+ break;
+
+ case SID_ATTR_TRANSFORM_WIDTH:
+ {
+ rSet.Put( SfxUInt32Item( SID_ATTR_TRANSFORM_WIDTH, aMgr.GetSize().getWidth() ) );
+ }
+ break;
+
+ case SID_ATTR_TRANSFORM_HEIGHT:
+ {
+ rSet.Put( SfxUInt32Item( SID_ATTR_TRANSFORM_HEIGHT, aMgr.GetSize().getHeight() ) );
+ }
+ break;
+
+ case FN_FORMAT_FRAME_DLG:
+ {
+ const SelectionType nSel = rSh.GetSelectionType();
+ if ( bParentCntProt || nSel & SelectionType::Graphic)
+ rSet.DisableItem( nWhich );
+ }
+ break;
+ // #i73249#
+ case FN_TITLE_DESCRIPTION_SHAPE:
+ case FN_NAME_SHAPE:
+ {
+ SwWrtShell &rWrtSh = GetShell();
+ SdrView* pSdrView = rWrtSh.GetDrawViewWithValidMarkList();
+ if ( !pSdrView ||
+ pSdrView->GetMarkedObjectCount() != 1 )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ }
+ break;
+
+ case FN_POSTIT:
+ {
+ SwFlyFrame* pFly = rSh.GetSelectedFlyFrame();
+ if (pFly)
+ {
+ SwFrameFormat* pFormat = pFly->GetFormat();
+ if (pFormat)
+ {
+ RndStdIds eAnchorId = pFormat->GetAnchor().GetAnchorId();
+ // SwWrtShell::InsertPostIt() only works on as-char and at-char anchored
+ // images.
+ if (eAnchorId != RndStdIds::FLY_AS_CHAR && eAnchorId != RndStdIds::FLY_AT_CHAR)
+ {
+ rSet.DisableItem(nWhich);
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ /* do nothing */;
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+SwFrameShell::SwFrameShell(SwView &_rView) :
+ SwBaseShell( _rView )
+{
+ SetName("Frame");
+
+ // #96392# Use this to announce it is the frame shell who creates the selection.
+ SwTransferable::CreateSelection( _rView.GetWrtShell(), this );
+
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Frame));
+}
+
+SwFrameShell::~SwFrameShell()
+{
+ // #96392# Only clear the selection if it was this frame shell who created it.
+ SwTransferable::ClearSelection( GetShell(), this );
+}
+
+void SwFrameShell::ExecFrameStyle(SfxRequest const & rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ bool bDefault = false;
+ if (!rSh.IsFrameSelected())
+ return;
+ // At first pick the default BoxItem out of the pool.
+ // If unequal to regular box item, then it has already
+ // been changed (New one is no default).
+ const SvxBoxItem* pPoolBoxItem = ::GetDfltAttr(RES_BOX);
+
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ SfxItemSetFixed<RES_BOX, RES_BOX> aFrameSet(rSh.GetAttrPool());
+
+ rSh.GetFlyFrameAttr( aFrameSet );
+ const SvxBoxItem& rBoxItem = aFrameSet.Get(RES_BOX);
+
+ if (SfxPoolItem::areSame(pPoolBoxItem, &rBoxItem))
+ bDefault = true;
+
+ std::unique_ptr<SvxBoxItem> aBoxItem(rBoxItem.Clone());
+
+ SvxBorderLine aBorderLine;
+
+ if(pArgs) // Any controller can sometimes deliver nothing #48169#
+ {
+ switch (rReq.GetSlot())
+ {
+ case SID_ATTR_BORDER:
+ {
+ if (const SvxBoxItem* pBoxItem = pArgs->GetItemIfSet(RES_BOX))
+ {
+ std::unique_ptr<SvxBoxItem> aNewBox(pBoxItem->Clone());
+ const SvxBorderLine* pBorderLine;
+
+ pBorderLine = aBoxItem->GetTop();
+ if (pBorderLine != nullptr)
+ lcl_FrameGetMaxLineWidth(pBorderLine, aBorderLine);
+ pBorderLine = aBoxItem->GetBottom();
+ if (pBorderLine != nullptr)
+ lcl_FrameGetMaxLineWidth(pBorderLine, aBorderLine);
+ pBorderLine = aBoxItem->GetLeft();
+ if (pBorderLine != nullptr)
+ lcl_FrameGetMaxLineWidth(pBorderLine, aBorderLine);
+ pBorderLine = aBoxItem->GetRight();
+ if (pBorderLine != nullptr)
+ lcl_FrameGetMaxLineWidth(pBorderLine, aBorderLine);
+
+ if(aBorderLine.GetOutWidth() == 0)
+ {
+ aBorderLine.SetBorderLineStyle(
+ SvxBorderLineStyle::SOLID);
+ aBorderLine.SetWidth( SvxBorderLineWidth::Hairline );
+ }
+ //Set distance only if the request is received from the controller.
+
+#if HAVE_FEATURE_SCRIPTING
+ if(!StarBASIC::IsRunning())
+#endif
+ {
+ // TODO: should this copy 4 individual Dist instead?
+ aNewBox->SetAllDistances(rBoxItem.GetSmallestDistance());
+ }
+
+ aBoxItem = std::move(aNewBox);
+
+ if( aBoxItem->GetTop() != nullptr )
+ aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::TOP);
+ if( aBoxItem->GetBottom() != nullptr )
+ aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::BOTTOM);
+ if( aBoxItem->GetLeft() != nullptr )
+ aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::LEFT);
+ if( aBoxItem->GetRight() != nullptr )
+ aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::RIGHT);
+ }
+ }
+ break;
+
+ case SID_FRAME_LINESTYLE:
+ {
+ if ( const SvxLineItem* pLineItem = pArgs->GetItemIfSet(SID_FRAME_LINESTYLE, false))
+ {
+ if ( pLineItem->GetLine() )
+ {
+ aBorderLine = *(pLineItem->GetLine());
+
+ if (!aBoxItem->GetTop() && !aBoxItem->GetBottom() &&
+ !aBoxItem->GetLeft() && !aBoxItem->GetRight())
+ {
+ aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::TOP);
+ aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::BOTTOM);
+ aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::LEFT);
+ aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::RIGHT);
+ }
+ else
+ {
+ if( aBoxItem->GetTop() )
+ {
+ aBorderLine.SetColor( aBoxItem->GetTop()->GetColor() );
+ aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::TOP);
+ }
+ if( aBoxItem->GetBottom() )
+ {
+ aBorderLine.SetColor( aBoxItem->GetBottom()->GetColor());
+ aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::BOTTOM);
+ }
+ if( aBoxItem->GetLeft() )
+ {
+ aBorderLine.SetColor( aBoxItem->GetLeft()->GetColor());
+ aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::LEFT);
+ }
+ if( aBoxItem->GetRight() )
+ {
+ aBorderLine.SetColor(aBoxItem->GetRight()->GetColor());
+ aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::RIGHT);
+ }
+ }
+ }
+ else
+ {
+ aBoxItem->SetLine(nullptr, SvxBoxItemLine::TOP);
+ aBoxItem->SetLine(nullptr, SvxBoxItemLine::BOTTOM);
+ aBoxItem->SetLine(nullptr, SvxBoxItemLine::LEFT);
+ aBoxItem->SetLine(nullptr, SvxBoxItemLine::RIGHT);
+ }
+ }
+ }
+ break;
+
+ case SID_FRAME_LINECOLOR:
+ {
+ if (const SvxColorItem* pColorItem = pArgs->GetItemIfSet(SID_FRAME_LINECOLOR, false))
+ {
+ const Color& rNewColor = pColorItem->GetValue();
+
+ if (!aBoxItem->GetTop() && !aBoxItem->GetBottom() &&
+ !aBoxItem->GetLeft() && !aBoxItem->GetRight())
+ {
+ aBorderLine.SetColor( rNewColor );
+ aBorderLine.SetBorderLineStyle(SvxBorderLineStyle::SOLID);
+ aBorderLine.SetWidth(SvxBorderLineWidth::Hairline);
+
+ aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::TOP);
+ aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::BOTTOM);
+ aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::LEFT);
+ aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::RIGHT);
+ }
+ else
+ {
+ if (aBoxItem->GetTop())
+ aBoxItem->GetTop()->SetColor(rNewColor);
+ if (aBoxItem->GetBottom())
+ aBoxItem->GetBottom()->SetColor(rNewColor);
+ if (aBoxItem->GetLeft())
+ aBoxItem->GetLeft()->SetColor(rNewColor);
+ if (aBoxItem->GetRight())
+ aBoxItem->GetRight()->SetColor(rNewColor);
+ }
+ }
+ }
+ break;
+ }
+ }
+ if (bDefault && (aBoxItem->GetTop() || aBoxItem->GetBottom() ||
+ aBoxItem->GetLeft() || aBoxItem->GetRight()))
+ {
+ aBoxItem->SetAllDistances(MIN_BORDER_DIST);
+ }
+ aFrameSet.Put( std::move(aBoxItem) );
+ // Template AutoUpdate
+ SwFrameFormat* pFormat = rSh.GetSelectedFrameFormat();
+ if(pFormat && pFormat->IsAutoUpdateOnDirectFormat())
+ {
+ rSh.AutoUpdateFrame(pFormat, aFrameSet);
+ }
+ else
+ rSh.SetFlyFrameAttr( aFrameSet );
+
+}
+
+static void lcl_FrameGetMaxLineWidth(const SvxBorderLine* pBorderLine, SvxBorderLine& rBorderLine)
+{
+ if(pBorderLine->GetWidth() > rBorderLine.GetWidth())
+ rBorderLine.SetWidth(pBorderLine->GetWidth());
+
+ rBorderLine.SetBorderLineStyle(pBorderLine->GetBorderLineStyle());
+ rBorderLine.SetColor(pBorderLine->GetColor());
+}
+
+void SwFrameShell::GetLineStyleState(SfxItemSet &rSet)
+{
+ SwWrtShell &rSh = GetShell();
+ bool bParentCntProt = rSh.IsSelObjProtected( FlyProtectFlags::Content|FlyProtectFlags::Parent ) != FlyProtectFlags::NONE;
+
+ if (bParentCntProt)
+ {
+ if (rSh.IsFrameSelected())
+ rSet.DisableItem( SID_FRAME_LINECOLOR );
+
+ rSet.DisableItem( SID_ATTR_BORDER );
+ rSet.DisableItem( SID_FRAME_LINESTYLE );
+ }
+ else
+ {
+ if (rSh.IsFrameSelected())
+ {
+ SfxItemSetFixed<RES_BOX, RES_BOX> aFrameSet( rSh.GetAttrPool() );
+
+ rSh.GetFlyFrameAttr(aFrameSet);
+
+ const SvxBorderLine* pLine = aFrameSet.Get(RES_BOX).GetTop();
+ rSet.Put(SvxColorItem(pLine ? pLine->GetColor() : Color(), SID_FRAME_LINECOLOR));
+ }
+ }
+}
+
+void SwFrameShell::StateInsert(SfxItemSet &rSet)
+{
+ const SelectionType nSel = GetShell().GetSelectionType();
+ if ( (nSel & SelectionType::Graphic)
+ || (nSel & SelectionType::Ole) )
+ {
+ rSet.DisableItem(FN_INSERT_FRAME);
+ }
+ else if ( GetShell().CursorInsideInputField() )
+ {
+ rSet.DisableItem(FN_INSERT_FRAME);
+ }
+}
+
+void SwFrameShell::GetDrawAttrStateTextFrame(SfxItemSet &rSet)
+{
+ SwWrtShell &rSh = GetShell();
+
+ if(rSh.IsFrameSelected())
+ {
+ rSh.GetFlyFrameAttr(rSet);
+ }
+ else
+ {
+ SdrView* pSdrView = rSh.GetDrawViewWithValidMarkList();
+
+ if(pSdrView)
+ {
+ rSet.Put(pSdrView->GetDefaultAttr());
+ }
+ }
+}
+
+void SwFrameShell::ExecDrawAttrArgsTextFrame(SfxRequest const & rReq)
+{
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ SwWrtShell& rSh = GetShell();
+
+ if(pArgs)
+ {
+ if(rSh.IsFrameSelected())
+ {
+ rSh.SetFlyFrameAttr(const_cast< SfxItemSet& >(*pArgs));
+ }
+ else
+ {
+ SdrView* pSdrView = rSh.GetDrawViewWithValidMarkList();
+
+ if(pSdrView)
+ {
+ pSdrView->SetDefaultAttr(*pArgs, false);
+ }
+ }
+ }
+ else
+ {
+ SfxDispatcher* pDis = rSh.GetView().GetViewFrame().GetDispatcher();
+
+ switch(rReq.GetSlot())
+ {
+ case SID_ATTR_FILL_STYLE:
+ case SID_ATTR_FILL_COLOR:
+ case SID_ATTR_FILL_GRADIENT:
+ case SID_ATTR_FILL_HATCH:
+ case SID_ATTR_FILL_BITMAP:
+ case SID_ATTR_FILL_TRANSPARENCE:
+ case SID_ATTR_FILL_FLOATTRANSPARENCE:
+ {
+ pDis->Execute(SID_ATTRIBUTES_AREA);
+ break;
+ }
+ }
+ }
+}
+
+void SwFrameShell::ExecDrawDlgTextFrame(SfxRequest const & rReq)
+{
+ switch(rReq.GetSlot())
+ {
+ case SID_ATTRIBUTES_AREA:
+ {
+ SwWrtShell& rSh = GetShell();
+
+ if(rSh.IsFrameSelected())
+ {
+ SdrModel& rModel = rSh.GetDrawView()->GetModel();
+ SfxItemSet aNewAttr(rModel.GetItemPool());
+
+ // get attributes from FlyFrame
+ rSh.GetFlyFrameAttr(aNewAttr);
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ VclPtr<AbstractSvxAreaTabDialog> pDlg(pFact->CreateSvxAreaTabDialog(
+ GetView().GetFrameWeld(),
+ &aNewAttr,
+ &rModel,
+ false,
+ false));
+
+ pDlg->StartExecuteAsync([pDlg, this](sal_Int32 nResult){
+ if(nResult == RET_OK)
+ {
+ // set attributes at FlyFrame
+ GetShell().SetFlyFrameAttr(const_cast< SfxItemSet& >(*pDlg->GetOutputItemSet()));
+
+ static sal_uInt16 aInval[] =
+ {
+ SID_ATTR_FILL_STYLE,
+ SID_ATTR_FILL_COLOR,
+ SID_ATTR_FILL_TRANSPARENCE,
+ SID_ATTR_FILL_FLOATTRANSPARENCE,
+ 0
+ };
+
+ SfxBindings &rBnd = GetView().GetViewFrame().GetBindings();
+
+ rBnd.Invalidate(aInval);
+ rBnd.Update(SID_ATTR_FILL_STYLE);
+ rBnd.Update(SID_ATTR_FILL_COLOR);
+ rBnd.Update(SID_ATTR_FILL_TRANSPARENCE);
+ rBnd.Update(SID_ATTR_FILL_FLOATTRANSPARENCE);
+ }
+ pDlg->disposeOnce();
+ });
+ }
+
+ break;
+ }
+ }
+}
+
+void SwFrameShell::DisableStateTextFrame(SfxItemSet &rSet)
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich(aIter.FirstWhich());
+
+ while(nWhich)
+ {
+ switch(nWhich)
+ {
+ case SID_ATTRIBUTES_AREA:
+ {
+ SwWrtShell& rSh = GetShell();
+
+ if(!rSh.IsFrameSelected())
+ {
+ rSet.DisableItem(nWhich);
+ }
+
+ break;
+ }
+ default:
+ {
+ rSet.DisableItem(nWhich);
+ break;
+ }
+ }
+
+ nWhich = aIter.NextWhich();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/grfsh.cxx b/sw/source/uibase/shells/grfsh.cxx
new file mode 100644
index 0000000000..bb090fed46
--- /dev/null
+++ b/sw/source/uibase/shells/grfsh.cxx
@@ -0,0 +1,1018 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cmdid.h>
+#include <hintids.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/UnitConversion.hxx>
+#include <svl/stritem.hxx>
+#include <svl/whiter.hxx>
+#include <svl/urihelper.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <editeng/sizeitem.hxx>
+#include <sfx2/request.hxx>
+#include <vcl/EnumContext.hxx>
+#include <sfx2/htmlmode.hxx>
+#include <svx/svdview.hxx>
+#include <editeng/brushitem.hxx>
+#include <svx/grfflt.hxx>
+#include <svx/compressgraphicdialog.hxx>
+#include <svx/tbxcolor.hxx>
+#include <svx/sdangitm.hxx>
+#include <osl/diagnose.h>
+#include <drawdoc.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <viewopt.hxx>
+#include <swmodule.hxx>
+#include <swundo.hxx>
+#include <uitool.hxx>
+#include <docsh.hxx>
+#include <grfsh.hxx>
+#include <frmmgr.hxx>
+#include <frmfmt.hxx>
+#include <grfatr.hxx>
+#include <swwait.hxx>
+#include <svx/extedit.hxx>
+#include <svx/graphichelper.hxx>
+#include <doc.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <svx/drawitem.hxx>
+#define ShellClass_SwGrfShell
+
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+#include <swabstdlg.hxx>
+#include <unocrsr.hxx>
+#include <flyfrm.hxx>
+#include <memory>
+
+constexpr OUString TOOLBOX_NAME = u"colorbar"_ustr;
+
+class SwGrfShell::SwExternalToolEdit
+ : public ExternalToolEdit
+{
+private:
+ SwWrtShell *const m_pShell;
+ std::shared_ptr<SwUnoCursor> const m_pCursor;
+
+public:
+ explicit SwExternalToolEdit(SwWrtShell *const pShell)
+ : m_pShell(pShell)
+ , m_pCursor( // need only Point, must point to SwGrfNode
+ pShell->GetDoc()->CreateUnoCursor(
+ *pShell->GetCurrentShellCursor().GetPoint()))
+ {
+ }
+
+ virtual void Update(Graphic & rGraphic) override
+ {
+ DBG_TESTSOLARMUTEX();
+ m_pShell->Push();
+ m_pShell->GetCurrentShellCursor().DeleteMark();
+ *m_pShell->GetCurrentShellCursor().GetPoint() = *m_pCursor->GetPoint();
+ m_pShell->ReRead(OUString(), OUString(), &rGraphic);
+ m_pShell->Pop();
+ }
+};
+
+SFX_IMPL_INTERFACE(SwGrfShell, SwBaseShell)
+
+void SwGrfShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("graphic");
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Grafik_Toolbox);
+}
+
+void SwGrfShell::Execute(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+
+ sal_uInt16 nSlot = rReq.GetSlot();
+ switch(nSlot)
+ {
+ case SID_OBJECT_ROTATE:
+ {
+ // RotGrfFlyFrame: start rotation when possible
+ SdrView* pSdrView = rSh.GetDrawViewWithValidMarkList();
+
+ if(rSh.IsRotationOfSwGrfNodePossible() && pSdrView->IsRotateAllowed())
+ {
+ if(GetView().IsDrawRotate())
+ {
+ rSh.SetDragMode(SdrDragMode::Move);
+ }
+ else
+ {
+ rSh.SetDragMode(SdrDragMode::Rotate);
+ }
+
+ GetView().FlipDrawRotate();
+ }
+ }
+ break;
+
+ case SID_TWAIN_TRANSFER:
+ {
+ GetView().ExecuteScan( rReq );
+ break;
+ }
+
+ case SID_SAVE_GRAPHIC:
+ {
+ GraphicAttr aGraphicAttr;
+ rSh.GetGraphicAttr(aGraphicAttr);
+
+ short nState = RET_CANCEL;
+ if (aGraphicAttr != GraphicAttr()) // the image has been modified
+ {
+ weld::Window* pWin = GetView().GetFrameWeld();
+ if (pWin)
+ {
+ nState = GraphicHelper::HasToSaveTransformedImage(pWin);
+ }
+ }
+ else
+ {
+ nState = RET_NO;
+ }
+
+ if (nState == RET_YES)
+ {
+ const GraphicObject* pGraphicObj = rSh.GetGraphicObj();
+ if (pGraphicObj)
+ {
+ Graphic aGraphic = pGraphicObj->GetTransformedGraphic(pGraphicObj->GetPrefSize(), pGraphicObj->GetPrefMapMode(), aGraphicAttr);
+ OUString sGrfNm;
+ OUString sFilterNm;
+ rSh.GetGrfNms( &sGrfNm, &sFilterNm );
+ GraphicHelper::ExportGraphic(GetView().GetFrameWeld(), aGraphic, sGrfNm);
+ }
+ }
+ else if (nState == RET_NO)
+ {
+ const Graphic *pGraphic = rSh.GetGraphic();
+ if(nullptr != pGraphic)
+ {
+ OUString sGrfNm;
+ OUString sFilterNm;
+ rSh.GetGrfNms( &sGrfNm, &sFilterNm );
+ GraphicHelper::ExportGraphic(GetView().GetFrameWeld(), *pGraphic, sGrfNm);
+ }
+ }
+ }
+ break;
+
+ case SID_COMPRESS_GRAPHIC:
+ {
+ const Graphic* pGraphic = rSh.GetGraphic();
+ if( pGraphic )
+ {
+ Size aSize (
+ convertTwipToMm100(rSh.GetAnyCurRect(CurRectType::FlyEmbedded).Width()),
+ convertTwipToMm100(rSh.GetAnyCurRect(CurRectType::FlyEmbedded).Height()));
+
+ SfxItemSetFixed<RES_GRFATR_MIRRORGRF, RES_GRFATR_CROPGRF> aSet( rSh.GetAttrPool() );
+ rSh.GetCurAttr( aSet );
+ SwMirrorGrf aMirror( aSet.Get(RES_GRFATR_MIRRORGRF) );
+ SwCropGrf aCrop( aSet.Get(RES_GRFATR_CROPGRF) );
+
+ tools::Rectangle aCropRectangle(
+ convertTwipToMm100(aCrop.GetLeft()),
+ convertTwipToMm100(aCrop.GetTop()),
+ convertTwipToMm100(aCrop.GetRight()),
+ convertTwipToMm100(aCrop.GetBottom()) );
+
+ Graphic aGraphic = *pGraphic;
+
+ CompressGraphicsDialog aDialog(GetView().GetFrameWeld(), std::move(aGraphic), aSize, aCropRectangle, GetView().GetViewFrame().GetBindings());
+ if (aDialog.run() == RET_OK)
+ {
+ rSh.StartAllAction();
+ rSh.StartUndo(SwUndoId::START);
+ tools::Rectangle aScaledCropedRectangle = aDialog.GetScaledCropRectangle();
+
+ aCrop.SetLeft( o3tl::toTwips( aScaledCropedRectangle.Left(), o3tl::Length::mm100 ));
+ aCrop.SetTop( o3tl::toTwips( aScaledCropedRectangle.Top(), o3tl::Length::mm100 ));
+ aCrop.SetRight( o3tl::toTwips( aScaledCropedRectangle.Right(), o3tl::Length::mm100 ));
+ aCrop.SetBottom( o3tl::toTwips( aScaledCropedRectangle.Bottom(), o3tl::Length::mm100 ));
+
+ Graphic aCompressedGraphic( aDialog.GetCompressedGraphic() );
+ rSh.ReRead(OUString(), OUString(), const_cast<const Graphic*>(&aCompressedGraphic));
+
+ rSh.SetAttrItem(aCrop);
+ rSh.SetAttrItem(aMirror);
+
+ rSh.EndUndo(SwUndoId::END);
+ rSh.EndAllAction();
+ }
+ }
+ }
+ break;
+ case SID_EXTERNAL_EDIT:
+ {
+ // When the graphic is selected to be opened via some external tool
+ // for advanced editing
+ GraphicObject const*const pGraphicObject(rSh.GetGraphicObj());
+ if(nullptr != pGraphicObject)
+ {
+ m_ExternalEdits.push_back(std::make_unique<SwExternalToolEdit>(
+ &rSh));
+ m_ExternalEdits.back()->Edit(pGraphicObject);
+ }
+ }
+ break;
+ case SID_CHANGE_PICTURE:
+ case SID_INSERT_GRAPHIC:
+ {
+ // #i123922# implement slot independent from the two below to
+ // bring up the insert graphic dialog and associated actions
+ SwView& rLclView = GetView();
+ rReq.SetReturnValue(SfxBoolItem(nSlot, rLclView.InsertGraphicDlg( rReq )));
+ break;
+ }
+ case FN_FORMAT_GRAFIC_DLG:
+ case FN_DRAW_WRAP_DLG:
+ {
+ SwFlyFrameAttrMgr aMgr( false, &rSh, rSh.IsFrameSelected() ?
+ Frmmgr_Type::NONE : Frmmgr_Type::GRF, nullptr);
+ const SwViewOption* pVOpt = rSh.GetViewOptions();
+ SwViewOption aUsrPref( *pVOpt );
+
+ SfxItemSetFixed<
+ RES_FRMATR_BEGIN, RES_GRFATR_CROPGRF,
+ // FillAttribute support:
+ XATTR_FILL_FIRST, XATTR_FILL_LAST,
+ SID_DOCFRAME, SID_DOCFRAME,
+ SID_REFERER, SID_REFERER,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
+ SID_ATTR_PAGE_SIZE, SID_ATTR_PAGE_SIZE, // 10051
+ // RotGrfFlyFrame: Need RotationAngle now
+ SID_ATTR_TRANSFORM_ANGLE, SID_ATTR_TRANSFORM_ANGLE, // 10095
+ // Items to hand over XPropertyList things like
+ // XColorList, XHatchList, XGradientList, and XBitmapList to
+ // the Area TabPage:
+ SID_COLOR_TABLE, SID_PATTERN_LIST, //10179
+ SID_HTML_MODE, SID_HTML_MODE, //10414
+ SID_ATTR_GRAF_KEEP_ZOOM, SID_ATTR_GRAF_KEEP_ZOOM, //10882
+ SID_ATTR_GRAF_FRMSIZE, SID_ATTR_GRAF_GRAPHIC, // 10884
+ // contains SID_ATTR_GRAF_FRMSIZE_PERCENT
+ FN_GET_PRINT_AREA, FN_GET_PRINT_AREA,
+ FN_PARAM_GRF_CONNECT, FN_PARAM_GRF_CONNECT,
+ FN_SET_FRM_NAME, FN_KEEP_ASPECT_RATIO,
+ FN_SET_FRM_ALT_NAME, FN_SET_FRM_ALT_NAME,
+ FN_UNO_DESCRIPTION, FN_UNO_DESCRIPTION> aSet( GetPool() );
+
+ // create needed items for XPropertyList entries from the DrawModel so that
+ // the Area TabPage can access them
+ const SwDrawModel* pDrawModel = rSh.GetView().GetDocShell()->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
+
+ aSet.Put(SvxColorListItem(pDrawModel->GetColorList(), SID_COLOR_TABLE));
+ aSet.Put(SvxGradientListItem(pDrawModel->GetGradientList(), SID_GRADIENT_LIST));
+ aSet.Put(SvxHatchListItem(pDrawModel->GetHatchList(), SID_HATCH_LIST));
+ aSet.Put(SvxBitmapListItem(pDrawModel->GetBitmapList(), SID_BITMAP_LIST));
+ aSet.Put(SvxPatternListItem(pDrawModel->GetPatternList(), SID_PATTERN_LIST));
+
+ sal_uInt16 nHtmlMode = ::GetHtmlMode(GetView().GetDocShell());
+ aSet.Put(SfxUInt16Item(SID_HTML_MODE, nHtmlMode));
+ FieldUnit eMetric = ::GetDfltMetric(0 != (nHtmlMode&HTMLMODE_ON));
+ SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)) );
+
+ const SwRect* pRect = &rSh.GetAnyCurRect(CurRectType::Page);
+ SwFormatFrameSize aFrameSize( SwFrameSize::Variable, pRect->Width(), pRect->Height());
+ aFrameSize.SetWhich( GetPool().GetWhich( SID_ATTR_PAGE_SIZE ) );
+ aSet.Put( aFrameSize );
+
+ aSet.Put(SfxStringItem(FN_SET_FRM_NAME, rSh.GetFlyName()));
+ aSet.Put(SfxStringItem(FN_UNO_DESCRIPTION, rSh.GetObjDescription()));
+ if ( nSlot == FN_FORMAT_GRAFIC_DLG )
+ {
+ // #i73249#
+ aSet.Put( SfxStringItem( FN_SET_FRM_ALT_NAME, rSh.GetObjTitle() ) );
+ }
+
+ pRect = &rSh.GetAnyCurRect(CurRectType::PagePrt);
+ aFrameSize.SetWidth( pRect->Width() );
+ aFrameSize.SetHeight( pRect->Height() );
+ aFrameSize.SetWhich( GetPool().GetWhich(FN_GET_PRINT_AREA) );
+ aSet.Put( aFrameSize );
+
+ aSet.Put( aMgr.GetAttrSet() );
+ SwFlyFrame* pFly = rSh.GetSelectedFlyFrame();
+ if (pFly)
+ {
+ // Work with the up to date layout size if possible.
+ SwFormatFrameSize aSize = aSet.Get(RES_FRM_SIZE);
+ aSize.SetWidth(pFly->getFrameArea().Width());
+ aSize.SetHeight(pFly->getFrameArea().Height());
+ aSet.Put(aSize);
+ }
+ aSet.SetParent( aMgr.GetAttrSet().GetParent() );
+
+ // At percentage values initialize size
+ SwFormatFrameSize aSizeCopy = aSet.Get(RES_FRM_SIZE);
+ if (aSizeCopy.GetWidthPercent() && aSizeCopy.GetWidthPercent() != SwFormatFrameSize::SYNCED)
+ aSizeCopy.SetWidth(rSh.GetAnyCurRect(CurRectType::FlyEmbedded).Width());
+ if (aSizeCopy.GetHeightPercent() && aSizeCopy.GetHeightPercent() != SwFormatFrameSize::SYNCED)
+ aSizeCopy.SetHeight(rSh.GetAnyCurRect(CurRectType::FlyEmbedded).Height());
+ // and now set the size for "external" tabpages
+ {
+ SvxSizeItem aSzItm( SID_ATTR_GRAF_FRMSIZE, aSizeCopy.GetSize() );
+ aSet.Put( aSzItm );
+
+ Size aSz( aSizeCopy.GetWidthPercent(), aSizeCopy.GetHeightPercent() );
+ if( SwFormatFrameSize::SYNCED == aSz.Width() ) aSz.setWidth( 0 );
+ if( SwFormatFrameSize::SYNCED == aSz.Height() ) aSz.setHeight( 0 );
+
+ aSzItm.SetSize( aSz );
+ aSzItm.SetWhich( SID_ATTR_GRAF_FRMSIZE_PERCENT );
+ aSet.Put( aSzItm );
+ }
+
+ OUString sGrfNm;
+ OUString sFilterNm;
+ rSh.GetGrfNms( &sGrfNm, &sFilterNm );
+ if( !sGrfNm.isEmpty() )
+ {
+ aSet.Put( SvxBrushItem( INetURLObject::decode( sGrfNm,
+ INetURLObject::DecodeMechanism::Unambiguous ),
+ sFilterNm, GPOS_LT,
+ SID_ATTR_GRAF_GRAPHIC ));
+ }
+ else
+ {
+ // #119353# - robust
+ const GraphicObject* pGrfObj = rSh.GetGraphicObj();
+ if ( pGrfObj )
+ {
+ aSet.Put( SvxBrushItem( *pGrfObj, GPOS_LT,
+ SID_ATTR_GRAF_GRAPHIC ) );
+ }
+ }
+ aSet.Put( SfxBoolItem( FN_PARAM_GRF_CONNECT, !sGrfNm.isEmpty() ) );
+
+ // get Mirror and Crop
+ {
+ SfxItemSetFixed<RES_GRFATR_MIRRORGRF, RES_GRFATR_CROPGRF> aTmpSet( rSh.GetAttrPool() );
+
+ rSh.GetCurAttr( aTmpSet );
+ aSet.Put( aTmpSet );
+ }
+
+ aSet.Put(SfxBoolItem(FN_KEEP_ASPECT_RATIO, aUsrPref.IsKeepRatio()));
+ aSet.Put(SfxBoolItem( SID_ATTR_GRAF_KEEP_ZOOM, aUsrPref.IsGrfKeepZoom()));
+
+ aSet.Put(SfxFrameItem( SID_DOCFRAME, &GetView().GetViewFrame().GetFrame()));
+
+ SfxObjectShell * sh = rSh.GetDoc()->GetPersist();
+ if (sh != nullptr && sh->HasName())
+ {
+ aSet.Put(
+ SfxStringItem(SID_REFERER, sh->GetMedium()->GetName()));
+ }
+
+ Size aUnrotatedSize;
+ Degree10 nCurrentRotation;
+ { // RotGrfFlyFrame: Add current RotationAngle value, convert from
+ // RES_GRFATR_ROTATION to SID_ATTR_TRANSFORM_ANGLE. Do not forget to
+ // convert from 10th degrees to 100th degrees
+ SfxItemSetFixed<RES_GRFATR_ROTATION, RES_GRFATR_ROTATION> aTmpSet( rSh.GetAttrPool() );
+ rSh.GetCurAttr( aTmpSet );
+ const SwRotationGrf& rRotation = aTmpSet.Get(RES_GRFATR_ROTATION);
+ nCurrentRotation = rRotation.GetValue();
+ aUnrotatedSize = rRotation.GetUnrotatedSize();
+ aSet.Put(SdrAngleItem(SID_ATTR_TRANSFORM_ANGLE, to<Degree100>(nCurrentRotation)));
+ }
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateFrameTabDialog("PictureDialog",
+ GetView().GetViewFrame(),
+ GetView().GetFrameWeld(),
+ aSet, false));
+ if (nSlot == FN_DRAW_WRAP_DLG)
+ pDlg->SetCurPageId("wrap");
+
+ if (pDlg->Execute() == RET_OK)
+ {
+ rSh.StartAllAction();
+ rSh.StartUndo(SwUndoId::START);
+ SfxItemSet* pSet = const_cast<SfxItemSet*>(pDlg->GetOutputItemSet());
+ rReq.Done(*pSet);
+ // change the 2 frmsize SizeItems to the correct SwFrameSizeItem
+ if( const SvxSizeItem* pSizeItem = pSet->GetItemIfSet(
+ SID_ATTR_GRAF_FRMSIZE, false ))
+ {
+ SwFormatFrameSize aSize;
+ const Size& rSz = pSizeItem->GetSize();
+ aSize.SetWidth( rSz.Width() );
+ aSize.SetHeight( rSz.Height() );
+
+ pSizeItem = pSet->GetItemIfSet( SID_ATTR_GRAF_FRMSIZE_PERCENT, false );
+ if( pSizeItem )
+ {
+ const Size& rRelativeSize = pSizeItem->GetSize();
+ aSize.SetWidthPercent( static_cast< sal_uInt8 >( rRelativeSize.Width() ) );
+ aSize.SetHeightPercent( static_cast< sal_uInt8 >( rRelativeSize.Height() ) );
+ }
+ pSet->Put( aSize );
+ }
+
+ // Templates AutoUpdate
+ SwFrameFormat* pFormat = rSh.GetSelectedFrameFormat();
+ if(pFormat && pFormat->IsAutoUpdateOnDirectFormat())
+ {
+ pFormat->SetFormatAttr(*pSet);
+ SfxItemSetFixed<
+ RES_FRM_SIZE, RES_FRM_SIZE,
+ RES_SURROUND, RES_ANCHOR> aShellSet( GetPool() );
+ aShellSet.Put(*pSet);
+ aMgr.SetAttrSet(aShellSet);
+ }
+ else
+ {
+ aMgr.SetAttrSet(*pSet);
+ }
+ aMgr.UpdateFlyFrame();
+
+ bool bApplyUsrPref = false;
+ if (const SfxBoolItem* pRatioItem = pSet->GetItemIfSet(
+ FN_KEEP_ASPECT_RATIO ))
+ {
+ aUsrPref.SetKeepRatio( pRatioItem->GetValue() );
+ bApplyUsrPref = true;
+ }
+ if( const SfxBoolItem* pZoomItem = pSet->GetItemIfSet(
+ SID_ATTR_GRAF_KEEP_ZOOM ))
+ {
+ aUsrPref.SetGrfKeepZoom( pZoomItem->GetValue() );
+ bApplyUsrPref = true;
+ }
+
+ if( bApplyUsrPref )
+ SW_MOD()->ApplyUsrPref(aUsrPref, &GetView());
+
+ // and now set all the graphic attributes and other stuff
+ if( const SvxBrushItem* pGraphicBrushItem = pSet->GetItemIfSet(
+ SID_ATTR_GRAF_GRAPHIC ))
+ {
+ if( !pGraphicBrushItem->GetGraphicLink().isEmpty() )
+ sGrfNm = pGraphicBrushItem->GetGraphicLink();
+ else
+ sGrfNm.clear();
+
+ if( !pGraphicBrushItem->GetGraphicFilter().isEmpty() )
+ sFilterNm = pGraphicBrushItem->GetGraphicFilter();
+ else
+ sFilterNm.clear();
+
+ if( !sGrfNm.isEmpty() )
+ {
+ SwDocShell* pDocSh = GetView().GetDocShell();
+ SwWait aWait( *pDocSh, true );
+ SfxMedium* pMedium = pDocSh->GetMedium();
+ INetURLObject aAbs;
+ if( pMedium )
+ aAbs = pMedium->GetURLObject();
+ rSh.ReRead( URIHelper::SmartRel2Abs(
+ aAbs, sGrfNm,
+ URIHelper::GetMaybeFileHdl() ),
+ sFilterNm );
+ }
+ }
+ if ( const SfxStringItem* pNameItem = pSet->GetItemIfSet(
+ FN_SET_FRM_ALT_NAME ))
+ {
+ // #i73249#
+ rSh.SetObjTitle( pNameItem->GetValue() );
+ }
+
+ if ( const SfxStringItem* pDescriptionItem = pSet->GetItemIfSet(
+ FN_UNO_DESCRIPTION ))
+ rSh.SetObjDescription( pDescriptionItem->GetValue() );
+
+ // RotGrfFlyFrame: Get and process evtl. changed RotationAngle
+ if ( const SdrAngleItem* pAngleItem = pSet->GetItemIfSet(SID_ATTR_TRANSFORM_ANGLE, false ))
+ {
+ const Degree10 aNewRotation = to<Degree10>(pAngleItem->GetValue() % 36000_deg100);
+
+ // RotGrfFlyFrame: Possible rotation change here, SwFlyFrameAttrMgr aMgr is available
+ aMgr.SetRotation(nCurrentRotation, aNewRotation, aUnrotatedSize);
+ }
+
+ SfxItemSetFixed<RES_GRFATR_BEGIN, RES_GRFATR_END-1> aGrfSet( rSh.GetAttrPool() );
+ aGrfSet.Put( *pSet );
+ if( aGrfSet.Count() )
+ rSh.SetAttrSet( aGrfSet );
+
+ rSh.EndUndo(SwUndoId::END);
+ rSh.EndAllAction();
+ }
+ }
+ break;
+
+ case FN_GRAPHIC_MIRROR_ON_EVEN_PAGES:
+ {
+ SfxItemSetFixed<RES_GRFATR_MIRRORGRF, RES_GRFATR_MIRRORGRF> aSet(rSh.GetAttrPool());
+ rSh.GetCurAttr( aSet );
+ SwMirrorGrf aGrf(aSet.Get(RES_GRFATR_MIRRORGRF));
+ aGrf.SetGrfToggle(!aGrf.IsGrfToggle());
+ rSh.SetAttrItem(aGrf);
+ }
+ break;
+
+ case SID_OBJECT_CROP:
+ {
+ GraphicObject const *pGraphicObject = rSh.GetGraphicObj();
+ if (nullptr != pGraphicObject && SdrDragMode::Crop != rSh.GetDragMode()) {
+ rSh.StartCropImage();
+ }
+ }
+ break;
+
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ return;
+ }
+}
+
+void SwGrfShell::ExecAttr( SfxRequest const &rReq )
+{
+ GraphicType nGrfType = GraphicType::NONE;
+ if (CNT_GRF == GetShell().GetCntType())
+ nGrfType = GetShell().GetGraphicType();
+ if (GraphicType::Bitmap == nGrfType ||
+ GraphicType::GdiMetafile == nGrfType)
+ {
+ SfxItemSetFixed<RES_GRFATR_BEGIN, RES_GRFATR_END -1> aGrfSet( GetShell().GetAttrPool() );
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem;
+ sal_uInt16 nSlot = rReq.GetSlot();
+ if( !pArgs || SfxItemState::SET != pArgs->GetItemState( nSlot, false, &pItem ))
+ pItem = nullptr;
+
+ switch( nSlot )
+ {
+ case SID_FLIP_VERTICAL:
+ case SID_FLIP_HORIZONTAL:
+ {
+ GetShell().GetCurAttr( aGrfSet );
+ SwMirrorGrf aMirror( aGrfSet.Get( RES_GRFATR_MIRRORGRF ) );
+ MirrorGraph nMirror = aMirror.GetValue();
+ if ( nSlot==SID_FLIP_HORIZONTAL )
+ switch( nMirror )
+ {
+ case MirrorGraph::Dont: nMirror = MirrorGraph::Vertical;
+ break;
+ case MirrorGraph::Horizontal: nMirror = MirrorGraph::Both;
+ break;
+ case MirrorGraph::Vertical: nMirror = MirrorGraph::Dont;
+ break;
+ case MirrorGraph::Both: nMirror = MirrorGraph::Horizontal;
+ break;
+ }
+ else
+ switch( nMirror )
+ {
+ case MirrorGraph::Dont: nMirror = MirrorGraph::Horizontal;
+ break;
+ case MirrorGraph::Vertical: nMirror = MirrorGraph::Both;
+ break;
+ case MirrorGraph::Horizontal: nMirror = MirrorGraph::Dont;
+ break;
+ case MirrorGraph::Both: nMirror = MirrorGraph::Vertical;
+ break;
+ }
+ aMirror.SetValue( nMirror );
+ aGrfSet.ClearItem();
+ aGrfSet.Put( aMirror );
+ }
+ break;
+
+ case SID_ATTR_GRAF_LUMINANCE:
+ if( pItem )
+ aGrfSet.Put( SwLuminanceGrf(
+ static_cast<const SfxInt16Item*>(pItem)->GetValue() ));
+ break;
+
+ case SID_ATTR_GRAF_CONTRAST:
+ if( pItem )
+ aGrfSet.Put( SwContrastGrf(
+ static_cast<const SfxInt16Item*>(pItem)->GetValue() ));
+ break;
+
+ case SID_ATTR_GRAF_RED:
+ if( pItem )
+ aGrfSet.Put( SwChannelRGrf(
+ static_cast<const SfxInt16Item*>(pItem)->GetValue() ));
+ break;
+
+ case SID_ATTR_GRAF_GREEN:
+ if( pItem )
+ aGrfSet.Put( SwChannelGGrf(
+ static_cast<const SfxInt16Item*>(pItem)->GetValue() ));
+ break;
+
+ case SID_ATTR_GRAF_BLUE:
+ if( pItem )
+ aGrfSet.Put( SwChannelBGrf(
+ static_cast<const SfxInt16Item*>(pItem)->GetValue() ));
+ break;
+
+ case SID_ATTR_GRAF_GAMMA:
+ if( pItem )
+ {
+ double fVal = static_cast<const SfxUInt32Item*>(pItem)->GetValue();
+ aGrfSet.Put( SwGammaGrf(fVal/100. ));
+ }
+ break;
+
+ case SID_ATTR_GRAF_TRANSPARENCE:
+ if( pItem )
+ aGrfSet.Put( SwTransparencyGrf(
+ static_cast< sal_Int8 >( static_cast<const SfxUInt16Item*>(pItem )->GetValue() ) ) );
+ break;
+
+ case SID_ATTR_GRAF_INVERT:
+ if( pItem )
+ aGrfSet.Put( SwInvertGrf(
+ static_cast<const SfxBoolItem*>(pItem)->GetValue() ));
+ break;
+
+ case SID_ATTR_GRAF_MODE:
+ if( pItem )
+ aGrfSet.Put( SwDrawModeGrf(
+ static_cast<GraphicDrawMode>(static_cast<const SfxUInt16Item*>(pItem)->GetValue()) ));
+ break;
+
+ case SID_COLOR_SETTINGS:
+ {
+ svx::ToolboxAccess aToolboxAccess( TOOLBOX_NAME );
+ aToolboxAccess.toggleToolbox();
+ break;
+ }
+
+ case SID_GRFFILTER:
+ case SID_GRFFILTER_INVERT:
+ case SID_GRFFILTER_SMOOTH:
+ case SID_GRFFILTER_SHARPEN:
+ case SID_GRFFILTER_REMOVENOISE:
+ case SID_GRFFILTER_SOBEL:
+ case SID_GRFFILTER_MOSAIC:
+ case SID_GRFFILTER_EMBOSS:
+ case SID_GRFFILTER_POSTER:
+ case SID_GRFFILTER_POPART:
+ case SID_GRFFILTER_SEPIA:
+ case SID_GRFFILTER_SOLARIZE:
+ if( GraphicType::Bitmap == nGrfType )
+ {
+ // #119353# - robust
+ const GraphicObject* pFilterObj( GetShell().GetGraphicObj() );
+ if ( pFilterObj )
+ {
+ GraphicObject aFilterObj( *pFilterObj );
+ if( SvxGraphicFilterResult::NONE ==
+ SvxGraphicFilter::ExecuteGrfFilterSlot( rReq, aFilterObj ))
+ GetShell().ReRead( OUString(), OUString(),
+ &aFilterObj.GetGraphic() );
+ }
+ }
+ break;
+
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ }
+
+ if( aGrfSet.Count() )
+ GetShell().SetAttrSet( aGrfSet );
+ }
+ GetView().GetViewFrame().GetBindings().Invalidate(rReq.GetSlot());
+}
+
+void SwGrfShell::GetAttrState(SfxItemSet &rSet)
+{
+ SwWrtShell &rSh = GetShell();
+ SfxItemSet aCoreSet( GetPool(), aNoTextNodeSetRange );
+ rSh.GetCurAttr( aCoreSet );
+ bool bParentCntProt = FlyProtectFlags::NONE != rSh.IsSelObjProtected( FlyProtectFlags::Content|FlyProtectFlags::Parent );
+ bool bIsGrfContent = CNT_GRF == GetShell().GetCntType();
+
+ SetGetStateSet( &rSet );
+
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while( nWhich )
+ {
+ bool bDisable = bParentCntProt;
+ switch( nWhich )
+ {
+ case SID_OBJECT_ROTATE:
+ {
+ // RotGrfFlyFrame: steer rotation state
+ const bool bIsRotate(GetView().IsDrawRotate());
+ SdrView* pSdrView = rSh.GetDrawViewWithValidMarkList();
+
+ if(!bIsRotate && !pSdrView->IsRotateAllowed())
+ {
+ rSet.DisableItem(nWhich);
+ }
+ else
+ {
+ rSet.Put(SfxBoolItem(nWhich, bIsRotate));
+ }
+
+ break;
+ }
+ case SID_INSERT_GRAPHIC:
+ case FN_FORMAT_GRAFIC_DLG:
+ case SID_TWAIN_TRANSFER:
+ if( bParentCntProt || !bIsGrfContent )
+ bDisable = true;
+ else if ( nWhich == SID_INSERT_GRAPHIC
+ && rSh.CursorInsideInputField() )
+ {
+ bDisable = true;
+ }
+ break;
+
+ case SID_SAVE_GRAPHIC:
+ case SID_EXTERNAL_EDIT:
+ if( rSh.GetGraphicType() == GraphicType::NONE || GetObjectShell()->isExportLocked())
+ bDisable = true;
+ break;
+
+ case SID_COLOR_SETTINGS:
+ {
+ if ( bParentCntProt || !bIsGrfContent )
+ bDisable = true;
+ else
+ {
+ svx::ToolboxAccess aToolboxAccess( TOOLBOX_NAME );
+ rSet.Put( SfxBoolItem( nWhich, aToolboxAccess.isToolboxVisible() ) );
+ }
+ break;
+ }
+
+ case SID_FLIP_HORIZONTAL:
+ if( !bParentCntProt )
+ {
+ MirrorGraph nState = aCoreSet.Get(
+ RES_GRFATR_MIRRORGRF ).GetValue();
+
+ rSet.Put(SfxBoolItem( nWhich, nState == MirrorGraph::Vertical ||
+ nState == MirrorGraph::Both));
+ }
+ break;
+
+ case SID_FLIP_VERTICAL:
+ if( !bParentCntProt )
+ {
+ MirrorGraph nState = aCoreSet.GetItem<SwMirrorGrf>( RES_GRFATR_MIRRORGRF )->GetValue();
+ rSet.Put(SfxBoolItem( nWhich, nState == MirrorGraph::Horizontal ||
+ nState == MirrorGraph::Both));
+ }
+ break;
+
+ case SID_ATTR_GRAF_LUMINANCE:
+ if( !bParentCntProt )
+ rSet.Put( SfxInt16Item( nWhich,
+ aCoreSet.Get(RES_GRFATR_LUMINANCE).GetValue() ));
+ break;
+
+ case SID_ATTR_GRAF_CONTRAST:
+ if( !bParentCntProt )
+ rSet.Put( SfxInt16Item( nWhich,
+ aCoreSet.Get(RES_GRFATR_CONTRAST).GetValue() ));
+ break;
+
+ case SID_ATTR_GRAF_RED:
+ if( !bParentCntProt )
+ rSet.Put( SfxInt16Item( nWhich,
+ aCoreSet.Get(RES_GRFATR_CHANNELR).GetValue() ));
+ break;
+
+ case SID_ATTR_GRAF_GREEN:
+ if( !bParentCntProt )
+ rSet.Put( SfxInt16Item( nWhich,
+ aCoreSet.Get(RES_GRFATR_CHANNELG).GetValue() ));
+ break;
+
+ case SID_ATTR_GRAF_BLUE:
+ if( !bParentCntProt )
+ rSet.Put( SfxInt16Item( nWhich,
+ aCoreSet.Get(RES_GRFATR_CHANNELB).GetValue() ));
+ break;
+
+ case SID_ATTR_GRAF_GAMMA:
+ if( !bParentCntProt )
+ rSet.Put( SfxUInt32Item( nWhich, static_cast< sal_uInt32 >(
+ aCoreSet.Get( RES_GRFATR_GAMMA ).GetValue() * 100 ) ) );
+ break;
+
+ case SID_ATTR_GRAF_TRANSPARENCE:
+ if( !bParentCntProt )
+ {
+ // #119353# - robust
+ const GraphicObject* pGrafObj = rSh.GetGraphicObj();
+ if ( pGrafObj )
+ {
+ if( pGrafObj->IsAnimated() ||
+ GraphicType::GdiMetafile == pGrafObj->GetType() )
+ bDisable = true;
+ else
+ rSet.Put( SfxUInt16Item( nWhich,
+ aCoreSet.Get(RES_GRFATR_TRANSPARENCY).GetValue() ));
+ }
+ }
+ break;
+
+ case SID_ATTR_GRAF_INVERT:
+ if( !bParentCntProt )
+ rSet.Put( SfxBoolItem( nWhich,
+ aCoreSet.Get(RES_GRFATR_INVERT).GetValue() ));
+ break;
+
+ case SID_ATTR_GRAF_MODE:
+ if( !bParentCntProt )
+ rSet.Put( SfxUInt16Item( nWhich, static_cast<sal_uInt16>(aCoreSet.Get(RES_GRFATR_DRAWMODE).GetValue()) ));
+ break;
+
+ case SID_GRFFILTER:
+ case SID_GRFFILTER_INVERT:
+ case SID_GRFFILTER_SMOOTH:
+ case SID_GRFFILTER_SHARPEN:
+ case SID_GRFFILTER_REMOVENOISE:
+ case SID_GRFFILTER_SOBEL:
+ case SID_GRFFILTER_MOSAIC:
+ case SID_GRFFILTER_EMBOSS:
+ case SID_GRFFILTER_POSTER:
+ case SID_GRFFILTER_POPART:
+ case SID_GRFFILTER_SEPIA:
+ case SID_GRFFILTER_SOLARIZE:
+ {
+ if( bParentCntProt || !bIsGrfContent )
+ bDisable = true;
+ // #i59688# load graphic only if type is unknown
+ else
+ {
+ const GraphicType eGraphicType( rSh.GetGraphicType() );
+ if ( ( eGraphicType == GraphicType::NONE ||
+ eGraphicType == GraphicType::Default ) &&
+ rSh.IsLinkedGrfSwapOut() )
+ {
+ rSet.DisableItem( nWhich );
+ if( AddGrfUpdateSlot( nWhich ))
+ rSh.GetGraphic(false); // start the loading
+ }
+ else
+ {
+ bDisable = eGraphicType != GraphicType::Bitmap;
+ }
+ }
+ }
+ break;
+
+ case SID_OBJECT_CROP:
+ {
+ bDisable = FlyProtectFlags::NONE != rSh.IsSelObjProtected( FlyProtectFlags::Content|FlyProtectFlags::Parent );
+ if( rSh.GetGraphicType() == GraphicType::NONE )
+ bDisable = true;
+ }
+ break;
+
+ default:
+ bDisable = false;
+ }
+
+ if( bDisable )
+ rSet.DisableItem( nWhich );
+ nWhich = aIter.NextWhich();
+ }
+ SetGetStateSet( nullptr );
+}
+
+void SwGrfShell::ExecuteRotation(SfxRequest const &rReq)
+{
+ // RotGrfFlyFrame: Modify rotation attribute instead of manipulating the graphic
+ Degree10 aRotation;
+
+ if (rReq.GetSlot() == SID_ROTATE_GRAPHIC_LEFT)
+ {
+ aRotation = 900_deg10;
+ }
+ else if (rReq.GetSlot() == SID_ROTATE_GRAPHIC_RIGHT)
+ {
+ aRotation = 2700_deg10;
+ }
+ else if (rReq.GetSlot() == SID_ROTATE_GRAPHIC_180)
+ {
+ aRotation = 1800_deg10;
+ }
+
+ if (rReq.GetSlot() != SID_ROTATE_GRAPHIC_RESET && 0_deg10 == aRotation)
+ return;
+
+ SwWrtShell& rShell = GetShell();
+ SfxItemSetFixed<RES_GRFATR_ROTATION, RES_GRFATR_ROTATION> aSet( rShell.GetAttrPool() );
+ rShell.GetCurAttr( aSet );
+ const SwRotationGrf& rRotation = aSet.Get(RES_GRFATR_ROTATION);
+ SwFlyFrameAttrMgr aMgr(false, &rShell, rShell.IsFrameSelected() ? Frmmgr_Type::NONE : Frmmgr_Type::GRF, nullptr);
+
+ // RotGrfFlyFrame: Possible rotation change here, SwFlyFrameAttrMgr aMgr is available
+ if (rReq.GetSlot() == SID_ROTATE_GRAPHIC_RESET)
+ {
+ aMgr.SetRotation(rRotation.GetValue(), 0_deg10, rRotation.GetUnrotatedSize());
+ }
+ else if(0_deg10 != aRotation)
+ {
+ const Degree10 aNewRotation((aRotation + rRotation.GetValue()) % 3600_deg10);
+
+ aMgr.SetRotation(rRotation.GetValue(), aNewRotation, rRotation.GetUnrotatedSize());
+ }
+}
+
+void SwGrfShell::GetAttrStateForRotation(SfxItemSet &rSet)
+{
+ SwWrtShell& rShell = GetShell();
+ bool bIsParentContentProtected = FlyProtectFlags::NONE != rShell.IsSelObjProtected( FlyProtectFlags::Content|FlyProtectFlags::Parent );
+
+ SetGetStateSet( &rSet );
+
+ SfxWhichIter aIterator( rSet );
+ sal_uInt16 nWhich = aIterator.FirstWhich();
+ while( nWhich )
+ {
+ bool bDisable = bIsParentContentProtected;
+ switch( nWhich )
+ {
+ case SID_ROTATE_GRAPHIC_LEFT:
+ case SID_ROTATE_GRAPHIC_RIGHT:
+ case SID_ROTATE_GRAPHIC_180:
+ {
+ if( rShell.GetGraphicType() == GraphicType::NONE )
+ {
+ bDisable = true;
+ }
+ break;
+ }
+ case SID_ROTATE_GRAPHIC_RESET:
+ {
+ // RotGrfFlyFrame: disable when already no rotation
+ SfxItemSetFixed<RES_GRFATR_ROTATION, RES_GRFATR_ROTATION> aSet( rShell.GetAttrPool() );
+ rShell.GetCurAttr( aSet );
+ const SwRotationGrf& rRotation = aSet.Get(RES_GRFATR_ROTATION);
+ bDisable = (0_deg10 == rRotation.GetValue());
+ break;
+ }
+ case SID_ATTR_TRANSFORM_ANGLE:
+ {
+ // RotGrfFlyFrame: get rotation value from RES_GRFATR_ROTATION and copy to rSet as
+ // SID_ATTR_TRANSFORM_ANGLE, convert from 10th degrees to 100th degrees
+ SfxItemSetFixed<RES_GRFATR_ROTATION, RES_GRFATR_ROTATION> aSet( rShell.GetAttrPool() );
+ rShell.GetCurAttr( aSet );
+ const SwRotationGrf& rRotation = aSet.Get(RES_GRFATR_ROTATION);
+ rSet.Put(SdrAngleItem(SID_ATTR_TRANSFORM_ANGLE, to<Degree100>(rRotation.GetValue())));
+ break;
+ }
+ default:
+ bDisable = false;
+ }
+
+ if( bDisable )
+ rSet.DisableItem( nWhich );
+ nWhich = aIterator.NextWhich();
+ }
+ SetGetStateSet( nullptr );
+}
+
+SwGrfShell::~SwGrfShell()
+{
+}
+
+SwGrfShell::SwGrfShell(SwView &_rView) :
+ SwBaseShell(_rView)
+{
+ SetName("Graphic");
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Graphic));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/grfshex.cxx b/sw/source/uibase/shells/grfshex.cxx
new file mode 100644
index 0000000000..45d4076452
--- /dev/null
+++ b/sw/source/uibase/shells/grfshex.cxx
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <textsh.hxx>
+#include <drawdoc.hxx>
+#include <doc.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <docsh.hxx>
+#include <avmedia/mediawindow.hxx>
+#include <editeng/sizeitem.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/stritem.hxx>
+#include <svx/svdomedia.hxx>
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/media/XPlayer.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::sfx2;
+
+bool SwTextShell::InsertMediaDlg( SfxRequest const & rReq )
+{
+ bool bRet = false;
+
+#if !HAVE_FEATURE_AVMEDIA
+ (void) rReq;
+#else
+ OUString aURL;
+ const SfxItemSet* pReqArgs = rReq.GetArgs();
+ vcl::Window& rWindow = GetView().GetViewFrame().GetWindow();
+ bool bAPI = false;
+
+ const SvxSizeItem* pSizeItem = rReq.GetArg<SvxSizeItem>(FN_PARAM_1);
+ const SfxBoolItem* pLinkItem = rReq.GetArg<SfxBoolItem>(FN_PARAM_2);
+ const bool bSizeUnknown = !pSizeItem;
+
+ if( pReqArgs )
+ {
+ const SfxStringItem* pStringItem = dynamic_cast<const SfxStringItem*>( &pReqArgs->Get( rReq.GetSlot() ) );
+ if( pStringItem )
+ {
+ aURL = pStringItem->GetValue();
+ bAPI = !aURL.isEmpty();
+ }
+ }
+
+ bool bLink(pLinkItem ? pLinkItem->GetValue() : true);
+
+ if (bAPI || ::avmedia::MediaWindow::executeMediaURLDialog(rWindow.GetFrameWeld(), aURL, & bLink))
+ {
+ Size aPrefSize;
+
+ if (!bSizeUnknown)
+ aPrefSize = pSizeItem->GetSize();
+ else
+ {
+ rWindow.EnterWait();
+
+ css::uno::Reference<css::frame::XDispatchProvider> xDispatchProvider(GetView().GetViewFrame().GetFrame().GetFrameInterface(), css::uno::UNO_QUERY);
+
+ rtl::Reference<avmedia::PlayerListener> xPlayerListener(new avmedia::PlayerListener(
+ [xDispatchProvider, aURL, bLink](const css::uno::Reference<css::media::XPlayer>& rPlayer){
+ css::awt::Size aSize = rPlayer->getPreferredPlayerWindowSize();
+ avmedia::MediaWindow::dispatchInsertAVMedia(xDispatchProvider, aSize, aURL, bLink);
+ }));
+
+ const bool bIsMediaURL = ::avmedia::MediaWindow::isMediaURL(aURL, "", true, xPlayerListener);
+
+ rWindow.LeaveWait();
+
+ if (!bIsMediaURL)
+ {
+ if( !bAPI )
+ ::avmedia::MediaWindow::executeFormatErrorBox(rWindow.GetFrameWeld());
+
+ return bRet;
+ }
+
+ return true;
+ }
+
+ rWindow.EnterWait();
+
+ SwWrtShell& rSh = GetShell();
+
+ if( !rSh.HasDrawView() )
+ rSh.MakeDrawView();
+
+ Size aDocSz( rSh.GetDocSize() );
+ const SwRect& rVisArea = rSh.VisArea();
+ Point aPos( rVisArea.Center() );
+ Size aSize;
+
+ if( rVisArea.Width() > aDocSz.Width())
+ aPos.setX( aDocSz.Width() / 2 + rVisArea.Left() );
+
+ if(rVisArea.Height() > aDocSz.Height())
+ aPos.setY( aDocSz.Height() / 2 + rVisArea.Top() );
+
+ if( aPrefSize.Width() && aPrefSize.Height() )
+ aSize = rWindow.PixelToLogic(aPrefSize, MapMode(MapUnit::MapTwip));
+ else
+ aSize = Size( 2835, 2835 );
+
+ OUString realURL;
+ if (bLink)
+ {
+ realURL = aURL;
+ }
+ else
+ {
+ uno::Reference<frame::XModel> const xModel(
+ rSh.GetDoc()->GetDocShell()->GetModel());
+ bRet = ::avmedia::EmbedMedia(xModel, aURL, realURL);
+ if (!bRet) { return bRet; }
+ }
+
+ rtl::Reference<SdrMediaObj> pObj = new SdrMediaObj(
+ *rSh.GetDoc()->getIDocumentDrawModelAccess().GetDrawModel(),
+ tools::Rectangle(aPos, aSize));
+
+ pObj->setURL( realURL, "" );
+ rSh.EnterStdMode();
+ rSh.SwFEShell::InsertDrawObj( *pObj, aPos );
+ bRet = true;
+
+ rWindow.LeaveWait();
+ }
+#endif
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/langhelper.cxx b/sw/source/uibase/shells/langhelper.cxx
new file mode 100644
index 0000000000..453e0c1d93
--- /dev/null
+++ b/sw/source/uibase/shells/langhelper.cxx
@@ -0,0 +1,549 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <string.h>
+
+#include <wrtsh.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <charfmt.hxx>
+
+#include <sfx2/bindings.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/sfxdlg.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/editdata.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/langitem.hxx>
+
+#include <svl/languageoptions.hxx>
+#include <svtools/langtab.hxx>
+#include <svl/slstitm.hxx>
+#include <svl/stritem.hxx>
+#include <svx/svxids.hrc>
+#include <osl/diagnose.h>
+
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <view.hxx>
+#include <viewopt.hxx>
+
+#include <langhelper.hxx>
+
+using namespace ::com::sun::star;
+
+namespace SwLangHelper
+{
+
+ void GetLanguageStatus( OutlinerView* pOLV, SfxItemSet& rSet )
+ {
+ ESelection aSelection = pOLV->GetSelection();
+ EditView& rEditView=pOLV->GetEditView();
+ EditEngine* pEditEngine=rEditView.GetEditEngine();
+
+ // the value of used script types
+ const SvtScriptType nScriptType =pOLV->GetSelectedScriptType();
+ OUString aScriptTypesInUse( OUString::number( static_cast<int>(nScriptType) ) );//pEditEngine->GetScriptType(aSelection)
+
+ // get keyboard language
+ OUString aKeyboardLang;
+ LanguageType nLang = rEditView.GetInputLanguage();
+ if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
+ aKeyboardLang = SvtLanguageTable::GetLanguageString( nLang );
+
+ // get the language that is in use
+ OUString aCurrentLang("*");
+ SfxItemSet aSet(pOLV->GetAttribs());
+ nLang = SwLangHelper::GetCurrentLanguage( aSet,nScriptType );
+ if (nLang != LANGUAGE_DONTKNOW)
+ aCurrentLang = SvtLanguageTable::GetLanguageString( nLang );
+
+ // build sequence for status value
+ uno::Sequence< OUString > aSeq{ aCurrentLang,
+ aScriptTypesInUse,
+ aKeyboardLang,
+ SwLangHelper::GetTextForLanguageGuessing( pEditEngine,
+ aSelection ) };
+
+ // set sequence as status value
+ SfxStringListItem aItem( SID_LANGUAGE_STATUS );
+ aItem.SetStringList( aSeq );
+ rSet.Put( aItem );
+ }
+
+ bool SetLanguageStatus( OutlinerView* pOLV, SfxRequest &rReq, SwView const &rView, SwWrtShell &rSh )
+ {
+ bool bRestoreSelection = false;
+ ESelection aSelection = pOLV->GetSelection();
+ EditView & rEditView = pOLV->GetEditView();
+ SfxItemSet aEditAttr(rEditView.GetEmptyItemSet());
+
+ // get the language
+ OUString aNewLangText;
+
+ const SfxStringItem* pItem = rReq.GetArg<SfxStringItem>(SID_LANGUAGE_STATUS);
+ if (pItem)
+ aNewLangText = pItem->GetValue();
+
+ //!! Remember the view frame right now...
+ //!! (call to GetView().GetViewFrame() will break if the
+ //!! SwTextShell got destroyed meanwhile.)
+ SfxViewFrame& rViewFrame = rView.GetViewFrame();
+
+ if (aNewLangText == "*" )
+ {
+ // open the dialog "Tools/Options/Languages and Locales - General"
+ SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateVclDialog( rView.GetFrameWeld(), SID_LANGUAGE_OPTIONS ));
+ pDlg->Execute();
+ }
+ else
+ {
+ // setting the new language...
+ if (!aNewLangText.isEmpty())
+ {
+ static constexpr OUString aSelectionLangPrefix(u"Current_"_ustr);
+ static constexpr OUString aParagraphLangPrefix(u"Paragraph_"_ustr);
+ static constexpr OUString aDocumentLangPrefix(u"Default_"_ustr);
+
+ sal_Int32 nPos = 0;
+ bool bForSelection = true;
+ bool bForParagraph = false;
+ if (-1 != (nPos = aNewLangText.indexOf( aSelectionLangPrefix )))
+ {
+ // ... for the current selection
+ aNewLangText = aNewLangText.replaceAt(nPos, aSelectionLangPrefix.getLength(), u"");
+ bForSelection = true;
+ }
+ else if (-1 != (nPos = aNewLangText.indexOf( aParagraphLangPrefix )))
+ {
+ // ... for the current paragraph language
+ aNewLangText = aNewLangText.replaceAt(nPos, aParagraphLangPrefix.getLength(), u"");
+ bForSelection = true;
+ bForParagraph = true;
+ }
+ else if (-1 != (nPos = aNewLangText.indexOf( aDocumentLangPrefix )))
+ {
+ // ... as default document language
+ aNewLangText = aNewLangText.replaceAt(nPos, aDocumentLangPrefix.getLength(), u"");
+ bForSelection = false;
+ }
+
+ if (bForParagraph)
+ {
+ bRestoreSelection = true;
+ SwLangHelper::SelectPara( rEditView, aSelection );
+ aSelection = pOLV->GetSelection();
+ }
+ if (!bForSelection) // document language to be changed...
+ {
+ rSh.StartAction();
+ rSh.LockView( true );
+ rSh.Push();
+
+ // prepare to apply new language to all text in document
+ rSh.SelAll();
+ rSh.ExtendedSelectAll();
+ }
+
+ if (aNewLangText == "LANGUAGE_NONE")
+ SwLangHelper::SetLanguage_None( rSh, pOLV, aSelection, bForSelection, aEditAttr );
+ else if (aNewLangText == "RESET_LANGUAGES")
+ SwLangHelper::ResetLanguages( rSh, pOLV );
+ else
+ SwLangHelper::SetLanguage( rSh, pOLV, aSelection, aNewLangText, bForSelection, aEditAttr );
+
+ if (!bForSelection)
+ {
+ // need to release view and restore selection...
+ rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+ rSh.LockView( false );
+ rSh.EndAction();
+ }
+ }
+ }
+
+ // invalidate slot to get the new language displayed
+ rViewFrame.GetBindings().Invalidate( rReq.GetSlot() );
+
+ rReq.Done();
+ return bRestoreSelection;
+ }
+
+ void SetLanguage( SwWrtShell &rWrtSh, std::u16string_view rLangText, bool bIsForSelection, SfxItemSet &rCoreSet )
+ {
+ SetLanguage( rWrtSh, nullptr , ESelection(), rLangText, bIsForSelection, rCoreSet );
+ }
+
+ void SetLanguage( SwWrtShell &rWrtSh, OutlinerView const * pOLV, const ESelection& rSelection, std::u16string_view rLangText, bool bIsForSelection, SfxItemSet &rCoreSet )
+ {
+ const LanguageType nLang = SvtLanguageTable::GetLanguageType( rLangText );
+ if (nLang == LANGUAGE_DONTKNOW)
+ return;
+
+ EditEngine* pEditEngine = pOLV ? pOLV->GetEditView().GetEditEngine() : nullptr;
+ OSL_ENSURE( !pOLV || pEditEngine, "OutlinerView without EditEngine???" );
+
+ //get ScriptType
+ TypedWhichId<SvxLanguageItem> nLangWhichId(0);
+ bool bIsSingleScriptType = true;
+ switch (SvtLanguageOptions::GetScriptTypeOfLanguage( nLang ))
+ {
+ case SvtScriptType::LATIN : nLangWhichId = pEditEngine ? EE_CHAR_LANGUAGE : RES_CHRATR_LANGUAGE; break;
+ case SvtScriptType::ASIAN : nLangWhichId = pEditEngine ? EE_CHAR_LANGUAGE_CJK : RES_CHRATR_CJK_LANGUAGE; break;
+ case SvtScriptType::COMPLEX : nLangWhichId = pEditEngine ? EE_CHAR_LANGUAGE_CTL : RES_CHRATR_CTL_LANGUAGE; break;
+ default:
+ bIsSingleScriptType = false;
+ OSL_FAIL("unexpected case" );
+ }
+ if (!bIsSingleScriptType)
+ return;
+
+ // change language for selection or paragraph
+ // (for paragraph is handled by previously having set the selection to the
+ // whole paragraph)
+ if (bIsForSelection)
+ {
+ // apply language to current selection
+ if (pEditEngine)
+ {
+ rCoreSet.Put( SvxLanguageItem( nLang, nLangWhichId ));
+ pEditEngine->QuickSetAttribs(rCoreSet, rSelection);
+ }
+ else
+ {
+ rWrtSh.GetCurAttr( rCoreSet );
+ rCoreSet.Put( SvxLanguageItem( nLang, nLangWhichId ));
+ rWrtSh.SetAttrSet( rCoreSet );
+ }
+ }
+ else // change language for all text
+ {
+ // set document default language
+ switch (nLangWhichId)
+ {
+ case EE_CHAR_LANGUAGE : nLangWhichId = RES_CHRATR_LANGUAGE; break;
+ case EE_CHAR_LANGUAGE_CJK : nLangWhichId = RES_CHRATR_CJK_LANGUAGE; break;
+ case EE_CHAR_LANGUAGE_CTL : nLangWhichId = RES_CHRATR_CTL_LANGUAGE; break;
+ }
+ //Set the default document language
+ rWrtSh.SetDefault( SvxLanguageItem( nLang, nLangWhichId ) );
+ rWrtSh.GetDoc()->GetDocShell()->Broadcast(SfxHint(SfxHintId::LanguageChanged));
+
+ // #i102191: hard set respective language attribute in text document
+ // (for all text in the document - which should be selected by now...)
+ rWrtSh.SetAttrItem( SvxLanguageItem( nLang, nLangWhichId ) );
+ }
+ }
+
+ void SetLanguage_None( SwWrtShell &rWrtSh, bool bIsForSelection, SfxItemSet &rCoreSet )
+ {
+ SetLanguage_None( rWrtSh,nullptr,ESelection(),bIsForSelection,rCoreSet );
+ }
+
+ void SetLanguage_None( SwWrtShell &rWrtSh, OutlinerView const * pOLV, const ESelection& rSelection, bool bIsForSelection, SfxItemSet &rCoreSet )
+ {
+ // EditEngine IDs
+ const sal_uInt16 aLangWhichId_EE[3] =
+ {
+ EE_CHAR_LANGUAGE,
+ EE_CHAR_LANGUAGE_CJK,
+ EE_CHAR_LANGUAGE_CTL
+ };
+
+ // Writer IDs
+ const sal_uInt16 aLangWhichId_Writer[3] =
+ {
+ RES_CHRATR_LANGUAGE,
+ RES_CHRATR_CJK_LANGUAGE,
+ RES_CHRATR_CTL_LANGUAGE
+ };
+
+ if (bIsForSelection)
+ {
+ // change language for selection or paragraph
+ // (for paragraph is handled by previously having set the selection to the
+ // whole paragraph)
+
+ EditEngine* pEditEngine = pOLV ? pOLV->GetEditView().GetEditEngine() : nullptr;
+ OSL_ENSURE( !pOLV || pEditEngine, "OutlinerView without EditEngine???" );
+ if (pEditEngine)
+ {
+ for (sal_uInt16 i : aLangWhichId_EE)
+ rCoreSet.Put( SvxLanguageItem( LANGUAGE_NONE, i ));
+ pEditEngine->QuickSetAttribs(rCoreSet, rSelection);
+ }
+ else
+ {
+ rWrtSh.GetCurAttr( rCoreSet );
+ for (sal_uInt16 i : aLangWhichId_Writer)
+ rCoreSet.Put( SvxLanguageItem( LANGUAGE_NONE, i ));
+ rWrtSh.SetAttrSet( rCoreSet );
+ }
+ }
+ else // change language for all text
+ {
+ o3tl::sorted_vector<sal_uInt16> aAttribs;
+ for (sal_uInt16 i : aLangWhichId_Writer)
+ {
+ rWrtSh.SetDefault( SvxLanguageItem( LANGUAGE_NONE, i ) );
+ aAttribs.insert( i );
+ }
+ rWrtSh.GetDoc()->GetDocShell()->Broadcast(SfxHint(SfxHintId::LanguageChanged));
+
+ // set all language attributes to default
+ // (for all text in the document - which should be selected by now...)
+ rWrtSh.ResetAttr( aAttribs );
+ }
+ }
+
+ void ResetLanguages( SwWrtShell &rWrtSh, OutlinerView const * pOLV )
+ {
+ // reset language for current selection.
+ // The selection should already have been expanded to the whole paragraph or
+ // to all text in the document if those are the ranges where to reset
+ // the language attributes
+
+ if (pOLV)
+ {
+ EditView &rEditView = pOLV->GetEditView();
+ rEditView.RemoveAttribs( true, EE_CHAR_LANGUAGE );
+ rEditView.RemoveAttribs( true, EE_CHAR_LANGUAGE_CJK );
+ rEditView.RemoveAttribs( true, EE_CHAR_LANGUAGE_CTL );
+
+ // ugly hack, as it seems that EditView/EditEngine does not update their spellchecking marks
+ // when setting a new language attribute
+ EditEngine* pEditEngine = rEditView.GetEditEngine();
+ EEControlBits nCntrl = pEditEngine->GetControlWord();
+ // turn off
+ pEditEngine->SetControlWord(nCntrl & ~EEControlBits::ONLINESPELLING);
+ //turn back on
+ pEditEngine->SetControlWord(nCntrl);
+ pEditEngine->CompleteOnlineSpelling();
+
+ rEditView.Invalidate();
+ }
+ else
+ {
+ rWrtSh.ResetAttr(
+ { RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE });
+ }
+ }
+
+ /// @returns : the language for the selected text that is set for the
+ /// specified attribute (script type).
+ /// If there are more than one languages used LANGUAGE_DONTKNOW will be returned.
+ /// @param nLangWhichId : one of
+ /// RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE,
+ LanguageType GetLanguage( SwWrtShell &rSh, TypedWhichId<SvxLanguageItem> nLangWhichId )
+ {
+ SfxItemSet aSet( rSh.GetAttrPool(), nLangWhichId, nLangWhichId );
+ rSh.GetCurAttr( aSet );
+
+ return GetLanguage(aSet,nLangWhichId);
+ }
+
+ LanguageType GetLanguage( SfxItemSet const & aSet, TypedWhichId<SvxLanguageItem> nLangWhichId )
+ {
+
+ LanguageType nLang = LANGUAGE_SYSTEM;
+
+ const SvxLanguageItem *pItem = nullptr;
+ SfxItemState nState = aSet.GetItemState( nLangWhichId, true, &pItem );
+ if (nState > SfxItemState::DEFAULT && pItem)
+ {
+ // the item is set and can be used
+ nLang = pItem->GetLanguage();
+ }
+ else if (nState == SfxItemState::DEFAULT)
+ {
+ // since the attribute is not set: retrieve the default value
+ nLang = aSet.GetPool()->GetDefaultItem( nLangWhichId ).GetLanguage();
+ }
+ else if (nState == SfxItemState::DONTCARE)
+ {
+ // there is more than one language...
+ nLang = LANGUAGE_DONTKNOW;
+ }
+ OSL_ENSURE( nLang != LANGUAGE_SYSTEM, "failed to get the language?" );
+
+ return nLang;
+ }
+
+ /// @returns: the language in use for the selected text.
+ /// 'In use' means the language(s) matching the script type(s) of the
+ /// selected text. Or in other words, the language a spell checker would use.
+ /// If there is more than one language LANGUAGE_DONTKNOW will be returned.
+ LanguageType GetCurrentLanguage( SwWrtShell &rSh )
+ {
+ //set language attribute to use according to the script type
+ TypedWhichId<SvxLanguageItem> nLangWhichId(0);
+ bool bIsSingleScriptType = true;
+ switch (rSh.GetScriptType())
+ {
+ case SvtScriptType::LATIN : nLangWhichId = RES_CHRATR_LANGUAGE; break;
+ case SvtScriptType::ASIAN : nLangWhichId = RES_CHRATR_CJK_LANGUAGE; break;
+ case SvtScriptType::COMPLEX : nLangWhichId = RES_CHRATR_CTL_LANGUAGE; break;
+ default: bIsSingleScriptType = false; break;
+ }
+
+ // get language according to the script type(s) in use
+ LanguageType nCurrentLang = LANGUAGE_SYSTEM;
+ if (bIsSingleScriptType)
+ nCurrentLang = GetLanguage( rSh, nLangWhichId );
+ else
+ {
+ // check if all script types are set to LANGUAGE_NONE and return
+ // that if this is the case. Otherwise, having multiple script types
+ // in use always means there are several languages in use...
+ const TypedWhichId<SvxLanguageItem> aScriptTypes[3] =
+ {
+ RES_CHRATR_LANGUAGE,
+ RES_CHRATR_CJK_LANGUAGE,
+ RES_CHRATR_CTL_LANGUAGE
+ };
+ nCurrentLang = LANGUAGE_NONE;
+ for (const TypedWhichId<SvxLanguageItem>& aScriptType : aScriptTypes)
+ {
+ LanguageType nTmpLang = GetLanguage( rSh, aScriptType );
+ if (nTmpLang != LANGUAGE_NONE)
+ {
+ nCurrentLang = LANGUAGE_DONTKNOW;
+ break;
+ }
+ }
+ }
+ OSL_ENSURE( nCurrentLang != LANGUAGE_SYSTEM, "failed to get the language?" );
+
+ return nCurrentLang;
+ }
+
+ /// @returns: the language in use for the selected text.
+ /// 'In use' means the language(s) matching the script type(s) of the
+ /// selected text. Or in other words, the language a spell checker would use.
+ /// If there is more than one language LANGUAGE_DONTKNOW will be returned.
+ LanguageType GetCurrentLanguage( SfxItemSet const & aSet, SvtScriptType nScriptType )
+ {
+ //set language attribute to use according to the script type
+ TypedWhichId<SvxLanguageItem> nLangWhichId(0);
+ bool bIsSingleScriptType = true;
+ switch (nScriptType)
+ {
+ case SvtScriptType::LATIN : nLangWhichId = EE_CHAR_LANGUAGE; break;
+ case SvtScriptType::ASIAN : nLangWhichId = EE_CHAR_LANGUAGE_CJK; break;
+ case SvtScriptType::COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break;
+ default: bIsSingleScriptType = false;
+ }
+
+ // get language according to the script type(s) in use
+ LanguageType nCurrentLang = LANGUAGE_SYSTEM;
+ if (bIsSingleScriptType)
+ nCurrentLang = GetLanguage( aSet, nLangWhichId );
+ else
+ {
+ // check if all script types are set to LANGUAGE_NONE and return
+ // that if this is the case. Otherwise, having multiple script types
+ // in use always means there are several languages in use...
+ const TypedWhichId<SvxLanguageItem> aScriptTypes[3] =
+ {
+ EE_CHAR_LANGUAGE,
+ EE_CHAR_LANGUAGE_CJK,
+ EE_CHAR_LANGUAGE_CTL
+ };
+ nCurrentLang = LANGUAGE_NONE;
+ for (const TypedWhichId<SvxLanguageItem>& aScriptType : aScriptTypes)
+ {
+ LanguageType nTmpLang = GetLanguage( aSet, aScriptType );
+ if (nTmpLang != LANGUAGE_NONE)
+ {
+ nCurrentLang = LANGUAGE_DONTKNOW;
+ break;
+ }
+ }
+ }
+ OSL_ENSURE( nCurrentLang != LANGUAGE_SYSTEM, "failed to get the language?" );
+
+ return nCurrentLang;
+ }
+
+ OUString GetTextForLanguageGuessing( SwWrtShell const &rSh )
+ {
+ // string for guessing language
+ OUString aText;
+ SwPaM *pCursor = rSh.GetCursor();
+ SwTextNode *pNode = pCursor->GetPointNode().GetTextNode();
+ if (pNode)
+ {
+ aText = pNode->GetText();
+ if (!aText.isEmpty())
+ {
+ sal_Int32 nEnd = pCursor->GetPoint()->GetContentIndex();
+ // at most 100 chars to the left...
+ const sal_Int32 nStt = nEnd > 100 ? nEnd - 100 : 0;
+ // ... and 100 to the right of the cursor position
+ nEnd = aText.getLength() - nEnd > 100 ? nEnd + 100 : aText.getLength();
+ aText = aText.copy( nStt, nEnd - nStt );
+ }
+ }
+ return aText;
+ }
+
+ OUString GetTextForLanguageGuessing(EditEngine const * rEditEngine, const ESelection& rDocSelection)
+ {
+ // string for guessing language
+
+ // get the full text of the paragraph that the end of selection is in
+ OUString aText = rEditEngine->GetText(rDocSelection.nEndPos);
+ if (!aText.isEmpty())
+ {
+ sal_Int32 nStt = 0;
+ sal_Int32 nEnd = rDocSelection.nEndPos;
+ // at most 100 chars to the left...
+ nStt = nEnd > 100 ? nEnd - 100 : 0;
+ // ... and 100 to the right of the cursor position
+ nEnd = aText.getLength() - nEnd > 100 ? nEnd + 100 : aText.getLength();
+ aText = aText.copy( nStt, nEnd - nStt );
+ }
+
+ return aText;
+ }
+
+ void SelectPara( EditView &rEditView, const ESelection &rCurSel )
+ {
+ ESelection aParaSel( rCurSel.nStartPara, 0, rCurSel.nStartPara, EE_TEXTPOS_ALL );
+ rEditView.SetSelection( aParaSel );
+ }
+
+ void SelectCurrentPara( SwWrtShell &rWrtSh )
+ {
+ // select current para
+ if (!rWrtSh.IsSttPara())
+ rWrtSh.MovePara( GoCurrPara, fnParaStart );
+ if (!rWrtSh.HasMark())
+ rWrtSh.SetMark();
+ rWrtSh.SwapPam();
+ if (!rWrtSh.IsEndPara())
+ rWrtSh.MovePara( GoCurrPara, fnParaEnd );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/listsh.cxx b/sw/source/uibase/shells/listsh.cxx
new file mode 100644
index 0000000000..f6100cc0a4
--- /dev/null
+++ b/sw/source/uibase/shells/listsh.cxx
@@ -0,0 +1,264 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cmdid.h>
+#include <sfx2/request.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/eitem.hxx>
+#include <svl/whiter.hxx>
+#include <osl/diagnose.h>
+
+#include <numrule.hxx>
+#include <wrtsh.hxx>
+#include <listsh.hxx>
+#include <view.hxx>
+
+#define ShellClass_SwListShell
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+
+#include <IDocumentOutlineNodes.hxx>
+
+SFX_IMPL_INTERFACE(SwListShell, SwBaseShell)
+
+void SwListShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Num_Toolbox);
+}
+
+
+// #i35572# Functionality of Numbering/Bullet toolbar
+// for outline numbered paragraphs should match the functions for outlines
+// available in the navigator. Therefore the code in the following
+// function is quite similar the code in SwContentTree::ExecCommand.
+static void lcl_OutlineUpDownWithSubPoints( SwWrtShell& rSh, bool bMove, bool bUp )
+{
+ const SwOutlineNodes::size_type nActPos = rSh.GetOutlinePos();
+ if ( !(nActPos < SwOutlineNodes::npos && rSh.IsOutlineMovable( nActPos )) )
+ return;
+
+ rSh.Push();
+ rSh.MakeOutlineSel( nActPos, nActPos, true );
+
+ if ( bMove )
+ {
+ const IDocumentOutlineNodes* pIDoc( rSh.getIDocumentOutlineNodesAccess() );
+ const int nActLevel = pIDoc->getOutlineLevel( nActPos );
+ SwOutlineNodes::difference_type nDir = 0;
+
+ if ( !bUp )
+ {
+ // Move down with subpoints:
+ SwOutlineNodes::size_type nActEndPos = nActPos + 1;
+ while ( nActEndPos < pIDoc->getOutlineNodesCount() &&
+ (!pIDoc->isOutlineInLayout(nActEndPos, *rSh.GetLayout())
+ || nActLevel < pIDoc->getOutlineLevel(nActEndPos)))
+ {
+ ++nActEndPos;
+ }
+
+ if ( nActEndPos < pIDoc->getOutlineNodesCount() )
+ {
+ // The current subpoint which should be moved
+ // starts at nActPos and ends at nActEndPos - 1
+ --nActEndPos;
+ SwOutlineNodes::size_type nDest = nActEndPos + 2;
+ while ( nDest < pIDoc->getOutlineNodesCount() &&
+ (!pIDoc->isOutlineInLayout(nDest, *rSh.GetLayout())
+ || nActLevel < pIDoc->getOutlineLevel(nDest)))
+ {
+ ++nDest;
+ }
+
+ nDir = nDest - 1 - nActEndPos;
+ }
+ }
+ else
+ {
+ // Move up with subpoints:
+ if ( nActPos > 0 )
+ {
+ SwOutlineNodes::size_type nDest = nActPos - 1;
+ while (nDest > 0 &&
+ (!pIDoc->isOutlineInLayout(nDest, *rSh.GetLayout())
+ || nActLevel < pIDoc->getOutlineLevel(nDest)))
+ {
+ --nDest;
+ }
+
+ nDir = nDest - nActPos;
+ }
+ }
+
+ if ( nDir )
+ {
+ rSh.MoveOutlinePara( nDir );
+ rSh.GotoOutline( nActPos + nDir );
+ }
+ }
+ else
+ {
+ // Up/down with subpoints:
+ rSh.OutlineUpDown( bUp ? -1 : 1 );
+ }
+
+ rSh.ClearMark();
+ rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+}
+
+void SwListShell::Execute(SfxRequest &rReq)
+{
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const sal_uInt16 nSlot = rReq.GetSlot();
+ SwWrtShell& rSh = GetShell();
+
+ // #i35572#
+ const SwNumRule* pCurRule = rSh.GetNumRuleAtCurrCursorPos();
+ OSL_ENSURE( pCurRule, "SwListShell::Execute without NumRule" );
+ bool bOutline = pCurRule && pCurRule->IsOutlineRule();
+
+ switch (nSlot)
+ {
+ case FN_NUM_BULLET_DOWN:
+ case FN_NUM_BULLET_UP:
+ {
+ SfxViewFrame& rFrame = GetView().GetViewFrame();
+
+ rReq.Done();
+ rSh.NumUpDown( nSlot == FN_NUM_BULLET_DOWN );
+ rFrame.GetBindings().Invalidate( SID_TABLE_CELL ); // Update status line!
+ }
+ break;
+
+ case FN_NUM_BULLET_NEXT:
+ rSh.GotoNextNum();
+ rReq.Done();
+ break;
+
+ case FN_NUM_BULLET_NONUM:
+ rSh.NoNum();
+ rReq.Done();
+ break;
+
+ case FN_NUM_BULLET_OUTLINE_DOWN:
+ if ( bOutline )
+ lcl_OutlineUpDownWithSubPoints( rSh, false, false );
+ else
+ rSh.MoveNumParas(false, false);
+ rReq.Done();
+ break;
+
+ case FN_NUM_BULLET_OUTLINE_MOVEDOWN:
+ if ( bOutline )
+ lcl_OutlineUpDownWithSubPoints( rSh, true, false );
+ else
+ rSh.MoveNumParas(true, false);
+ rReq.Done();
+ break;
+
+ case FN_NUM_BULLET_OUTLINE_MOVEUP:
+ if ( bOutline )
+ lcl_OutlineUpDownWithSubPoints( rSh, true, true );
+ else
+ rSh.MoveNumParas(true, true);
+ rReq.Done();
+ break;
+
+ case FN_NUM_BULLET_OUTLINE_UP:
+ if ( bOutline )
+ lcl_OutlineUpDownWithSubPoints( rSh, false, true );
+ else
+ rSh.MoveNumParas(false, true);
+ rReq.Done();
+ break;
+
+ case FN_NUM_BULLET_PREV:
+ rSh.GotoPrevNum();
+ rReq.Done();
+ break;
+
+ case FN_NUM_OR_NONUM:
+ {
+ bool bApi = rReq.IsAPI();
+ bool bDelete = !rSh.IsNoNum(!bApi);
+ if(pArgs )
+ bDelete = static_cast<const SfxBoolItem &>(pArgs->Get(rReq.GetSlot())).GetValue();
+ rSh.NumOrNoNum( bDelete, !bApi );
+ rReq.AppendItem( SfxBoolItem( nSlot, bDelete ) );
+ rReq.Done();
+ }
+ break;
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ return;
+ }
+}
+
+void SwListShell::GetState(SfxItemSet &rSet)
+{
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ SwWrtShell& rSh = GetShell();
+ sal_uInt8 nCurrentNumLevel = rSh.GetNumLevel();
+ while ( nWhich )
+ {
+ switch( nWhich )
+ {
+ case FN_NUM_OR_NONUM:
+ rSet.Put(SfxBoolItem(nWhich, GetShell().IsNoNum(false)));
+ break;
+ case FN_NUM_BULLET_OUTLINE_UP:
+ case FN_NUM_BULLET_UP:
+ if(!nCurrentNumLevel)
+ rSet.DisableItem(nWhich);
+ break;
+ case FN_NUM_BULLET_OUTLINE_DOWN :
+ {
+ sal_uInt8 nUpper = 0;
+ sal_uInt8 nLower = 0;
+ rSh.GetCurrentOutlineLevels( nUpper, nLower );
+ if(nLower == (MAXLEVEL - 1))
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case FN_NUM_BULLET_DOWN:
+ if(nCurrentNumLevel == (MAXLEVEL - 1))
+ rSet.DisableItem(nWhich);
+ break;
+
+ case FN_NUM_BULLET_NONUM:
+ if ( rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+SwListShell::SwListShell(SwView &_rView) :
+ SwBaseShell(_rView)
+{
+ SetName("List");
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/mediash.cxx b/sw/source/uibase/shells/mediash.cxx
new file mode 100644
index 0000000000..ab3628bfe1
--- /dev/null
+++ b/sw/source/uibase/shells/mediash.cxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cmdid.h>
+#include <sfx2/request.hxx>
+#include <svx/svdview.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <mediash.hxx>
+
+#include <sfx2/objface.hxx>
+#include <vcl/EnumContext.hxx>
+#include <svx/MediaShellHelpers.hxx>
+
+#define ShellClass_SwMediaShell
+#include <swslots.hxx>
+
+using namespace svx;
+
+SFX_IMPL_INTERFACE(SwMediaShell, SwBaseShell)
+
+void SwMediaShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("media");
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible,
+ ToolbarId::Media_Toolbox);
+}
+
+void SwMediaShell::ExecMedia(SfxRequest const& rReq)
+{
+ SwWrtShell* pSh = &GetShell();
+ SdrView* pSdrView = pSh->GetDrawView();
+
+ if (!pSdrView)
+ return;
+
+ const bool bChanged = pSdrView->GetModel().IsChanged();
+ pSdrView->GetModel().SetChanged(false);
+
+ switch (rReq.GetSlot())
+ {
+ case SID_DELETE:
+ if (pSh->IsObjSelected())
+ {
+ pSh->SetModified();
+ pSh->DelSelectedObj();
+
+ if (pSh->IsSelFrameMode())
+ pSh->LeaveSelFrameMode();
+
+ GetView().AttrChangedNotify(nullptr);
+ }
+ break;
+
+ case SID_AVMEDIA_TOOLBOX:
+ if (pSh->IsObjSelected())
+ MediaShellHelpers::Execute(pSdrView, rReq);
+ break;
+
+ default:
+ break;
+ }
+
+ if (pSdrView->GetModel().IsChanged())
+ GetShell().SetModified();
+ else if (bChanged)
+ pSdrView->GetModel().SetChanged();
+}
+
+void SwMediaShell::GetMediaState(SfxItemSet& rSet)
+{
+ MediaShellHelpers::GetState(GetShell().GetDrawView(), rSet);
+}
+
+SwMediaShell::SwMediaShell(SwView& _rView)
+ : SwBaseShell(_rView)
+{
+ SetName("Media Playback");
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Media));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/navsh.cxx b/sw/source/uibase/shells/navsh.cxx
new file mode 100644
index 0000000000..c34bebdbc7
--- /dev/null
+++ b/sw/source/uibase/shells/navsh.cxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <cmdid.h>
+#include <svx/svdview.hxx>
+#include <svl/whiter.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/objface.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <navsh.hxx>
+#define ShellClass_SwNavigationShell
+#include <swslots.hxx>
+#include <navmgr.hxx>
+
+SFX_IMPL_INTERFACE(SwNavigationShell, SwBaseShell)
+
+void SwNavigationShell::InitInterface_Impl() {}
+
+SwNavigationShell::SwNavigationShell(SwView& _rView)
+ : SwBaseShell(_rView)
+{
+ SetName("Navigation");
+}
+
+void SwNavigationShell::Execute(SfxRequest const& rReq)
+{
+ SwWrtShell* pSh = &GetShell();
+ SdrView* pSdrView = pSh->GetDrawView();
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const sal_uInt16 nSlotId = rReq.GetSlot();
+ bool bChanged = pSdrView->GetModel().IsChanged();
+ pSdrView->GetModel().SetChanged(false);
+ SwNavigationMgr& aSwNavigationMgr = pSh->GetNavigationMgr();
+ const SfxPoolItem* pItem;
+ if (pArgs)
+ pArgs->GetItemState(nSlotId, false, &pItem);
+
+ if (pSdrView->IsTextEdit())
+ pSh->EndTextEdit();
+ if (pSh->GetView().IsDrawMode())
+ pSh->GetView().LeaveDrawCreate();
+ pSh->EnterStdMode();
+
+ switch (nSlotId)
+ {
+ case FN_NAVIGATION_BACK:
+ aSwNavigationMgr.goBack();
+ break;
+
+ case FN_NAVIGATION_FORWARD:
+ aSwNavigationMgr.goForward();
+ break;
+ default:
+ break;
+ }
+ if (pSdrView->GetModel().IsChanged())
+ GetShell().SetModified();
+ else if (bChanged)
+ pSdrView->GetModel().SetChanged();
+}
+
+// determine if the buttons should be enabled/disabled
+
+void SwNavigationShell::GetState(SfxItemSet& rSet)
+{
+ SwWrtShell* pSh = &GetShell();
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ SwNavigationMgr& aNavigationMgr = pSh->GetNavigationMgr();
+ while (nWhich)
+ {
+ switch (nWhich)
+ {
+ case FN_NAVIGATION_BACK:
+ if (!aNavigationMgr.backEnabled())
+ {
+ rSet.DisableItem(FN_NAVIGATION_BACK);
+ }
+ break;
+ case FN_NAVIGATION_FORWARD:
+ if (!aNavigationMgr.forwardEnabled())
+ {
+ rSet.DisableItem(FN_NAVIGATION_FORWARD);
+ }
+ break;
+ default:
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/olesh.cxx b/sw/source/uibase/shells/olesh.cxx
new file mode 100644
index 0000000000..28e8e153ee
--- /dev/null
+++ b/sw/source/uibase/shells/olesh.cxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/objface.hxx>
+#include <vcl/EnumContext.hxx>
+#include <view.hxx>
+#include <frmsh.hxx>
+#include <olesh.hxx>
+
+#include <sfx2/sidebar/SidebarController.hxx>
+
+#define ShellClass_SwOleShell
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+
+using namespace css::uno;
+using namespace sfx2::sidebar;
+
+namespace {
+
+bool inChartOrMathContext(const SwView& rViewShell)
+{
+ SidebarController* pSidebar = SidebarController::GetSidebarControllerForView(&rViewShell);
+ if (pSidebar)
+ return pSidebar->hasChartOrMathContextCurrently();
+
+ return false;
+}
+
+} // anonymous namespace
+
+SFX_IMPL_INTERFACE(SwOleShell, SwFrameShell)
+
+void SwOleShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("oleobject");
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Ole_Toolbox);
+}
+
+void SwOleShell::Activate(bool bMDI)
+{
+ if(!inChartOrMathContext(GetView()))
+ SwFrameShell::Activate(bMDI);
+ else
+ {
+ // Avoid context changes for chart/math during activation / deactivation.
+ const bool bIsContextBroadcasterEnabled (SfxShell::SetContextBroadcasterEnabled(false));
+
+ SwFrameShell::Activate(bMDI);
+
+ SfxShell::SetContextBroadcasterEnabled(bIsContextBroadcasterEnabled);
+ }
+}
+
+void SwOleShell::Deactivate(bool bMDI)
+{
+ if(!inChartOrMathContext(GetView()))
+ SwFrameShell::Deactivate(bMDI);
+ else
+ {
+ // Avoid context changes for chart/math during activation / deactivation.
+ const bool bIsContextBroadcasterEnabled (SfxShell::SetContextBroadcasterEnabled(false));
+
+ SwFrameShell::Deactivate(bMDI);
+
+ SfxShell::SetContextBroadcasterEnabled(bIsContextBroadcasterEnabled);
+ }
+}
+
+SwOleShell::SwOleShell(SwView &_rView) :
+ SwFrameShell(_rView)
+
+{
+ SetName("Object");
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::OLE));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/slotadd.cxx b/sw/source/uibase/shells/slotadd.cxx
new file mode 100644
index 0000000000..b8253ce75f
--- /dev/null
+++ b/sw/source/uibase/shells/slotadd.cxx
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_options.h>
+
+#include <cmdid.h>
+#include <unomid.h>
+#include <svx/unomid.hxx>
+
+#include <svl/globalnameitem.hxx>
+#include <editeng/memberids.h>
+#include <svl/imageitm.hxx>
+#include <svl/rectitem.hxx>
+#include <sfx2/objitem.hxx>
+#include <sfx2/objsh.hxx>
+#include <svx/rulritem.hxx>
+#include <svx/statusitem.hxx>
+#include <sfx2/zoomitem.hxx>
+#include <svx/viewlayoutitem.hxx>
+#include <svx/zoomslideritem.hxx>
+#include <svx/hlnkitem.hxx>
+#include <svx/SmartTagItem.hxx>
+#include <svl/ptitem.hxx>
+#include <svx/pageitem.hxx>
+#include <svl/srchitem.hxx>
+#include <sfx2/tplpitem.hxx>
+#include <sfx2/watermarkitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/protitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/autokernitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/spltitem.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/pbinitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/prntitem.hxx>
+#include <editeng/orphitem.hxx>
+#include <editeng/widwitem.hxx>
+#include <editeng/lineitem.hxx>
+#include <editeng/pmdlitem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/formatbreakitem.hxx>
+#include <editeng/hyphenzoneitem.hxx>
+#include <editeng/escapementitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/adjustitem.hxx>
+#include <editeng/crossedoutitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/contouritem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/sizeitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <svx/sdmetitm.hxx>
+#include <svx/sdprcitm.hxx>
+#include <svx/xlnstit.hxx>
+#include <svx/xlnedit.hxx>
+#include <svx/xfillit0.hxx>
+#include <svx/xflclit.hxx>
+#include <svx/xflgrit.hxx>
+#include <svx/xflhtit.hxx>
+#include <svx/xbtmpit.hxx>
+#include <svx/xlineit0.hxx>
+#include <svx/xlnwtit.hxx>
+#include <svx/xlndsit.hxx>
+#include <svx/xlnclit.hxx>
+#include <svx/xtextit0.hxx>
+#include <svx/xftadit.hxx>
+#include <svx/xftdiit.hxx>
+#include <svx/xftstit.hxx>
+#include <svx/xftmrit.hxx>
+#include <svx/xftouit.hxx>
+#include <svx/xftshit.hxx>
+#include <svx/xftshcit.hxx>
+#include <svx/xftshxy.hxx>
+#include <svx/grafctrl.hxx>
+
+#include <paratr.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtsrnd.hxx>
+#include <envimg.hxx>
+#include <fmtline.hxx>
+#include <svx/clipfmtitem.hxx>
+#include <editeng/blinkitem.hxx>
+#include <svl/slstitm.hxx>
+#include <editeng/paravertalignitem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <svx/postattr.hxx>
+#include <sfx2/frame.hxx>
+#include <svx/chrtitem.hxx>
+#include <svx/drawitem.hxx>
+#include <avmedia/mediaitem.hxx>
+
+#define avmedia_MediaItem ::avmedia::MediaItem
+
+#include <svx/xflftrit.hxx>
+#include <svx/xlncapit.hxx>
+#include <svx/xlinjoit.hxx>
+#include <svx/galleryitem.hxx>
+#include <svx/sdangitm.hxx>
+
+#define SFX_TYPEMAP
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/tabsh.cxx b/sw/source/uibase/shells/tabsh.cxx
new file mode 100644
index 0000000000..87df4f059d
--- /dev/null
+++ b/sw/source/uibase/shells/tabsh.cxx
@@ -0,0 +1,1682 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+#include <svl/imageitm.hxx>
+#include <svl/numformat.hxx>
+#include <svl/zforlist.hxx>
+#include <svl/stritem.hxx>
+#include <svl/whiter.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/spltitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/lineitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <svx/numinf.hxx>
+#include <svx/svddef.hxx>
+#include <svx/svxdlg.hxx>
+#include <sfx2/bindings.hxx>
+#include <vcl/weld.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <vcl/EnumContext.hxx>
+#include <o3tl/enumrange.hxx>
+#include <comphelper/lok.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <editeng/itemtype.hxx>
+#include <osl/diagnose.h>
+
+#include <fmtornt.hxx>
+#include <fmtlsplt.hxx>
+#include <fmtrowsplt.hxx>
+#include <fmtfsize.hxx>
+#include <swmodule.hxx>
+#include <wrtsh.hxx>
+#include <rootfrm.hxx>
+#include <wview.hxx>
+#include <frmatr.hxx>
+#include <uitool.hxx>
+#include <inputwin.hxx>
+#include <uiitems.hxx>
+#include <tabsh.hxx>
+#include <swtablerep.hxx>
+#include <tablemgr.hxx>
+#include <cellatr.hxx>
+#include <frmfmt.hxx>
+#include <swundo.hxx>
+#include <swtable.hxx>
+#include <docsh.hxx>
+#include <tblsel.hxx>
+#include <viewopt.hxx>
+#include <tabfrm.hxx>
+
+#include <strings.hrc>
+#include <cmdid.h>
+#include <unobaseclass.hxx>
+
+#define ShellClass_SwTableShell
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+
+#include <swabstdlg.hxx>
+
+#include <memory>
+
+using ::editeng::SvxBorderLine;
+using namespace ::com::sun::star;
+
+SFX_IMPL_INTERFACE(SwTableShell, SwBaseShell)
+
+void SwTableShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("table");
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Table_Toolbox);
+}
+
+
+const WhichRangesContainer aUITableAttrRange(svl::Items<
+ RES_LR_SPACE, RES_UL_SPACE,
+ RES_PAGEDESC, RES_BREAK,
+ RES_BACKGROUND, RES_BACKGROUND,
+ RES_BOX, RES_SHADOW,
+ RES_KEEP, RES_KEEP,
+ RES_LAYOUT_SPLIT, RES_LAYOUT_SPLIT,
+ RES_FRAMEDIR, RES_FRAMEDIR,
+ RES_ROW_SPLIT, RES_ROW_SPLIT,
+// #i29550#
+ RES_COLLAPSING_BORDERS, RES_COLLAPSING_BORDERS,
+// <-- collapsing borders
+ XATTR_FILL_FIRST, XATTR_FILL_LAST,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_SHADOW,
+ SID_RULER_BORDERS, SID_RULER_BORDERS,
+ SID_ATTR_BRUSH_ROW, SID_ATTR_BRUSH_TABLE, // ??? This is very strange range
+// SID_BACKGRND_DESTINATION, SID_BACKGRND_DESTINATION, // included into above
+// SID_HTML_MODE, SID_HTML_MODE, // included into above
+ FN_TABLE_REP, FN_TABLE_REP,
+ FN_TABLE_SET_VERT_ALIGN, FN_TABLE_SET_VERT_ALIGN,
+ FN_TABLE_BOX_TEXTORIENTATION, FN_TABLE_BOX_TEXTORIENTATION,
+ FN_PARAM_TABLE_NAME, FN_PARAM_TABLE_NAME,
+ FN_PARAM_TABLE_HEADLINE, FN_PARAM_TABLE_HEADLINE
+>);
+
+const WhichRangesContainer& SwuiGetUITableAttrRange()
+{
+ return aUITableAttrRange;
+}
+
+static void lcl_SetAttr( SwWrtShell &rSh, const SfxPoolItem &rItem )
+{
+ SfxItemSet aSet( rSh.GetView().GetPool(), rItem.Which(), rItem.Which());
+ aSet.Put( rItem );
+ rSh.SetTableAttr( aSet );
+}
+
+static std::shared_ptr<SwTableRep> lcl_TableParamToItemSet( SfxItemSet& rSet, SwWrtShell &rSh )
+{
+ std::shared_ptr<SwTableRep> pRep;
+
+ SwFrameFormat *pFormat = rSh.GetTableFormat();
+ SwTabCols aCols;
+ rSh.GetTabCols( aCols );
+
+ //At first get the simple attributes.
+ rSet.Put( SfxStringItem( FN_PARAM_TABLE_NAME, pFormat->GetName()));
+ rSet.Put( SfxUInt16Item( FN_PARAM_TABLE_HEADLINE, rSh.GetRowsToRepeat() ) );
+ rSet.Put( pFormat->GetShadow() );
+ rSet.Put(SfxUInt16Item(FN_TABLE_SET_VERT_ALIGN, rSh.GetBoxAlign()));
+ rSet.Put( pFormat->GetFrameDir() );
+
+ SvxULSpaceItem aULSpace( pFormat->GetULSpace() );
+ rSet.Put( aULSpace );
+
+ const sal_uInt16 nBackgroundDestination = rSh.GetViewOptions()->GetTableDest();
+ rSet.Put(SfxUInt16Item(SID_BACKGRND_DESTINATION, nBackgroundDestination ));
+ std::unique_ptr<SvxBrushItem> aBrush(std::make_unique<SvxBrushItem>(RES_BACKGROUND));
+ if(rSh.GetRowBackground(aBrush))
+ {
+ aBrush->SetWhich(SID_ATTR_BRUSH_ROW);
+ rSet.Put( *aBrush );
+ }
+ else
+ rSet.InvalidateItem(SID_ATTR_BRUSH_ROW);
+ rSh.GetTabBackground(aBrush);
+ aBrush->SetWhich(SID_ATTR_BRUSH_TABLE);
+ rSet.Put( *aBrush );
+
+ // text direction in boxes
+ std::unique_ptr<SvxFrameDirectionItem> aBoxDirection(std::make_unique<SvxFrameDirectionItem>(SvxFrameDirection::Environment, RES_FRAMEDIR));
+ if(rSh.GetBoxDirection( aBoxDirection ))
+ {
+ aBoxDirection->SetWhich(FN_TABLE_BOX_TEXTORIENTATION);
+ rSet.Put(*aBoxDirection);
+ }
+
+ bool bSelectAll = rSh.StartsWith_() == SwCursorShell::StartsWith::Table && rSh.ExtendedSelectedAll();
+ bool bTableSel = rSh.IsTableMode() || bSelectAll;
+ if(!bTableSel)
+ {
+ rSh.StartAllAction();
+ rSh.Push();
+ rSh.GetView().GetViewFrame().GetDispatcher()->Execute( FN_TABLE_SELECT_ALL );
+ }
+ SvxBoxInfoItem aBoxInfo( SID_ATTR_BORDER_INNER );
+
+ // Table variant: If multiple table cells are selected.
+ rSh.GetCursor(); //Thus GetCursorCnt() returns the right thing
+ aBoxInfo.SetTable ((rSh.IsTableMode() && rSh.GetCursorCnt() > 1) ||
+ !bTableSel);
+ // Always show distance field.
+ aBoxInfo.SetDist (true);
+ // Set minimum size in tables and paragraphs.
+ aBoxInfo.SetMinDist( !bTableSel || rSh.IsTableMode() ||
+ rSh.GetSelectionType() &
+ (SelectionType::Text | SelectionType::Table));
+ // Always set the default spacing.
+ aBoxInfo.SetDefDist (MIN_BORDER_DIST);
+ // Individual lines can have DontCare status only in tables.
+ aBoxInfo.SetValid( SvxBoxInfoItemValidFlags::DISABLE, !bTableSel || !rSh.IsTableMode() );
+
+ rSet.Put(aBoxInfo);
+ rSh.GetTabBorders( rSet );
+
+ //row split
+ std::unique_ptr<SwFormatRowSplit> pSplit = rSh.GetRowSplit();
+ if(pSplit)
+ rSet.Put(std::move(pSplit));
+
+ if(!bTableSel)
+ {
+ rSh.ClearMark();
+ rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+ rSh.EndAllAction();
+ }
+
+ SwTabCols aTabCols;
+ rSh.GetTabCols( aTabCols );
+
+ // Pointer will be deleted after the dialogue execution.
+ pRep = std::make_shared<SwTableRep>(aTabCols);
+ pRep->SetSpace(aCols.GetRightMax());
+
+ sal_uInt16 nPercent = 0;
+ auto nWidth = ::GetTableWidth(pFormat, aCols, &nPercent, &rSh );
+ // The table width is wrong for relative values.
+ if (nPercent)
+ nWidth = pRep->GetSpace() * nPercent / 100;
+ const sal_uInt16 nAlign = pFormat->GetHoriOrient().GetHoriOrient();
+ pRep->SetAlign(nAlign);
+ SvxLRSpaceItem aLRSpace( pFormat->GetLRSpace() );
+ SwTwips nLeft = aLRSpace.GetLeft();
+ SwTwips nRight = aLRSpace.GetRight();
+ SwTwips nDiff = pRep->GetSpace() - nRight - nLeft - nWidth;
+ if(nAlign != text::HoriOrientation::FULL && std::abs(nDiff) > 2)
+ {
+ SwTwips nLR = pRep->GetSpace() - nWidth;
+ switch ( nAlign )
+ {
+ case text::HoriOrientation::CENTER:
+ nLeft = nRight = nLR / 2;
+ break;
+ case text::HoriOrientation::LEFT:
+ nRight = nLR;
+ nLeft = 0;
+ break;
+ case text::HoriOrientation::RIGHT:
+ nLeft = nLR;
+ nRight = 0;
+ break;
+ case text::HoriOrientation::LEFT_AND_WIDTH:
+ nRight = nLR - nLeft;
+ break;
+ case text::HoriOrientation::NONE:
+ if(!nPercent)
+ nWidth = pRep->GetSpace() - nLeft - nRight;
+ break;
+ }
+ }
+ pRep->SetLeftSpace(nLeft);
+ pRep->SetRightSpace(nRight);
+
+ pRep->SetWidth(nWidth);
+ pRep->SetWidthPercent(nPercent);
+ // Are individual rows / cells are selected, the column processing will be changed.
+ pRep->SetLineSelected(bTableSel && ! rSh.HasWholeTabSelection());
+ rSet.Put(SwPtrItem(FN_TABLE_REP, pRep.get()));
+ return pRep;
+}
+
+void ItemSetToTableParam( const SfxItemSet& rSet,
+ SwWrtShell &rSh )
+{
+ rSh.StartAllAction();
+ rSh.StartUndo( SwUndoId::TABLE_ATTR );
+
+ if(const SfxUInt16Item* pDestItem = rSet.GetItemIfSet(SID_BACKGRND_DESTINATION, false))
+ {
+ SwViewOption aUsrPref( *rSh.GetViewOptions() );
+ aUsrPref.SetTableDest(static_cast<sal_uInt8>(pDestItem->GetValue()));
+ SW_MOD()->ApplyUsrPref(aUsrPref, &rSh.GetView());
+ }
+ bool bBorder = ( SfxItemState::SET == rSet.GetItemState( RES_BOX ) ||
+ SfxItemState::SET == rSet.GetItemState( SID_ATTR_BORDER_INNER ) );
+ const SvxBrushItem* pBackgroundItem = rSet.GetItemIfSet( RES_BACKGROUND, false );
+ const SvxBrushItem* pRowItem = rSet.GetItemIfSet( SID_ATTR_BRUSH_ROW, false );
+ const SvxBrushItem* pTableItem = rSet.GetItemIfSet( SID_ATTR_BRUSH_TABLE, false );
+ bool bBackground = pBackgroundItem || pRowItem || pTableItem;
+ const SwFormatRowSplit* pSplit = rSet.GetItemIfSet( RES_ROW_SPLIT, false );
+ bool bRowSplit = pSplit != nullptr;
+ const SvxFrameDirectionItem* pBoxDirection = rSet.GetItemIfSet( FN_TABLE_BOX_TEXTORIENTATION, false );
+ bool bBoxDirection = pBoxDirection != nullptr;
+ if( bBackground || bBorder || bRowSplit || bBoxDirection)
+ {
+ // The border will be applied to the present selection.
+ // If there is no selection, the table will be completely selected.
+ // The background will always be applied to the current state.
+ bool bTableSel = rSh.IsTableMode();
+ rSh.StartAllAction();
+
+ if(bBackground)
+ {
+ if(pBackgroundItem)
+ rSh.SetBoxBackground( *pBackgroundItem );
+ if(pRowItem)
+ {
+ std::unique_ptr<SvxBrushItem> aBrush(pRowItem->Clone());
+ aBrush->SetWhich(RES_BACKGROUND);
+ rSh.SetRowBackground(*aBrush);
+ }
+ if(pTableItem)
+ {
+ std::unique_ptr<SvxBrushItem> aBrush(pTableItem->Clone());
+ aBrush->SetWhich(RES_BACKGROUND);
+ rSh.SetTabBackground( *aBrush );
+ }
+ }
+
+ if(bBoxDirection)
+ {
+ SvxFrameDirectionItem aDirection( SvxFrameDirection::Environment, RES_FRAMEDIR );
+ aDirection.SetValue(pBoxDirection->GetValue());
+ rSh.SetBoxDirection(aDirection);
+ }
+
+ if(bBorder || bRowSplit)
+ {
+ rSh.Push();
+ if(!bTableSel)
+ {
+ rSh.GetView().GetViewFrame().GetDispatcher()->Execute( FN_TABLE_SELECT_ALL );
+ }
+ if(bBorder)
+ rSh.SetTabBorders( rSet );
+
+ if(bRowSplit)
+ {
+ rSh.SetRowSplit(*pSplit);
+ }
+
+ if(!bTableSel)
+ {
+ rSh.ClearMark();
+ }
+ rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+ }
+
+ rSh.EndAllAction();
+ }
+
+ SwTabCols aTabCols;
+ bool bTabCols = false;
+ SwTableRep* pRep = nullptr;
+ SwFrameFormat *pFormat = rSh.GetTableFormat();
+ SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aSet( rSh.GetAttrPool() );
+ if(const SwPtrItem* pRepItem = rSet.GetItemIfSet( FN_TABLE_REP, false ))
+ {
+ pRep = static_cast<SwTableRep*>(pRepItem->GetValue());
+
+ const SwTwips nWidth = pRep->GetWidth();
+ if ( text::HoriOrientation::FULL == pRep->GetAlign() )
+ {
+ SwFormatHoriOrient aAttr( pFormat->GetHoriOrient() );
+ aAttr.SetHoriOrient( text::HoriOrientation::FULL );
+ aSet.Put( aAttr );
+ }
+ else
+ {
+ SwFormatFrameSize aSz( SwFrameSize::Variable, nWidth );
+ if(pRep->GetWidthPercent())
+ {
+ aSz.SetWidthPercent( static_cast<sal_uInt8>(pRep->GetWidthPercent()) );
+ }
+ aSet.Put(aSz);
+ }
+
+ SvxLRSpaceItem aLRSpace( RES_LR_SPACE );
+ aLRSpace.SetLeft(pRep->GetLeftSpace());
+ aLRSpace.SetRight(pRep->GetRightSpace());
+ aSet.Put( aLRSpace );
+
+ sal_Int16 eOrient = pRep->GetAlign();
+ SwFormatHoriOrient aAttr( 0, eOrient );
+ aSet.Put( aAttr );
+ // The item must only be recorded while manual alignment, so that the
+ // alignment is not overwritten by the distances while recording.
+ if(eOrient != text::HoriOrientation::NONE)
+ const_cast<SfxItemSet&>(rSet).ClearItem( SID_ATTR_LRSPACE );
+
+ if(pRep->HasColsChanged())
+ {
+ bTabCols = true;
+ }
+ }
+
+ if( const SfxUInt16Item* pHeadlineItem = rSet.GetItemIfSet( FN_PARAM_TABLE_HEADLINE, false ))
+ rSh.SetRowsToRepeat( pHeadlineItem->GetValue() );
+
+ if( const SfxUInt16Item* pAlignItem = rSet.GetItemIfSet( FN_TABLE_SET_VERT_ALIGN, false ))
+ rSh.SetBoxAlign(pAlignItem->GetValue());
+
+ if( const SfxStringItem* pNameItem = rSet.GetItemIfSet( FN_PARAM_TABLE_NAME, false ))
+ rSh.SetTableName( *pFormat, pNameItem->GetValue() );
+
+ // Copy the chosen attributes in the ItemSet.
+ static const sal_uInt16 aIds[] =
+ {
+ RES_PAGEDESC,
+ RES_BREAK,
+ RES_KEEP,
+ RES_LAYOUT_SPLIT,
+ RES_UL_SPACE,
+ RES_SHADOW,
+ RES_FRAMEDIR,
+ // #i29550#
+ RES_COLLAPSING_BORDERS,
+ // <-- collapsing borders
+ 0
+ };
+ const SfxPoolItem* pItem = nullptr;
+ for( const sal_uInt16* pIds = aIds; *pIds; ++pIds )
+ if( SfxItemState::SET == rSet.GetItemState( *pIds, false, &pItem))
+ aSet.Put( *pItem );
+
+ if(bTabCols)
+ {
+ rSh.GetTabCols( aTabCols );
+ bool bSingleLine = pRep->FillTabCols( aTabCols );
+ rSh.SetTabCols( aTabCols, bSingleLine );
+ }
+
+ if( aSet.Count() )
+ rSh.SetTableAttr( aSet );
+
+ rSh.EndUndo( SwUndoId::TABLE_ATTR );
+ rSh.EndAllAction();
+}
+
+static void lcl_TabGetMaxLineWidth(const SvxBorderLine* pBorderLine, SvxBorderLine& rBorderLine)
+{
+ if(pBorderLine->GetWidth() > rBorderLine.GetWidth())
+ rBorderLine.SetWidth(pBorderLine->GetWidth());
+
+ rBorderLine.SetBorderLineStyle(pBorderLine->GetBorderLineStyle());
+ rBorderLine.SetColor(pBorderLine->GetColor());
+}
+
+static bool lcl_BoxesInTrackedRows(SwWrtShell &rSh, const SwSelBoxes& rBoxes)
+{
+ // cursor and selection are there only in tracked rows
+ bool bRet = true;
+ SwRedlineTable::size_type nRedlinePos = 0;
+ if ( rBoxes.empty() )
+ bRet = rSh.GetCursor()->GetPointNode().GetTableBox()->GetUpper()->IsTracked(nRedlinePos);
+ else
+ {
+ tools::Long nBoxes = rBoxes.size();
+ SwTableLine* pPrevLine = nullptr;
+ for ( tools::Long i = 0; i < nBoxes; i++ )
+ {
+ SwTableLine* pLine = rBoxes[i]->GetUpper();
+ if ( pLine != pPrevLine )
+ bRet &= pLine->IsTracked(nRedlinePos);
+ pPrevLine = pLine;
+ }
+ }
+
+ return bRet;
+}
+
+static bool lcl_CursorInDeletedTable(SwWrtShell &rSh)
+{
+ // cursor and selection are there only in deleted table in Show Changes mode
+ if ( rSh.GetLayout()->IsHideRedlines() )
+ return false;
+
+ SwTableNode* pTableNd = rSh.GetCursor()->GetPoint()->GetNode().FindTableNode();
+ return pTableNd && pTableNd->GetTable().IsDeleted();
+}
+
+void SwTableShell::Execute(SfxRequest &rReq)
+{
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ SwWrtShell &rSh = GetShell();
+
+ // At first the slots which doesn't need a FrameMgr.
+ bool bMore = false;
+ const SfxPoolItem* pItem = nullptr;
+ sal_uInt16 nSlot = rReq.GetSlot();
+ if(pArgs)
+ pArgs->GetItemState(GetPool().GetWhich(nSlot), false, &pItem);
+ bool bCallDone = false;
+ switch ( nSlot )
+ {
+ case SID_ATTR_BORDER:
+ {
+ if(!pArgs)
+ break;
+ // Create items, because we have to rework anyway.
+ std::shared_ptr<SvxBoxItem> aBox(std::make_shared<SvxBoxItem>(RES_BOX));
+ SfxItemSetFixed<RES_BOX, RES_BOX,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER>
+ aCoreSet( GetPool() );
+ SvxBoxInfoItem aCoreInfo( SID_ATTR_BORDER_INNER );
+ aCoreSet.Put(aCoreInfo);
+ rSh.GetTabBorders( aCoreSet );
+ const SvxBoxItem& rCoreBox = aCoreSet.Get(RES_BOX);
+ const SvxBoxItem *pBoxItem = pArgs->GetItemIfSet(RES_BOX);
+ if ( pBoxItem )
+ {
+ aBox.reset(pBoxItem->Clone());
+ sal_Int16 nDefValue = MIN_BORDER_DIST;
+ if ( !rReq.IsAPI() )
+ nDefValue = 55;
+ if (!rReq.IsAPI() || aBox->GetSmallestDistance() < MIN_BORDER_DIST)
+ {
+ for( SvxBoxItemLine k : o3tl::enumrange<SvxBoxItemLine>() )
+ aBox->SetDistance( std::max(rCoreBox.GetDistance(k), nDefValue) , k );
+ }
+ }
+ else
+ OSL_ENSURE( false, "where is BoxItem?" );
+
+ //since the drawing layer also supports borders the which id might be a different one
+ std::shared_ptr<SvxBoxInfoItem> aInfo(std::make_shared<SvxBoxInfoItem>(SID_ATTR_BORDER_INNER));
+ if (const SvxBoxInfoItem* pBoxInfoItem = pArgs->GetItemIfSet(SID_ATTR_BORDER_INNER))
+ {
+ aInfo.reset(pBoxInfoItem->Clone());
+ }
+ else if( const SvxBoxInfoItem* pBoxInfoInnerItem = pArgs->GetItemIfSet(SDRATTR_TABLE_BORDER_INNER))
+ {
+ aInfo.reset(pBoxInfoInnerItem->Clone());
+ aInfo->SetWhich(SID_ATTR_BORDER_INNER);
+ }
+
+ aInfo->SetTable( true );
+ aInfo->SetValid( SvxBoxInfoItemValidFlags::DISABLE, false );
+
+// The attributes of all lines will be read and the strongest wins.
+ const SvxBorderLine* pBorderLine;
+ SvxBorderLine aBorderLine;
+ if ((pBorderLine = rCoreBox.GetTop()) != nullptr)
+ lcl_TabGetMaxLineWidth(pBorderLine, aBorderLine);
+ if ((pBorderLine = rCoreBox.GetBottom()) != nullptr)
+ lcl_TabGetMaxLineWidth(pBorderLine, aBorderLine);
+ if ((pBorderLine = rCoreBox.GetLeft()) != nullptr)
+ lcl_TabGetMaxLineWidth(pBorderLine, aBorderLine);
+ if ((pBorderLine = rCoreBox.GetRight()) != nullptr)
+ lcl_TabGetMaxLineWidth(pBorderLine, aBorderLine);
+ if ((pBorderLine = aCoreInfo.GetHori()) != nullptr)
+ lcl_TabGetMaxLineWidth(pBorderLine, aBorderLine);
+ if ((pBorderLine = aCoreInfo.GetVert()) != nullptr)
+ lcl_TabGetMaxLineWidth(pBorderLine, aBorderLine);
+
+ if(aBorderLine.GetOutWidth() == 0)
+ {
+ aBorderLine.SetBorderLineStyle(SvxBorderLineStyle::SOLID);
+ aBorderLine.SetWidth( SvxBorderLineWidth::VeryThin );
+ }
+
+ if( aBox->GetTop() != nullptr )
+ {
+ aBox->SetLine(&aBorderLine, SvxBoxItemLine::TOP);
+ }
+ if( aBox->GetBottom() != nullptr )
+ {
+ aBox->SetLine(&aBorderLine, SvxBoxItemLine::BOTTOM);
+ }
+ if( aBox->GetLeft() != nullptr )
+ {
+ aBox->SetLine(&aBorderLine, SvxBoxItemLine::LEFT);
+ }
+ if( aBox->GetRight() != nullptr )
+ {
+ aBox->SetLine(&aBorderLine, SvxBoxItemLine::RIGHT);
+ }
+ if( aInfo->GetHori() != nullptr )
+ {
+ aInfo->SetLine(&aBorderLine, SvxBoxInfoItemLine::HORI);
+ }
+ if( aInfo->GetVert() != nullptr )
+ {
+ aInfo->SetLine(&aBorderLine, SvxBoxInfoItemLine::VERT);
+ }
+
+ aCoreSet.Put( *aBox );
+ aCoreSet.Put( *aInfo );
+ rSh.SetTabBorders( aCoreSet );
+
+ // we must record the "real" values because otherwise the lines can't be reconstructed on playtime
+ // the coding style of the controller (setting lines with width 0) is not transportable via Query/PutValue in
+ // the SvxBoxItem
+ rReq.AppendItem( *aBox );
+ rReq.AppendItem( *aInfo );
+ bCallDone = true;
+ break;
+ }
+ case FN_INSERT_TABLE:
+ InsertTable( rReq );
+ break;
+ case FN_FORMAT_TABLE_DLG:
+ {
+ //#127012# get the bindings before the dialog is called
+ // it might happen that this shell is removed after closing the dialog
+ SfxBindings& rBindings = GetView().GetViewFrame().GetBindings();
+ SfxItemSet aCoreSet( GetPool(), aUITableAttrRange);
+
+ FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( &rSh.GetView()) != nullptr );
+ SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)));
+ std::shared_ptr<SwTableRep> pTableRep(::lcl_TableParamToItemSet(aCoreSet, rSh));
+
+ aCoreSet.Put(SfxUInt16Item(SID_HTML_MODE, ::GetHtmlMode(GetView().GetDocShell())));
+ rSh.GetTableAttr(aCoreSet);
+ // GetTableAttr overwrites the background!
+ std::unique_ptr<SvxBrushItem> aBrush(std::make_unique<SvxBrushItem>(RES_BACKGROUND));
+ if(rSh.GetBoxBackground(aBrush))
+ aCoreSet.Put( *aBrush );
+ else
+ aCoreSet.InvalidateItem( RES_BACKGROUND );
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateSwTableTabDlg(GetView().GetFrameWeld(), &aCoreSet, &rSh));
+
+ if (pDlg)
+ {
+ if (pItem)
+ pDlg->SetCurPageId(static_cast<const SfxStringItem *>(pItem)->GetValue());
+
+ auto pRequest = std::make_shared<SfxRequest>(rReq);
+ rReq.Ignore(); // the 'old' request is not relevant any more
+
+ const bool bTableMode = rSh.IsTableMode();
+ SwPaM* pCursor = bTableMode ? rSh.GetTableCrs() : rSh.GetCursor(); // tdf#142165 use table cursor if in table mode
+ auto vCursors = CopyPaMRing(*pCursor); // tdf#135636 make a copy to use at later apply
+ pDlg->StartExecuteAsync([pDlg, pRequest, pTableRep, &rBindings, &rSh, vCursors, bTableMode](sal_Int32 nResult){
+ if (RET_OK == nResult)
+ {
+ if (!bTableMode && rSh.IsTableMode()) // tdf#140977 drop current table-cursor if setting a replacement
+ rSh.TableCursorToCursor(); // non-table one
+
+ // tdf#135636 set the selection at dialog launch as current selection
+ rSh.SetSelection(*vCursors->front()); // UpdateCursor() will be called which in the case
+ // of a table selection should recreate a
+ // SwShellTableCursor if the selection is more than a single cell
+
+ if (bTableMode && !rSh.IsTableMode()) // tdf#142721 ensure the new selection is a SwShellTableCursor in
+ rSh.SelTableBox(); // the case of a single cell
+
+ const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
+
+ //to record FN_INSERT_TABLE correctly
+ pRequest->SetSlot(FN_FORMAT_TABLE_DLG);
+ pRequest->Done(*pOutSet);
+
+ ItemSetToTableParam(*pOutSet, rSh);
+ }
+
+ rBindings.Update(SID_RULER_BORDERS);
+ rBindings.Update(SID_ATTR_TABSTOP);
+ rBindings.Update(SID_RULER_BORDERS_VERTICAL);
+ rBindings.Update(SID_ATTR_TABSTOP_VERTICAL);
+
+ pDlg->disposeOnce();
+ });
+ }
+ else
+ {
+ if (rReq.GetArgs())
+ ItemSetToTableParam(*rReq.GetArgs(), rSh);
+
+ rBindings.Update(SID_RULER_BORDERS);
+ rBindings.Update(SID_ATTR_TABSTOP);
+ rBindings.Update(SID_RULER_BORDERS_VERTICAL);
+ rBindings.Update(SID_ATTR_TABSTOP_VERTICAL);
+ }
+
+ break;
+ }
+ case SID_ATTR_BRUSH:
+ case SID_ATTR_BRUSH_ROW :
+ case SID_ATTR_BRUSH_TABLE :
+ if(rReq.GetArgs())
+ ItemSetToTableParam(*rReq.GetArgs(), rSh);
+ break;
+ case FN_NUM_FORMAT_TABLE_DLG:
+ {
+ if (SwView* pView = GetActiveView())
+ {
+ FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( pView) != nullptr );
+ SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)));
+ SvNumberFormatter* pFormatter = rSh.GetNumberFormatter();
+ auto pCoreSet = std::make_shared<SfxItemSetFixed<SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_INFO>>( GetPool() );
+
+ SfxItemSetFixed<RES_BOXATR_FORMAT, RES_BOXATR_FORMAT,
+ RES_BOXATR_VALUE, RES_BOXATR_VALUE>
+ aBoxSet( *pCoreSet->GetPool() );
+ rSh.GetTableBoxFormulaAttrs( aBoxSet );
+
+ SfxItemState eState = aBoxSet.GetItemState(RES_BOXATR_FORMAT);
+ if(eState == SfxItemState::DEFAULT)
+ {
+ pCoreSet->Put( SfxUInt32Item( SID_ATTR_NUMBERFORMAT_VALUE,
+ pFormatter->GetFormatIndex(NF_TEXT, LANGUAGE_SYSTEM)));
+ }
+ else
+ pCoreSet->Put( SfxUInt32Item( SID_ATTR_NUMBERFORMAT_VALUE,
+ aBoxSet.Get(
+ RES_BOXATR_FORMAT ).GetValue() ));
+
+ pCoreSet->Put( SvxNumberInfoItem( pFormatter,
+ aBoxSet.Get(
+ RES_BOXATR_VALUE).GetValue(),
+ rSh.GetTableBoxText(), SID_ATTR_NUMBERFORMAT_INFO ));
+
+ SwWrtShell* pSh = &rSh;
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ VclPtr<SfxAbstractDialog> pDlg(pFact->CreateNumFormatDialog(GetView().GetFrameWeld(), *pCoreSet));
+
+ pDlg->StartExecuteAsync([pDlg, pCoreSet, pSh](sal_uInt32 nResult){
+ if (RET_OK == nResult)
+ {
+ const SvxNumberInfoItem* pNumberFormatItem
+ = pSh->GetView().GetDocShell()->GetItem( SID_ATTR_NUMBERFORMAT_INFO );
+
+ if( pNumberFormatItem )
+ {
+ for ( sal_uInt32 key : pNumberFormatItem->GetDelFormats() )
+ pNumberFormatItem->GetNumberFormatter()->DeleteEntry( key );
+ }
+
+ const SfxPoolItem* pNumberFormatValueItem =
+ pDlg->GetOutputItemSet()->GetItemIfSet(
+ SID_ATTR_NUMBERFORMAT_VALUE, false);
+ if( pNumberFormatValueItem )
+ {
+ SfxItemSetFixed<RES_BOXATR_FORMAT, RES_BOXATR_FORMAT>
+ aBoxFormatSet( *pCoreSet->GetPool() );
+ aBoxFormatSet.Put( SwTableBoxNumFormat(
+ static_cast<const SfxUInt32Item*>(pNumberFormatValueItem)->GetValue() ));
+ pSh->SetTableBoxFormulaAttrs( aBoxFormatSet );
+
+ }
+ }
+
+ pDlg->disposeOnce();
+ });
+ }
+ break;
+ }
+ case FN_CALC_TABLE:
+ rSh.UpdateTable();
+ bCallDone = true;
+ break;
+ case FN_TABLE_DELETE_COL:
+ if ( rSh.DeleteCol() && rSh.HasSelection() )
+ rSh.EnterStdMode();
+ bCallDone = true;
+ break;
+ case FN_END_TABLE:
+ rSh.MoveTable( GotoCurrTable, fnTableEnd );
+ bCallDone = true;
+ break;
+ case FN_START_TABLE:
+ rSh.MoveTable( GotoCurrTable, fnTableStart );
+ bCallDone = true;
+ break;
+ case FN_GOTO_NEXT_CELL:
+ {
+ bool bAppendLine = true;
+ if( pItem )
+ bAppendLine = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ rReq.SetReturnValue( SfxBoolItem( nSlot,
+ rSh.GoNextCell( bAppendLine ) ) );
+ bCallDone = true;
+ break;
+ }
+ case FN_GOTO_PREV_CELL:
+ rReq.SetReturnValue( SfxBoolItem( nSlot, rSh.GoPrevCell() ) );
+ bCallDone = true;
+ break;
+ case FN_TABLE_DELETE_ROW:
+ if ( rSh.DeleteRow() && rSh.HasSelection() )
+ rSh.EnterStdMode();
+ bCallDone = true;
+ break;
+ case FN_TABLE_MERGE_CELLS:
+ if ( rSh.IsTableMode() )
+ switch ( rSh.MergeTab() )
+ {
+ case TableMergeErr::Ok:
+ bCallDone = true;
+ [[fallthrough]];
+ case TableMergeErr::NoSelection:
+ break;
+ case TableMergeErr::TooComplex:
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetView().GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_ERR_TABLE_MERGE)));
+ xInfoBox->run();
+ break;
+ }
+ default:
+ OSL_ENSURE( false, "unknown return value MergeTab.");
+ break;
+ }
+ break;
+ case SID_TABLE_MINIMAL_COLUMN_WIDTH:
+ case FN_TABLE_ADJUST_CELLS:
+ case FN_TABLE_BALANCE_CELLS:
+ {
+ bool bBalance = (FN_TABLE_BALANCE_CELLS == nSlot);
+ const bool bNoShrink = FN_TABLE_ADJUST_CELLS == nSlot;
+ if ( rSh.IsAdjustCellWidthAllowed(bBalance) )
+ {
+ {
+ // remove actions to make a valid table selection
+ UnoActionRemoveContext aRemoveContext(rSh.GetDoc());
+ }
+ rSh.AdjustCellWidth(bBalance, bNoShrink);
+ }
+ bCallDone = true;
+ break;
+ }
+ case SID_TABLE_MINIMAL_ROW_HEIGHT:
+ {
+ const SwFormatFrameSize aSz;
+ rSh.SetRowHeight( aSz );
+ bCallDone = true;
+ break;
+ }
+ case FN_TABLE_OPTIMAL_HEIGHT:
+ {
+ rSh.BalanceRowHeight(/*bTstOnly=*/false, /*bOptimize=*/true);
+ rSh.BalanceRowHeight(/*bTstOnly=*/false, /*bOptimize=*/false);
+ bCallDone = true;
+ break;
+ }
+ case FN_TABLE_BALANCE_ROWS:
+ if ( rSh.BalanceRowHeight(true) )
+ rSh.BalanceRowHeight(false);
+ bCallDone = true;
+ break;
+ case FN_TABLE_SELECT_ALL:
+ rSh.EnterStdMode();
+ rSh.MoveTable( GotoCurrTable, fnTableStart );
+ rSh.SttSelect();
+ rSh.MoveTable( GotoCurrTable, fnTableEnd );
+ rSh.EndSelect();
+ bCallDone = true;
+ break;
+ case FN_TABLE_SELECT_COL:
+ rSh.EnterStdMode();
+ rSh.SelectTableCol();
+ bCallDone = true;
+ break;
+ case FN_TABLE_SELECT_ROW:
+ rSh.EnterStdMode();
+ rSh.SelectTableRow();
+ bCallDone = true;
+ break;
+ case FN_TABLE_SET_READ_ONLY_CELLS:
+ rSh.ProtectCells();
+ rSh.ResetSelect( nullptr, false );
+ bCallDone = true;
+ break;
+ case FN_TABLE_UNSET_READ_ONLY_CELLS:
+ rSh.UnProtectCells();
+ bCallDone = true;
+ break;
+ case SID_AUTOFORMAT:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractSwAutoFormatDlg> pDlg(pFact->CreateSwAutoFormatDlg(GetView().GetFrameWeld(), &rSh));
+ pDlg->Execute();
+ break;
+ }
+ case FN_TABLE_SET_ROW_HEIGHT:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateSwTableHeightDialog(GetView().GetFrameWeld(), rSh));
+ pDlg->Execute();
+ break;
+ }
+ case FN_NUMBER_BULLETS:
+ case FN_NUM_BULLET_ON:
+ OSL_ENSURE( false, "function may not be called now." );
+ break;
+
+
+ // 2015/06 The following two are deprecated but kept for ascending
+ // compatibility
+ case FN_TABLE_INSERT_COL:
+ case FN_TABLE_INSERT_ROW:
+ // fallback
+ case FN_TABLE_INSERT_COL_BEFORE:
+ case FN_TABLE_INSERT_ROW_BEFORE:
+ case FN_TABLE_INSERT_COL_AFTER:
+ case FN_TABLE_INSERT_ROW_AFTER:
+ {
+ bool bColumn = rReq.GetSlot() == FN_TABLE_INSERT_COL_BEFORE
+ || rReq.GetSlot() == FN_TABLE_INSERT_COL_AFTER
+ || rReq.GetSlot() == FN_TABLE_INSERT_COL;
+ sal_uInt16 nCount = 0;
+ bool bAfter = true;
+ if (pItem)
+ {
+ nCount = static_cast<const SfxInt16Item* >(pItem)->GetValue();
+ if(const SfxBoolItem* pAfterItem = pArgs->GetItemIfSet(FN_PARAM_INSERT_AFTER))
+ bAfter = pAfterItem->GetValue();
+ }
+ else if( !rReq.IsAPI() )
+ {
+ SwSelBoxes aBoxes;
+ ::GetTableSel( rSh, aBoxes );
+ if ( !aBoxes.empty() )
+ {
+ tools::Long maxX = 0;
+ tools::Long maxY = 0;
+ tools::Long minX = std::numeric_limits<tools::Long>::max();
+ tools::Long minY = std::numeric_limits<tools::Long>::max();
+ tools::Long nbBoxes = aBoxes.size();
+ for ( tools::Long i = 0; i < nbBoxes; i++ )
+ {
+ Point aCoord ( aBoxes[i]->GetCoordinates() );
+ if ( aCoord.X() < minX ) minX = aCoord.X();
+ if ( aCoord.X() > maxX ) maxX = aCoord.X();
+ if ( aCoord.Y() < minY ) minY = aCoord.Y();
+ if ( aCoord.Y() > maxY ) maxY = aCoord.Y();
+ }
+ if (bColumn)
+ nCount = maxX - minX + 1;
+ else
+ nCount = maxY - minY + 1;
+ }
+ bAfter = rReq.GetSlot() == FN_TABLE_INSERT_COL_AFTER
+ || rReq.GetSlot() == FN_TABLE_INSERT_ROW_AFTER
+ || rReq.GetSlot() == FN_TABLE_INSERT_ROW
+ || rReq.GetSlot() == FN_TABLE_INSERT_COL;
+ }
+
+ if( nCount )
+ {
+ // i74180: Table border patch submitted by chensuchun:
+ // -->get the SvxBoxInfoItem of the table before insert
+ SfxItemSet aCoreSet( GetPool(), aUITableAttrRange);
+ ::lcl_TableParamToItemSet( aCoreSet, rSh );
+ bool bSetInnerBorders = false;
+ SwUndoId nUndoId = SwUndoId::EMPTY;
+ // <--End
+
+ if( bColumn )
+ {
+ rSh.StartUndo( SwUndoId::TABLE_INSCOL );
+ rSh.InsertCol( nCount, bAfter );
+ bSetInnerBorders = true;
+ nUndoId = SwUndoId::TABLE_INSCOL;
+ }
+ else if ( !rSh.IsInRepeatedHeadline() )
+ {
+ rSh.StartUndo( SwUndoId::TABLE_INSROW );
+ rSh.InsertRow( nCount, bAfter );
+ bSetInnerBorders = true;
+ nUndoId = SwUndoId::TABLE_INSROW;
+ }
+
+ // -->after inserting,reset the inner table borders
+ if ( bSetInnerBorders )
+ {
+ const SvxBoxInfoItem& aBoxInfo(aCoreSet.Get(SID_ATTR_BORDER_INNER));
+ SfxItemSetFixed<SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER> aSet( GetPool() );
+ aSet.Put( aBoxInfo );
+ ItemSetToTableParam( aSet, rSh );
+ rSh.EndUndo( nUndoId );
+ }
+
+ bCallDone = true;
+ break;
+ }
+
+ nSlot = bColumn ? FN_TABLE_INSERT_COL_DLG : FN_TABLE_INSERT_ROW_DLG;
+
+ [[fallthrough]]; // on Count = 0 appears the dialog
+ }
+ case FN_TABLE_INSERT_COL_DLG:
+ case FN_TABLE_INSERT_ROW_DLG:
+ {
+ const SfxSlot* pSlot = GetStaticInterface()->GetSlot(nSlot);
+ if ( FN_TABLE_INSERT_ROW_DLG != nSlot || !rSh.IsInRepeatedHeadline())
+ {
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SvxAbstractInsRowColDlg> pDlg(pFact->CreateSvxInsRowColDlg(GetView().GetFrameWeld(),
+ nSlot == FN_TABLE_INSERT_COL_DLG, pSlot->GetCommand()));
+ if( pDlg->Execute() == 1 )
+ {
+ const TypedWhichId<SfxUInt16Item> nDispatchSlot = (nSlot == FN_TABLE_INSERT_COL_DLG)
+ ? FN_TABLE_INSERT_COL_AFTER : FN_TABLE_INSERT_ROW_AFTER;
+ SfxUInt16Item aCountItem( nDispatchSlot, pDlg->getInsertCount() );
+ SfxBoolItem aAfter( FN_PARAM_INSERT_AFTER, !pDlg->isInsertBefore() );
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+ rVFrame.GetDispatcher()->ExecuteList(nDispatchSlot,
+ SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
+ { &aCountItem, &aAfter });
+ }
+ }
+ break;
+ }
+ case FN_TABLE_SPLIT_CELLS:
+ {
+ tools::Long nCount=0;
+ bool bHorizontal=true;
+ bool bProportional = false;
+ const SfxInt32Item* pSplit = rReq.GetArg<SfxInt32Item>(FN_TABLE_SPLIT_CELLS);
+ const SfxBoolItem* pHor = rReq.GetArg<SfxBoolItem>(FN_PARAM_1);
+ const SfxBoolItem* pProp = rReq.GetArg<SfxBoolItem>(FN_PARAM_2);
+ if ( pSplit )
+ {
+ nCount = pSplit->GetValue();
+ if ( pHor )
+ bHorizontal = pHor->GetValue();
+ if ( pProp )
+ bProportional = pProp->GetValue();
+ }
+ else
+ {
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ SwWrtShell* pSh = &rSh;
+ const tools::Long nMaxVert = rSh.GetAnyCurRect( CurRectType::Frame ).Width() / MINLAY;
+ VclPtr<SvxAbstractSplitTableDialog> pDlg(pFact->CreateSvxSplitTableDialog(GetView().GetFrameWeld(), rSh.IsTableVertical(), nMaxVert));
+ if(rSh.IsSplitVerticalByDefault())
+ pDlg->SetSplitVerticalByDefault();
+ pDlg->StartExecuteAsync([pDlg, pSh](int nResult) {
+ if (nResult == RET_OK)
+ {
+ tools::Long nCount2 = pDlg->GetCount();
+ bool bHorizontal2 = pDlg->IsHorizontal();
+ bool bProportional2 = pDlg->IsProportional();
+
+ // tdf#60242: remember choice for next time
+ bool bVerticalWasChecked = !pDlg->IsHorizontal();
+ pSh->SetSplitVerticalByDefault(bVerticalWasChecked);
+
+ if ( nCount2 > 1 )
+ pSh->SplitTab(!bHorizontal2, static_cast< sal_uInt16 >( nCount2-1 ), bProportional2 );
+ }
+
+ pDlg->disposeOnce();
+ });
+ }
+
+ if ( nCount>1 )
+ {
+ rSh.SplitTab(!bHorizontal, static_cast< sal_uInt16 >( nCount-1 ), bProportional );
+ bCallDone = true;
+ }
+ else
+ rReq.Ignore();
+ break;
+ }
+
+ case FN_TABLE_SPLIT_TABLE:
+ {
+ const SfxUInt16Item* pType = rReq.GetArg<SfxUInt16Item>(FN_PARAM_1);
+ if( pType )
+ {
+ switch( static_cast<SplitTable_HeadlineOption>(pType->GetValue()) )
+ {
+ case SplitTable_HeadlineOption::NONE :
+ case SplitTable_HeadlineOption::BorderCopy:
+ case SplitTable_HeadlineOption::ContentCopy:
+ case SplitTable_HeadlineOption::BoxAttrCopy:
+ case SplitTable_HeadlineOption::BoxAttrAllCopy:
+ rSh.SplitTable(static_cast<SplitTable_HeadlineOption>(pType->GetValue())) ;
+ break;
+ default: ;//wrong parameter, do nothing
+ }
+ }
+ else
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ VclPtr<AbstractSplitTableDialog> pDlg(pFact->CreateSplitTableDialog(GetView().GetFrameWeld(), rSh));
+
+ SwWrtShell* pSh = &rSh;
+
+ pDlg->StartExecuteAsync([pDlg, pSh](int nResult) {
+ if (nResult == RET_OK)
+ {
+ const auto aSplitMode = pDlg->GetSplitMode();
+ pSh->SplitTable( aSplitMode );
+ }
+
+ pDlg->disposeOnce();
+ });
+ rReq.Ignore(); // We're already handling the request in our async bit
+ }
+ break;
+ }
+
+ case FN_TABLE_MERGE_TABLE:
+ {
+ bool bPrev = rSh.CanMergeTable();
+ bool bNext = rSh.CanMergeTable( false );
+
+ if( bPrev && bNext )
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateTableMergeDialog(GetView().GetFrameWeld(), bPrev));
+ if( RET_OK != pDlg->Execute())
+ bPrev = bNext = false;
+ }
+
+ if( bPrev || bNext )
+ rSh.MergeTable( bPrev );
+ break;
+ }
+
+ case FN_TABLE_MODE_FIX :
+ case FN_TABLE_MODE_FIX_PROP :
+ case FN_TABLE_MODE_VARIABLE :
+ {
+ rSh.SetTableChgMode( FN_TABLE_MODE_FIX == nSlot
+ ? TableChgMode::FixedWidthChangeAbs
+ : FN_TABLE_MODE_FIX_PROP == nSlot
+ ? TableChgMode::FixedWidthChangeProp
+ : TableChgMode::VarWidthChangeAbs );
+
+ SfxBindings& rBind = GetView().GetViewFrame().GetBindings();
+ static sal_uInt16 aInva[] =
+ { FN_TABLE_MODE_FIX,
+ FN_TABLE_MODE_FIX_PROP,
+ FN_TABLE_MODE_VARIABLE,
+ 0
+ };
+ rBind.Invalidate( aInva );
+ bCallDone = true;
+ break;
+ }
+ case FN_TABLE_AUTOSUM:
+ {
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+ rVFrame.GetDispatcher()->Execute(FN_EDIT_FORMULA, SfxCallMode::SYNCHRON);
+ const sal_uInt16 nId = SwInputChild::GetChildWindowId();
+ SwInputChild* pChildWin = static_cast<SwInputChild*>(rVFrame.
+ GetChildWindow( nId ));
+ OUString sSum;
+ GetShell().GetAutoSum(sSum);
+ if( pChildWin )
+ pChildWin->SetFormula( sSum );
+
+ break;
+ }
+ case FN_TABLE_HEADLINE_REPEAT:
+ if(0 != rSh.GetRowsToRepeat())
+ rSh.SetRowsToRepeat( 0 );
+ else
+ rSh.SetRowsToRepeat(rSh.GetRowSelectionFromTop());
+ break;
+ case FN_TABLE_SELECT_CELL :
+ rSh.SelectTableCell();
+ break;
+ case FN_TABLE_DELETE_TABLE :
+ {
+ rSh.StartAction();
+ rSh.StartUndo();
+ rSh.GetView().GetViewFrame().GetDispatcher()->Execute(FN_TABLE_SELECT_ALL);
+ rSh.DeleteTable();
+ rSh.EndUndo();
+ rSh.EndAction();
+ //'this' is already destroyed
+ return;
+ }
+ case SID_ATTR_TABLE_ROW_HEIGHT:
+ {
+ const SfxUInt32Item* pItem2 = rReq.GetArg<SfxUInt32Item>(SID_ATTR_TABLE_ROW_HEIGHT);
+ if (pItem2)
+ {
+ tools::Long nNewHeight = pItem2->GetValue();
+ std::unique_ptr<SwFormatFrameSize> pHeight = rSh.GetRowHeight();
+ if ( pHeight )
+ {
+ if (pHeight->GetHeightSizeType() == SwFrameSize::Variable)
+ pHeight->SetHeightSizeType(SwFrameSize::Minimum);
+ pHeight->SetHeight(nNewHeight);
+ rSh.SetRowHeight(*pHeight);
+ }
+ }
+ return;
+ }
+ case SID_ATTR_TABLE_COLUMN_WIDTH:
+ {
+ const SfxUInt32Item* pItem2 = rReq.GetArg<SfxUInt32Item>(SID_ATTR_TABLE_COLUMN_WIDTH);
+ if (pItem2)
+ {
+ tools::Long nNewWidth = pItem2->GetValue();
+ SwTableFUNC aFunc( &rSh );
+ aFunc.InitTabCols();
+ aFunc.SetColWidth(aFunc.GetCurColNum(), nNewWidth);
+ }
+ return;
+ }
+ default:
+ bMore = true;
+ }
+
+ if ( !bMore )
+ {
+ if(bCallDone)
+ rReq.Done();
+ return;
+ }
+
+ // Now the slots which are working directly on the TableFormat.
+ switch ( nSlot )
+ {
+ case SID_ATTR_ULSPACE:
+ if(pItem)
+ {
+ SvxULSpaceItem aULSpace( *static_cast<const SvxULSpaceItem*>(pItem) );
+ aULSpace.SetWhich( RES_UL_SPACE );
+ ::lcl_SetAttr( rSh, aULSpace );
+ }
+ break;
+
+ case SID_ATTR_LRSPACE:
+ if(pItem)
+ {
+ SfxItemSetFixed<RES_LR_SPACE, RES_LR_SPACE,
+ RES_HORI_ORIENT, RES_HORI_ORIENT> aSet( GetPool() );
+ SvxLRSpaceItem aLRSpace( *static_cast<const SvxLRSpaceItem*>(pItem) );
+ aLRSpace.SetWhich( RES_LR_SPACE );
+ aSet.Put( aLRSpace );
+ rSh.SetTableAttr( aSet );
+ }
+ break;
+ // The last case branch which needs a table manager!!
+ case FN_TABLE_SET_COL_WIDTH:
+ {
+ SwTableFUNC aMgr( &rSh );
+ aMgr.ColWidthDlg(GetView().GetFrameWeld());
+ break;
+ }
+ case SID_TABLE_VERT_NONE:
+ case SID_TABLE_VERT_CENTER:
+ case SID_TABLE_VERT_BOTTOM:
+ {
+ const sal_uInt16 nAlign = nSlot == SID_TABLE_VERT_NONE ?
+ text::VertOrientation::NONE :
+ nSlot == SID_TABLE_VERT_CENTER ?
+ text::VertOrientation::CENTER : text::VertOrientation::BOTTOM;
+ rSh.SetBoxAlign(nAlign);
+ bCallDone = true;
+ break;
+ }
+
+ case SID_ATTR_PARA_SPLIT:
+ if ( pItem )
+ {
+ SwFormatLayoutSplit aSplit( static_cast<const SvxFormatSplitItem*>(pItem)->GetValue());
+ SfxItemSetFixed<RES_LAYOUT_SPLIT, RES_LAYOUT_SPLIT> aSet(GetPool());
+ aSet.Put(aSplit);
+ rSh.SetTableAttr(aSet);
+ }
+ break;
+
+ case SID_ATTR_PARA_KEEP:
+ if ( pItem )
+ {
+ SvxFormatKeepItem aKeep( *static_cast<const SvxFormatKeepItem*>(pItem) );
+ aKeep.SetWhich( RES_KEEP );
+ SfxItemSetFixed<RES_KEEP, RES_KEEP> aSet(GetPool());
+ aSet.Put(aKeep);
+ rSh.SetTableAttr(aSet);
+ }
+ break;
+ case FN_TABLE_ROW_SPLIT :
+ {
+ const SfxBoolItem* pBool = static_cast<const SfxBoolItem*>(pItem);
+ std::unique_ptr<SwFormatRowSplit> pSplit;
+ if(!pBool)
+ {
+ pSplit = rSh.GetRowSplit();
+ if(pSplit)
+ pSplit->SetValue(!pSplit->GetValue());
+ else
+ pSplit.reset(new SwFormatRowSplit(true));
+ }
+ else
+ {
+ pSplit.reset(new SwFormatRowSplit(pBool->GetValue()));
+ }
+ rSh.SetRowSplit( *pSplit );
+ break;
+ }
+
+ default:
+ OSL_ENSURE( false, "wrong Dispatcher" );
+ return;
+ }
+ if(bCallDone)
+ rReq.Done();
+}
+
+void SwTableShell::GetState(SfxItemSet &rSet)
+{
+ SfxWhichIter aIter( rSet );
+ SwWrtShell &rSh = GetShell();
+ SwFrameFormat *pFormat = rSh.GetTableFormat();
+ // os #124829# crash report: in case of an invalid shell selection return immediately
+ if(!pFormat)
+ return;
+ sal_uInt16 nSlot = aIter.FirstWhich();
+ while ( nSlot )
+ {
+ switch ( nSlot )
+ {
+ case FN_TABLE_MERGE_CELLS:
+ if ( !rSh.IsTableMode() )
+ rSet.DisableItem(FN_TABLE_MERGE_CELLS);
+ break;
+ case SID_TABLE_MINIMAL_COLUMN_WIDTH:
+ case FN_TABLE_ADJUST_CELLS:
+ if ( !rSh.IsAdjustCellWidthAllowed() )
+ rSet.DisableItem(nSlot);
+ break;
+
+ case FN_TABLE_BALANCE_CELLS:
+ if ( !rSh.IsAdjustCellWidthAllowed(true) )
+ rSet.DisableItem(FN_TABLE_BALANCE_CELLS);
+ break;
+
+ case FN_TABLE_OPTIMAL_HEIGHT:
+ case FN_TABLE_BALANCE_ROWS:
+ if ( !rSh.BalanceRowHeight(true) )
+ rSet.DisableItem(nSlot);
+ break;
+ case FN_OPTIMIZE_TABLE:
+ if ( !rSh.IsTableMode() &&
+ !rSh.IsAdjustCellWidthAllowed() &&
+ !rSh.IsAdjustCellWidthAllowed(true) &&
+ !rSh.BalanceRowHeight(true) )
+ rSet.DisableItem(FN_OPTIMIZE_TABLE);
+ break;
+ case SID_INSERT_DIAGRAM:
+ {
+ SvtModuleOptions aMOpt;
+ if ( !aMOpt.IsMath() || rSh.IsTableComplexForChart() )
+ rSet.DisableItem(nSlot);
+ }
+ break;
+
+ case FN_INSERT_TABLE:
+ if ( rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem( nSlot );
+ }
+ break;
+
+ case SID_TABLE_MINIMAL_ROW_HEIGHT:
+ {
+ // Disable if auto height already is enabled.
+ std::unique_ptr<SwFormatFrameSize> pSz = rSh.GetRowHeight();
+ if ( pSz )
+ {
+ if ( SwFrameSize::Variable == pSz->GetHeightSizeType() )
+ rSet.DisableItem( nSlot );
+ }
+ break;
+ }
+ case FN_TABLE_INSERT_COL_BEFORE:
+ case FN_TABLE_INSERT_COL_AFTER:
+ {
+ SfxImageItem aImageItem(nSlot);
+ if (pFormat->GetFrameDir().GetValue() == SvxFrameDirection::Environment)
+ {
+ // Inherited from superordinate object (page or frame).
+ // If the table spans multiple pages, direction is set by the first page.
+ SwIterator<SwTabFrame, SwFrameFormat> aIterT(*pFormat);
+ for (SwTabFrame* pFrame = aIterT.First(); pFrame;
+ pFrame = static_cast<SwTabFrame*>(pFrame->GetPrecede()))
+ aImageItem.SetMirrored(pFrame->IsRightToLeft());
+ }
+ else
+ aImageItem.SetMirrored(pFormat->GetFrameDir().GetValue() == SvxFrameDirection::Horizontal_RL_TB);
+ rSet.Put(aImageItem);
+ break;
+ }
+ case FN_TABLE_INSERT_ROW:
+ case FN_TABLE_INSERT_ROW_AFTER:
+ case FN_TABLE_INSERT_ROW_DLG:
+ if ( rSh.IsInRepeatedHeadline() )
+ rSet.DisableItem( nSlot );
+ break;
+ case RES_LR_SPACE:
+ rSet.Put(pFormat->GetLRSpace());
+ break;
+ case RES_UL_SPACE:
+ rSet.Put(pFormat->GetULSpace());
+ break;
+
+ case SID_TABLE_VERT_NONE:
+ case SID_TABLE_VERT_CENTER:
+ case SID_TABLE_VERT_BOTTOM:
+ {
+ const sal_uInt16 nAlign = rSh.GetBoxAlign();
+ bool bSet = (nSlot == SID_TABLE_VERT_NONE && nAlign == text::VertOrientation::NONE) ||
+ (nSlot == SID_TABLE_VERT_CENTER && nAlign == text::VertOrientation::CENTER) ||
+ (nSlot == SID_TABLE_VERT_BOTTOM && nAlign == text::VertOrientation::BOTTOM);
+ rSet.Put(SfxBoolItem(nSlot, bSet));
+ break;
+ }
+
+ case FN_TABLE_MODE_FIX :
+ case FN_TABLE_MODE_FIX_PROP :
+ case FN_TABLE_MODE_VARIABLE :
+ {
+ TableChgMode nMode = rSh.GetTableChgMode();
+ bool bSet = (nSlot == FN_TABLE_MODE_FIX && nMode == TableChgMode::FixedWidthChangeAbs) ||
+ (nSlot == FN_TABLE_MODE_FIX_PROP && nMode == TableChgMode::FixedWidthChangeProp) ||
+ (nSlot == FN_TABLE_MODE_VARIABLE && nMode == TableChgMode::VarWidthChangeAbs);
+ rSet.Put(SfxBoolItem(nSlot, bSet));
+ }
+ break;
+
+ case SID_ATTR_PARA_SPLIT:
+ rSet.Put( pFormat->GetKeep() );
+ break;
+
+ case SID_ATTR_PARA_KEEP:
+ rSet.Put( pFormat->GetLayoutSplit() );
+ break;
+ case FN_TABLE_SPLIT_TABLE:
+ if ( rSh.IsInHeadline() )
+ rSet.DisableItem( nSlot );
+ break;
+ case FN_TABLE_MERGE_TABLE:
+ {
+ bool bAsk;
+ if( !rSh.CanMergeTable( true, &bAsk ))
+ rSet.DisableItem( nSlot );
+ break;
+ }
+
+ case FN_TABLE_DELETE_ROW:
+ {
+ SwSelBoxes aBoxes;
+ ::GetTableSel( rSh, aBoxes, SwTableSearchType::Row );
+ if( ::HasProtectedCells( aBoxes ) || lcl_BoxesInTrackedRows( rSh, aBoxes ) )
+ rSet.DisableItem( nSlot );
+ }
+ break;
+ case FN_TABLE_DELETE_COL:
+ {
+ SwSelBoxes aBoxes;
+ ::GetTableSel( rSh, aBoxes, SwTableSearchType::Col );
+ if( ::HasProtectedCells( aBoxes ) || lcl_CursorInDeletedTable( rSh ) )
+ rSet.DisableItem( nSlot );
+ }
+ break;
+ case FN_TABLE_DELETE_TABLE:
+ if( lcl_CursorInDeletedTable( rSh ) )
+ rSet.DisableItem( nSlot );
+ break;
+
+ case FN_TABLE_UNSET_READ_ONLY_CELLS:
+ // disable in readonly sections, but enable in protected cells
+ if( !rSh.CanUnProtectCells() )
+ rSet.DisableItem( nSlot );
+ break;
+ case RES_ROW_SPLIT:
+ {
+ const SwFormatLayoutSplit& rTabSplit = pFormat->GetLayoutSplit();
+ if ( !rTabSplit.GetValue() )
+ {
+ rSet.DisableItem( nSlot );
+ }
+ else
+ {
+ std::unique_ptr<SwFormatRowSplit> pSplit = rSh.GetRowSplit();
+ if(pSplit)
+ rSet.Put(std::move(pSplit));
+ else
+ rSet.InvalidateItem( nSlot );
+ }
+ break;
+ }
+ case FN_TABLE_HEADLINE_REPEAT:
+ if(0 != rSh.GetRowsToRepeat())
+ rSet.Put(SfxBoolItem(nSlot, true));
+ else if(!rSh.GetRowSelectionFromTop())
+ rSet.DisableItem( nSlot );
+ else
+ rSet.Put(SfxBoolItem(nSlot, false));
+ break;
+ case FN_TABLE_SELECT_CELL :
+ if(rSh.HasBoxSelection())
+ rSet.DisableItem( nSlot );
+ break;
+ case SID_ATTR_TABLE_ROW_HEIGHT:
+ {
+ SfxUInt32Item aRowHeight(SID_ATTR_TABLE_ROW_HEIGHT);
+ std::unique_ptr<SwFormatFrameSize> pHeight = rSh.GetRowHeight();
+ if (pHeight)
+ {
+ tools::Long nHeight = pHeight->GetHeight();
+ aRowHeight.SetValue(nHeight);
+ rSet.Put(aRowHeight);
+
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ // TODO: set correct unit
+ MapUnit eTargetUnit = MapUnit::MapInch;
+ OUString sHeight = GetMetricText(nHeight,
+ MapUnit::MapTwip, eTargetUnit, nullptr);
+
+ OUString sPayload = ".uno:TableRowHeight=" + sHeight;
+
+ GetViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED,
+ OUStringToOString(sPayload, RTL_TEXTENCODING_ASCII_US));
+ }
+ }
+ break;
+ }
+ case SID_ATTR_TABLE_COLUMN_WIDTH:
+ {
+ SfxUInt32Item aColumnWidth(SID_ATTR_TABLE_COLUMN_WIDTH);
+ SwTableFUNC aFunc( &rSh );
+ aFunc.InitTabCols();
+ SwTwips nWidth = aFunc.GetColWidth(aFunc.GetCurColNum());
+ aColumnWidth.SetValue(nWidth);
+ rSet.Put(aColumnWidth);
+
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ // TODO: set correct unit
+ MapUnit eTargetUnit = MapUnit::MapInch;
+ OUString sWidth = GetMetricText(nWidth,
+ MapUnit::MapTwip, eTargetUnit, nullptr);
+
+ OUString sPayload = ".uno:TableColumWidth=" + sWidth;
+
+ GetViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED,
+ OUStringToOString(sPayload, RTL_TEXTENCODING_ASCII_US));
+ }
+
+ break;
+ }
+ }
+ nSlot = aIter.NextWhich();
+ }
+}
+
+SwTableShell::SwTableShell(SwView &_rView) :
+ SwBaseShell(_rView)
+{
+ SetName("Table");
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Table));
+}
+
+void SwTableShell::GetFrameBorderState(SfxItemSet &rSet)
+{
+ SfxItemSetFixed<RES_BOX, RES_BOX,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER> aCoreSet( GetPool() );
+ SvxBoxInfoItem aBoxInfo( SID_ATTR_BORDER_INNER );
+ aCoreSet.Put( aBoxInfo );
+ GetShell().GetTabBorders( aCoreSet );
+ rSet.Put( aCoreSet );
+}
+
+void SwTableShell::ExecTableStyle(SfxRequest& rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ if(!pArgs)
+ return;
+
+ switch ( rReq.GetSlot() )
+ {
+ case SID_FRAME_LINESTYLE:
+ case SID_FRAME_LINECOLOR:
+ if ( rReq.GetSlot() == SID_FRAME_LINESTYLE )
+ {
+ const SvxLineItem &rLineItem = pArgs->Get( SID_FRAME_LINESTYLE );
+ const SvxBorderLine* pBorderLine = rLineItem.GetLine();
+ rSh.SetTabLineStyle( nullptr, true, pBorderLine);
+ }
+ else
+ {
+ const SvxColorItem &rNewColorItem = pArgs->Get( SID_FRAME_LINECOLOR );
+ rSh.SetTabLineStyle( &rNewColorItem.GetValue() );
+ }
+
+ rReq.Done();
+
+ break;
+ }
+}
+
+void SwTableShell::GetLineStyleState(SfxItemSet &rSet)
+{
+ SfxItemSetFixed<RES_BOX, RES_BOX,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER> aCoreSet( GetPool() );
+ SvxBoxInfoItem aCoreInfo( SID_ATTR_BORDER_INNER );
+ aCoreSet.Put(aCoreInfo);
+ GetShell().GetTabBorders( aCoreSet );
+
+ const SvxBoxItem& rBoxItem = aCoreSet.Get( RES_BOX );
+ const SvxBorderLine* pLine = rBoxItem.GetTop();
+
+ rSet.Put( SvxColorItem( pLine ? pLine->GetColor() : Color(), SID_FRAME_LINECOLOR ) );
+ SvxLineItem aLine( SID_FRAME_LINESTYLE );
+ aLine.SetLine(pLine);
+ rSet.Put( aLine );
+}
+
+void SwTableShell::ExecNumberFormat(SfxRequest const & rReq)
+{
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ SwWrtShell &rSh = GetShell();
+
+ // At first the slots, which doesn't need a FrameMgr.
+ const SfxPoolItem* pItem = nullptr;
+ const sal_uInt16 nSlot = rReq.GetSlot();
+ if(pArgs)
+ pArgs->GetItemState(GetPool().GetWhich(nSlot), false, &pItem);
+
+ // Always acquire the language from the current cursor position.
+ LanguageType eLang = rSh.GetCurLang();
+ SvNumberFormatter* pFormatter = rSh.GetNumberFormatter();
+ sal_uInt32 nNumberFormat = NUMBERFORMAT_ENTRY_NOT_FOUND;
+ SvNumFormatType nFormatType = SvNumFormatType::ALL;
+ sal_uInt16 nOffset = 0;
+
+ switch ( nSlot )
+ {
+ case FN_NUMBER_FORMAT:
+ if( pItem )
+ {
+ // Determine index for string.
+ OUString aCode( static_cast<const SfxStringItem*>(pItem)->GetValue() );
+ nNumberFormat = pFormatter->GetEntryKey( aCode, eLang );
+ if( NUMBERFORMAT_ENTRY_NOT_FOUND == nNumberFormat )
+ {
+ // Re-enter
+ sal_Int32 nErrPos;
+ SvNumFormatType nType;
+ if( !pFormatter->PutEntry( aCode, nErrPos, nType,
+ nNumberFormat, eLang ))
+ nNumberFormat = NUMBERFORMAT_ENTRY_NOT_FOUND;
+ }
+ }
+ break;
+ case FN_NUMBER_STANDARD: nFormatType = SvNumFormatType::NUMBER; break;
+ case FN_NUMBER_SCIENTIFIC: nFormatType = SvNumFormatType::SCIENTIFIC; break;
+ case FN_NUMBER_DATE: nFormatType = SvNumFormatType::DATE; break;
+ case FN_NUMBER_TIME: nFormatType = SvNumFormatType::TIME; break;
+ case FN_NUMBER_CURRENCY: nFormatType = SvNumFormatType::CURRENCY; break;
+ case FN_NUMBER_PERCENT: nFormatType = SvNumFormatType::PERCENT; break;
+
+ case FN_NUMBER_TWODEC: // #.##0,00
+ nFormatType = SvNumFormatType::NUMBER;
+ nOffset = NF_NUMBER_1000DEC2;
+ break;
+
+ default:
+ OSL_FAIL("wrong dispatcher");
+ return;
+ }
+
+ if( nFormatType != SvNumFormatType::ALL )
+ nNumberFormat = pFormatter->GetStandardFormat( nFormatType, eLang ) + nOffset;
+
+ if( NUMBERFORMAT_ENTRY_NOT_FOUND != nNumberFormat )
+ {
+ SfxItemSetFixed<RES_BOXATR_FORMAT, RES_BOXATR_FORMAT> aBoxSet( GetPool() );
+ aBoxSet.Put( SwTableBoxNumFormat( nNumberFormat ));
+ rSh.SetTableBoxFormulaAttrs( aBoxSet );
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/textdrw.cxx b/sw/source/uibase/shells/textdrw.cxx
new file mode 100644
index 0000000000..881468c5d7
--- /dev/null
+++ b/sw/source/uibase/shells/textdrw.cxx
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+
+#include <svx/svdview.hxx>
+#include <tools/urlobj.hxx>
+#include <svx/svdobjkind.hxx>
+#include <svx/svdouno.hxx>
+#include <com/sun/star/form/FormButtonType.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <osl/diagnose.h>
+
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <edtwin.hxx>
+#include <swundo.hxx>
+#include <basesh.hxx>
+
+#include <docsh.hxx>
+#include <sfx2/docfile.hxx>
+#include <svl/urihelper.hxx>
+#include <avmedia/mediawindow.hxx>
+
+using namespace ::com::sun::star;
+
+void SwBaseShell::InsertURLButton(const OUString& rURL, const OUString& rTarget, const OUString& rText)
+{
+ SwWrtShell& rSh = GetShell();
+
+ if (!rSh.HasDrawView())
+ rSh.MakeDrawView();
+ SdrView *pSdrView = rSh.GetDrawView();
+
+ // OBJ_FM_BUTTON
+ pSdrView->SetDesignMode();
+ pSdrView->SetCurrentObj(SdrObjKind::FormButton);
+ pSdrView->SetEditMode(false);
+
+ Point aStartPos(rSh.GetCharRect().Pos() + Point(0, 1));
+
+ rSh.StartAction();
+ rSh.StartUndo( SwUndoId::UI_INSERT_URLBTN );
+ if (rSh.BeginCreate(SdrObjKind::FormButton, SdrInventor::FmForm, aStartPos))
+ {
+ pSdrView->SetOrtho(false);
+ Size aSz(GetView().GetEditWin().PixelToLogic(Size(140, 20)));
+ Point aEndPos(aSz.Width(), aSz.Height());
+
+ rSh.MoveCreate(aStartPos + aEndPos);
+ rSh.EndCreate(SdrCreateCmd::ForceEnd);
+
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ if (rMarkList.GetMark(0))
+ {
+ SdrUnoObj* pUnoCtrl = dynamic_cast<SdrUnoObj*>( rMarkList.GetMark(0)->GetMarkedSdrObj() );
+ OSL_ENSURE( pUnoCtrl, "not an SdrUnoObj" );
+ if (!pUnoCtrl)
+ return;
+
+ uno::Reference< awt::XControlModel > xControlModel = pUnoCtrl->GetUnoControlModel();
+
+ OSL_ENSURE( xControlModel.is(), "UNO-Control without Model" );
+ if (!xControlModel.is())
+ return;
+
+ uno::Reference< beans::XPropertySet > xPropSet(xControlModel, uno::UNO_QUERY);
+
+ uno::Any aTmp;
+
+ aTmp <<= rText;
+ xPropSet->setPropertyValue( "Label", aTmp );
+
+ SfxMedium* pMedium = rSh.GetView().GetDocShell()->GetMedium();
+ INetURLObject aAbs;
+ if( pMedium )
+ aAbs = pMedium->GetURLObject();
+
+ aTmp <<= URIHelper::SmartRel2Abs(aAbs, rURL);
+ xPropSet->setPropertyValue( "TargetURL", aTmp );
+
+ if( !rTarget.isEmpty() )
+ {
+ aTmp <<= rTarget;
+ xPropSet->setPropertyValue( "TargetFrame", aTmp );
+ }
+
+ aTmp <<= form::FormButtonType_URL;
+ xPropSet->setPropertyValue( "ButtonType", aTmp );
+
+#if HAVE_FEATURE_AVMEDIA
+ if ( ::avmedia::MediaWindow::isMediaURL( rURL, ""/*TODO?*/ ) )
+ {
+ // #105638# OJ
+ aTmp <<= true;
+ xPropSet->setPropertyValue("DispatchURLInternal", aTmp );
+ }
+#endif
+ }
+
+ if (rSh.IsObjSelected())
+ {
+ rSh.UnSelectFrame();
+ }
+ }
+ rSh.EndUndo( SwUndoId::UI_INSERT_URLBTN );
+ rSh.EndAction();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/textfld.cxx b/sw/source/uibase/shells/textfld.cxx
new file mode 100644
index 0000000000..68561d8b8d
--- /dev/null
+++ b/sw/source/uibase/shells/textfld.cxx
@@ -0,0 +1,1805 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/beans/PropertyValues.hpp>
+#include <AnnotationWin.hxx>
+#include <comphelper/lok.hxx>
+#include <hintids.hxx>
+#include <IDocumentFieldsAccess.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/lnkbase.hxx>
+#include <txtfld.hxx>
+#include <svl/itempool.hxx>
+#include <svl/numformat.hxx>
+#include <tools/lineend.hxx>
+#include <svl/whiter.hxx>
+#include <svl/eitem.hxx>
+#include <svl/macitem.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/request.hxx>
+#include <svx/postattr.hxx>
+#include <svx/hlnkitem.hxx>
+#include <svx/svxdlg.hxx>
+#include <osl/diagnose.h>
+#include <fmthdft.hxx>
+#include <fmtinfmt.hxx>
+#include <fldwrap.hxx>
+#include <redline.hxx>
+#include <view.hxx>
+#include <viewopt.hxx>
+#include <wrtsh.hxx>
+#include <textsh.hxx>
+#include <docufld.hxx>
+#include <ddefld.hxx>
+#include <fldmgr.hxx>
+#include <uitool.hxx>
+#include <cmdid.h>
+#include <strings.hrc>
+#include <sfx2/event.hxx>
+#include <swabstdlg.hxx>
+#include <doc.hxx>
+#include <PostItMgr.hxx>
+#include <swmodule.hxx>
+#include <svtools/strings.hrc>
+#include <svtools/svtresid.hxx>
+
+#include <editeng/ulspitem.hxx>
+#include <xmloff/odffields.hxx>
+#include <IDocumentContentOperations.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <svl/zforlist.hxx>
+#include <svl/zformat.hxx>
+#include <svx/xfillit0.hxx>
+#include <svx/pageitem.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+#include <IMark.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <officecfg/Office/Compatibility.hxx>
+#include <ndtxt.hxx>
+#include <translatehelper.hxx>
+#include <sfx2/dispatch.hxx>
+
+
+using namespace nsSwDocInfoSubType;
+
+static OUString lcl_BuildTitleWithRedline( const SwRangeRedline *pRedline )
+{
+ const OUString sTitle(SwResId(STR_REDLINE_COMMENT));
+
+ TranslateId pResId;
+ switch( pRedline->GetType() )
+ {
+ case RedlineType::Insert:
+ pResId = STR_REDLINE_INSERTED;
+ break;
+ case RedlineType::Delete:
+ pResId = STR_REDLINE_DELETED;
+ break;
+ case RedlineType::Format:
+ case RedlineType::ParagraphFormat:
+ pResId = STR_REDLINE_FORMATTED;
+ break;
+ case RedlineType::Table:
+ pResId = STR_REDLINE_TABLECHG;
+ break;
+ case RedlineType::FmtColl:
+ pResId = STR_REDLINE_FMTCOLLSET;
+ break;
+ default:
+ return sTitle;
+ }
+
+ return sTitle + SwResId(pResId);
+}
+
+void SwTextShell::ExecField(SfxRequest &rReq)
+{
+ SwWrtShell& rSh = GetShell();
+ const SfxPoolItem* pItem = nullptr;
+
+ sal_uInt16 nSlot = rReq.GetSlot();
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ if(pArgs)
+ pArgs->GetItemState(GetPool().GetWhich(nSlot), false, &pItem);
+
+ bool bMore = false;
+ bool bIsText = true;
+ SwFieldTypesEnum nInsertType = SwFieldTypesEnum::Date;
+ sal_uInt16 nInsertSubType = 0;
+ sal_uInt32 nInsertFormat = 0;
+
+ switch(nSlot)
+ {
+ case FN_EDIT_FIELD:
+ {
+ SwField* pField = rSh.GetCurField(true);
+ if( pField )
+ {
+ switch ( pField->GetTypeId() )
+ {
+ case SwFieldTypesEnum::DDE:
+ {
+ ::sfx2::SvBaseLink& rLink = static_cast<SwDDEFieldType*>(pField->GetTyp())->
+ GetBaseLink();
+ if(rLink.IsVisible())
+ {
+ if (officecfg::Office::Common::Security::Scripting::DisableActiveContent::get())
+ {
+ std::unique_ptr<weld::MessageDialog> xError(
+ Application::CreateMessageDialog(
+ nullptr, VclMessageType::Warning, VclButtonsType::Ok,
+ SvtResId(STR_WARNING_EXTERNAL_LINK_EDIT_DISABLED)));
+ xError->run();
+ break;
+ }
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractLinksDialog> pDlg(pFact->CreateLinksDialog(GetView().GetFrameWeld(), &rSh.GetLinkManager(), false, &rLink));
+ pDlg->Execute();
+ }
+ break;
+ }
+ default:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateSwFieldEditDlg( GetView() ));
+ pDlg->Execute();
+ }
+ }
+ }
+ break;
+ }
+ case FN_UPDATE_SEL_FIELD:
+ {
+ SwField *pField = rSh.GetCurField();
+
+ if (pField)
+ {
+ rSh.UpdateOneField(*pField);
+ }
+ break;
+ }
+ case FN_EXECUTE_MACROFIELD:
+ {
+ SwField* pField = rSh.GetCurField();
+ if(pField && pField->GetTyp()->Which() == SwFieldIds::Macro)
+ {
+
+ const OUString& rMacro = static_cast<SwMacroField*>(pField)->GetMacro();
+ sal_Int32 nPos = rMacro.indexOf('.');
+ if(nPos != -1)
+ {
+ SvxMacro aMacro( rMacro.copy(nPos + 1), rMacro.copy(0,nPos), STARBASIC );
+ rSh.ExecMacro(aMacro);
+ }
+ }
+ }
+ break;
+
+ case FN_GOTO_NEXT_INPUTFLD:
+ case FN_GOTO_PREV_INPUTFLD:
+ {
+ bool bRet = false;
+ SwFieldType* pField = rSh.GetFieldType( 0, SwFieldIds::Input );
+ const bool bAddSetExpressionFields = !( rSh.GetViewOptions()->IsReadonly() );
+ if ( pField != nullptr
+ && rSh.MoveFieldType(
+ pField,
+ FN_GOTO_NEXT_INPUTFLD == nSlot,
+ SwFieldIds::Unknown,
+ bAddSetExpressionFields ) )
+ {
+ rSh.ClearMark();
+ if (!rSh.IsMultiSelection()
+ && (nullptr != dynamic_cast<const SwTextInputField*>(
+ SwCursorShell::GetTextFieldAtCursor(rSh.GetCursor(), ::sw::GetTextAttrMode::Default))))
+ {
+ rSh.SttSelect();
+ rSh.SelectTextModel(
+ SwCursorShell::StartOfInputFieldAtPos( *(rSh.GetCursor()->Start()) ) + 1,
+ SwCursorShell::EndOfInputFieldAtPos( *(rSh.GetCursor()->Start()) ) - 1 );
+ }
+ else if (SwField* pCurrentField = rSh.GetCurField(true))
+ {
+ rSh.StartInputFieldDlg(pCurrentField, false, false, GetView().GetFrameWeld());
+ }
+ bRet = true;
+ }
+
+ rReq.SetReturnValue( SfxBoolItem( nSlot, bRet ));
+ }
+ break;
+
+ case FN_GOTO_MARK:
+ {
+ const SfxStringItem* pName = rReq.GetArg<SfxStringItem>(FN_GOTO_MARK);
+ if (pName)
+ {
+ rSh.GotoMark(pName->GetValue());
+ }
+ }
+ break;
+ default:
+ bMore = true;
+ }
+ if(!bMore)
+ return;
+
+ // Here come the slots with FieldMgr.
+ SwFieldMgr aFieldMgr(GetShellPtr());
+ switch(nSlot)
+ {
+ case FN_INSERT_DBFIELD:
+ {
+ bool bRes = false;
+ if( pItem )
+ {
+ sal_uInt32 nFormat = 0;
+ SwFieldTypesEnum nType = SwFieldTypesEnum::Date;
+ OUString aPar1 = static_cast<const SfxStringItem *>(pItem)->GetValue();
+ OUString aPar2;
+ sal_Int32 nCommand = 0;
+
+ if( const SfxUInt16Item* pFieldItem = pArgs->GetItemIfSet( FN_PARAM_FIELD_TYPE,
+ false ))
+ nType = static_cast<SwFieldTypesEnum>(pFieldItem->GetValue());
+ aPar1 += OUStringChar(DB_DELIM);
+ if( SfxItemState::SET == pArgs->GetItemState(
+ FN_PARAM_1, false, &pItem ))
+ {
+ aPar1 += static_cast<const SfxStringItem *>(pItem)->GetValue();
+ }
+ if( SfxItemState::SET == pArgs->GetItemState(
+ FN_PARAM_3, false, &pItem ))
+ nCommand = static_cast<const SfxInt32Item*>(pItem)->GetValue();
+ aPar1 += OUStringChar(DB_DELIM)
+ + OUString::number(nCommand)
+ + OUStringChar(DB_DELIM);
+ if( SfxItemState::SET == pArgs->GetItemState(
+ FN_PARAM_2, false, &pItem ))
+ {
+ aPar1 += static_cast<const SfxStringItem *>(pItem)->GetValue();
+ }
+ if( const SfxStringItem* pContentItem = pArgs->GetItemIfSet(
+ FN_PARAM_FIELD_CONTENT, false ))
+ aPar2 = pContentItem->GetValue();
+ if( const SfxUInt32Item* pFormatItem = pArgs->GetItemIfSet(
+ FN_PARAM_FIELD_FORMAT, false ))
+ nFormat = pFormatItem->GetValue();
+ OSL_FAIL("Command is not yet used");
+ SwInsertField_Data aData(nType, 0, aPar1, aPar2, nFormat, GetShellPtr(), ' '/*separator*/ );
+ bRes = aFieldMgr.InsertField(aData);
+ }
+ rReq.SetReturnValue(SfxBoolItem( nSlot, bRes ));
+ }
+ break;
+ case FN_INSERT_FIELD_CTRL:
+ case FN_INSERT_FIELD:
+ {
+ bool bRes = false;
+ if( pItem && nSlot != FN_INSERT_FIELD_CTRL)
+ {
+ sal_uInt32 nFormat = 0;
+ SwFieldTypesEnum nType = SwFieldTypesEnum::Date;
+ sal_uInt16 nSubType = 0;
+ OUString aPar1 = static_cast<const SfxStringItem *>(pItem)->GetValue();
+ OUString aPar2;
+ sal_Unicode cSeparator = ' ';
+
+ if( const SfxUInt16Item* pTypeItem = pArgs->GetItemIfSet( FN_PARAM_FIELD_TYPE,
+ false ))
+ nType = static_cast<SwFieldTypesEnum>(pTypeItem->GetValue());
+ else if (pArgs->GetItemState(FN_PARAM_4, false, &pItem) == SfxItemState::SET)
+ {
+ const OUString& rTypeName = static_cast<const SfxStringItem *>(pItem)->GetValue();
+ nType = SwFieldTypeFromString(rTypeName);
+ }
+ if( const SfxUInt16Item* pSubtypeItem = pArgs->GetItemIfSet( FN_PARAM_FIELD_SUBTYPE,
+ false ))
+ nSubType = pSubtypeItem->GetValue();
+ if( const SfxStringItem* pContentItem = pArgs->GetItemIfSet(
+ FN_PARAM_FIELD_CONTENT, false ))
+ aPar2 = pContentItem->GetValue();
+ if( const SfxUInt32Item* pFormatItem = pArgs->GetItemIfSet(
+ FN_PARAM_FIELD_FORMAT, false ))
+ nFormat = pFormatItem->GetValue();
+ if( SfxItemState::SET == pArgs->GetItemState(
+ FN_PARAM_3, false, &pItem ))
+ {
+ OUString sTmp = static_cast<const SfxStringItem *>(pItem)->GetValue();
+ if(!sTmp.isEmpty())
+ cSeparator = sTmp[0];
+ }
+ if (pArgs->GetItemState(FN_PARAM_5, false, &pItem) == SfxItemState::SET)
+ {
+ // Wrap the field in the requested container instead of inserting it
+ // directly at the cursor position.
+ const OUString& rWrapper = static_cast<const SfxStringItem *>(pItem)->GetValue();
+ if (rWrapper == "Footnote")
+ {
+ GetShellPtr()->InsertFootnote(OUString());
+ }
+ else if (rWrapper == "Endnote")
+ {
+ GetShellPtr()->InsertFootnote(OUString(), /*bEndNote=*/true);
+ }
+ }
+ SwInsertField_Data aData(nType, nSubType, aPar1, aPar2, nFormat, GetShellPtr(), cSeparator );
+ bRes = aFieldMgr.InsertField( aData );
+ }
+ else
+ {
+ //#i5788# prevent closing of the field dialog while a modal dialog ( Input field dialog ) is active
+ if(!GetView().GetViewFrame().IsInModalMode())
+ {
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+ rVFrame.ToggleChildWindow(FN_INSERT_FIELD);
+ bRes = rVFrame.GetChildWindow( nSlot ) != nullptr;
+ Invalidate(rReq.GetSlot());
+ Invalidate(FN_INSERT_FIELD_CTRL);
+ rReq.Ignore();
+ }
+ }
+ rReq.SetReturnValue(SfxBoolItem( nSlot, bRes ));
+ }
+ break;
+
+ case FN_INSERT_REF_FIELD:
+ {
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+ if (!rVFrame.HasChildWindow(FN_INSERT_FIELD))
+ rVFrame.ToggleChildWindow(FN_INSERT_FIELD); // Show dialog
+
+ // Switch Fielddlg at a new TabPage
+ sal_uInt16 nId = SwFieldDlgWrapper::GetChildWindowId();
+ SwFieldDlgWrapper *pWrp = static_cast<SwFieldDlgWrapper*>(rVFrame.GetChildWindow(nId));
+ if (pWrp)
+ pWrp->ShowReferencePage();
+ rReq.Ignore();
+ }
+ break;
+ case FN_DELETE_COMMENT:
+ {
+ const SvxPostItIdItem* pIdItem = rReq.GetArg<SvxPostItIdItem>(SID_ATTR_POSTIT_ID);
+ if (pIdItem && !pIdItem->GetValue().isEmpty() && GetView().GetPostItMgr())
+ {
+ GetView().GetPostItMgr()->Delete(pIdItem->GetValue().toUInt32());
+ }
+ else if ( GetView().GetPostItMgr() &&
+ GetView().GetPostItMgr()->HasActiveSidebarWin() )
+ {
+ GetView().GetPostItMgr()->DeleteActiveSidebarWin();
+ }
+ break;
+ }
+ case FN_DELETE_COMMENT_THREAD:
+ {
+ const SvxPostItIdItem* pIdItem = rReq.GetArg<SvxPostItIdItem>(SID_ATTR_POSTIT_ID);
+ if (pIdItem && !pIdItem->GetValue().isEmpty() && GetView().GetPostItMgr())
+ {
+ GetView().GetPostItMgr()->DeleteCommentThread(pIdItem->GetValue().toUInt32());
+ }
+ else if ( GetView().GetPostItMgr() &&
+ GetView().GetPostItMgr()->HasActiveSidebarWin() )
+ {
+ GetView().GetPostItMgr()->DeleteActiveSidebarWin();
+ }
+ break;
+ }
+ case FN_RESOLVE_NOTE:
+ {
+ const SvxPostItIdItem* pIdItem = rReq.GetArg<SvxPostItIdItem>(SID_ATTR_POSTIT_ID);
+ if (pIdItem && !pIdItem->GetValue().isEmpty() && GetView().GetPostItMgr())
+ {
+ GetView().GetPostItMgr()->ToggleResolved(pIdItem->GetValue().toUInt32());
+ }
+ break;
+ }
+ case FN_RESOLVE_NOTE_THREAD:
+ {
+ const SvxPostItIdItem* pIdItem = rReq.GetArg<SvxPostItIdItem>(SID_ATTR_POSTIT_ID);
+ if (pIdItem && !pIdItem->GetValue().isEmpty() && GetView().GetPostItMgr())
+ {
+ GetView().GetPostItMgr()->ToggleResolvedForThread(pIdItem->GetValue().toUInt32());
+ }
+ break;
+ }
+ case FN_DELETE_ALL_NOTES:
+ if ( GetView().GetPostItMgr() )
+ GetView().GetPostItMgr()->Delete();
+ break;
+ case FN_FORMAT_ALL_NOTES:
+ {
+ SwPostItMgr* pPostItMgr = GetView().GetPostItMgr();
+ if (pPostItMgr)
+ pPostItMgr->ExecuteFormatAllDialog(GetView());
+ }
+ break;
+ case FN_DELETE_NOTE_AUTHOR:
+ {
+ const SfxStringItem* pNoteItem = rReq.GetArg<SfxStringItem>(nSlot);
+ if ( pNoteItem && GetView().GetPostItMgr() )
+ GetView().GetPostItMgr()->Delete( pNoteItem->GetValue() );
+ }
+ break;
+ case FN_HIDE_NOTE:
+ if ( GetView().GetPostItMgr() &&
+ GetView().GetPostItMgr()->HasActiveSidebarWin() )
+ {
+ GetView().GetPostItMgr()->HideActiveSidebarWin();
+ }
+ break;
+ case FN_HIDE_ALL_NOTES:
+ if ( GetView().GetPostItMgr() )
+ GetView().GetPostItMgr()->Hide();
+ break;
+ case FN_HIDE_NOTE_AUTHOR:
+ {
+ const SfxStringItem* pNoteItem = rReq.GetArg<SfxStringItem>(nSlot);
+ if ( pNoteItem && GetView().GetPostItMgr() )
+ GetView().GetPostItMgr()->Hide( pNoteItem->GetValue() );
+ }
+ break;
+ case FN_REPLY:
+ {
+ const SvxPostItIdItem* pIdItem = rReq.GetArg<SvxPostItIdItem>(SID_ATTR_POSTIT_ID);
+ if (pIdItem && !pIdItem->GetValue().isEmpty())
+ {
+ SwFieldType* pType = rSh.GetDoc()->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Postit, OUString(), false);
+ if(pType->FindFormatForPostItId(pIdItem->GetValue().toUInt32()))
+ {
+ auto pMgr = GetView().GetPostItMgr();
+ auto pWin = pMgr->GetAnnotationWin(pIdItem->GetValue().toUInt32());
+ if(pWin)
+ {
+ OUString sText;
+ if(const auto pTextItem = rReq.GetArg<SvxPostItTextItem>(SID_ATTR_POSTIT_TEXT))
+ sText = pTextItem->GetValue();
+ pMgr->RegisterAnswerText(sText);
+ pWin->ExecuteCommand(nSlot);
+
+ SwPostItField* pLatestPostItField = pMgr->GetLatestPostItField();
+ if (pLatestPostItField)
+ {
+ // Set the parent postit id of the reply.
+ pLatestPostItField->SetParentPostItId(pIdItem->GetValue().toUInt32());
+
+ // If name of the replied comment is empty, we need to set a name in order to connect them in the xml file.
+ pWin->GeneratePostItName(); // Generates a name if the current name is empty.
+
+ pLatestPostItField->SetParentName(pWin->GetPostItField()->GetName());
+ }
+ }
+ }
+ }
+ }
+ break;
+ case FN_POSTIT:
+ {
+ rSh.InsertPostIt(aFieldMgr, rReq);
+ }
+ break;
+ case SID_EDIT_POSTIT:
+ {
+ const SvxPostItIdItem* pIdItem = rReq.GetArg<SvxPostItIdItem>(SID_ATTR_POSTIT_ID);
+ if (pIdItem && !pIdItem->GetValue().isEmpty())
+ {
+ const SvxPostItTextItem* pTextItem = rReq.GetArg<SvxPostItTextItem>(SID_ATTR_POSTIT_TEXT);
+ OUString sText;
+ if ( pTextItem )
+ sText = pTextItem->GetValue();
+
+ sw::annotation::SwAnnotationWin* pAnnotationWin = GetView().GetPostItMgr()->GetAnnotationWin(pIdItem->GetValue().toUInt32());
+ if (pAnnotationWin)
+ {
+ pAnnotationWin->UpdateText(sText);
+
+ // explicit state update to get the Undo state right
+ GetView().AttrChangedNotify(nullptr);
+ }
+ }
+ }
+ break;
+ case FN_REDLINE_COMMENT:
+ {
+ /* this code can be used once we want redline comments in the margin, all other stuff can
+ then be deleted
+ String sComment;
+ const SwRangeRedline *pRedline = rSh.GetCurrRedline();
+
+ if (pRedline)
+ {
+ sComment = pRedline->GetComment();
+ if ( !sComment.Len() )
+ GetView().GetDocShell()->Broadcast(SwRedlineHint(pRedline,SWREDLINE_INSERTED));
+ const_cast<SwRangeRedline*>(pRedline)->Broadcast(SwRedlineHint(pRedline,SWREDLINE_FOCUS,&GetView()));
+ }
+ */
+
+ const SwRangeRedline *pRedline = rSh.GetCurrRedline();
+ SwDoc *pDoc = rSh.GetDoc();
+ // If index is specified, goto and select the appropriate redline
+ if (pArgs && pArgs->GetItemState(nSlot, false, &pItem) == SfxItemState::SET)
+ {
+ const sal_uInt32 nChangeId = static_cast<const SfxUInt32Item*>(pItem)->GetValue();
+ const SwRedlineTable& rRedlineTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
+ for (SwRedlineTable::size_type nRedline = 0; nRedline < rRedlineTable.size(); ++nRedline)
+ {
+ if (nChangeId == rRedlineTable[nRedline]->GetId())
+ pRedline = rSh.GotoRedline(nRedline, true);
+ }
+ }
+
+ OUString sCommentText;
+ const SfxStringItem* pTextItem = rReq.GetArg<SvxPostItTextItem>(SID_ATTR_POSTIT_TEXT);
+ if (pTextItem)
+ sCommentText = pTextItem->GetValue();
+
+ if (pRedline)
+ {
+ // In case of LOK and comment text is already provided, skip
+ // dialog creation and just change the redline comment directly
+ if (comphelper::LibreOfficeKit::isActive() && !sCommentText.isEmpty())
+ {
+ rSh.SetRedlineComment(sCommentText);
+ GetView().AttrChangedNotify(nullptr);
+ MaybeNotifyRedlineModification(const_cast<SwRangeRedline&>(*pRedline), pRedline->GetDoc());
+ break;
+ }
+
+ OUString sComment = convertLineEnd(pRedline->GetComment(), GetSystemLineEnd());
+
+ bool bTravel = false;
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ::DialogGetRanges fnGetRange = pFact->GetDialogGetRangesFunc();
+ SfxItemSet aSet(GetPool(), fnGetRange());
+ aSet.Put(SvxPostItTextItem(sComment, SID_ATTR_POSTIT_TEXT));
+ aSet.Put(SvxPostItAuthorItem(pRedline->GetAuthorString(), SID_ATTR_POSTIT_AUTHOR));
+
+ aSet.Put( SvxPostItDateItem( GetAppLangDateTimeString(
+ pRedline->GetRedlineData().GetTimeStamp() ),
+ SID_ATTR_POSTIT_DATE ));
+
+ // Traveling only if more than one field.
+ rSh.StartAction();
+
+ rSh.Push();
+ const SwRangeRedline *pActRed = rSh.SelPrevRedline();
+
+ if (pActRed == pRedline)
+ { // New cursor is at the beginning of the current redlines.
+ rSh.Pop(); // Throw old cursor away
+ rSh.Push();
+ pActRed = rSh.SelPrevRedline();
+ }
+
+ bool bPrev = pActRed != nullptr;
+ rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+ rSh.EndAction();
+
+ rSh.ClearMark();
+ // Select current redline.
+ pActRed = rSh.SelNextRedline();
+ if (pActRed != pRedline)
+ rSh.SelPrevRedline();
+
+ rSh.StartAction();
+ rSh.Push();
+ pActRed = rSh.SelNextRedline();
+ bool bNext = pActRed != nullptr;
+ rSh.Pop(SwCursorShell::PopMode::DeleteCurrent); // Restore cursor position
+
+ if( rSh.IsCursorPtAtEnd() )
+ rSh.SwapPam();
+
+ rSh.EndAction();
+
+ bTravel |= bNext || bPrev;
+
+ SvxAbstractDialogFactory* pFact2 = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractSvxPostItDialog> pDlg(pFact2->CreateSvxPostItDialog(GetView().GetFrameWeld(), aSet, bTravel));
+ pDlg->HideAuthor();
+
+ pDlg->SetText(lcl_BuildTitleWithRedline(pRedline));
+
+ if (bTravel)
+ {
+ pDlg->EnableTravel(bNext, bPrev);
+ pDlg->SetPrevHdl(LINK(this, SwTextShell, RedlinePrevHdl));
+ pDlg->SetNextHdl(LINK(this, SwTextShell, RedlineNextHdl));
+ }
+
+ SwViewShell::SetCareDialog(pDlg->GetDialog());
+ g_bNoInterrupt = true;
+
+ if ( pDlg->Execute() == RET_OK )
+ {
+ const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
+ OUString sMsg(pOutSet->Get(SID_ATTR_POSTIT_TEXT).GetValue());
+
+ // Insert or change a comment
+ rSh.SetRedlineComment(sMsg);
+ }
+
+ SwViewShell::SetCareDialog(nullptr);
+ pDlg.disposeAndClear();
+ g_bNoInterrupt = false;
+ rSh.ClearMark();
+ GetView().AttrChangedNotify(nullptr);
+ }
+ }
+ break;
+
+ case FN_JAVAEDIT:
+ {
+ OUString aType, aText;
+ bool bIsUrl=false;
+ bool bNew=false;
+ bool bUpdate = false;
+ SwFieldMgr aMgr;
+ if ( pItem )
+ {
+ aText = static_cast<const SfxStringItem*>(pItem)->GetValue();
+ const SfxStringItem* pType = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
+ const SfxBoolItem* pIsUrl = rReq.GetArg<SfxBoolItem>(FN_PARAM_1);
+ if ( pType )
+ aType = pType->GetValue();
+ if ( pIsUrl )
+ bIsUrl = pIsUrl->GetValue();
+
+ SwScriptField* pField = static_cast<SwScriptField*>(aMgr.GetCurField());
+ bNew = !pField || (pField->GetTyp()->Which() != SwFieldIds::Script);
+ bUpdate = pField && ( bIsUrl != static_cast<bool>(pField->GetFormat()) || pField->GetPar2() != aType || pField->GetPar1() != aText );
+ }
+ else
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractJavaEditDialog> pDlg(pFact->CreateJavaEditDialog(GetView().GetFrameWeld(), &rSh));
+ if ( pDlg->Execute() )
+ {
+ aType = pDlg->GetScriptType();
+ aText = pDlg->GetScriptText();
+ bIsUrl = pDlg->IsUrl();
+ bNew = pDlg->IsNew();
+ bUpdate = pDlg->IsUpdate();
+ rReq.AppendItem( SfxStringItem( FN_JAVAEDIT, aText ) );
+ rReq.AppendItem( SfxStringItem( FN_PARAM_2, aType ) );
+ rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bIsUrl ) );
+ }
+ }
+
+ if( bNew )
+ {
+ SwInsertField_Data aData(SwFieldTypesEnum::Script, 0, aType, aText, bIsUrl ? 1 : 0);
+ aMgr.InsertField(aData);
+ rReq.Done();
+ }
+ else if( bUpdate )
+ {
+ aMgr.UpdateCurField( bIsUrl ? 1 : 0, aType, aText );
+ rSh.SetUndoNoResetModified();
+ rReq.Done();
+ }
+ else
+ rReq.Ignore();
+ }
+ break;
+
+ case FN_INSERT_FLD_DATE :
+ case FN_INSERT_FLD_DATE_VAR:
+ {
+ nInsertType = SwFieldTypesEnum::Date;
+ nInsertSubType = nSlot == FN_INSERT_FLD_DATE ? 0 : 1;
+ bIsText = false;
+ // use long date format for Hungarian
+ SwPaM* pCursorPos = rSh.GetCursor();
+ if( pCursorPos )
+ {
+ LanguageType nLang = pCursorPos->GetPoint()->GetNode().GetTextNode()->GetLang(pCursorPos->GetPoint()->GetContentIndex());
+ if (nLang == LANGUAGE_HUNGARIAN)
+ nInsertFormat = rSh.GetNumberFormatter()->GetFormatIndex(NF_DATE_SYSTEM_LONG, nLang);
+ }
+ goto FIELD_INSERT;
+ }
+ case FN_INSERT_FLD_TIME :
+ case FN_INSERT_FLD_TIME_VAR:
+ nInsertType = SwFieldTypesEnum::Time;
+ nInsertSubType = nSlot == FN_INSERT_FLD_TIME ? 0 : 1;
+ bIsText = false;
+ goto FIELD_INSERT;
+ case FN_INSERT_FLD_PGNUMBER:
+ nInsertType = SwFieldTypesEnum::PageNumber;
+ nInsertFormat = SVX_NUM_PAGEDESC; // Like page template
+ bIsText = false;
+ goto FIELD_INSERT;
+ case FN_INSERT_FLD_PGCOUNT :
+ nInsertType = SwFieldTypesEnum::DocumentStatistics;
+ nInsertSubType = 0;
+ bIsText = false;
+ nInsertFormat = SVX_NUM_PAGEDESC;
+ goto FIELD_INSERT;
+ case FN_INSERT_FLD_TOPIC :
+ nInsertType = SwFieldTypesEnum::DocumentInfo;
+ nInsertSubType = DI_SUBJECT;
+ goto FIELD_INSERT;
+ case FN_INSERT_FLD_TITLE :
+ nInsertType = SwFieldTypesEnum::DocumentInfo;
+ nInsertSubType = DI_TITLE;
+ goto FIELD_INSERT;
+ case FN_INSERT_FLD_AUTHOR :
+ nInsertType = SwFieldTypesEnum::DocumentInfo;
+ nInsertSubType = DI_CREATE|DI_SUB_AUTHOR;
+
+FIELD_INSERT:
+ {
+ //format conversion should only be done for number formatter formats
+ if(!nInsertFormat)
+ nInsertFormat = aFieldMgr.GetDefaultFormat(nInsertType, bIsText, rSh.GetNumberFormatter());
+ SwInsertField_Data aData(nInsertType, nInsertSubType,
+ OUString(), OUString(), nInsertFormat);
+ aFieldMgr.InsertField(aData);
+ rReq.Done();
+ }
+ break;
+
+ case FN_INSERT_TEXT_FORMFIELD:
+ {
+ OUString aFieldType(ODF_FORMTEXT);
+ const SfxStringItem* pFieldType = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if (pFieldType)
+ {
+ // Allow overwriting the default type.
+ aFieldType = pFieldType->GetValue();
+ }
+
+ OUString aFieldCode;
+ const SfxStringItem* pFieldCode = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
+ if (pFieldCode)
+ {
+ // Allow specifying a field code/command.
+ aFieldCode = pFieldCode->GetValue();
+ }
+
+ if (rSh.HasReadonlySel())
+ {
+ // Inform the user that the request has been ignored.
+ auto xInfo = std::make_shared<weld::GenericDialogController>(
+ GetView().GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui",
+ "InfoReadonlyDialog");
+ weld::DialogController::runAsync(xInfo, [](sal_Int32 /*nResult*/) {});
+ break;
+ }
+
+ rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
+
+ SwPaM* pCursorPos = rSh.GetCursor();
+ if(pCursorPos)
+ {
+ // Insert five En Space into the text field so the field has extent
+ static constexpr OUStringLiteral vEnSpaces = u"\u2002\u2002\u2002\u2002\u2002";
+ OUString aFieldResult(vEnSpaces);
+ const SfxStringItem* pFieldResult = rReq.GetArg<SfxStringItem>(FN_PARAM_3);
+ if (pFieldResult)
+ {
+ // Allow specifying a field result / expanded value.
+ aFieldResult = pFieldResult->GetValue();
+ }
+
+ const SfxStringItem* pWrapper = rReq.GetArg<SfxStringItem>(FN_PARAM_4);
+ if (pWrapper)
+ {
+ // Wrap the fieldmark in the requested container instead of inserting it
+ // directly at the cursor position.
+ OUString aWrapper = pWrapper->GetValue();
+ if (aWrapper == "Footnote")
+ {
+ rSh.InsertFootnote(OUString());
+ }
+ else if (aWrapper == "Endnote")
+ {
+ // It's important that there is no Start/EndAction() around this, so the
+ // inner EndAction() triggers a layout update and the cursor can jump to the
+ // created SwFootnoteFrame.
+ rSh.InsertFootnote(OUString(), /*bEndNote=*/true);
+ }
+ }
+
+ // Don't update the layout after inserting content and before deleting temporary
+ // text nodes.
+ rSh.StartAction();
+
+ // Split node to remember where the start position is.
+ bool bSuccess = rSh.GetDoc()->getIDocumentContentOperations().SplitNode(
+ *pCursorPos->GetPoint(), false);
+ if(bSuccess)
+ {
+ SwPaM aFieldPam(*pCursorPos->GetPoint());
+ aFieldPam.Move(fnMoveBackward, GoInContent);
+ if (pFieldResult)
+ {
+ // Paste HTML content.
+ SwTranslateHelper::PasteHTMLToPaM(rSh, pCursorPos, aFieldResult.toUtf8());
+ if (pCursorPos->GetPoint()->GetContentIndex() == 0)
+ {
+ // The paste created a last empty text node, remove it.
+ SwPaM aPam(*pCursorPos->GetPoint());
+ aPam.SetMark();
+ aPam.Move(fnMoveBackward, GoInContent);
+ rSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(aPam);
+ }
+ }
+ else
+ {
+ // Insert default placeholder.
+ rSh.GetDoc()->getIDocumentContentOperations().InsertString(*pCursorPos,
+ aFieldResult);
+ }
+ // Undo the above SplitNode().
+ aFieldPam.SetMark();
+ aFieldPam.Move(fnMoveForward, GoInContent);
+ rSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(aFieldPam);
+ *aFieldPam.GetMark() = *pCursorPos->GetPoint();
+
+ IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess();
+ sw::mark::IFieldmark* pFieldmark = pMarksAccess->makeFieldBookmark(
+ aFieldPam, OUString(), aFieldType, aFieldPam.Start());
+ if (pFieldmark && !aFieldCode.isEmpty())
+ {
+ pFieldmark->GetParameters()->insert(
+ std::pair<OUString, uno::Any>(ODF_CODE_PARAM, uno::Any(aFieldCode)));
+ }
+ }
+ rSh.EndAction();
+ }
+
+ rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
+ rSh.GetView().GetViewFrame().GetBindings().Invalidate( SID_UNDO );
+ }
+ break;
+ case FN_INSERT_CHECKBOX_FORMFIELD:
+ {
+ rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
+
+ SwPaM* pCursorPos = rSh.GetCursor();
+ if(pCursorPos)
+ {
+ IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess();
+ pMarksAccess->makeNoTextFieldBookmark(*pCursorPos, OUString(), ODF_FORMCHECKBOX);
+ }
+
+ rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
+ rSh.GetView().GetViewFrame().GetBindings().Invalidate( SID_UNDO );
+ }
+ break;
+ case FN_INSERT_DROPDOWN_FORMFIELD:
+ {
+ rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
+
+ SwPaM* pCursorPos = rSh.GetCursor();
+ if(pCursorPos)
+ {
+ IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess();
+ pMarksAccess->makeNoTextFieldBookmark(*pCursorPos, OUString(), ODF_FORMDROPDOWN);
+ }
+
+ rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
+ rSh.GetView().GetViewFrame().GetBindings().Invalidate( SID_UNDO );
+ }
+ break;
+ case FN_INSERT_DATE_FORMFIELD:
+ {
+ rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
+
+ SwPaM* pCursorPos = rSh.GetCursor();
+ if(pCursorPos)
+ {
+ // Insert five enspaces into the text field so the field has extent
+ sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = {8194, 8194, 8194, 8194, 8194};
+ bool bSuccess = rSh.GetDoc()->getIDocumentContentOperations().InsertString(*pCursorPos, OUString(vEnSpaces, ODF_FORMFIELD_DEFAULT_LENGTH));
+ if(bSuccess)
+ {
+ IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess();
+ SwPaM aFieldPam(pCursorPos->GetPoint()->GetNode(), pCursorPos->GetPoint()->GetContentIndex() - ODF_FORMFIELD_DEFAULT_LENGTH,
+ pCursorPos->GetPoint()->GetNode(), pCursorPos->GetPoint()->GetContentIndex());
+ sw::mark::IFieldmark* pFieldBM = pMarksAccess->makeFieldBookmark(aFieldPam, OUString(), ODF_FORMDATE,
+ aFieldPam.Start());
+
+ // Use a default date format and language
+ sw::mark::IFieldmark::parameter_map_t* pParameters = pFieldBM->GetParameters();
+ SvNumberFormatter* pFormatter = rSh.GetDoc()->GetNumberFormatter();
+ sal_uInt32 nStandardFormat = pFormatter->GetStandardFormat(SvNumFormatType::DATE);
+ const SvNumberformat* pFormat = pFormatter->GetEntry(nStandardFormat);
+
+ (*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= pFormat->GetFormatstring();
+ (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] <<= LanguageTag(pFormat->GetLanguage()).getBcp47();
+ }
+ }
+
+ rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
+ rSh.GetView().GetViewFrame().GetBindings().Invalidate( SID_UNDO );
+ }
+ break;
+ case FN_UPDATE_TEXT_FORMFIELDS:
+ {
+ // This updates multiple fieldmarks in a document, based on their field name & field command
+ // prefix.
+ OUString aFieldType;
+ const SfxStringItem* pFieldType = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if (pFieldType)
+ {
+ aFieldType = pFieldType->GetValue();
+ }
+ OUString aFieldCommandPrefix;
+ const SfxStringItem* pFieldCommandPrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
+ if (pFieldCommandPrefix)
+ {
+ aFieldCommandPrefix = pFieldCommandPrefix->GetValue();
+ }
+ uno::Sequence<beans::PropertyValues> aFields;
+ const SfxUnoAnyItem* pFields = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_3);
+ if (pFields)
+ {
+ pFields->GetValue() >>= aFields;
+ }
+
+ rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::UPDATE_FORM_FIELDS, nullptr);
+ rSh.StartAction();
+
+ IDocumentMarkAccess* pMarkAccess = rSh.GetDoc()->getIDocumentMarkAccess();
+ sal_Int32 nFieldIndex = 0;
+ for (auto it = pMarkAccess->getFieldmarksBegin(); it != pMarkAccess->getFieldmarksEnd(); ++it)
+ {
+ auto pFieldmark = dynamic_cast<sw::mark::IFieldmark*>(*it);
+ assert(pFieldmark);
+ if (pFieldmark->GetFieldname() != aFieldType)
+ {
+ continue;
+ }
+
+ auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM);
+ if (itParam == pFieldmark->GetParameters()->end())
+ {
+ continue;
+ }
+
+ OUString aCommand;
+ itParam->second >>= aCommand;
+ if (!aCommand.startsWith(aFieldCommandPrefix))
+ {
+ continue;
+ }
+
+ if (aFields.getLength() <= nFieldIndex)
+ {
+ continue;
+ }
+
+ comphelper::SequenceAsHashMap aMap(aFields[nFieldIndex++]);
+ itParam->second = aMap["FieldCommand"];
+ SwPaM aPaM(pFieldmark->GetMarkPos(), pFieldmark->GetOtherMarkPos());
+ aPaM.Normalize();
+ // Skip field start & separator.
+ aPaM.GetPoint()->AdjustContent(2);
+ // Skip field end.
+ aPaM.GetMark()->AdjustContent(-1);
+ rSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(aPaM);
+ OUString aFieldResult;
+ aMap["FieldResult"] >>= aFieldResult;
+ SwTranslateHelper::PasteHTMLToPaM(rSh, &aPaM, aFieldResult.toUtf8());
+ }
+
+ rSh.EndAction();
+ rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::UPDATE_FORM_FIELDS, nullptr);
+ }
+ break;
+ case FN_DELETE_TEXT_FORMFIELDS:
+ {
+ // This deletes all fieldmarks that match the provided field type & field command prefix.
+ OUString aFieldType;
+ const SfxStringItem* pFieldType = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if (pFieldType)
+ {
+ aFieldType = pFieldType->GetValue();
+ }
+ OUString aFieldCommandPrefix;
+ const SfxStringItem* pFieldCommandPrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
+ if (pFieldCommandPrefix)
+ {
+ aFieldCommandPrefix = pFieldCommandPrefix->GetValue();
+ }
+ rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::DELETE_FORM_FIELDS, nullptr);
+ rSh.StartAction();
+
+ IDocumentMarkAccess* pMarkAccess = rSh.GetDoc()->getIDocumentMarkAccess();
+ std::vector<sw::mark::IMark*> aRemovals;
+ for (auto it = pMarkAccess->getFieldmarksBegin(); it != pMarkAccess->getFieldmarksEnd(); ++it)
+ {
+ auto pFieldmark = dynamic_cast<sw::mark::IFieldmark*>(*it);
+ assert(pFieldmark);
+ if (pFieldmark->GetFieldname() != aFieldType)
+ {
+ continue;
+ }
+
+ if (!aFieldCommandPrefix.isEmpty())
+ {
+ auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM);
+ if (itParam == pFieldmark->GetParameters()->end())
+ {
+ continue;
+ }
+
+ OUString aCommand;
+ itParam->second >>= aCommand;
+ if (!aCommand.startsWith(aFieldCommandPrefix))
+ {
+ continue;
+ }
+ }
+
+ aRemovals.push_back(pFieldmark);
+ }
+
+ for (const auto& pMark : aRemovals)
+ {
+ pMarkAccess->deleteMark(pMark);
+ }
+
+ rSh.EndAction();
+ rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::DELETE_FORM_FIELDS, nullptr);
+ }
+ break;
+ case FN_PGNUMBER_WIZARD:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ VclPtr<AbstractSwPageNumberDlg> pDlg(
+ pFact->CreateSwPageNumberDlg(GetView().GetFrameWeld()));
+ auto pShell = GetShellPtr();
+
+ const SwPageDesc& rCurrDesc = rSh.GetPageDesc(rSh.GetCurPageDesc());
+ pDlg->SetPageNumberType(rCurrDesc.GetNumType().GetNumberingType());
+
+ pDlg->StartExecuteAsync([pShell, &rSh, pDlg](int nResult) {
+ if ( nResult == RET_OK )
+ {
+ auto rDoc = rSh.GetDoc();
+
+ rSh.LockView(true);
+ rSh.StartAllAction();
+ rSh.SwCursorShell::Push();
+ rDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_PAGE_NUMBER, nullptr);
+
+ const size_t nPageDescIndex = rSh.GetCurPageDesc();
+ const SwPageDesc& rDesc = rSh.GetPageDesc(nPageDescIndex);
+ const bool bHeader = !pDlg->GetPageNumberPosition();
+ const bool bHeaderAlreadyOn = rDesc.GetMaster().GetHeader().IsActive();
+ const bool bFooterAlreadyOn = rDesc.GetMaster().GetFooter().IsActive();
+ const bool bIsSinglePage = rDesc.GetFollow() != &rDesc;
+ const size_t nMirrorPagesNeeded = rDesc.IsFirstShared() ? 2 : 3;
+ const OUString sBookmarkName = OUString::Concat("PageNumWizard_")
+ + (bHeader ? "HEADER" : "FOOTER") + "_" + rDesc.GetName();
+ IDocumentMarkAccess& rIDMA = *rSh.getIDocumentMarkAccess();
+
+ // Allow wizard to be re-run: delete previously wizard-inserted page number.
+ // Try before creating non-shared header: avoid copying ODD bookmark onto EVEN page.
+ IDocumentMarkAccess::const_iterator_t ppMark = rIDMA.findMark(
+ sBookmarkName + OUString::number(rSh.GetVirtPageNum()));
+ if (ppMark != rIDMA.getAllMarksEnd() && *ppMark)
+ {
+ SwPaM aDeleteOldPageNum((*ppMark)->GetMarkStart(), (*ppMark)->GetMarkEnd());
+ rDoc->getIDocumentContentOperations().DeleteAndJoin(aDeleteOldPageNum);
+ }
+
+ SwPageDesc aNewDesc(rDesc);
+ bool bChangePageDesc = false;
+ if (pDlg->GetPageNumberType() != aNewDesc.GetNumType().GetNumberingType())
+ {
+ bChangePageDesc = true;
+ SvxNumberType aNewType(rDesc.GetNumType());
+ aNewType.SetNumberingType(pDlg->GetPageNumberType());
+ aNewDesc.SetNumType(aNewType);
+ }
+
+ // Insert header/footer
+ if ((bHeader && !bHeaderAlreadyOn) || (!bHeader && !bFooterAlreadyOn))
+ {
+ bChangePageDesc = true;
+ SwFrameFormat &rMaster = aNewDesc.GetMaster();
+ if (bHeader)
+ rMaster.SetFormatAttr(SwFormatHeader(/*On=*/true));
+ else
+ rMaster.SetFormatAttr(SwFormatFooter(/*On=*/true));
+
+ // Init copied from ChangeHeaderOrFooter: keep in sync
+ constexpr tools::Long constTwips_5mm = o3tl::toTwips(5, o3tl::Length::mm);
+ const SvxULSpaceItem aUL(bHeader ? 0 : constTwips_5mm,
+ bHeader ? constTwips_5mm : 0,
+ RES_UL_SPACE);
+ const XFillStyleItem aFill(drawing::FillStyle_NONE);
+ SwFrameFormat& rFormat
+ = bHeader
+ ? const_cast<SwFrameFormat&>(*rMaster.GetHeader().GetHeaderFormat())
+ : const_cast<SwFrameFormat&>(*rMaster.GetFooter().GetFooterFormat());
+ rFormat.SetFormatAttr(aUL);
+ rFormat.SetFormatAttr(aFill);
+
+ // Might as well turn on margin mirroring too - if appropriate
+ if (pDlg->GetMirrorOnEvenPages() && !bHeaderAlreadyOn && !bFooterAlreadyOn
+ && !bIsSinglePage
+ && (aNewDesc.ReadUseOn() & UseOnPage::Mirror) == UseOnPage::All)
+ {
+ aNewDesc.WriteUseOn(rDesc.ReadUseOn() | UseOnPage::Mirror);
+ }
+ }
+
+ const bool bCreateMirror = !bIsSinglePage && pDlg->GetMirrorOnEvenPages()
+ && nMirrorPagesNeeded <= rSh.GetPageCnt();
+ if (bCreateMirror)
+ {
+ // Use different left/right header/footer
+ if ((bHeader && rDesc.IsHeaderShared()) || (!bHeader && rDesc.IsFooterShared()))
+ {
+ bChangePageDesc = true;
+ if (bHeader)
+ aNewDesc.ChgHeaderShare(/*Share=*/false);
+ else
+ aNewDesc.ChgFooterShare(/*Share=*/false);
+ }
+ }
+
+ if (bChangePageDesc)
+ rSh.ChgPageDesc(nPageDescIndex, aNewDesc);
+
+ // Go to the header or footer insert position
+ bool bInHF = false;
+ bool bSkipMirror = true;
+ size_t nEvenPage = 0;
+ if (bCreateMirror || !rSh.GetCurrFrame())
+ {
+ // Come here if Currframe can't be found, otherwise Goto*Text will crash.
+ // Get*PageNum will also be invalid (0), so we have no idea where we are.
+ // (Since not asking for mirror, the likelihood is that the bHeader is shared,
+ // in which case it doesn't matter anyway, and we just hope for the best.)
+ // Read the code in this block assuming that bCreateMirror is true.
+
+ // There are enough pages that there probably is a valid odd page.
+ // However, that is not guaranteed: perhaps the page style switched,
+ // or a blank page was forced, or some other complexity.
+ bInHF = rSh.SetCursorInHdFt(nPageDescIndex, bHeader, /*Even=*/true);
+ if (bInHF)
+ {
+ // Remember valid EVEN page. Mirror it if also a valid ODD or FIRST page
+ nEvenPage = rSh.GetVirtPageNum();
+ assert (nEvenPage && "couldn't find page number. Use a bool instead");
+ }
+
+ bInHF = rSh.SetCursorInHdFt(nPageDescIndex, bHeader, /*Even=*/false);
+ if (bInHF && nEvenPage)
+ {
+ // Even though the cursor may be on a FIRST page,
+ // the user requested mirrored pages, and we have both ODD and EVEN,
+ // so set page numbers on these two pages, and leave FIRST alone.
+ bSkipMirror = false;
+ }
+ if (!bInHF)
+ {
+ // no ODD page, look for FIRST page
+ bInHF = rSh.SetCursorInHdFt(nPageDescIndex, bHeader, false, /*First=*/true);
+ if (bInHF && nEvenPage)
+ {
+ // Unlikely but valid situation: EVEN and FIRST pages, but no ODD page.
+ // In this case, the first header gets the specified page number
+ // and the even header is mirrored, with an empty odd header,
+ // as the user (somewhat) requested.
+ bSkipMirror = false;
+ }
+ }
+ assert((bInHF || nEvenPage) && "Impossible - why couldn't the move happen?");
+ assert((bInHF || nEvenPage == rSh.GetVirtPageNum()) && "Unexpected move");
+ }
+ else
+ {
+ if (bHeader)
+ bInHF = rSh.GotoHeaderText();
+ else
+ bInHF = rSh.GotoFooterText();
+ assert(bInHF && "shouldn't have a problem going to text when no mirroring");
+ }
+
+ // Allow wizard to be re-run: delete previously wizard-inserted page number.
+ // Now that the cursor may have moved to a different page, try delete again.
+ ppMark = rIDMA.findMark(sBookmarkName + OUString::number(rSh.GetVirtPageNum()));
+ if (ppMark != rIDMA.getAllMarksEnd() && *ppMark)
+ {
+ SwPaM aDeleteOldPageNum((*ppMark)->GetMarkStart(), (*ppMark)->GetMarkEnd());
+ rDoc->getIDocumentContentOperations().DeleteAndJoin(aDeleteOldPageNum);
+ }
+
+ SwTextNode* pTextNode = rSh.GetCursor()->GetPoint()->GetNode().GetTextNode();
+
+ // Insert new line if there is already text in header/footer
+ if (pTextNode && !pTextNode->GetText().isEmpty())
+ {
+ rDoc->getIDocumentContentOperations().SplitNode(*rSh.GetCursor()->GetPoint(), false);
+
+ // Go back to start of header/footer
+ if (bHeader)
+ rSh.GotoHeaderText();
+ else
+ rSh.GotoFooterText();
+ }
+
+ // Set alignment for the new line
+ switch (pDlg->GetPageNumberAlignment())
+ {
+ case 0:
+ {
+ SvxAdjustItem aAdjustItem(SvxAdjust::Left, RES_PARATR_ADJUST);
+ rSh.SetAttrItem(aAdjustItem);
+ break;
+ }
+ case 1:
+ {
+ SvxAdjustItem aAdjustItem(SvxAdjust::Center, RES_PARATR_ADJUST);
+ rSh.SetAttrItem(aAdjustItem);
+ break;
+ }
+ case 2:
+ {
+ SvxAdjustItem aAdjustItem(SvxAdjust::Right, RES_PARATR_ADJUST);
+ rSh.SetAttrItem(aAdjustItem);
+ break;
+ }
+ }
+
+ sal_Int32 nStartContentIndex = rSh.GetCursor()->Start()->GetContentIndex();
+ assert(!nStartContentIndex && "earlier split node if not empty, but not zero?");
+
+ // Insert page number
+ SwFieldMgr aMgr(pShell);
+ SwInsertField_Data aData(SwFieldTypesEnum::PageNumber, 0,
+ OUString(), OUString(), SVX_NUM_PAGEDESC);
+ aMgr.InsertField(aData);
+ if (pDlg->GetIncludePageTotal())
+ {
+ rDoc->getIDocumentContentOperations().InsertString(*rSh.GetCursor(), " / ");
+ SwInsertField_Data aPageTotalData(SwFieldTypesEnum::DocumentStatistics, DS_PAGE,
+ OUString(), OUString(), SVX_NUM_PAGEDESC);
+ aMgr.InsertField(aPageTotalData);
+ }
+
+ // Mark inserted fields with a bookmark - so it can be found/removed if re-run
+ SwPaM aNewBookmarkPaM(*rSh.GetCursor()->Start());
+ aNewBookmarkPaM.SetMark();
+ assert(aNewBookmarkPaM.GetPointContentNode() && "only SetContent on content node");
+ aNewBookmarkPaM.Start()->SetContent(nStartContentIndex);
+ rIDMA.makeMark(aNewBookmarkPaM,
+ sBookmarkName + OUString::number(rSh.GetVirtPageNum()),
+ IDocumentMarkAccess::MarkType::BOOKMARK,
+ sw::mark::InsertMode::New);
+
+ // Mirror on the even pages
+ if (!bSkipMirror && bCreateMirror
+ && rSh.SetCursorInHdFt(nPageDescIndex, bHeader, /*Even=*/true))
+ {
+ assert(nEvenPage && "what? no even page and yet we got here?");
+ ppMark = rIDMA.findMark(sBookmarkName + OUString::number(rSh.GetVirtPageNum()));
+ if (ppMark != rIDMA.getAllMarksEnd() && *ppMark)
+ {
+ SwPaM aDeleteOldPageNum((*ppMark)->GetMarkStart(), (*ppMark)->GetMarkEnd());
+ rDoc->getIDocumentContentOperations().DeleteAndJoin(aDeleteOldPageNum);
+ }
+
+ pTextNode = rSh.GetCursor()->GetPoint()->GetNode().GetTextNode();
+
+ // Insert new line if there is already text in header/footer
+ if (pTextNode && !pTextNode->GetText().isEmpty())
+ {
+ rDoc->getIDocumentContentOperations().SplitNode(
+ *rSh.GetCursor()->GetPoint(), false);
+ // Go back to start of header/footer
+ rSh.SetCursorInHdFt(nPageDescIndex, bHeader, /*Even=*/true);
+ }
+
+ // mirror the adjustment
+ assert(pDlg->GetPageNumberAlignment() != 1 && "cannot have Center and bMirror");
+ SvxAdjust eAdjust = SvxAdjust::Left;
+ if (!pDlg->GetPageNumberAlignment())
+ eAdjust = SvxAdjust::Right;
+ SvxAdjustItem aMirrorAdjustItem(eAdjust, RES_PARATR_ADJUST);
+ rSh.SetAttrItem(aMirrorAdjustItem);
+
+ nStartContentIndex = rSh.GetCursor()->Start()->GetContentIndex();
+
+ // Insert page number
+ SwFieldMgr aEvenMgr(pShell);
+ aEvenMgr.InsertField(aData);
+ if (pDlg->GetIncludePageTotal())
+ {
+ rDoc->getIDocumentContentOperations().InsertString(*rSh.GetCursor(), " / ");
+ SwInsertField_Data aPageTotalData(SwFieldTypesEnum::DocumentStatistics,
+ DS_PAGE, OUString(), OUString(),
+ SVX_NUM_PAGEDESC);
+ aMgr.InsertField(aPageTotalData);
+ }
+
+ // Mark inserted fields with a bookmark - so it can be found/removed if re-run
+ SwPaM aNewEvenBookmarkPaM(*rSh.GetCursor()->Start());
+ aNewEvenBookmarkPaM.SetMark();
+ aNewEvenBookmarkPaM.Start()->SetContent(nStartContentIndex);
+ rIDMA.makeMark(aNewEvenBookmarkPaM,
+ sBookmarkName + OUString::number(rSh.GetVirtPageNum()),
+ IDocumentMarkAccess::MarkType::BOOKMARK,
+ sw::mark::InsertMode::New);
+ }
+
+ rSh.SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent);
+ rSh.EndAllAction();
+ rSh.LockView(false);
+ rDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_PAGE_NUMBER, nullptr);
+ }
+ pDlg->disposeOnce();
+ });
+ rReq.Done();
+ }
+ break;
+ case FN_UPDATE_TEXT_FORMFIELD:
+ {
+ // This updates a single fieldmark under the current cursor.
+ OUString aFieldType;
+ const SfxStringItem* pFieldType = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if (pFieldType)
+ {
+ aFieldType = pFieldType->GetValue();
+ }
+ OUString aFieldCommandPrefix;
+ const SfxStringItem* pFieldCommandPrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
+ if (pFieldCommandPrefix)
+ {
+ aFieldCommandPrefix = pFieldCommandPrefix->GetValue();
+ }
+ uno::Sequence<beans::PropertyValue> aField;
+ const SfxUnoAnyItem* pFields = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_3);
+ if (pFields)
+ {
+ pFields->GetValue() >>= aField;
+ }
+
+ IDocumentMarkAccess& rIDMA = *rSh.getIDocumentMarkAccess();
+ SwPosition& rCursor = *rSh.GetCursor()->GetPoint();
+ sw::mark::IFieldmark* pFieldmark = rIDMA.getInnerFieldmarkFor(rCursor);
+ if (!pFieldmark)
+ {
+ break;
+ }
+
+ if (pFieldmark->GetFieldname() != aFieldType)
+ {
+ break;
+ }
+
+ auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM);
+ if (itParam == pFieldmark->GetParameters()->end())
+ {
+ break;
+ }
+
+ OUString aCommand;
+ itParam->second >>= aCommand;
+ if (!aCommand.startsWith(aFieldCommandPrefix))
+ {
+ break;
+ }
+
+ rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::UPDATE_FORM_FIELD, nullptr);
+ rSh.StartAction();
+ comphelper::SequenceAsHashMap aMap(aField);
+ itParam->second = aMap["FieldCommand"];
+ SwPaM aPaM(pFieldmark->GetMarkPos(), pFieldmark->GetOtherMarkPos());
+ aPaM.Normalize();
+ // Skip field start & separator.
+ aPaM.GetPoint()->AdjustContent(2);
+ // Skip field end.
+ aPaM.GetMark()->AdjustContent(-1);
+ rSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(aPaM);
+ OUString aFieldResult;
+ aMap["FieldResult"] >>= aFieldResult;
+ SwTranslateHelper::PasteHTMLToPaM(rSh, &aPaM, aFieldResult.toUtf8());
+
+ rSh.EndAction();
+ rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::UPDATE_FORM_FIELD, nullptr);
+ }
+ break;
+ default:
+ OSL_FAIL("wrong dispatcher");
+ return;
+ }
+}
+
+void SwTextShell::StateField( SfxItemSet &rSet )
+{
+ SwWrtShell& rSh = GetShell();
+ SfxWhichIter aIter( rSet );
+ const SwField* pField = nullptr;
+ bool bGetField = false;
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while (nWhich)
+ {
+ switch (nWhich)
+ {
+ case FN_DELETE_COMMENT:
+ case FN_DELETE_NOTE_AUTHOR:
+ case FN_DELETE_ALL_NOTES:
+ case FN_FORMAT_ALL_NOTES:
+ case FN_HIDE_NOTE:
+ case FN_HIDE_NOTE_AUTHOR:
+ case FN_HIDE_ALL_NOTES:
+ {
+ SwPostItMgr* pPostItMgr = GetView().GetPostItMgr();
+ if ( !pPostItMgr )
+ rSet.InvalidateItem( nWhich );
+ else if ( !pPostItMgr->HasActiveSidebarWin() )
+ {
+ rSet.InvalidateItem( FN_DELETE_COMMENT );
+ rSet.InvalidateItem( FN_HIDE_NOTE );
+ }
+ // tdf#137568 do not offer comment formatting, if no comments are present
+ if (!pPostItMgr || !pPostItMgr->HasNotes())
+ rSet.DisableItem( FN_FORMAT_ALL_NOTES );
+ }
+ break;
+
+ case FN_EDIT_FIELD:
+ {
+ if( !bGetField )
+ {
+ pField = rSh.GetCurField(true);
+ bGetField = true;
+ }
+
+ SwFieldIds nTempWhich = pField ? pField->GetTyp()->Which() : SwFieldIds::Unknown;
+ if( SwFieldIds::Unknown == nTempWhich ||
+ SwFieldIds::Postit == nTempWhich ||
+ SwFieldIds::Script == nTempWhich ||
+ SwFieldIds::TableOfAuthorities == nTempWhich )
+ rSet.DisableItem( nWhich );
+ else if( SwFieldIds::Dde == nTempWhich &&
+ !static_cast<SwDDEFieldType*>(pField->GetTyp())->GetBaseLink().IsVisible())
+ {
+ // nested links cannot be edited
+ rSet.DisableItem( nWhich );
+ }
+ }
+ break;
+
+ case FN_UPDATE_SEL_FIELD:
+ {
+ pField = rSh.GetCurField();
+
+ if (!pField)
+ rSet.DisableItem( nWhich );
+ }
+
+ break;
+
+ case FN_EXECUTE_MACROFIELD:
+ {
+ if(!bGetField)
+ {
+ pField = rSh.GetCurField();
+ bGetField = true;
+ }
+ if(!pField || pField->GetTyp()->Which() != SwFieldIds::Macro)
+ rSet.DisableItem(nWhich);
+ }
+ break;
+
+ case FN_INSERT_FIELD:
+ {
+ if ( rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ else
+ {
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+ //#i5788# prevent closing of the field dialog while a modal dialog ( Input field dialog ) is active
+ if(!rVFrame.IsInModalMode() &&
+ rVFrame.KnowsChildWindow(FN_INSERT_FIELD) && !rVFrame.HasChildWindow(FN_INSERT_FIELD_DATA_ONLY) )
+ rSet.Put(SfxBoolItem( FN_INSERT_FIELD, rVFrame.HasChildWindow(nWhich)));
+ else
+ rSet.DisableItem(FN_INSERT_FIELD);
+ }
+ }
+ break;
+
+ case FN_INSERT_REF_FIELD:
+ {
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+ if ( !rVFrame.KnowsChildWindow(FN_INSERT_FIELD)
+ || rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem(FN_INSERT_REF_FIELD);
+ }
+ }
+ break;
+
+ case FN_INSERT_FIELD_CTRL:
+ if ( rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ else
+ {
+ rSet.Put(SfxBoolItem( nWhich, GetView().GetViewFrame().HasChildWindow(FN_INSERT_FIELD)));
+ }
+ break;
+
+ case FN_REDLINE_COMMENT:
+ if (!comphelper::LibreOfficeKit::isActive() && !rSh.GetCurrRedline())
+ rSet.DisableItem(nWhich);
+ break;
+
+ case FN_REPLY:
+ if (!comphelper::LibreOfficeKit::isActive())
+ rSet.DisableItem(nWhich);
+ break;
+
+ case FN_POSTIT :
+ case FN_JAVAEDIT :
+ {
+ bool bCurField = false;
+ pField = rSh.GetCurField();
+ if(nWhich == FN_POSTIT)
+ bCurField = pField && pField->GetTyp()->Which() == SwFieldIds::Postit;
+ else
+ bCurField = pField && pField->GetTyp()->Which() == SwFieldIds::Script;
+
+ if( !bCurField && rSh.IsReadOnlyAvailable() && rSh.HasReadonlySel() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ else if ( rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ // tdf#86188, tdf#135794: Allow disabling comment insertion
+ // on footnote/endnote/header/frames for better OOXML interoperability
+ else if (!officecfg::Office::Compatibility::View::AllowCommentsInFootnotes::get() &&
+ (rSh.IsCursorInFootnote() || rSh.IsInHeaderFooter() ||
+ rSh.GetCurrFlyFrame(/*bCalcFrame=*/false)))
+ {
+ rSet.DisableItem(nWhich);
+ }
+ }
+
+ break;
+
+ case FN_INSERT_FLD_AUTHOR:
+ case FN_INSERT_FLD_DATE:
+ case FN_INSERT_FLD_PGCOUNT:
+ case FN_INSERT_FLD_PGNUMBER:
+ case FN_INSERT_FLD_TIME:
+ case FN_INSERT_FLD_TITLE:
+ case FN_INSERT_FLD_TOPIC:
+ case FN_INSERT_DBFIELD:
+ if ( rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ break;
+
+ case FN_INSERT_TEXT_FORMFIELD:
+ case FN_INSERT_CHECKBOX_FORMFIELD:
+ case FN_INSERT_DROPDOWN_FORMFIELD:
+ case FN_INSERT_DATE_FORMFIELD:
+ if ( rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ else
+ {
+ // Check whether we are in a text form field
+ SwPosition aCursorPos(*rSh.GetCursor()->GetPoint());
+ sw::mark::IFieldmark* pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aCursorPos);
+ if ((!pFieldBM || pFieldBM->GetFieldname() != ODF_FORMTEXT)
+ && aCursorPos.GetContentIndex() > 0)
+ {
+ SwPosition aPos(*aCursorPos.GetContentNode(), aCursorPos.GetContentIndex() - 1);
+ pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos);
+ }
+ if (pFieldBM && pFieldBM->GetFieldname() == ODF_FORMTEXT &&
+ (aCursorPos > pFieldBM->GetMarkStart() && aCursorPos < pFieldBM->GetMarkEnd() ))
+ {
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwTextShell::InsertHyperlink(const SvxHyperlinkItem& rHlnkItem)
+{
+ const OUString& rName = rHlnkItem.GetName();
+ const OUString& rURL = rHlnkItem.GetURL();
+ const OUString& rTarget = rHlnkItem.GetTargetFrame();
+ const OUString& rReplacementText = rHlnkItem.GetReplacementText();
+ sal_uInt16 nType = o3tl::narrowing<sal_uInt16>(rHlnkItem.GetInsertMode());
+ nType &= ~HLINK_HTMLMODE;
+ const SvxMacroTableDtor* pMacroTable = rHlnkItem.GetMacroTable();
+
+ SwWrtShell& rSh = GetShell();
+
+ if( !(rSh.GetSelectionType() & SelectionType::Text) )
+ return;
+
+ rSh.StartAction();
+ SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
+ rSh.GetCurAttr( aSet );
+
+ if(SfxItemState::SET == aSet.GetItemState(RES_TXTATR_INETFMT, false))
+ {
+ // Select links
+ rSh.SwCursorShell::SelectTextAttr(RES_TXTATR_INETFMT, false);
+ }
+ switch (nType)
+ {
+ case HLINK_DEFAULT:
+ case HLINK_FIELD:
+ {
+ SwFormatINetFormat aINetFormat( rURL, rTarget );
+ aINetFormat.SetName(rHlnkItem.GetIntName());
+ if(pMacroTable)
+ {
+ const SvxMacro *pMacro = pMacroTable->Get( SvMacroItemId::OnMouseOver );
+ if( pMacro )
+ aINetFormat.SetMacro(SvMacroItemId::OnMouseOver, *pMacro);
+ pMacro = pMacroTable->Get( SvMacroItemId::OnClick );
+ if( pMacro )
+ aINetFormat.SetMacro(SvMacroItemId::OnClick, *pMacro);
+ pMacro = pMacroTable->Get( SvMacroItemId::OnMouseOut );
+ if( pMacro )
+ aINetFormat.SetMacro(SvMacroItemId::OnMouseOut, *pMacro);
+ }
+ rSh.SttSelect();
+ // inserting mention
+ if (comphelper::LibreOfficeKit::isActive() && !rReplacementText.isEmpty())
+ {
+ SwPaM* pCursorPos = rSh.GetCursor();
+ // move cursor backwards to select @mention
+ for(int i=0; i < rReplacementText.getLength(); i++)
+ pCursorPos->Move(fnMoveBackward);
+ rSh.InsertURL( aINetFormat, rName, false );
+ }
+ else
+ {
+ rSh.InsertURL( aINetFormat, rName, true );
+ }
+ rSh.EndSelect();
+ }
+ break;
+
+ case HLINK_BUTTON:
+ bool bSel = rSh.HasSelection();
+ if(bSel)
+ rSh.DelRight();
+ InsertURLButton( rURL, rTarget, rName );
+ rSh.EnterStdMode();
+ break;
+ }
+ rSh.EndAction();
+}
+
+IMPL_LINK( SwTextShell, RedlineNextHdl, AbstractSvxPostItDialog&, rDlg, void )
+{
+ SwWrtShell* pSh = GetShellPtr();
+
+ // Insert or change a comment.
+ pSh->SetRedlineComment(rDlg.GetNote());
+
+ const SwRangeRedline *pRedline = pSh->GetCurrRedline();
+
+ if (!pRedline)
+ return;
+
+ // Traveling only if more than one field.
+ if( !pSh->IsCursorPtAtEnd() )
+ pSh->SwapPam(); // Move the cursor behind the Redline.
+
+ pSh->Push();
+ const SwRangeRedline *pActRed = pSh->SelNextRedline();
+ pSh->Pop((pActRed != nullptr) ? SwCursorShell::PopMode::DeleteStack : SwCursorShell::PopMode::DeleteCurrent);
+
+ bool bEnable = false;
+
+ if (pActRed)
+ {
+ pSh->StartAction();
+ pSh->Push();
+ bEnable = pSh->SelNextRedline() != nullptr;
+ pSh->Pop(SwCursorShell::PopMode::DeleteCurrent);
+ pSh->EndAction();
+ }
+
+ rDlg.EnableTravel(bEnable, true);
+
+ if( pSh->IsCursorPtAtEnd() )
+ pSh->SwapPam();
+
+ pRedline = pSh->GetCurrRedline();
+ OUString sComment = convertLineEnd(pRedline->GetComment(), GetSystemLineEnd());
+
+ rDlg.SetNote(sComment);
+ rDlg.ShowLastAuthor( pRedline->GetAuthorString(),
+ GetAppLangDateTimeString(
+ pRedline->GetRedlineData().GetTimeStamp() ));
+
+ rDlg.SetText(lcl_BuildTitleWithRedline(pRedline));
+
+}
+
+IMPL_LINK( SwTextShell, RedlinePrevHdl, AbstractSvxPostItDialog&, rDlg, void )
+{
+ SwWrtShell* pSh = GetShellPtr();
+
+ // Insert or change a comment.
+ pSh->SetRedlineComment(rDlg.GetNote());
+
+ const SwRangeRedline *pRedline = pSh->GetCurrRedline();
+
+ if (!pRedline)
+ return;
+
+ // Traveling only if more than one field.
+ pSh->Push();
+ const SwRangeRedline *pActRed = pSh->SelPrevRedline();
+ pSh->Pop((pActRed != nullptr) ? SwCursorShell::PopMode::DeleteStack : SwCursorShell::PopMode::DeleteCurrent);
+
+ bool bEnable = false;
+
+ if (pActRed)
+ {
+ pSh->StartAction();
+ pSh->Push();
+ bEnable = pSh->SelPrevRedline() != nullptr;
+ pSh->Pop(SwCursorShell::PopMode::DeleteCurrent);
+ pSh->EndAction();
+ }
+
+ rDlg.EnableTravel(true, bEnable);
+
+ pRedline = pSh->GetCurrRedline();
+ OUString sComment = convertLineEnd(pRedline->GetComment(), GetSystemLineEnd());
+
+ rDlg.SetNote(sComment);
+ rDlg.ShowLastAuthor(pRedline->GetAuthorString(),
+ GetAppLangDateTimeString(
+ pRedline->GetRedlineData().GetTimeStamp() ));
+
+ rDlg.SetText(lcl_BuildTitleWithRedline(pRedline));
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/textglos.cxx b/sw/source/uibase/shells/textglos.cxx
new file mode 100644
index 0000000000..d229964d20
--- /dev/null
+++ b/sw/source/uibase/shells/textglos.cxx
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/request.hxx>
+#include <svl/eitem.hxx>
+#include <svl/stritem.hxx>
+#include <osl/diagnose.h>
+
+#include <view.hxx>
+#include <cmdid.h>
+#include <textsh.hxx>
+#include <initui.hxx>
+#include <gloshdl.hxx>
+#include <glosdoc.hxx>
+#include <gloslst.hxx>
+#include <swabstdlg.hxx>
+
+void SwTextShell::ExecGlossary(SfxRequest &rReq)
+{
+ const sal_uInt16 nSlot = rReq.GetSlot();
+ ::GetGlossaries()->UpdateGlosPath(!rReq.IsAPI() ||
+ FN_GLOSSARY_DLG == nSlot );
+ SwGlossaryHdl* pGlosHdl = GetView().GetGlosHdl();
+ // Update SwGlossaryList?
+ bool bUpdateList = false;
+
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem = nullptr;
+ if(pArgs)
+ pArgs->GetItemState(nSlot, false, &pItem );
+
+ switch( nSlot )
+ {
+ case FN_GLOSSARY_DLG:
+ pGlosHdl->GlossaryDlg();
+ bUpdateList = true;
+ rReq.Ignore();
+ break;
+ case FN_EXPAND_GLOSSARY:
+ {
+ bool bReturn;
+ bReturn = pGlosHdl->ExpandGlossary(rReq.GetFrameWeld());
+ rReq.SetReturnValue( SfxBoolItem( nSlot, bReturn ) );
+ rReq.Done();
+ }
+ break;
+ case FN_NEW_GLOSSARY:
+ if(pItem && pArgs->Count() == 3 )
+ {
+ OUString aGroup = static_cast<const SfxStringItem *>(pItem)->GetValue();
+ OUString aName;
+ if(SfxItemState::SET == pArgs->GetItemState(FN_PARAM_1, false, &pItem ))
+ aName = static_cast<const SfxStringItem *>(pItem)->GetValue();
+ OUString aShortName;
+ if(SfxItemState::SET == pArgs->GetItemState(FN_PARAM_2, false, &pItem ))
+ aShortName = static_cast<const SfxStringItem *>(pItem)->GetValue();
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ::GlossarySetActGroup fnSetActGroup = pFact->SetGlossaryActGroupFunc();
+ if ( fnSetActGroup )
+ (*fnSetActGroup)( aGroup );
+ pGlosHdl->SetCurGroup(aGroup, true);
+ // Chosen group must be created in NewGlossary if necessary!
+ pGlosHdl->NewGlossary( aName, aShortName, true );
+ rReq.Done();
+ }
+ bUpdateList = true;
+ break;
+ case FN_SET_ACT_GLOSSARY:
+ if(pItem)
+ {
+ OUString aGroup = static_cast<const SfxStringItem *>(pItem)->GetValue();
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ::GlossarySetActGroup fnSetActGroup = pFact->SetGlossaryActGroupFunc();
+ if ( fnSetActGroup )
+ (*fnSetActGroup)( aGroup );
+ rReq.Done();
+ }
+ break;
+ case FN_INSERT_GLOSSARY:
+ {
+ if(pItem && pArgs->Count() > 1)
+ {
+ OUString aGroup = static_cast<const SfxStringItem *>(pItem)->GetValue();
+ OUString aName;
+ if(SfxItemState::SET == pArgs->GetItemState(FN_PARAM_1, false, &pItem ))
+ aName = static_cast<const SfxStringItem *>(pItem)->GetValue();
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ::GlossarySetActGroup fnSetActGroup = pFact->SetGlossaryActGroupFunc();
+ if ( fnSetActGroup )
+ (*fnSetActGroup)( aGroup );
+ pGlosHdl->SetCurGroup(aGroup, true);
+ rReq.SetReturnValue(SfxBoolItem(nSlot, pGlosHdl->InsertGlossary( aName )));
+ rReq.Done();
+ }
+ }
+ break;
+ default:
+ OSL_FAIL("wrong dispatcher");
+ return;
+ }
+ if(bUpdateList)
+ {
+ SwGlossaryList* pList = ::GetGlossaryList();
+ if(pList->IsActive())
+ pList->Update();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/textidx.cxx b/sw/source/uibase/shells/textidx.cxx
new file mode 100644
index 0000000000..35642a73f1
--- /dev/null
+++ b/sw/source/uibase/shells/textidx.cxx
@@ -0,0 +1,324 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/eitem.hxx>
+#include <editeng/sizeitem.hxx>
+#include <osl/diagnose.h>
+#include <fmtfsize.hxx>
+#include <fldbas.hxx>
+#include <uiitems.hxx>
+#include <viewopt.hxx>
+#include <cmdid.h>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <textsh.hxx>
+#include <idxmrk.hxx>
+#include <toxmgr.hxx>
+#include <swabstdlg.hxx>
+
+#include <ndtxt.hxx>
+#include <fmtfld.hxx>
+#include <IDocumentFieldsAccess.hxx>
+
+void SwTextShell::ExecIdx(SfxRequest const &rReq)
+{
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem = nullptr;
+ const sal_uInt16 nSlot = rReq.GetSlot();
+ if (pArgs)
+ pArgs->GetItemState(nSlot, false, &pItem);
+
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+
+ switch (nSlot)
+ {
+ case FN_EDIT_AUTH_ENTRY_DLG:
+ {
+ SwWrtShell& rShell = GetShell();
+
+ const bool bWasViewLocked = rShell.IsViewLocked();
+ rShell.LockView(true);
+
+ if (const SwField* const pCurrentField = rShell.GetCurField();
+ !rShell.HasReadonlySel() && pCurrentField != nullptr
+ && pCurrentField->GetTyp()->Which() == SwFieldIds::TableOfAuthorities)
+ {
+ // Since the cursor is on a bibliography mark (e.g. "[1]"), open the edit dialog as usual
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(
+ pFact->CreateSwAutoMarkDialog(GetView().GetFrameWeld(), rShell));
+ pDlg->Execute();
+ }
+ else if (const SwTOXBase* const pCurrentTOX = rShell.GetCurTOX();
+ pCurrentTOX != nullptr && pCurrentTOX->GetType() == TOX_AUTHORITIES
+ && (rShell.GetCursor()->GetPoint()->GetNode()
+ .FindSectionNode()->GetSection().GetType()
+ == SectionType::ToxContent))
+ {
+ // Since the cursor is in the bibliography table, find the first mark that would match the given row
+ const SwNode* const pTableRowNode = &rShell.GetCursor()->GetPoint()->GetNode();
+ const OUString& rTableRowText
+ = static_cast<const SwTextNode*>(pTableRowNode)->GetText();
+
+ const SwFieldType* pAuthField
+ = rShell.GetDoc()->getIDocumentFieldsAccess().GetFieldType(
+ SwFieldIds::TableOfAuthorities, OUString(), false);
+
+ if (pAuthField)
+ {
+ bool bMatchingMarkFound = false;
+ {
+ std::vector<SwFormatField*> vFields;
+ pAuthField->GatherFields(vFields);
+ for (auto pFormatField : vFields)
+ {
+ if (const SwField* pIteratedField = nullptr;
+ pFormatField != nullptr
+ && (pIteratedField = pFormatField->GetField()) != nullptr
+ && (pIteratedField->GetTyp()->Which()
+ == SwFieldIds::TableOfAuthorities))
+ {
+ OUString sMarkText
+ = static_cast<const SwAuthorityField*>(pIteratedField)
+ ->GetAuthority(rShell.GetLayout(),
+ &pCurrentTOX->GetTOXForm());
+
+ if (sMarkText == rTableRowText)
+ {
+ // Since the text generated from the mark would match the given row
+ // move cursor to it, set bMatchingMarkFound and break
+ rShell.GotoFormatField(*pFormatField);
+ bMatchingMarkFound = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (bMatchingMarkFound)
+ {
+ // Since matching mark has been found and cursor has been moved to it,
+ // open the edit dialog
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(
+ pFact->CreateSwAutoMarkDialog(GetView().GetFrameWeld(), rShell));
+ pDlg->Execute();
+
+ // Refresh TOX
+ rShell.GetCursor_()->GetPoint()->Assign(*pTableRowNode);
+ rShell.UpdateTableOf(*pCurrentTOX);
+ }
+ else
+ {
+ // I think this ideally should be a pop-up warning, right?
+ SAL_WARN("sw", "No matching bibliography mark found. "
+ "This feature is only guaranteed to work if the bibliography table is up to date.");
+ }
+ }
+ }
+
+ if (!bWasViewLocked)
+ rShell.LockView(false);
+ }
+ break;
+ case FN_INSERT_AUTH_ENTRY_DLG:
+ {
+ // no BASIC support
+ rVFrame.ToggleChildWindow(FN_INSERT_AUTH_ENTRY_DLG);
+ Invalidate(rReq.GetSlot());
+ }
+ break;
+ case FN_INSERT_IDX_ENTRY_DLG:
+ {
+ rVFrame.ToggleChildWindow(FN_INSERT_IDX_ENTRY_DLG);
+ Invalidate(rReq.GetSlot());
+ }
+ break;
+ case FN_EDIT_IDX_ENTRY_DLG:
+ {
+ SwTOXMgr aMgr(GetShellPtr());
+ short nRet = RET_OK;
+ if(aMgr.GetTOXMarkCount() > 1)
+ { // Several marks, which should it be?
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pMultDlg(pFact->CreateMultiTOXMarkDlg(GetView().GetFrameWeld(), aMgr));
+ nRet = pMultDlg->Execute();
+ }
+ if( nRet == RET_OK)
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateIndexMarkModalDlg(GetView().GetFrameWeld(), GetShell(), aMgr.GetCurTOXMark()));
+ pDlg->Execute();
+ }
+ break;
+ }
+ case FN_IDX_MARK_TO_IDX:
+ {
+ GetShell().GotoTOXMarkBase();
+ break;
+ }
+ case FN_INSERT_MULTI_TOX:
+ {
+ SfxItemSetFixed<
+ RES_FRM_SIZE, RES_FRM_SIZE,
+ RES_LR_SPACE, RES_LR_SPACE,
+ RES_BACKGROUND, RES_BACKGROUND,
+ RES_COL, RES_COL,
+ XATTR_FILL_FIRST, XATTR_FILL_LAST,
+ SID_ATTR_PAGE_SIZE, SID_ATTR_PAGE_SIZE,
+ FN_PARAM_TOX_TYPE, FN_PARAM_TOX_TYPE> aSet( GetPool() );
+ SwWrtShell& rSh = GetShell();
+ SwRect aRect;
+ rSh.CalcBoundRect(aRect, RndStdIds::FLY_AS_CHAR);
+
+ tools::Long nWidth = aRect.Width();
+ aSet.Put(SwFormatFrameSize(SwFrameSize::Variable, nWidth));
+ // Height = width for a more consistent preview (analogous to edit range)
+ aSet.Put(SvxSizeItem(SID_ATTR_PAGE_SIZE, Size(nWidth, nWidth)));
+ const SwTOXBase* pCurTOX = nullptr;
+ bool bGlobal = false;
+ if(pItem)
+ {
+ pCurTOX = static_cast<const SwTOXBase*>(static_cast<const SwPtrItem*>(pItem)->GetValue());
+ bGlobal = true;
+ }
+ else
+ pCurTOX = rSh.GetCurTOX();
+ if(pCurTOX)
+ {
+ const SfxItemSet* pSet = pCurTOX->GetAttrSet();
+ if(pSet)
+ aSet.Put(*pSet);
+ }
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ VclPtr<AbstractMultiTOXTabDialog> pDlg(pFact->CreateMultiTOXTabDialog(
+ GetView().GetFrameWeld(), aSet, rSh, const_cast<SwTOXBase*>(pCurTOX),
+ bGlobal));
+ pDlg->StartExecuteAsync([pDlg](sal_Int32 /*nResult*/){
+ pDlg->disposeOnce();
+ });
+ }
+ break;
+ case FN_REMOVE_CUR_TOX:
+ {
+ SwWrtShell& rSh = GetShell();
+ const SwTOXBase* pBase = rSh.GetCurTOX();
+ OSL_ENSURE(pBase, "no TOXBase to remove");
+ if( pBase )
+ rSh.DeleteTOX(*pBase, true);
+ }
+ break;
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ return;
+ }
+}
+
+void SwTextShell::GetIdxState(SfxItemSet &rSet)
+{
+ SwWrtShell& rSh = GetShell();
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+ SwInsertIdxMarkWrapper *pIdxMrk = static_cast<SwInsertIdxMarkWrapper*>(
+ rVFrame.GetChildWindow(FN_INSERT_IDX_ENTRY_DLG));
+
+ SfxChildWindow* pAuthMark = rVFrame.GetChildWindow(FN_INSERT_AUTH_ENTRY_DLG);
+
+ const bool bHtmlMode = 0 != ::GetHtmlMode( GetView().GetDocShell() );
+ const SwTOXBase* pBase = nullptr;
+ if( bHtmlMode || nullptr != ( pBase = rSh.GetCurTOX()) )
+ {
+ if( pBase )
+ {
+ if(pBase->IsTOXBaseInReadonly())
+ {
+ rSet.DisableItem( FN_INSERT_MULTI_TOX );
+ }
+ }
+
+ rSet.DisableItem( FN_EDIT_IDX_ENTRY_DLG );
+ if(pBase == nullptr // tdf#72955: Hide the "Bibliography Entry" command if there is no TOX in the selection
+ || pBase->GetType() != TOX_AUTHORITIES // or if it is not a bibliography table
+ || (rSh.GetCursor()->GetPoint()->GetNode().FindSectionNode()->GetSection().GetType() != SectionType::ToxContent)) // or if it's the heading
+ rSet.DisableItem(FN_EDIT_AUTH_ENTRY_DLG);
+
+ if(!pIdxMrk)
+ rSet.DisableItem( FN_INSERT_IDX_ENTRY_DLG );
+ else
+ rSet.Put(SfxBoolItem(FN_INSERT_IDX_ENTRY_DLG, true));
+
+ if(!pAuthMark)
+ rSet.DisableItem( FN_INSERT_AUTH_ENTRY_DLG );
+ else
+ rSet.Put(SfxBoolItem(FN_INSERT_AUTH_ENTRY_DLG, true));
+
+ }
+ else if ( rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem( FN_INSERT_IDX_ENTRY_DLG );
+ rSet.DisableItem( FN_INSERT_AUTH_ENTRY_DLG );
+ rSet.DisableItem( FN_EDIT_AUTH_ENTRY_DLG );
+ rSet.DisableItem( FN_EDIT_IDX_ENTRY_DLG );
+ rSet.DisableItem( FN_INSERT_MULTI_TOX );
+ rSet.DisableItem( FN_REMOVE_CUR_TOX );
+ }
+ else
+ {
+
+ bool bEnableEdit = true;
+ bool bInReadonly = rSh.HasReadonlySel();
+ if(bInReadonly)
+ bEnableEdit = false;
+ else
+ {
+ SwTOXMarks aArr;
+ rSh.GetCurTOXMarks( aArr );
+ if( aArr.empty())
+ bEnableEdit = false;
+ }
+
+ if(!bEnableEdit)
+ rSet.DisableItem( FN_EDIT_IDX_ENTRY_DLG );
+
+ if(bInReadonly)
+ {
+ rSet.DisableItem(FN_INSERT_IDX_ENTRY_DLG);
+ rSet.DisableItem( FN_INSERT_MULTI_TOX );
+ }
+ else
+ rSet.Put(SfxBoolItem(FN_INSERT_IDX_ENTRY_DLG,
+ nullptr != pIdxMrk));
+
+ SwField* pField = rSh.GetCurField();
+
+ if(bInReadonly)
+ rSet.DisableItem(FN_INSERT_AUTH_ENTRY_DLG);
+ else
+ rSet.Put(SfxBoolItem(FN_INSERT_AUTH_ENTRY_DLG, nullptr != pAuthMark));
+
+ if( bInReadonly || !pField ||
+ pField->GetTyp()->Which() != SwFieldIds::TableOfAuthorities)
+ rSet.DisableItem(FN_EDIT_AUTH_ENTRY_DLG);
+ rSet.DisableItem(FN_REMOVE_CUR_TOX);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/textsh.cxx b/sw/source/uibase/shells/textsh.cxx
new file mode 100644
index 0000000000..0924935b3d
--- /dev/null
+++ b/sw/source/uibase/shells/textsh.cxx
@@ -0,0 +1,1107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+
+#include <hintids.hxx>
+#include <comphelper/string.hxx>
+#include <svl/globalnameitem.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/frmdescr.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/viewfrm.hxx>
+
+#include <i18nutil/transliteration.hxx>
+#include <svl/eitem.hxx>
+#include <svl/ptitem.hxx>
+#include <svl/stritem.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <svx/hlnkitem.hxx>
+#include <svl/whiter.hxx>
+#include <sfx2/request.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/sizeitem.hxx>
+#include <editeng/svxacorr.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <sfx2/htmlmode.hxx>
+#include <svtools/htmlcfg.hxx>
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
+#include <osl/diagnose.h>
+
+#include <comphelper/classids.hxx>
+#include <editeng/acorrcfg.hxx>
+#include <wdocsh.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtclds.hxx>
+#include <fmtfsize.hxx>
+#include <swmodule.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <doc.hxx>
+#include <IDocumentChartDataProviderAccess.hxx>
+#include <uitool.hxx>
+#include <cmdid.h>
+#include <globals.hrc>
+#include <frmmgr.hxx>
+#include <textsh.hxx>
+#include <frmfmt.hxx>
+#include <tablemgr.hxx>
+#include <swundo.hxx>
+#include <breakit.hxx>
+#include <edtwin.hxx>
+#include <strings.hrc>
+#include <unochart.hxx>
+#include <chartins.hxx>
+#include <viewopt.hxx>
+
+#define ShellClass_SwTextShell
+#include <sfx2/msg.hxx>
+#include <vcl/EnumContext.hxx>
+#include <swslots.hxx>
+#include <SwRewriter.hxx>
+#include <SwCapObjType.hxx>
+
+#include <svx/svxdlg.hxx>
+#include <swabstdlg.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <drawdoc.hxx>
+#include <svtools/embedhlp.hxx>
+#include <sfx2/event.hxx>
+#include <com/sun/star/ui/dialogs/DialogClosedEvent.hpp>
+#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
+#include <IDocumentUndoRedo.hxx>
+#include <formatcontentcontrol.hxx>
+
+using namespace ::com::sun::star;
+
+SFX_IMPL_INTERFACE(SwTextShell, SwBaseShell)
+
+IMPL_STATIC_LINK( SwTextShell, DialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, pEvent, void )
+{
+ if (SwView* pView = GetActiveView())
+ {
+ SwWrtShell& rWrtShell = pView->GetWrtShell();
+
+ sal_Int16 nDialogRet = pEvent->DialogResult;
+ if( nDialogRet == ui::dialogs::ExecutableDialogResults::CANCEL )
+ {
+ rWrtShell.Undo();
+ rWrtShell.GetIDocumentUndoRedo().ClearRedo();
+ }
+ else
+ {
+ OSL_ENSURE( nDialogRet == ui::dialogs::ExecutableDialogResults::OK,
+ "dialog execution failed" );
+ }
+ }
+}
+
+void SwTextShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("text");
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Text_Toolbox_Sw);
+
+ GetStaticInterface()->RegisterChildWindow(FN_EDIT_FORMULA);
+ GetStaticInterface()->RegisterChildWindow(FN_INSERT_FIELD);
+ GetStaticInterface()->RegisterChildWindow(FN_INSERT_IDX_ENTRY_DLG);
+ GetStaticInterface()->RegisterChildWindow(FN_INSERT_AUTH_ENTRY_DLG);
+ GetStaticInterface()->RegisterChildWindow(SID_RUBY_DIALOG);
+ GetStaticInterface()->RegisterChildWindow(FN_WORDCOUNT_DIALOG);
+}
+
+
+void SwTextShell::ExecInsert(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+
+ OSL_ENSURE( !rSh.IsObjSelected() && !rSh.IsFrameSelected(),
+ "wrong shell on dispatcher" );
+
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem = nullptr;
+ const sal_uInt16 nSlot = rReq.GetSlot();
+ if(pArgs)
+ pArgs->GetItemState(nSlot, false, &pItem );
+
+ switch( nSlot )
+ {
+ case FN_INSERT_STRING:
+ if( pItem )
+ rSh.InsertByWord(static_cast<const SfxStringItem *>(pItem)->GetValue());
+ break;
+
+ case FN_INSERT_SOFT_HYPHEN:
+ if( CHAR_SOFTHYPHEN != rSh.SwCursorShell::GetChar() &&
+ CHAR_SOFTHYPHEN != rSh.SwCursorShell::GetChar( true, -1 ))
+ rSh.Insert( OUString( CHAR_SOFTHYPHEN ) );
+ break;
+
+ case FN_INSERT_HARDHYPHEN:
+ case FN_INSERT_HARD_SPACE:
+ {
+ const sal_Unicode cIns = FN_INSERT_HARD_SPACE == nSlot ? CHAR_HARDBLANK : CHAR_HARDHYPHEN;
+
+ SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get();
+ SvxAutoCorrect* pACorr = rACfg.GetAutoCorrect();
+ if( pACorr && rACfg.IsAutoFormatByInput()
+ && pACorr->IsAutoCorrFlag(
+ ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
+ ACFlags::AddNonBrkSpace | ACFlags::ChgOrdinalNumber | ACFlags::TransliterateRTL |
+ ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr | ACFlags::Autocorrect |
+ ACFlags::SetDOIAttr ) )
+ {
+ rSh.AutoCorrect( *pACorr, cIns );
+ }
+ else
+ {
+ rSh.Insert( OUString( cIns ) );
+ }
+ }
+ break;
+
+ case FN_INSERT_NNBSP: // shift+mod2/alt+space inserts some other character w/o going through SwEditWin::KeyInput(), at least on macOS
+ case SID_INSERT_RLM :
+ case SID_INSERT_LRM :
+ case SID_INSERT_WJ :
+ case SID_INSERT_ZWSP:
+ {
+ sal_Unicode cIns = 0;
+ switch(nSlot)
+ {
+ case SID_INSERT_RLM : cIns = CHAR_RLM ; break;
+ case SID_INSERT_LRM : cIns = CHAR_LRM ; break;
+ case SID_INSERT_ZWSP : cIns = CHAR_ZWSP ; break;
+ case SID_INSERT_WJ: cIns = CHAR_WJ; break;
+ case FN_INSERT_NNBSP: cIns = CHAR_NNBSP; break;
+ }
+ rSh.Insert( OUString( cIns ) );
+ }
+ break;
+
+ case FN_INSERT_BREAK:
+ {
+ if (!rSh.CursorInsideInputField() && !rSh.CursorInsideContentControl())
+ {
+ rSh.SplitNode();
+ }
+ else
+ {
+ rSh.InsertLineBreak();
+ }
+ }
+ rReq.Done();
+ break;
+
+ case FN_INSERT_PAGEBREAK:
+ rSh.InsertPageBreak();
+ rReq.Done();
+ break;
+
+ case FN_INSERT_LINEBREAK:
+ rSh.InsertLineBreak();
+ rReq.Done();
+ break;
+
+ case FN_INSERT_CONTENT_CONTROL:
+ rSh.InsertContentControl(SwContentControlType::RICH_TEXT);
+ rReq.Done();
+ break;
+
+ case FN_INSERT_CHECKBOX_CONTENT_CONTROL:
+ rSh.InsertContentControl(SwContentControlType::CHECKBOX);
+ rReq.Done();
+ break;
+
+ case FN_INSERT_DROPDOWN_CONTENT_CONTROL:
+ rSh.InsertContentControl(SwContentControlType::DROP_DOWN_LIST);
+ rReq.Done();
+ break;
+
+ case FN_INSERT_PICTURE_CONTENT_CONTROL:
+ rSh.InsertContentControl(SwContentControlType::PICTURE);
+ rReq.Done();
+ break;
+
+ case FN_INSERT_DATE_CONTENT_CONTROL:
+ rSh.InsertContentControl(SwContentControlType::DATE);
+ rReq.Done();
+ break;
+
+ case FN_INSERT_PLAIN_TEXT_CONTENT_CONTROL:
+ rSh.InsertContentControl(SwContentControlType::PLAIN_TEXT);
+ rReq.Done();
+ break;
+
+ case FN_INSERT_COMBO_BOX_CONTENT_CONTROL:
+ rSh.InsertContentControl(SwContentControlType::COMBO_BOX);
+ rReq.Done();
+ break;
+
+ case FN_CONTENT_CONTROL_PROPERTIES:
+ {
+ SwWrtShell& rWrtSh = GetShell();
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateSwContentControlDlg(GetView().GetFrameWeld(), rWrtSh));
+ VclAbstractDialog::AsyncContext aContext;
+ aContext.maEndDialogFn = [](sal_Int32){};
+ pDlg->StartExecuteAsync(aContext);
+ rReq.Done();
+ break;
+ }
+
+ case FN_INSERT_COLUMN_BREAK:
+ rSh.InsertColumnBreak();
+ rReq.Done();
+ break;
+
+ case SID_HYPERLINK_SETLINK:
+ if (pItem)
+ InsertHyperlink(*static_cast<const SvxHyperlinkItem *>(pItem));
+ rReq.Done();
+ break;
+
+#if HAVE_FEATURE_AVMEDIA
+ case SID_INSERT_AVMEDIA:
+ rReq.SetReturnValue(SfxBoolItem(nSlot, InsertMediaDlg( rReq )));
+ break;
+#endif
+
+ case SID_INSERT_OBJECT:
+ {
+ const SfxGlobalNameItem* pNameItem = rReq.GetArg<SfxGlobalNameItem>(SID_INSERT_OBJECT);
+ SvGlobalName *pName = nullptr;
+ SvGlobalName aName;
+ if ( pNameItem )
+ {
+ aName = pNameItem->GetValue();
+ pName = &aName;
+ }
+
+ svt::EmbeddedObjectRef xObj;
+ rSh.InsertObject( xObj, pName, nSlot);
+ rReq.Done();
+ break;
+ }
+ case SID_INSERT_FLOATINGFRAME:
+ {
+ svt::EmbeddedObjectRef xObj;
+ const SfxStringItem* pNameItem = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ const SfxStringItem* pURLItem = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
+ const SvxSizeItem* pMarginItem = rReq.GetArg<SvxSizeItem>(FN_PARAM_3);
+ const SfxByteItem* pScrollingItem = rReq.GetArg<SfxByteItem>(FN_PARAM_4);
+ const SfxBoolItem* pBorderItem = rReq.GetArg<SfxBoolItem>(FN_PARAM_5);
+
+ if(pURLItem) // URL is a _must_
+ {
+ comphelper::EmbeddedObjectContainer aCnt;
+ OUString aName;
+ xObj.Assign( aCnt.CreateEmbeddedObject( SvGlobalName( SO3_IFRAME_CLASSID ).GetByteSequence(), aName ),
+ embed::Aspects::MSOLE_CONTENT );
+ (void)svt::EmbeddedObjectRef::TryRunningState( xObj.GetObject() );
+ uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY );
+ if ( xSet.is() )
+ {
+ try
+ {
+ ScrollingMode eScroll = ScrollingMode::Auto;
+ if( pScrollingItem && pScrollingItem->GetValue() <= int(ScrollingMode::Auto) )
+ eScroll = static_cast<ScrollingMode>(pScrollingItem->GetValue());
+
+ Size aMargin;
+ if ( pMarginItem )
+ aMargin = pMarginItem->GetSize();
+
+ xSet->setPropertyValue("FrameURL", uno::Any( pURLItem->GetValue() ) );
+ if ( pNameItem )
+ xSet->setPropertyValue("FrameName", uno::Any( pNameItem->GetValue() ) );
+
+ if ( eScroll == ScrollingMode::Auto )
+ xSet->setPropertyValue("FrameIsAutoScroll",
+ uno::Any( true ) );
+ else
+ xSet->setPropertyValue("FrameIsScrollingMode",
+ uno::Any( eScroll == ScrollingMode::Yes ) );
+
+ if ( pBorderItem )
+ xSet->setPropertyValue("FrameIsBorder",
+ uno::Any( pBorderItem->GetValue() ) );
+
+ if ( pMarginItem )
+ {
+ xSet->setPropertyValue("FrameMarginWidth",
+ uno::Any( sal_Int32( aMargin.Width() ) ) );
+
+ xSet->setPropertyValue("FrameMarginHeight",
+ uno::Any( sal_Int32( aMargin.Height() ) ) );
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ }
+ }
+
+ rSh.InsertOleObject( xObj );
+ }
+ else
+ {
+ rSh.InsertObject( xObj, nullptr, nSlot);
+ rReq.Done();
+ }
+ }
+ break;
+ case SID_INSERT_DIAGRAM:
+ {
+ SvtModuleOptions aMOpt;
+ if ( !aMOpt.IsChart() )
+ break;
+ if(!rReq.IsAPI())
+ {
+ SwInsertChart( LINK( this, SwTextShell, DialogClosedHdl ) );
+ }
+ else
+ {
+ uno::Reference< chart2::data::XDataProvider > xDataProvider;
+ bool bFillWithData = true;
+ OUString aRangeString;
+ if (!GetShell().IsTableComplexForChart())
+ {
+ SwFrameFormat* pTableFormat = GetShell().GetTableFormat();
+ aRangeString = pTableFormat->GetName() + "."
+ + GetShell().GetBoxNms();
+
+ // get table data provider
+ xDataProvider.set( GetView().GetDocShell()->getIDocumentChartDataProviderAccess().GetChartDataProvider() );
+ }
+ else
+ bFillWithData = false; // will create chart with only it's default image
+
+ SwTableFUNC( &rSh ).InsertChart( xDataProvider, bFillWithData, aRangeString );
+ rSh.LaunchOLEObj();
+
+ svt::EmbeddedObjectRef& xObj = rSh.GetOLEObject();
+ if(pItem && xObj.is())
+ {
+ Size aSize(static_cast<const SvxSizeItem*>(pItem)->GetSize());
+ aSize = o3tl::convert(aSize, o3tl::Length::twip, o3tl::Length::mm100);
+
+ if(aSize.Width() > MINLAY&& aSize.Height()> MINLAY)
+ {
+ awt::Size aSz;
+ aSz.Width = aSize.Width();
+ aSz.Height = aSize.Height();
+ xObj->setVisualAreaSize( xObj.GetViewAspect(), aSz );
+ }
+ }
+ }
+ }
+ break;
+
+ case FN_INSERT_SMA:
+ {
+ // #i34343# Inserting a math object into an autocompletion crashes
+ // the suggestion has to be removed before
+ GetView().GetEditWin().StopQuickHelp();
+ SvGlobalName aGlobalName( SO3_SM_CLASSID );
+ rSh.InsertObject( svt::EmbeddedObjectRef(), &aGlobalName );
+ }
+ break;
+
+ case FN_INSERT_TABLE:
+ InsertTable( rReq );
+ break;
+
+ case FN_INSERT_FRAME_INTERACT_NOCOL:
+ case FN_INSERT_FRAME_INTERACT:
+ {
+ sal_uInt16 nCols = 1;
+ bool bModifier1 = rReq.GetModifier() == KEY_MOD1;
+ if(pArgs)
+ {
+ const SfxUInt16Item* pColsItem = nullptr;
+ if(FN_INSERT_FRAME_INTERACT_NOCOL != nSlot &&
+ (pColsItem = pArgs->GetItemIfSet(SID_ATTR_COLUMNS, false)))
+ nCols = pColsItem->GetValue();
+ if(const SfxUInt16Item* pModifierItem = pArgs->GetItemIfSet(SID_MODIFIER, false))
+ bModifier1 |= KEY_MOD1 == pModifierItem->GetValue();
+ }
+ if(bModifier1 )
+ {
+ SwEditWin& rEdtWin = GetView().GetEditWin();
+ Size aWinSize = rEdtWin.GetSizePixel();
+ Point aStartPos(aWinSize.Width()/2, aWinSize.Height() / 2);
+ aStartPos = rEdtWin.PixelToLogic(aStartPos);
+ constexpr tools::Long constTwips_2cm = o3tl::toTwips(2, o3tl::Length::cm);
+ constexpr tools::Long constTwips_4cm = o3tl::toTwips(4, o3tl::Length::cm);
+ aStartPos.AdjustX(-constTwips_4cm);
+ aStartPos.AdjustY(-constTwips_2cm);
+ Size aSize(2 * constTwips_4cm, 2 * constTwips_2cm);
+ GetShell().LockPaint(LockPaintReason::InsertFrame);
+ GetShell().StartAllAction();
+ SwFlyFrameAttrMgr aMgr( true, GetShellPtr(), Frmmgr_Type::TEXT, nullptr );
+ if(nCols > 1)
+ {
+ SwFormatCol aCol;
+ aCol.Init( nCols, aCol.GetGutterWidth(), aCol.GetWishWidth() );
+ aMgr.SetCol( aCol );
+ }
+ aMgr.InsertFlyFrame(RndStdIds::FLY_AT_PARA, aStartPos, aSize);
+ GetShell().EndAllAction();
+ GetShell().UnlockPaint();
+ }
+ else
+ {
+ GetView().InsFrameMode(nCols);
+ }
+ rReq.Ignore();
+ }
+ break;
+ case FN_INSERT_FRAME:
+ {
+ bool bSingleCol = false;
+ if( nullptr!= dynamic_cast< SwWebDocShell*>( GetView().GetDocShell()) )
+ {
+ if( HTML_CFG_MSIE == SvxHtmlOptions::GetExportMode() )
+ {
+ bSingleCol = true;
+ }
+
+ }
+ // Create new border
+ SwFlyFrameAttrMgr aMgr( true, GetShellPtr(), Frmmgr_Type::TEXT, nullptr );
+ if(pArgs)
+ {
+ Size aSize(aMgr.GetSize());
+ aSize.setWidth( GetShell().GetAnyCurRect(CurRectType::PagePrt).Width() );
+ Point aPos = aMgr.GetPos();
+ RndStdIds eAnchor = RndStdIds::FLY_AT_PARA;
+ if(pArgs->GetItemState(nSlot, false, &pItem) == SfxItemState::SET)
+ eAnchor = static_cast<RndStdIds>(static_cast<const SfxUInt16Item *>(pItem)->GetValue());
+ if(pArgs->GetItemState(FN_PARAM_1, false, &pItem) == SfxItemState::SET)
+ aPos = static_cast<const SfxPointItem *>(pItem)->GetValue();
+ if(pArgs->GetItemState(FN_PARAM_2, false, &pItem) == SfxItemState::SET)
+ aSize = static_cast<const SvxSizeItem *>(pItem)->GetSize();
+ if(const SfxUInt16Item* pColsItem = pArgs->GetItemIfSet(SID_ATTR_COLUMNS, false))
+ {
+ const sal_uInt16 nCols = pColsItem->GetValue();
+ if( !bSingleCol && 1 < nCols )
+ {
+ SwFormatCol aFormatCol;
+ aFormatCol.Init( nCols , (rReq.IsAPI() ? 0
+ : DEF_GUTTER_WIDTH), USHRT_MAX );
+ aMgr.SetCol(aFormatCol);
+ }
+ }
+
+ GetShell().LockPaint(LockPaintReason::InsertFrame);
+ GetShell().StartAllAction();
+
+ aMgr.InsertFlyFrame(eAnchor, aPos, aSize);
+
+ GetShell().EndAllAction();
+ GetShell().UnlockPaint();
+ }
+ else
+ {
+ SfxItemSet aSet = CreateInsertFrameItemSet(aMgr);
+
+ FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebDocShell*>( GetView().GetDocShell()) != nullptr );
+ SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)));
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateFrameTabDialog("FrameDialog",
+ GetView().GetViewFrame(),
+ GetView().GetFrameWeld(),
+ aSet));
+ pDlg->StartExecuteAsync([aSet, pDlg, nSlot, this](sal_Int32 nResult) {
+ if (nResult == RET_OK && pDlg->GetOutputItemSet())
+ {
+ SwFlyFrameAttrMgr aAttrMgr( true, GetShellPtr(), Frmmgr_Type::TEXT, nullptr );
+ //local variable necessary at least after call of .AutoCaption() because this could be deleted at this point
+ SwWrtShell& rShell = GetShell();
+ rShell.LockPaint(LockPaintReason::InsertFrame);
+ rShell.StartAllAction();
+ rShell.StartUndo(SwUndoId::INSERT);
+
+ SfxItemSet aOutSet(*pDlg->GetOutputItemSet());
+ const SvxBoxItem* pBox = aSet.GetItem(RES_BOX);
+ if (pBox && !aOutSet.HasItem(RES_BOX))
+ {
+ // The input set had border info but the output set not, then copy it over
+ // to not lose the custom border info. This can happen when a whole table
+ // is selected and that case has its own defaults, not matching the frame
+ // style.
+ aOutSet.Put(*pBox);
+ }
+ aAttrMgr.SetAttrSet(aOutSet);
+
+ // At first delete the selection at the ClickToEditField.
+ if( rShell.IsInClickToEdit() )
+ rShell.DelRight();
+
+ aAttrMgr.InsertFlyFrame();
+
+ uno::Reference< frame::XDispatchRecorder > xRecorder =
+ GetView().GetViewFrame().GetBindings().GetRecorder();
+ if ( xRecorder.is() )
+ {
+ //FN_INSERT_FRAME
+ sal_uInt16 nAnchor = static_cast<sal_uInt16>(aAttrMgr.GetAnchor());
+ SfxRequest aReq(GetView().GetViewFrame(), FN_INSERT_FRAME);
+ aReq.AppendItem(SfxUInt16Item(nSlot, nAnchor));
+ aReq.AppendItem(SfxPointItem(FN_PARAM_1, rShell.GetObjAbsPos()));
+ aReq.AppendItem(SvxSizeItem(FN_PARAM_2, rShell.GetObjSize()));
+ aReq.Done();
+ }
+
+ GetView().AutoCaption(FRAME_CAP);
+
+ {
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UndoArg1, SwResId(STR_FRAME));
+
+ rShell.EndUndo(SwUndoId::INSERT, &aRewriter);
+ }
+ rShell.EndAllAction();
+ rShell.UnlockPaint();
+ }
+ pDlg->disposeOnce();
+ });
+ }
+ break;
+ }
+ case FN_FORMAT_COLUMN :
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ VclPtr<VclAbstractDialog> pColDlg(pFact->CreateSwColumnDialog(GetView().GetFrameWeld(), rSh));
+ pColDlg->StartExecuteAsync([=](sal_Int32 /*nResult*/){
+ pColDlg->disposeOnce();
+ });
+ }
+ break;
+
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ return;
+ }
+}
+
+static bool lcl_IsMarkInSameSection( SwWrtShell& rWrtSh, const SwSection* pSect )
+{
+ rWrtSh.SwapPam();
+ bool bRet = pSect == rWrtSh.GetCurrSection();
+ rWrtSh.SwapPam();
+ return bRet;
+}
+
+void SwTextShell::StateInsert( SfxItemSet &rSet )
+{
+ const bool bHtmlModeOn = ::GetHtmlMode(GetView().GetDocShell()) & HTMLMODE_ON;
+ SfxWhichIter aIter( rSet );
+ SwWrtShell &rSh = GetShell();
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ SvtModuleOptions aMOpt;
+ SfxObjectCreateMode eCreateMode =
+ GetView().GetDocShell()->GetCreateMode();
+ const bool bCursorInHidden = rSh.IsInHiddenRange(/*bSelect=*/false);
+
+ while ( nWhich )
+ {
+ switch ( nWhich )
+ {
+ case SID_INSERT_AVMEDIA:
+ if ( GetShell().IsSelFrameMode()
+ || GetShell().CursorInsideInputField()
+ || SfxObjectCreateMode::EMBEDDED == eCreateMode
+ || bCursorInHidden )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case SID_INSERT_DIAGRAM:
+ if( !aMOpt.IsChart()
+ || GetShell().CursorInsideInputField()
+ || eCreateMode == SfxObjectCreateMode::EMBEDDED
+ || bCursorInHidden )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case FN_INSERT_SMA:
+ if( !aMOpt.IsMath()
+ || eCreateMode == SfxObjectCreateMode::EMBEDDED
+ || bCursorInHidden
+ || rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case SID_INSERT_FLOATINGFRAME:
+ case SID_INSERT_OBJECT:
+ {
+ if( eCreateMode == SfxObjectCreateMode::EMBEDDED || bCursorInHidden )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ else if( GetShell().IsSelFrameMode()
+ || GetShell().CursorInsideInputField() )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ else if(SID_INSERT_FLOATINGFRAME == nWhich && bHtmlModeOn)
+ {
+ const sal_uInt16 nExport = SvxHtmlOptions::GetExportMode();
+ if(HTML_CFG_MSIE != nExport && HTML_CFG_WRITER != nExport )
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+
+ case FN_INSERT_FRAME_INTERACT_NOCOL :
+ case FN_INSERT_FRAME_INTERACT:
+ {
+ if( GetShell().IsSelFrameMode()
+ || rSh.IsTableMode()
+ || GetShell().CursorInsideInputField()
+ || bCursorInHidden )
+ rSet.DisableItem(nWhich);
+ }
+ break;
+
+ case SID_HYPERLINK_GETLINK:
+ {
+ SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
+ rSh.GetCurAttr( aSet );
+
+ SvxHyperlinkItem aHLinkItem;
+ if(const SwFormatINetFormat* pINetFormat = aSet.GetItemIfSet(RES_TXTATR_INETFMT, false))
+ {
+ aHLinkItem.SetURL(pINetFormat->GetValue());
+ aHLinkItem.SetTargetFrame(pINetFormat->GetTargetFrame());
+ aHLinkItem.SetIntName(pINetFormat->GetName());
+ const SvxMacro *pMacro = pINetFormat->GetMacro( SvMacroItemId::OnMouseOver );
+ if( pMacro )
+ aHLinkItem.SetMacro(HyperDialogEvent::MouseOverObject, *pMacro);
+
+ pMacro = pINetFormat->GetMacro( SvMacroItemId::OnClick );
+ if( pMacro )
+ aHLinkItem.SetMacro(HyperDialogEvent::MouseClickObject, *pMacro);
+
+ pMacro = pINetFormat->GetMacro( SvMacroItemId::OnMouseOut );
+ if( pMacro )
+ aHLinkItem.SetMacro(HyperDialogEvent::MouseOutObject, *pMacro);
+
+ // Get the text of the Link.
+ rSh.StartAction();
+ const bool bAtEnd(rSh.IsCursorPtAtEnd());
+ if(!bAtEnd) // tdf#91832: ensure forward selection
+ rSh.SwapPam();
+ rSh.CreateCursor();
+ if(!bAtEnd)
+ rSh.SwapPam();
+ rSh.SwCursorShell::SelectTextAttr(RES_TXTATR_INETFMT,true);
+ OUString sLinkName = rSh.GetSelText();
+ aHLinkItem.SetName(sLinkName);
+ aHLinkItem.SetInsertMode(HLINK_FIELD);
+ rSh.DestroyCursor();
+ rSh.EndAction();
+ }
+ else
+ {
+ OUString sReturn = rSh.GetSelText();
+ sReturn = sReturn.copy(0, std::min<sal_Int32>(255, sReturn.getLength()));
+ aHLinkItem.SetName(comphelper::string::stripEnd(sReturn, ' '));
+ }
+
+ aHLinkItem.SetInsertMode(static_cast<SvxLinkInsertMode>(aHLinkItem.GetInsertMode() |
+ (bHtmlModeOn ? HLINK_HTMLMODE : 0)));
+ aHLinkItem.SetMacroEvents ( HyperDialogEvent::MouseOverObject|
+ HyperDialogEvent::MouseClickObject | HyperDialogEvent::MouseOutObject );
+
+ rSet.Put(aHLinkItem);
+ }
+ break;
+
+ case FN_INSERT_FRAME:
+ if (rSh.IsSelFrameMode() )
+ {
+ const SelectionType nSel = rSh.GetSelectionType();
+ if( ((SelectionType::Graphic | SelectionType::Ole ) & nSel ) || bCursorInHidden )
+ rSet.DisableItem(nWhich);
+ }
+ else if ( rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ break;
+
+ case FN_FORMAT_COLUMN :
+ {
+ //#i80458# column dialog cannot work if the selection contains different page styles and different sections
+ bool bDisable = true;
+ if( rSh.GetFlyFrameFormat() || rSh.GetSelectedPageDescs() )
+ bDisable = false;
+ if( bDisable )
+ {
+ const SwSection* pCurrSection = rSh.GetCurrSection();
+ const sal_uInt16 nFullSectCnt = rSh.GetFullSelectedSectionCount();
+ if( pCurrSection && ( !rSh.HasSelection() || 0 != nFullSectCnt ))
+ bDisable = false;
+ else if(
+ rSh.HasSelection() && rSh.IsInsRegionAvailable() &&
+ ( !pCurrSection || ( 1 != nFullSectCnt &&
+ lcl_IsMarkInSameSection( rSh, pCurrSection ) )))
+ bDisable = false;
+ }
+ if(bDisable)
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwTextShell::ExecDelete(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ switch( rReq.GetSlot() )
+ {
+ case FN_DELETE_SENT:
+ if( rSh.IsTableMode() )
+ {
+ rSh.DeleteRow();
+ rSh.EnterStdMode();
+ }
+ else
+ rSh.DelToEndOfSentence();
+ break;
+ case FN_DELETE_BACK_SENT:
+ rSh.DelToStartOfSentence();
+ break;
+ case FN_DELETE_WORD:
+ rSh.DelNxtWord();
+ break;
+ case FN_DELETE_BACK_WORD:
+ rSh.DelPrvWord();
+ break;
+ case FN_DELETE_LINE:
+ rSh.DelToEndOfLine();
+ break;
+ case FN_DELETE_BACK_LINE:
+ rSh.DelToStartOfLine();
+ break;
+ case FN_DELETE_PARA:
+ rSh.DelToEndOfPara();
+ break;
+ case FN_DELETE_BACK_PARA:
+ rSh.DelToStartOfPara();
+ break;
+ case FN_DELETE_WHOLE_LINE:
+ rSh.DelLine();
+ break;
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ return;
+ }
+ rReq.Done();
+}
+
+void SwTextShell::ExecTransliteration( SfxRequest const & rReq )
+{
+ using namespace ::com::sun::star::i18n;
+ TransliterationFlags nMode = TransliterationFlags::NONE;
+
+ switch( rReq.GetSlot() )
+ {
+ case SID_TRANSLITERATE_SENTENCE_CASE:
+ nMode = TransliterationFlags::SENTENCE_CASE;
+ break;
+ case SID_TRANSLITERATE_TITLE_CASE:
+ nMode = TransliterationFlags::TITLE_CASE;
+ break;
+ case SID_TRANSLITERATE_TOGGLE_CASE:
+ nMode = TransliterationFlags::TOGGLE_CASE;
+ break;
+ case SID_TRANSLITERATE_UPPER:
+ nMode = TransliterationFlags::LOWERCASE_UPPERCASE;
+ break;
+ case SID_TRANSLITERATE_LOWER:
+ nMode = TransliterationFlags::UPPERCASE_LOWERCASE;
+ break;
+
+ case SID_TRANSLITERATE_HALFWIDTH:
+ nMode = TransliterationFlags::FULLWIDTH_HALFWIDTH;
+ break;
+ case SID_TRANSLITERATE_FULLWIDTH:
+ nMode = TransliterationFlags::HALFWIDTH_FULLWIDTH;
+ break;
+
+ case SID_TRANSLITERATE_HIRAGANA:
+ nMode = TransliterationFlags::KATAKANA_HIRAGANA;
+ break;
+ case SID_TRANSLITERATE_KATAKANA:
+ nMode = TransliterationFlags::HIRAGANA_KATAKANA;
+ break;
+
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ }
+
+ if( nMode != TransliterationFlags::NONE )
+ GetShell().TransliterateText( nMode );
+}
+
+void SwTextShell::ExecRotateTransliteration( SfxRequest const & rReq )
+{
+ if( rReq.GetSlot() == SID_TRANSLITERATE_ROTATE_CASE )
+ GetShell().TransliterateText( m_aRotateCase.getNextMode() );
+}
+
+SwTextShell::SwTextShell(SwView &_rView) :
+ SwBaseShell(_rView)
+{
+ SetName("Text");
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Text));
+}
+
+SwTextShell::~SwTextShell()
+{
+}
+
+SfxItemSet SwTextShell::CreateInsertFrameItemSet(SwFlyFrameAttrMgr& rMgr)
+{
+ SfxItemSet aSet(GetPool(), svl::Items<
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ XATTR_FILL_FIRST, XATTR_FILL_LAST, // tdf#95003
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
+ SID_ATTR_PAGE_SIZE, SID_ATTR_PAGE_SIZE,
+ SID_COLOR_TABLE, SID_PATTERN_LIST,
+ SID_HTML_MODE, SID_HTML_MODE,
+ FN_GET_PRINT_AREA, FN_GET_PRINT_AREA,
+ FN_SET_FRM_NAME, FN_SET_FRM_NAME>);
+ aSet.Put(SfxUInt16Item(SID_HTML_MODE, ::GetHtmlMode(GetView().GetDocShell())));
+
+ // For the Area tab page.
+ GetShell().GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->PutAreaListItems(aSet);
+
+ const SwRect &rPg = GetShell().GetAnyCurRect(CurRectType::Page);
+ SwFormatFrameSize aFrameSize(SwFrameSize::Variable, rPg.Width(), rPg.Height());
+ aFrameSize.SetWhich(GetPool().GetWhich(SID_ATTR_PAGE_SIZE));
+ aSet.Put(aFrameSize);
+
+ const SwRect &rPr = GetShell().GetAnyCurRect(CurRectType::PagePrt);
+ SwFormatFrameSize aPrtSize(SwFrameSize::Variable, rPr.Width(), rPr.Height());
+ aPrtSize.SetWhich(GetPool().GetWhich(FN_GET_PRINT_AREA));
+ aSet.Put(aPrtSize);
+
+ aSet.Put(rMgr.GetAttrSet());
+ aSet.SetParent( rMgr.GetAttrSet().GetParent() );
+
+ // Delete minimum size in columns.
+ SvxBoxInfoItem aBoxInfo(aSet.Get(SID_ATTR_BORDER_INNER));
+ const SvxBoxItem& rBox = aSet.Get(RES_BOX);
+ aBoxInfo.SetMinDist(false);
+ aBoxInfo.SetDefDist(rBox.GetDistance(SvxBoxItemLine::LEFT));
+ aSet.Put(aBoxInfo);
+
+ if (!SwFlyFrameAttrMgr::SingleTableSelected(GetShell()))
+ {
+ SwFormatAnchor aAnchor(RndStdIds::FLY_AT_CHAR);
+ aSet.Put(aAnchor);
+ }
+
+ return aSet;
+}
+
+void SwTextShell::InsertSymbol( SfxRequest& rReq )
+{
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ const SfxStringItem* pItem = nullptr;
+ if( pArgs )
+ pItem = pArgs->GetItemIfSet(SID_CHARMAP, false);
+
+ OUString aChars, aFontName;
+ if ( pItem )
+ {
+ aChars = pItem->GetValue();
+ const SfxStringItem* pFontItem = pArgs->GetItemIfSet( SID_ATTR_SPECIALCHAR, false );
+ if ( pFontItem )
+ aFontName = pFontItem->GetValue();
+ }
+
+ SwWrtShell &rSh = GetShell();
+ SfxItemSetFixed<RES_CHRATR_FONT, RES_CHRATR_FONT,
+ RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONT,
+ RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_FONT> aSet( GetPool() );
+ rSh.GetCurAttr( aSet );
+ SvtScriptType nScript = rSh.GetScriptType();
+
+ std::shared_ptr<SvxFontItem> aFont(std::make_shared<SvxFontItem>(RES_CHRATR_FONT));
+ {
+ SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONT, *aSet.GetPool() );
+ aSetItem.GetItemSet().Put( aSet, false );
+ const SfxPoolItem* pI = aSetItem.GetItemOfScript( nScript );
+ if( pI )
+ {
+ aFont.reset(static_cast<SvxFontItem*>(pI->Clone()));
+ }
+ else
+ {
+ TypedWhichId<SvxFontItem> nFontWhich =
+ GetWhichOfScript(
+ RES_CHRATR_FONT,
+ SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetAppLanguage() ) );
+ aFont.reset(aSet.Get(nFontWhich).Clone());
+ }
+
+ if (aFontName.isEmpty())
+ aFontName = aFont->GetFamilyName();
+ }
+
+ vcl::Font aNewFont(aFontName, Size(1,1)); // Size only because CTOR.
+ if( aChars.isEmpty() )
+ {
+ // Set selected font as default.
+ SfxAllItemSet aAllSet( rSh.GetAttrPool() );
+ aAllSet.Put( SfxBoolItem( FN_PARAM_1, false ) );
+
+ SwViewOption aOpt(*GetShell().GetViewOptions());
+ const OUString& sSymbolFont = aOpt.GetSymbolFont();
+ if( aFontName.isEmpty() && !sSymbolFont.isEmpty() )
+ aAllSet.Put( SfxStringItem( SID_FONT_NAME, sSymbolFont ) );
+ else
+ aAllSet.Put( SfxStringItem( SID_FONT_NAME, aFont->GetFamilyName() ) );
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ auto xFrame = GetView().GetViewFrame().GetFrame().GetFrameInterface();
+ ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateCharMapDialog(GetView().GetFrameWeld(), aAllSet, xFrame));
+ pDlg->Execute();
+ return;
+ }
+
+ if( aChars.isEmpty() )
+ return;
+
+ rSh.StartAllAction();
+
+ // Delete selected content.
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, SwResId(STR_SPECIALCHAR));
+
+ rSh.StartUndo( SwUndoId::INSERT, &aRewriter );
+ if ( rSh.HasSelection() )
+ {
+ rSh.DelRight();
+ aSet.ClearItem();
+ rSh.GetCurAttr( aSet );
+
+ SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONT, *aSet.GetPool() );
+ aSetItem.GetItemSet().Put( aSet, false );
+ const SfxPoolItem* pI = aSetItem.GetItemOfScript( nScript );
+ if( pI )
+ {
+ aFont.reset(static_cast<SvxFontItem*>(pI->Clone()));
+ }
+ else
+ {
+ TypedWhichId<SvxFontItem> nFontWhich =
+ GetWhichOfScript(
+ RES_CHRATR_FONT,
+ SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetAppLanguage() ) );
+ aFont.reset(aSet.Get( nFontWhich ).Clone());
+ }
+ }
+
+ // Insert character.
+ rSh.Insert( aChars );
+
+ // #108876# a font attribute has to be set always due to a guessed script type
+ if( !aNewFont.GetFamilyName().isEmpty() )
+ {
+ std::unique_ptr<SvxFontItem> aNewFontItem(aFont->Clone());
+ aNewFontItem->SetFamilyName( aNewFont.GetFamilyName() );
+ aNewFontItem->SetFamily( aNewFont.GetFamilyType());
+ aNewFontItem->SetPitch( aNewFont.GetPitch());
+ aNewFontItem->SetCharSet( aNewFont.GetCharSet() );
+
+ SfxItemSetFixed<RES_CHRATR_FONT, RES_CHRATR_FONT,
+ RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONT,
+ RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_FONT> aRestoreSet( GetPool() );
+
+ nScript = g_pBreakIt->GetAllScriptsOfText( aChars );
+ if( SvtScriptType::LATIN & nScript )
+ {
+ aRestoreSet.Put( aSet.Get( RES_CHRATR_FONT ) );
+ aNewFontItem->SetWhich(RES_CHRATR_FONT);
+ aSet.Put( *aNewFontItem );
+ }
+ if( SvtScriptType::ASIAN & nScript )
+ {
+ aRestoreSet.Put( aSet.Get( RES_CHRATR_CJK_FONT ) );
+ aNewFontItem->SetWhich(RES_CHRATR_CJK_FONT);
+ aSet.Put( *aNewFontItem );
+ }
+ if( SvtScriptType::COMPLEX & nScript )
+ {
+ aRestoreSet.Put( aSet.Get( RES_CHRATR_CTL_FONT ) );
+ aNewFontItem->SetWhich(RES_CHRATR_CTL_FONT);
+ aSet.Put( *aNewFontItem );
+ }
+
+ rSh.SetMark();
+ rSh.ExtendSelection( false, aChars.getLength() );
+ rSh.SetAttrSet( aSet, SetAttrMode::DONTEXPAND | SetAttrMode::NOFORMATATTR );
+ if( !rSh.IsCursorPtAtEnd() )
+ rSh.SwapPam();
+
+ rSh.ClearMark();
+
+ // #i75891#
+ // SETATTR_DONTEXPAND does not work if there are already hard attributes.
+ // Therefore we have to restore the font attributes.
+ rSh.SetMark();
+ rSh.SetAttrSet( aRestoreSet );
+ rSh.ClearMark();
+
+ rSh.UpdateAttr();
+
+ // Why was this done? aFont is not used anymore below, we are not
+ // in a loop and it's a local variable...?
+ // aFont = aNewFontItem;
+ }
+
+ rSh.EndAllAction();
+ rSh.EndUndo();
+
+ if ( !aChars.isEmpty() )
+ {
+ rReq.AppendItem( SfxStringItem( SID_CHARMAP, aChars ) );
+ rReq.AppendItem( SfxStringItem( SID_ATTR_SPECIALCHAR, aNewFont.GetFamilyName() ) );
+ rReq.Done();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/textsh1.cxx b/sw/source/uibase/shells/textsh1.cxx
new file mode 100644
index 0000000000..2bf6c670e4
--- /dev/null
+++ b/sw/source/uibase/shells/textsh1.cxx
@@ -0,0 +1,2822 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <config_features.h>
+
+#include <com/sun/star/i18n/WordType.hpp>
+#include <com/sun/star/linguistic2/XThesaurus.hpp>
+
+#include <hintids.hxx>
+#include <cmdid.h>
+#include <comphelper/lok.hxx>
+
+#include <i18nutil/unicode.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <svtools/langtab.hxx>
+#include <svl/numformat.hxx>
+#include <svl/slstitm.hxx>
+#include <svl/stritem.hxx>
+#include <sfx2/htmlmode.hxx>
+#include <svl/whiter.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <vcl/unohelp2.hxx>
+#include <vcl/weld.hxx>
+#include <sfx2/request.hxx>
+#include <svl/eitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/svxacorr.hxx>
+#include <svl/cjkoptions.hxx>
+#include <svl/ctloptions.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <charfmt.hxx>
+#include <svx/SmartTagItem.hxx>
+#include <svx/xflgrit.hxx>
+#include <svx/xflhtit.hxx>
+#include <svx/xfillit0.hxx>
+#include <fmtinfmt.hxx>
+#include <wrtsh.hxx>
+#include <wview.hxx>
+#include <swmodule.hxx>
+#include <viewopt.hxx>
+#include <uitool.hxx>
+#include <textsh.hxx>
+#include <IMark.hxx>
+#include <swdtflvr.hxx>
+#include <swundo.hxx>
+#include <reffld.hxx>
+#include <docsh.hxx>
+#include <inputwin.hxx>
+#include <chrdlgmodes.hxx>
+#include <fmtcol.hxx>
+#include <cellatr.hxx>
+#include <edtwin.hxx>
+#include <fldmgr.hxx>
+#include <strings.hrc>
+#include <paratr.hxx>
+#include <vcl/svapp.hxx>
+#include <sfx2/app.hxx>
+#include <breakit.hxx>
+#include <SwSmartTagMgr.hxx>
+#include <editeng/acorrcfg.hxx>
+#include <swabstdlg.hxx>
+#include <sfx2/sfxdlg.hxx>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/linguistic2/ProofreadingResult.hpp>
+#include <com/sun/star/linguistic2/XDictionary.hpp>
+#include <com/sun/star/linguistic2/XSpellAlternatives.hpp>
+#include <editeng/unolingu.hxx>
+#include <doc.hxx>
+#include <drawdoc.hxx>
+#include <view.hxx>
+#include <pam.hxx>
+#include <sfx2/objface.hxx>
+#include <langhelper.hxx>
+#include <uiitems.hxx>
+#include <svx/nbdtmgfact.hxx>
+#include <svx/nbdtmg.hxx>
+#include <SwRewriter.hxx>
+#include <svx/drawitem.hxx>
+#include <numrule.hxx>
+#include <memory>
+#include <xmloff/odffields.hxx>
+#include <bookmark.hxx>
+#include <linguistic/misc.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+#include <comphelper/scopeguard.hxx>
+#include <authfld.hxx>
+#include <config_wasm_strip.h>
+#if HAVE_FEATURE_CURL && !ENABLE_WASM_STRIP_EXTRA
+#include <officecfg/Office/Common.hxx>
+#include <officecfg/Office/Linguistic.hxx>
+#include <svl/visitem.hxx>
+#include <translatelangselect.hxx>
+#endif // HAVE_FEATURE_CURL && ENABLE_WASM_STRIP_EXTRA
+#include <translatehelper.hxx>
+#include <IDocumentContentOperations.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtrfmrk.hxx>
+#include <cntfrm.hxx>
+#include <flyfrm.hxx>
+
+using namespace ::com::sun::star;
+using namespace com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace com::sun::star::style;
+using namespace svx::sidebar;
+
+static void sw_CharDialogResult(const SfxItemSet* pSet, SwWrtShell &rWrtSh, std::shared_ptr<SfxItemSet> const & pCoreSet, bool bSel,
+ bool bSelectionPut, bool bApplyToParagraph, SfxRequest *pReq);
+
+static void sw_CharDialog(SwWrtShell& rWrtSh, bool bUseDialog, bool bApplyToParagraph,
+ sal_uInt16 nSlot, const SfxItemSet* pArgs, SfxRequest* pReq)
+{
+ FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( &rWrtSh.GetView()) != nullptr );
+ SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)));
+ auto pCoreSet = std::make_shared<SfxItemSetFixed<
+ RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
+ RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
+ RES_BACKGROUND, RES_SHADOW,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
+ SID_HTML_MODE, SID_HTML_MODE,
+ SID_ATTR_CHAR_WIDTH_FIT_TO_LINE, SID_ATTR_CHAR_WIDTH_FIT_TO_LINE,
+ FN_PARAM_SELECTION, FN_PARAM_SELECTION>> ( rWrtSh.GetView().GetPool() );
+ rWrtSh.GetCurAttr(*pCoreSet);
+
+ bool bSel = rWrtSh.HasSelection();
+ bool bSelectionPut = false;
+ if(bSel || rWrtSh.IsInWord())
+ {
+ if(!bSel)
+ {
+ rWrtSh.StartAction();
+ rWrtSh.Push();
+ if(!rWrtSh.SelectTextAttr( RES_TXTATR_INETFMT ))
+ rWrtSh.SelWrd();
+ }
+ pCoreSet->Put(SfxStringItem(FN_PARAM_SELECTION, rWrtSh.GetSelText()));
+ bSelectionPut = true;
+ if(!bSel)
+ {
+ rWrtSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+ rWrtSh.EndAction();
+ }
+ }
+ pCoreSet->Put(SfxUInt16Item(SID_ATTR_CHAR_WIDTH_FIT_TO_LINE, rWrtSh.GetScalingOfSelectedText()));
+
+ ::ConvertAttrCharToGen(*pCoreSet);
+
+ // Setting the BoxInfo
+ ::PrepareBoxInfo(*pCoreSet, rWrtSh);
+
+ pCoreSet->Put(SfxUInt16Item(SID_HTML_MODE, ::GetHtmlMode(rWrtSh.GetView().GetDocShell())));
+ VclPtr<SfxAbstractTabDialog> pDlg;
+ if ( bUseDialog && GetActiveView() )
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ pDlg.reset(pFact->CreateSwCharDlg(rWrtSh.GetView().GetFrameWeld(), rWrtSh.GetView(), *pCoreSet, SwCharDlgMode::Std));
+
+ if (nSlot == FN_INSERT_HYPERLINK)
+ pDlg->SetCurPageId("hyperlink");
+ else if (nSlot == SID_CHAR_DLG_EFFECT)
+ pDlg->SetCurPageId("fonteffects");
+ else if (nSlot == SID_CHAR_DLG_POSITION)
+ pDlg->SetCurPageId("position");
+ else if (nSlot == SID_CHAR_DLG_FOR_PARAGRAPH)
+ pDlg->SetCurPageId("font");
+ else if (pReq)
+ {
+ const SfxStringItem* pItem = (*pReq).GetArg<SfxStringItem>(FN_PARAM_1);
+ if (pItem)
+ pDlg->SetCurPageId(pItem->GetValue());
+ }
+ }
+
+ if (bUseDialog)
+ {
+ std::shared_ptr<SfxRequest> pRequest;
+ if (pReq)
+ {
+ pRequest = std::make_shared<SfxRequest>(*pReq);
+ pReq->Ignore(); // the 'old' request is not relevant any more
+ }
+ pDlg->StartExecuteAsync([pDlg, &rWrtSh, pCoreSet, bSel, bSelectionPut, bApplyToParagraph, pRequest](sal_Int32 nResult){
+ if (nResult == RET_OK)
+ {
+ sw_CharDialogResult(pDlg->GetOutputItemSet(), rWrtSh, pCoreSet, bSel, bSelectionPut,
+ bApplyToParagraph, pRequest.get());
+ }
+ pDlg->disposeOnce();
+ });
+ }
+ else if (pArgs)
+ {
+ sw_CharDialogResult(pArgs, rWrtSh, pCoreSet, bSel, bSelectionPut, bApplyToParagraph, pReq);
+ }
+}
+
+static void sw_CharDialogResult(const SfxItemSet* pSet, SwWrtShell& rWrtSh, std::shared_ptr<SfxItemSet> const & pCoreSet, bool bSel,
+ bool bSelectionPut, bool bApplyToParagraph, SfxRequest* pReq)
+{
+ SfxItemSet aTmpSet( *pSet );
+ ::ConvertAttrGenToChar(aTmpSet, *pCoreSet);
+
+ const bool bWasLocked = rWrtSh.IsViewLocked();
+ if (bApplyToParagraph)
+ {
+ rWrtSh.StartAction();
+ rWrtSh.LockView(true);
+ rWrtSh.Push();
+ SwLangHelper::SelectCurrentPara(rWrtSh);
+ }
+
+ const SfxStringItem* pSelectionItem;
+ bool bInsert = false;
+ sal_Int32 nInsert = 0;
+
+ // The old item is for unknown reasons back in the set again.
+ if( !bSelectionPut && (pSelectionItem = aTmpSet.GetItemIfSet(FN_PARAM_SELECTION, false)) )
+ {
+ OUString sInsert = pSelectionItem->GetValue();
+ bInsert = !sInsert.isEmpty();
+ if(bInsert)
+ {
+ nInsert = sInsert.getLength();
+ rWrtSh.StartAction();
+ rWrtSh.Insert( sInsert );
+ rWrtSh.SetMark();
+ rWrtSh.ExtendSelection(false, sInsert.getLength());
+ SfxRequest aReq(rWrtSh.GetView().GetViewFrame(), FN_INSERT_STRING);
+ aReq.AppendItem( SfxStringItem( FN_INSERT_STRING, sInsert ) );
+ aReq.Done();
+ SfxRequest aReq1(rWrtSh.GetView().GetViewFrame(), FN_CHAR_LEFT);
+ aReq1.AppendItem( SfxInt32Item(FN_PARAM_MOVE_COUNT, nInsert) );
+ aReq1.AppendItem( SfxBoolItem(FN_PARAM_MOVE_SELECTION, true) );
+ aReq1.Done();
+ }
+ }
+ aTmpSet.ClearItem(FN_PARAM_SELECTION);
+
+ SwTextFormatColl* pColl = rWrtSh.GetCurTextFormatColl();
+ if(bSel && rWrtSh.IsSelFullPara() && pColl && pColl->IsAutoUpdateOnDirectFormat())
+ {
+ rWrtSh.AutoUpdatePara(pColl, aTmpSet);
+ }
+ else
+ rWrtSh.SetAttrSet( aTmpSet );
+ if (pReq)
+ pReq->Done(aTmpSet);
+ if(bInsert)
+ {
+ SfxRequest aReq1(rWrtSh.GetView().GetViewFrame(), FN_CHAR_RIGHT);
+ aReq1.AppendItem( SfxInt32Item(FN_PARAM_MOVE_COUNT, nInsert) );
+ aReq1.AppendItem( SfxBoolItem(FN_PARAM_MOVE_SELECTION, false) );
+ aReq1.Done();
+ rWrtSh.SwapPam();
+ rWrtSh.ClearMark();
+ rWrtSh.DontExpandFormat();
+ rWrtSh.EndAction();
+ }
+
+ if (bApplyToParagraph)
+ {
+ rWrtSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+ rWrtSh.LockView(bWasLocked);
+ rWrtSh.EndAction();
+ }
+}
+
+
+static void sw_ParagraphDialogResult(SfxItemSet* pSet, SwWrtShell &rWrtSh, SfxRequest& rReq, SwPaM* pPaM)
+{
+ if (!pSet)
+ return;
+
+ rReq.Done( *pSet );
+ ::SfxToSwPageDescAttr( rWrtSh, *pSet );
+ // #i56253#
+ // enclose all undos.
+ // Thus, check conditions, if actions will be performed.
+ const bool bUndoNeeded( pSet->Count() ||
+ SfxItemState::SET == pSet->GetItemState(FN_NUMBER_NEWSTART) ||
+ SfxItemState::SET == pSet->GetItemState(FN_NUMBER_NEWSTART_AT) );
+ if ( bUndoNeeded )
+ {
+ rWrtSh.StartUndo( SwUndoId::INSATTR );
+ }
+ if( pSet->Count() )
+ {
+ rWrtSh.StartAction();
+ if ( const SfxStringItem* pDropTextItem = pSet->GetItemIfSet(FN_DROP_TEXT, false) )
+ {
+ if ( !pDropTextItem->GetValue().isEmpty() )
+ rWrtSh.ReplaceDropText(pDropTextItem->GetValue(), pPaM);
+ }
+ rWrtSh.SetAttrSet(*pSet, SetAttrMode::DEFAULT, pPaM);
+ rWrtSh.EndAction();
+ SwTextFormatColl* pColl = rWrtSh.GetPaMTextFormatColl(pPaM);
+ if(pColl && pColl->IsAutoUpdateOnDirectFormat())
+ {
+ rWrtSh.AutoUpdatePara(pColl, *pSet, pPaM);
+ }
+ }
+
+ if( SfxItemState::SET == pSet->GetItemState(FN_NUMBER_NEWSTART) )
+ {
+ //SetNumRuleStart(true) restarts the numbering at the value
+ //that is defined at the starting point of the numbering level
+ //otherwise the SetNodeNumStart() value determines the start
+ //if it's set to something different than USHRT_MAX
+
+ bool bStart = static_cast<const SfxBoolItem&>(pSet->Get(FN_NUMBER_NEWSTART)).GetValue();
+
+ // Default value for restart value has to be USHRT_MAX
+ // in order to indicate that the restart value of the list
+ // style has to be used on restart.
+ sal_uInt16 nNumStart = USHRT_MAX;
+ if( SfxItemState::SET == pSet->GetItemState(FN_NUMBER_NEWSTART_AT) )
+ {
+ nNumStart = pSet->Get(FN_NUMBER_NEWSTART_AT).GetValue();
+ }
+ rWrtSh.SetNumRuleStart(bStart, pPaM);
+ rWrtSh.SetNodeNumStart(nNumStart);
+ }
+ else if( SfxItemState::SET == pSet->GetItemState(FN_NUMBER_NEWSTART_AT) )
+ {
+ rWrtSh.SetNodeNumStart(pSet->Get(FN_NUMBER_NEWSTART_AT).GetValue());
+ rWrtSh.SetNumRuleStart(false, pPaM);
+ }
+ // #i56253#
+ if ( bUndoNeeded )
+ {
+ rWrtSh.EndUndo( SwUndoId::INSATTR );
+ }
+}
+
+namespace {
+
+void InsertBreak(SwWrtShell& rWrtSh,
+ sal_uInt16 nKind,
+ ::std::optional<sal_uInt16> oPageNumber,
+ const OUString& rTemplateName, std::optional<SwLineBreakClear> oClear)
+{
+ switch ( nKind )
+ {
+ case 1 :
+ rWrtSh.InsertLineBreak(oClear);
+ break;
+ case 2 :
+ rWrtSh.InsertColumnBreak(); break;
+ case 3 :
+ {
+ rWrtSh.StartAllAction();
+ if( !rTemplateName.isEmpty() )
+ rWrtSh.InsertPageBreak( &rTemplateName, oPageNumber );
+ else
+ rWrtSh.InsertPageBreak();
+ rWrtSh.EndAllAction();
+ }
+ }
+}
+
+OUString GetLocalURL(const SwWrtShell& rSh)
+{
+ SwField* pField = rSh.GetCurField();
+ if (!pField)
+ {
+ return OUString();
+ }
+
+ if (pField->GetTyp()->Which() != SwFieldIds::TableOfAuthorities)
+ {
+ return OUString();
+ }
+
+ const auto& rAuthorityField = *static_cast<const SwAuthorityField*>(pField);
+ SwAuthEntry* pAuthEntry = rAuthorityField.GetAuthEntry();
+ if (!pAuthEntry)
+ {
+ return OUString();
+ }
+
+ const OUString& rLocalURL = pAuthEntry->GetAuthorField(AUTH_FIELD_LOCAL_URL);
+ return rLocalURL;
+}
+
+void UpdateSections(SfxRequest& rReq, SwWrtShell& rWrtSh)
+{
+ OUString aSectionNamePrefix;
+ const SfxStringItem* pSectionNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if (pSectionNamePrefix)
+ {
+ aSectionNamePrefix = pSectionNamePrefix->GetValue();
+ }
+
+ uno::Sequence<beans::PropertyValues> aSections;
+ const SfxUnoAnyItem* pSections = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_2);
+ if (pSections)
+ {
+ pSections->GetValue() >>= aSections;
+ }
+
+ rWrtSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::UPDATE_SECTIONS, nullptr);
+ rWrtSh.StartAction();
+
+ SwDoc* pDoc = rWrtSh.GetDoc();
+ sal_Int32 nSectionIndex = 0;
+ const SwSectionFormats& rFormats = pDoc->GetSections();
+ IDocumentContentOperations& rIDCO = pDoc->getIDocumentContentOperations();
+ for (size_t i = 0; i < rFormats.size(); ++i)
+ {
+ const SwSectionFormat* pFormat = rFormats[i];
+ if (!pFormat->GetName().startsWith(aSectionNamePrefix))
+ {
+ continue;
+ }
+
+ if (nSectionIndex >= aSections.getLength())
+ {
+ break;
+ }
+
+ comphelper::SequenceAsHashMap aMap(aSections[nSectionIndex++]);
+ OUString aSectionName = aMap["RegionName"].get<OUString>();
+ if (aSectionName != pFormat->GetName())
+ {
+ const_cast<SwSectionFormat*>(pFormat)->SetFormatName(aSectionName, /*bBroadcast=*/true);
+ SwSectionData aSectionData(*pFormat->GetSection());
+ aSectionData.SetSectionName(aSectionName);
+ pDoc->UpdateSection(i, aSectionData);
+ }
+
+ const SwFormatContent& rContent = pFormat->GetContent();
+ const SwNodeIndex* pContentNodeIndex = rContent.GetContentIdx();
+ if (pContentNodeIndex)
+ {
+ SwPaM aSectionStart(SwPosition{*pContentNodeIndex});
+ aSectionStart.Move(fnMoveForward, GoInContent);
+ SwPaM* pCursorPos = rWrtSh.GetCursor();
+ *pCursorPos = aSectionStart;
+ rWrtSh.EndOfSection(/*bSelect=*/true);
+ rIDCO.DeleteAndJoin(*pCursorPos);
+ rWrtSh.EndSelect();
+
+ OUString aSectionText = aMap["Content"].get<OUString>();
+ SwTranslateHelper::PasteHTMLToPaM(rWrtSh, pCursorPos, aSectionText.toUtf8());
+ }
+ }
+
+ rWrtSh.EndAction();
+ rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::UPDATE_SECTIONS, nullptr);
+}
+
+void DeleteSections(SfxRequest& rReq, SwWrtShell& rWrtSh)
+{
+ OUString aSectionNamePrefix;
+ const SfxStringItem* pSectionNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if (pSectionNamePrefix)
+ {
+ aSectionNamePrefix = pSectionNamePrefix->GetValue();
+ }
+
+ rWrtSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::DELETE_SECTIONS, nullptr);
+ rWrtSh.StartAction();
+ comphelper::ScopeGuard g(
+ [&rWrtSh]
+ {
+ rWrtSh.EndAction();
+ rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::DELETE_SECTIONS, nullptr);
+ });
+
+ SwDoc* pDoc = rWrtSh.GetDoc();
+ SwSectionFormats& rFormats = pDoc->GetSections();
+ std::vector<SwSectionFormat*> aRemovals;
+ for (size_t i = 0; i < rFormats.size(); ++i)
+ {
+ SwSectionFormat* pFormat = rFormats[i];
+
+ if (!aSectionNamePrefix.isEmpty())
+ {
+ if (!pFormat->GetName().startsWith(aSectionNamePrefix))
+ {
+ continue;
+ }
+ }
+
+ aRemovals.push_back(pFormat);
+ }
+
+ for (const auto& pFormat : aRemovals)
+ {
+ // Just delete the format, not the content of the section.
+ pDoc->DelSectionFormat(pFormat);
+ }
+}
+
+void UpdateBookmarks(SfxRequest& rReq, SwWrtShell& rWrtSh)
+{
+ if (rWrtSh.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS))
+ {
+ return;
+ }
+
+ OUString aBookmarkNamePrefix;
+ const SfxStringItem* pBookmarkNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if (pBookmarkNamePrefix)
+ {
+ aBookmarkNamePrefix = pBookmarkNamePrefix->GetValue();
+ }
+
+ uno::Sequence<beans::PropertyValues> aBookmarks;
+ const SfxUnoAnyItem* pBookmarks = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_2);
+ if (pBookmarks)
+ {
+ pBookmarks->GetValue() >>= aBookmarks;
+ }
+
+ rWrtSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::UPDATE_BOOKMARKS, nullptr);
+ rWrtSh.StartAction();
+
+ IDocumentMarkAccess& rIDMA = *rWrtSh.GetDoc()->getIDocumentMarkAccess();
+ sal_Int32 nBookmarkIndex = 0;
+ bool bSortMarks = false;
+ for (auto it = rIDMA.getBookmarksBegin(); it != rIDMA.getBookmarksEnd(); ++it)
+ {
+ auto pMark = dynamic_cast<sw::mark::Bookmark*>(*it);
+ assert(pMark);
+ if (!pMark->GetName().startsWith(aBookmarkNamePrefix))
+ {
+ continue;
+ }
+
+ if (aBookmarks.getLength() <= nBookmarkIndex)
+ {
+ continue;
+ }
+
+ comphelper::SequenceAsHashMap aMap(aBookmarks[nBookmarkIndex++]);
+ if (aMap["Bookmark"].get<OUString>() != pMark->GetName())
+ {
+ rIDMA.renameMark(pMark, aMap["Bookmark"].get<OUString>());
+ }
+
+ OUString aBookmarkText = aMap["BookmarkText"].get<OUString>();
+
+ // Insert markers to remember where the paste positions are.
+ SwPaM aMarkers(pMark->GetMarkEnd());
+ IDocumentContentOperations& rIDCO = rWrtSh.GetDoc()->getIDocumentContentOperations();
+ bool bSuccess = rIDCO.InsertString(aMarkers, "XY");
+ if (bSuccess)
+ {
+ SwPaM aPasteEnd(pMark->GetMarkEnd());
+ aPasteEnd.Move(fnMoveForward, GoInContent);
+
+ // Paste HTML content.
+ SwPaM* pCursorPos = rWrtSh.GetCursor();
+ *pCursorPos = aPasteEnd;
+ SwTranslateHelper::PasteHTMLToPaM(rWrtSh, pCursorPos, aBookmarkText.toUtf8());
+
+ // Update the bookmark to point to the new content.
+ SwPaM aPasteStart(pMark->GetMarkEnd());
+ aPasteStart.Move(fnMoveForward, GoInContent);
+ SwPaM aStartMarker(pMark->GetMarkStart(), *aPasteStart.GetPoint());
+ SwPaM aEndMarker(*aPasteEnd.GetPoint(), *aPasteEnd.GetPoint());
+ aEndMarker.GetMark()->AdjustContent(1);
+ pMark->SetMarkPos(*aPasteStart.GetPoint());
+ pMark->SetOtherMarkPos(*aPasteEnd.GetPoint());
+ bSortMarks = true;
+
+ // Remove markers. the start marker includes the old content as well.
+ rIDCO.DeleteAndJoin(aStartMarker);
+ rIDCO.DeleteAndJoin(aEndMarker);
+ }
+ }
+ if (bSortMarks)
+ {
+ rIDMA.assureSortedMarkContainers();
+ }
+
+ rWrtSh.EndAction();
+ rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::UPDATE_BOOKMARKS, nullptr);
+}
+
+void UpdateBookmark(SfxRequest& rReq, SwWrtShell& rWrtSh)
+{
+ if (rWrtSh.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS))
+ {
+ return;
+ }
+
+ OUString aBookmarkNamePrefix;
+ const SfxStringItem* pBookmarkNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if (pBookmarkNamePrefix)
+ {
+ aBookmarkNamePrefix = pBookmarkNamePrefix->GetValue();
+ }
+
+ uno::Sequence<beans::PropertyValue> aBookmark;
+ const SfxUnoAnyItem* pBookmarks = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_2);
+ if (pBookmarks)
+ {
+ pBookmarks->GetValue() >>= aBookmark;
+ }
+
+ IDocumentMarkAccess& rIDMA = *rWrtSh.GetDoc()->getIDocumentMarkAccess();
+ SwPosition& rCursor = *rWrtSh.GetCursor()->GetPoint();
+ auto pBookmark = dynamic_cast<sw::mark::Bookmark*>(rIDMA.getOneInnermostBookmarkFor(rCursor));
+ if (!pBookmark || !pBookmark->GetName().startsWith(aBookmarkNamePrefix))
+ {
+ return;
+ }
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, pBookmark->GetName());
+ rWrtSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::UPDATE_BOOKMARK, &aRewriter);
+ rWrtSh.StartAction();
+ comphelper::ScopeGuard g(
+ [&rWrtSh, &aRewriter]
+ {
+ rWrtSh.EndAction();
+ rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::UPDATE_BOOKMARK, &aRewriter);
+ });
+
+
+ comphelper::SequenceAsHashMap aMap(aBookmark);
+ if (aMap["Bookmark"].get<OUString>() != pBookmark->GetName())
+ {
+ rIDMA.renameMark(pBookmark, aMap["Bookmark"].get<OUString>());
+ }
+
+ // Insert markers to remember where the paste positions are.
+ SwPaM aMarkers(pBookmark->GetMarkEnd());
+ IDocumentContentOperations& rIDCO = rWrtSh.GetDoc()->getIDocumentContentOperations();
+ if (!rIDCO.InsertString(aMarkers, "XY"))
+ {
+ return;
+ }
+
+ SwPaM aPasteEnd(pBookmark->GetMarkEnd());
+ aPasteEnd.Move(fnMoveForward, GoInContent);
+
+ OUString aBookmarkText = aMap["BookmarkText"].get<OUString>();
+
+ // Paste HTML content.
+ SwPaM* pCursorPos = rWrtSh.GetCursor();
+ *pCursorPos = aPasteEnd;
+ SwTranslateHelper::PasteHTMLToPaM(rWrtSh, pCursorPos, aBookmarkText.toUtf8());
+
+ // Update the bookmark to point to the new content.
+ SwPaM aPasteStart(pBookmark->GetMarkEnd());
+ aPasteStart.Move(fnMoveForward, GoInContent);
+ SwPaM aStartMarker(pBookmark->GetMarkStart(), *aPasteStart.GetPoint());
+ SwPaM aEndMarker(*aPasteEnd.GetPoint(), *aPasteEnd.GetPoint());
+ aEndMarker.GetMark()->AdjustContent(1);
+ pBookmark->SetMarkPos(*aPasteStart.GetPoint());
+ pBookmark->SetOtherMarkPos(*aPasteEnd.GetPoint());
+
+ // Remove markers. the start marker includes the old content as well.
+ rIDCO.DeleteAndJoin(aStartMarker);
+ rIDCO.DeleteAndJoin(aEndMarker);
+ rIDMA.assureSortedMarkContainers();
+}
+
+void DeleteBookmarks(SfxRequest& rReq, SwWrtShell& rWrtSh)
+{
+ if (rWrtSh.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS))
+ {
+ return;
+ }
+
+ OUString aBookmarkNamePrefix;
+ const SfxStringItem* pBookmarkNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if (pBookmarkNamePrefix)
+ {
+ aBookmarkNamePrefix = pBookmarkNamePrefix->GetValue();
+ }
+
+ rWrtSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::DELETE_BOOKMARKS, nullptr);
+ rWrtSh.StartAction();
+ comphelper::ScopeGuard g(
+ [&rWrtSh]
+ {
+ rWrtSh.EndAction();
+ rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::DELETE_BOOKMARKS, nullptr);
+ });
+
+ IDocumentMarkAccess* pMarkAccess = rWrtSh.GetDoc()->getIDocumentMarkAccess();
+ std::vector<sw::mark::IMark*> aRemovals;
+ for (auto it = pMarkAccess->getBookmarksBegin(); it != pMarkAccess->getBookmarksEnd(); ++it)
+ {
+ auto pBookmark = dynamic_cast<sw::mark::Bookmark*>(*it);
+ assert(pBookmark);
+
+ if (!aBookmarkNamePrefix.isEmpty())
+ {
+ if (!pBookmark->GetName().startsWith(aBookmarkNamePrefix))
+ {
+ continue;
+ }
+ }
+
+ aRemovals.push_back(pBookmark);
+ }
+
+ for (const auto& pMark : aRemovals)
+ {
+ pMarkAccess->deleteMark(pMark);
+ }
+}
+
+void DeleteFields(SfxRequest& rReq, SwWrtShell& rWrtSh)
+{
+ const SfxStringItem* pTypeName = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if (!pTypeName || pTypeName->GetValue() != "SetRef")
+ {
+ // This is implemented so far only for reference marks.
+ return;
+ }
+
+ OUString aNamePrefix;
+ const SfxStringItem* pNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
+ if (pNamePrefix)
+ {
+ aNamePrefix = pNamePrefix->GetValue();
+ }
+
+ SwDoc* pDoc = rWrtSh.GetDoc();
+ pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::DELETE_FIELDS, nullptr);
+ rWrtSh.StartAction();
+ comphelper::ScopeGuard g(
+ [&rWrtSh]
+ {
+ rWrtSh.EndAction();
+ rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::DELETE_FIELDS, nullptr);
+ });
+
+ std::vector<const SwFormatRefMark*> aRemovals;
+ for (sal_uInt16 i = 0; i < pDoc->GetRefMarks(); ++i)
+ {
+ const SwFormatRefMark* pRefMark = pDoc->GetRefMark(i);
+ if (!aNamePrefix.isEmpty())
+ {
+ if (!pRefMark->GetRefName().startsWith(aNamePrefix))
+ {
+ continue;
+ }
+ }
+
+ aRemovals.push_back(pRefMark);
+ }
+
+ for (const auto& pMark : aRemovals)
+ {
+ pDoc->DeleteFormatRefMark(pMark);
+ }
+}
+}
+
+void SwTextShell::Execute(SfxRequest &rReq)
+{
+ bool bUseDialog = true;
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ SwWrtShell& rWrtSh = GetShell();
+ const SfxPoolItem* pItem = nullptr;
+ const sal_uInt16 nSlot = rReq.GetSlot();
+ if(pArgs)
+ pArgs->GetItemState(GetPool().GetWhich(nSlot), false, &pItem);
+ switch( nSlot )
+ {
+ case SID_UNICODE_NOTATION_TOGGLE:
+ {
+ tools::Long nMaxUnits = 256;
+ sal_Int32 nSelLength = rWrtSh.GetSelText().getLength();
+ if( rWrtSh.IsSelection() && !rWrtSh.IsMultiSelection() && (nSelLength < nMaxUnits) )
+ nMaxUnits = nSelLength;
+
+ tools::Long index = 0;
+ ToggleUnicodeCodepoint aToggle;
+ while( nMaxUnits-- && aToggle.AllowMoreInput(rWrtSh.GetChar(true, index-1)) )
+ --index;
+
+ OUString sReplacement = aToggle.ReplacementString();
+ if( !sReplacement.isEmpty() )
+ {
+ if (rWrtSh.HasReadonlySel() && !rWrtSh.CursorInsideInputField())
+ {
+ // Only break if there's something to do; don't nag with the dialog otherwise
+ rWrtSh.InfoReadOnlyDialog(false);
+ break;
+ }
+ SwRewriter aRewriter;
+ aRewriter.AddRule( UndoArg1, aToggle.StringToReplace() );
+ aRewriter.AddRule( UndoArg2, SwResId(STR_YIELDS) );
+ aRewriter.AddRule( UndoArg3, sReplacement );
+ rWrtSh.StartUndo(SwUndoId::REPLACE, &aRewriter);
+ rWrtSh.GetCursor()->Normalize(false);
+
+ rWrtSh.ClearMark();
+ if( rWrtSh.IsInSelect() ) // cancel any in-progress keyboard selection as well
+ rWrtSh.EndSelect();
+
+ for( sal_uInt32 i=aToggle.CharsToDelete(); i > 0; --i )
+ rWrtSh.DelLeft();
+ rWrtSh.Insert2( sReplacement );
+ rWrtSh.EndUndo(SwUndoId::REPLACE, &aRewriter);
+ }
+ }
+ break;
+
+ case SID_LANGUAGE_STATUS:
+ {
+ // get the language
+ OUString aNewLangText;
+ const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(SID_LANGUAGE_STATUS);
+ if (pItem2)
+ aNewLangText = pItem2->GetValue();
+
+ //!! Remember the view frame right now...
+ //!! (call to GetView().GetViewFrame() will break if the
+ //!! SwTextShell got destroyed meanwhile.)
+ SfxViewFrame& rViewFrame = GetView().GetViewFrame();
+
+ if (aNewLangText == "*")
+ {
+ // open the dialog "Tools/Options/Languages and Locales - General"
+ // to set the documents default language
+ SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateVclDialog(GetView().GetFrameWeld(), SID_LANGUAGE_OPTIONS));
+ pDlg->Execute();
+ }
+ else
+ {
+ //!! We have to use StartAction / EndAction bracketing in
+ //!! order to prevent possible destruction of the SwTextShell
+ //!! due to the selection changes coming below.
+ rWrtSh.StartAction();
+ // prevent view from jumping because of (temporary) selection changes
+ rWrtSh.LockView( true );
+
+ // setting the new language...
+ if (!aNewLangText.isEmpty())
+ {
+ static constexpr OUString aSelectionLangPrefix(u"Current_"_ustr);
+ static constexpr OUString aParagraphLangPrefix(u"Paragraph_"_ustr);
+ static constexpr OUString aDocumentLangPrefix(u"Default_"_ustr);
+
+ SfxItemSetFixed
+ <RES_CHRATR_LANGUAGE, RES_CHRATR_LANGUAGE,
+ RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_LANGUAGE,
+ RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_LANGUAGE> aCoreSet( GetPool() );
+
+ sal_Int32 nPos = 0;
+ bool bForSelection = true;
+ bool bForParagraph = false;
+ if (-1 != (nPos = aNewLangText.indexOf( aSelectionLangPrefix )))
+ {
+ // ... for the current selection
+ aNewLangText = aNewLangText.replaceAt(nPos, aSelectionLangPrefix.getLength(), u"");
+ bForSelection = true;
+ }
+ else if (-1 != (nPos = aNewLangText.indexOf(aParagraphLangPrefix)))
+ {
+ // ... for the current paragraph language
+ aNewLangText = aNewLangText.replaceAt(nPos, aParagraphLangPrefix.getLength(), u"");
+ bForSelection = true;
+ bForParagraph = true;
+ }
+ else if (-1 != (nPos = aNewLangText.indexOf(aDocumentLangPrefix)))
+ {
+ // ... as default document language
+ aNewLangText = aNewLangText.replaceAt(nPos, aDocumentLangPrefix.getLength(), u"");
+ bForSelection = false;
+ }
+
+ if (bForParagraph || !bForSelection)
+ {
+ rWrtSh.Push(); // save selection for later restoration
+ rWrtSh.ClearMark(); // fdo#67796: invalidate table crsr
+ }
+
+ if (bForParagraph)
+ SwLangHelper::SelectCurrentPara( rWrtSh );
+
+ if (!bForSelection) // document language to be changed...
+ {
+ rWrtSh.SelAll();
+ rWrtSh.ExtendedSelectAll();
+ }
+
+ rWrtSh.StartUndo( ( !bForParagraph && !bForSelection ) ? SwUndoId::SETDEFTATTR : SwUndoId::EMPTY );
+ if (aNewLangText == "LANGUAGE_NONE")
+ SwLangHelper::SetLanguage_None( rWrtSh, bForSelection, aCoreSet );
+ else if (aNewLangText == "RESET_LANGUAGES")
+ SwLangHelper::ResetLanguages( rWrtSh );
+ else
+ SwLangHelper::SetLanguage( rWrtSh, aNewLangText, bForSelection, aCoreSet );
+ rWrtSh.EndUndo();
+
+ if (bForParagraph || !bForSelection)
+ {
+ rWrtSh.Pop(SwCursorShell::PopMode::DeleteCurrent); // restore selection...
+ }
+ }
+
+ rWrtSh.LockView( false );
+ rWrtSh.EndAction();
+ }
+
+ // invalidate slot to get the new language displayed
+ rViewFrame.GetBindings().Invalidate( nSlot );
+
+ rReq.Done();
+ break;
+ }
+
+ case SID_THES:
+ {
+ // replace word/selection with text from selected sub menu entry
+ OUString aReplaceText;
+ const SfxStringItem* pItem2 = rReq.GetArg(FN_PARAM_THES_WORD_REPLACE);
+ if (pItem2)
+ aReplaceText = pItem2->GetValue();
+ if (!aReplaceText.isEmpty())
+ {
+ SwView &rView2 = rWrtSh.GetView();
+ const bool bSelection = rWrtSh.HasSelection();
+ const OUString aLookUpText = rView2.GetThesaurusLookUpText( bSelection );
+ rView2.InsertThesaurusSynonym( aReplaceText, aLookUpText, bSelection );
+ }
+ }
+ break;
+
+ case SID_CHARMAP:
+ {
+ InsertSymbol( rReq );
+ }
+ break;
+ case FN_INSERT_FOOTNOTE:
+ case FN_INSERT_ENDNOTE:
+ {
+ OUString aStr;
+ const SfxStringItem* pFont = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ const SfxStringItem* pNameItem = rReq.GetArg<SfxStringItem>(nSlot);
+ if ( pNameItem )
+ aStr = pNameItem->GetValue();
+ bool bFont = pFont && !pFont->GetValue().isEmpty();
+ rWrtSh.StartUndo( SwUndoId::UI_INSERT_FOOTNOTE );
+ rWrtSh.InsertFootnote( aStr, nSlot == FN_INSERT_ENDNOTE, !bFont );
+ if ( bFont )
+ {
+ rWrtSh.Left( SwCursorSkipMode::Chars, true, 1, false );
+ SfxItemSetFixed<RES_CHRATR_FONT, RES_CHRATR_FONT> aSet( rWrtSh.GetAttrPool() );
+ rWrtSh.GetCurAttr( aSet );
+ rWrtSh.SetAttrSet( aSet, SetAttrMode::DONTEXPAND );
+ rWrtSh.ResetSelect(nullptr, false);
+ rWrtSh.EndSelect();
+ rWrtSh.GotoFootnoteText();
+ }
+ rWrtSh.EndUndo( SwUndoId::UI_INSERT_FOOTNOTE );
+ rReq.Done();
+ }
+ break;
+ case FN_INSERT_FOOTNOTE_DLG:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractInsFootNoteDlg> pDlg(pFact->CreateInsFootNoteDlg(
+ GetView().GetFrameWeld(), rWrtSh));
+ pDlg->SetHelpId(GetStaticInterface()->GetSlot(nSlot)->GetCommand());
+ if ( pDlg->Execute() == RET_OK )
+ {
+ const sal_uInt16 nId = pDlg->IsEndNote() ? FN_INSERT_ENDNOTE : FN_INSERT_FOOTNOTE;
+ SfxRequest aReq(GetView().GetViewFrame(), nId);
+ if ( !pDlg->GetStr().isEmpty() )
+ aReq.AppendItem( SfxStringItem( nId, pDlg->GetStr() ) );
+ if ( !pDlg->GetFontName().isEmpty() )
+ aReq.AppendItem( SfxStringItem( FN_PARAM_1, pDlg->GetFontName() ) );
+ ExecuteSlot( aReq );
+ }
+
+ rReq.Ignore();
+ }
+ break;
+ case FN_FORMAT_FOOTNOTE_DLG:
+ case FN_FORMAT_CURRENT_FOOTNOTE_DLG:
+ {
+ GetView().ExecFormatFootnote();
+ break;
+ }
+ case SID_INSERTDOC:
+ {
+ GetView().ExecuteInsertDoc( rReq, pItem );
+ break;
+ }
+ case FN_FORMAT_RESET:
+ {
+ // #i78856, reset all attributes but not the language attributes
+ // (for this build an array of all relevant attributes and
+ // remove the languages from that)
+ o3tl::sorted_vector<sal_uInt16> aAttribs;
+
+ constexpr std::pair<sal_uInt16, sal_uInt16> aResetableSetRange[] = {
+ // tdf#40496: we don't want to change writing direction, so exclude RES_FRAMEDIR:
+ { RES_FRMATR_BEGIN, RES_FRAMEDIR - 1 },
+ { RES_FRAMEDIR + 1, RES_FRMATR_END - 1 },
+ { RES_CHRATR_BEGIN, RES_CHRATR_LANGUAGE - 1 },
+ { RES_CHRATR_LANGUAGE + 1, RES_CHRATR_CJK_LANGUAGE - 1 },
+ { RES_CHRATR_CJK_LANGUAGE + 1, RES_CHRATR_CTL_LANGUAGE - 1 },
+ { RES_CHRATR_CTL_LANGUAGE + 1, RES_CHRATR_END - 1 },
+ { RES_PARATR_BEGIN, RES_PARATR_END - 1 },
+ { RES_PARATR_LIST_AUTOFMT, RES_PARATR_LIST_AUTOFMT },
+ { RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER },
+ { RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END - 1 },
+ };
+ for (const auto& [nBegin, nEnd] : aResetableSetRange)
+ {
+ for (sal_uInt16 i = nBegin; i <= nEnd; ++i)
+ aAttribs.insert( i );
+ }
+ rWrtSh.ResetAttr( aAttribs );
+
+ // also clear the direct formatting flag inside SwTableBox(es)
+ if (SwFEShell* pFEShell = GetView().GetDocShell()->GetFEShell())
+ pFEShell->UpdateTableStyleFormatting(nullptr, true);
+
+ rReq.Done();
+ break;
+ }
+ case FN_INSERT_BREAK_DLG:
+ {
+ if ( pItem )
+ {
+ ::std::optional<sal_uInt16> oPageNumber;
+ std::optional<SwLineBreakClear> oClear;
+ OUString aTemplateName;
+ sal_uInt16 nKind = static_cast<const SfxInt16Item*>(pItem)->GetValue();
+ const SfxStringItem* pTemplate = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ const SfxUInt16Item* pNumber = rReq.GetArg<SfxUInt16Item>(FN_PARAM_2);
+ const SfxBoolItem* pIsNumberFilled = rReq.GetArg<SfxBoolItem>(FN_PARAM_3);
+ if ( pTemplate )
+ aTemplateName = pTemplate->GetValue();
+ if ( pNumber && pIsNumberFilled && pIsNumberFilled->GetValue() )
+ oPageNumber = pNumber->GetValue();
+
+ InsertBreak(rWrtSh, nKind, oPageNumber, aTemplateName, oClear);
+ }
+ else
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+
+ std::shared_ptr<AbstractSwBreakDlg> pAbstractDialog(pFact->CreateSwBreakDlg(GetView().GetFrameWeld(), rWrtSh));
+ std::shared_ptr<weld::DialogController> pDialogController(pAbstractDialog->getDialogController());
+
+ weld::DialogController::runAsync(pDialogController,
+ [pAbstractDialog, &rWrtSh] (sal_Int32 nResult) {
+ if( RET_OK == nResult )
+ {
+ sal_uInt16 nKind = pAbstractDialog->GetKind();
+ OUString aTemplateName = pAbstractDialog->GetTemplateName();
+ ::std::optional<sal_uInt16> oPageNumber = pAbstractDialog->GetPageNumber();
+ std::optional<SwLineBreakClear> oClear = pAbstractDialog->GetClear();
+
+ InsertBreak(rWrtSh, nKind, oPageNumber, aTemplateName, oClear);
+ }
+ });
+ }
+
+ break;
+ }
+ case FN_INSERT_BOOKMARK:
+ {
+ const SfxStringItem* pBookmarkText = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ SwPaM* pCursorPos = rWrtSh.GetCursor();
+ if ( pItem )
+ {
+ rWrtSh.StartAction();
+ OUString sName = static_cast<const SfxStringItem*>(pItem)->GetValue();
+
+ if (pBookmarkText)
+ {
+ OUString aBookmarkText = pBookmarkText->GetValue();
+ // Split node to remember where the start position is.
+ bool bSuccess = rWrtSh.GetDoc()->getIDocumentContentOperations().SplitNode(
+ *pCursorPos->GetPoint(), /*bChkTableStart=*/false);
+ if (bSuccess)
+ {
+ SwPaM aBookmarkPam(*pCursorPos->GetPoint());
+ aBookmarkPam.Move(fnMoveBackward, GoInContent);
+
+ // Paste HTML content.
+ SwTranslateHelper::PasteHTMLToPaM(
+ rWrtSh, pCursorPos, aBookmarkText.toUtf8());
+ if (pCursorPos->GetPoint()->GetContentIndex() == 0)
+ {
+ // The paste created a last empty text node, remove it.
+ SwPaM aPam(*pCursorPos->GetPoint());
+ aPam.SetMark();
+ aPam.Move(fnMoveBackward, GoInContent);
+ rWrtSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(aPam);
+ }
+
+ // Undo the above SplitNode().
+ aBookmarkPam.SetMark();
+ aBookmarkPam.Move(fnMoveForward, GoInContent);
+ rWrtSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(
+ aBookmarkPam);
+ *aBookmarkPam.GetMark() = *pCursorPos->GetPoint();
+ *pCursorPos = aBookmarkPam;
+ }
+ }
+
+ rWrtSh.SetBookmark( vcl::KeyCode(), sName );
+ if (pBookmarkText)
+ {
+ pCursorPos->DeleteMark();
+ }
+ rWrtSh.EndAction();
+ break;
+ }
+ [[fallthrough]];
+ }
+ case FN_EDIT_BOOKMARK:
+ {
+ ::std::optional<OUString> oName;
+ if (pItem)
+ {
+ oName.emplace(static_cast<const SfxStringItem*>(pItem)->GetValue());
+ }
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateSwInsertBookmarkDlg(GetView().GetFrameWeld(), rWrtSh, oName ? &*oName : nullptr));
+ VclAbstractDialog::AsyncContext aContext;
+ aContext.maEndDialogFn = [](sal_Int32){};
+ pDlg->StartExecuteAsync(aContext);
+ }
+
+ break;
+ }
+ case FN_UPDATE_BOOKMARKS:
+ {
+ // This updates all bookmarks in the document that match the conditions specified in
+ // rReq.
+ UpdateBookmarks(rReq, rWrtSh);
+ break;
+ }
+ case FN_UPDATE_BOOKMARK:
+ {
+ // This updates the bookmark under the cursor.
+ UpdateBookmark(rReq, rWrtSh);
+ break;
+ }
+ case FN_DELETE_BOOKMARK:
+ {
+ // This deletes a bookmark with the specified name.
+ if (pItem && !rWrtSh.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS))
+ {
+ IDocumentMarkAccess* const pMarkAccess = rWrtSh.getIDocumentMarkAccess();
+ pMarkAccess->deleteMark(pMarkAccess->findMark(static_cast<const SfxStringItem*>(pItem)->GetValue()), false);
+ }
+ break;
+ }
+ case FN_DELETE_BOOKMARKS:
+ {
+ // This deletes all bookmarks in the document matching a specified prefix.
+ DeleteBookmarks(rReq, rWrtSh);
+ break;
+ }
+ case FN_DELETE_FIELDS:
+ {
+ // This deletes all fields in the document matching a specified type & prefix.
+ DeleteFields(rReq, rWrtSh);
+ break;
+ }
+ case FN_UPDATE_SECTIONS:
+ {
+ UpdateSections(rReq, rWrtSh);
+ break;
+ }
+ case FN_DELETE_SECTIONS:
+ {
+ // This deletes all sections in the document matching a specified prefix. Note that the
+ // section is deleted, but not its contents.
+ DeleteSections(rReq, rWrtSh);
+ break;
+ }
+ case FN_SET_REMINDER:
+ {
+ // collect and sort navigator reminder names
+ IDocumentMarkAccess* const pMarkAccess = rWrtSh.getIDocumentMarkAccess();
+ std::vector< OUString > vNavMarkNames;
+ for(IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getAllMarksBegin();
+ ppMark != pMarkAccess->getAllMarksEnd();
+ ++ppMark)
+ {
+ if( IDocumentMarkAccess::GetType(**ppMark) == IDocumentMarkAccess::MarkType::NAVIGATOR_REMINDER )
+ vNavMarkNames.push_back((*ppMark)->GetName());
+ }
+ std::sort(vNavMarkNames.begin(), vNavMarkNames.end());
+
+ // we are maxed out so delete the first one
+ // this assumes that IDocumentMarkAccess generates Names in ascending order
+ if(vNavMarkNames.size() == MAX_MARKS)
+ pMarkAccess->deleteMark(pMarkAccess->findMark(vNavMarkNames[0]), false);
+
+ rWrtSh.SetBookmark(vcl::KeyCode(), OUString(), IDocumentMarkAccess::MarkType::NAVIGATOR_REMINDER);
+ SwView::SetActMark(vNavMarkNames.size() < MAX_MARKS ? vNavMarkNames.size() : MAX_MARKS-1);
+
+ break;
+ }
+ case FN_AUTOFORMAT_REDLINE_APPLY:
+ {
+ SvxSwAutoFormatFlags aFlags(SvxAutoCorrCfg::Get().GetAutoCorrect()->GetSwFlags());
+ // This must always be false for the postprocessing.
+ aFlags.bAFormatByInput = false;
+ aFlags.bWithRedlining = true;
+ rWrtSh.AutoFormat( &aFlags, false );
+ aFlags.bWithRedlining = false;
+
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+ if (rVFrame.HasChildWindow(FN_REDLINE_ACCEPT))
+ rVFrame.ToggleChildWindow(FN_REDLINE_ACCEPT);
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractSwModalRedlineAcceptDlg> xDlg(pFact->CreateSwModalRedlineAcceptDlg(GetView().GetEditWin().GetFrameWeld()));
+
+ xDlg->Execute();
+ rReq.Done();
+ }
+ break;
+
+ case FN_AUTOFORMAT_APPLY:
+ {
+ SvxSwAutoFormatFlags aFlags(SvxAutoCorrCfg::Get().GetAutoCorrect()->GetSwFlags());
+ // This must always be false for the postprocessing.
+ aFlags.bAFormatByInput = false;
+ rWrtSh.AutoFormat( &aFlags, false );
+ rReq.Done();
+ }
+ break;
+ case FN_AUTOFORMAT_AUTO:
+ {
+ SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get();
+ bool bSet = pItem ? static_cast<const SfxBoolItem*>(pItem)->GetValue() : !rACfg.IsAutoFormatByInput();
+ if( bSet != rACfg.IsAutoFormatByInput() )
+ {
+ rACfg.SetAutoFormatByInput( bSet );
+ rACfg.Commit();
+ GetView().GetViewFrame().GetBindings().Invalidate( nSlot );
+ if ( !pItem )
+ rReq.AppendItem( SfxBoolItem( GetPool().GetWhich(nSlot), bSet ) );
+ rReq.Done();
+ }
+ }
+ break;
+ case FN_AUTO_CORRECT:
+ {
+ // At first set to blank as default.
+ rWrtSh.AutoCorrect( *SvxAutoCorrCfg::Get().GetAutoCorrect(), ' ' );
+ rReq.Done();
+ }
+ break;
+ case FN_TABLE_SORT_DIALOG:
+ case FN_SORTING_DLG:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateSwSortingDialog(GetView().GetFrameWeld(), rWrtSh));
+ pDlg->Execute();
+ rReq.Done();
+ }
+ break;
+ case FN_NUMBERING_OUTLINE_DLG:
+ {
+ GetView().ExecNumberingOutline(GetPool());
+ rReq.Done();
+ }
+ break;
+ case FN_CALCULATE:
+ {
+ rtl::Reference<SwTransferable> pTransfer = new SwTransferable( rWrtSh );
+ pTransfer->CalculateAndCopy();
+ rReq.Done();
+ }
+ break;
+ case FN_GOTO_REFERENCE:
+ {
+ SwField *pField = rWrtSh.GetCurField();
+ if(pField && pField->GetTypeId() == SwFieldTypesEnum::GetRef)
+ {
+ rWrtSh.StartAllAction();
+ rWrtSh.SwCursorShell::GotoRefMark( static_cast<SwGetRefField*>(pField)->GetSetRefName(),
+ static_cast<SwGetRefField*>(pField)->GetSubType(),
+ static_cast<SwGetRefField*>(pField)->GetSeqNo(),
+ static_cast<SwGetRefField*>(pField)->GetFlags() );
+ rWrtSh.EndAllAction();
+ rReq.Done();
+ }
+ }
+ break;
+ case FN_EDIT_FORMULA:
+ {
+ const sal_uInt16 nId = SwInputChild::GetChildWindowId();
+ SfxViewFrame& rVFrame = GetView().GetViewFrame();
+ if(pItem)
+ {
+ //if the ChildWindow is active it has to be removed
+ if( rVFrame.HasChildWindow( nId ) )
+ {
+ rVFrame.ToggleChildWindow( nId );
+ rVFrame.GetBindings().InvalidateAll( true );
+ }
+
+ OUString sFormula(static_cast<const SfxStringItem*>(pItem)->GetValue());
+ SwFieldMgr aFieldMgr;
+ rWrtSh.StartAllAction();
+ bool bDelSel = rWrtSh.HasSelection();
+ if( bDelSel )
+ {
+ rWrtSh.StartUndo( SwUndoId::START );
+ rWrtSh.DelRight();
+ }
+ else
+ {
+ rWrtSh.EnterStdMode();
+ }
+
+ if( !bDelSel && aFieldMgr.GetCurField() && SwFieldTypesEnum::Formel == aFieldMgr.GetCurTypeId() )
+ aFieldMgr.UpdateCurField( aFieldMgr.GetCurField()->GetFormat(), OUString(), sFormula );
+ else if( !sFormula.isEmpty() )
+ {
+ if( rWrtSh.IsCursorInTable() )
+ {
+ SfxItemSetFixed<RES_BOXATR_FORMULA, RES_BOXATR_FORMULA> aSet( rWrtSh.GetAttrPool() );
+ aSet.Put( SwTableBoxFormula( sFormula ));
+ rWrtSh.SetTableBoxFormulaAttrs( aSet );
+ rWrtSh.UpdateTable();
+ }
+ else
+ {
+ SvNumberFormatter* pFormatter = rWrtSh.GetNumberFormatter();
+ const sal_uInt32 nSysNumFormat = pFormatter->GetFormatIndex( NF_NUMBER_STANDARD, LANGUAGE_SYSTEM);
+ SwInsertField_Data aData(SwFieldTypesEnum::Formel, nsSwGetSetExpType::GSE_FORMULA, OUString(), sFormula, nSysNumFormat);
+ aFieldMgr.InsertField(aData);
+ }
+ }
+
+ if( bDelSel )
+ rWrtSh.EndUndo( SwUndoId::END );
+ rWrtSh.EndAllAction();
+ rReq.Done();
+ }
+ else
+ {
+ rWrtSh.EndAllTableBoxEdit();
+ rVFrame.ToggleChildWindow( nId );
+ if( !rVFrame.HasChildWindow( nId ) )
+ rVFrame.GetBindings().InvalidateAll( true );
+ rReq.Ignore();
+ }
+ }
+
+ break;
+ case FN_TABLE_UNSET_READ_ONLY:
+ {
+ rWrtSh.UnProtectTables();
+ }
+ break;
+ case SID_EDIT_HYPERLINK:
+ GetView().GetViewFrame().SetChildWindow(SID_HYPERLINK_DIALOG, true);
+ break;
+ case SID_REMOVE_HYPERLINK:
+ {
+ bool bSel = rWrtSh.HasSelection();
+ if(!bSel)
+ {
+ rWrtSh.StartAction();
+ rWrtSh.Push();
+ if(!rWrtSh.SelectTextAttr( RES_TXTATR_INETFMT ))
+ rWrtSh.SelWrd();
+ }
+ //now remove the attribute
+ rWrtSh.ResetAttr({ RES_TXTATR_INETFMT });
+ if(!bSel)
+ {
+ rWrtSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+ rWrtSh.EndAction();
+ }
+ }
+ break;
+ case SID_ATTR_BRUSH_CHAR :
+ case SID_ATTR_CHAR_SCALEWIDTH :
+ case SID_ATTR_CHAR_ROTATED :
+ case FN_TXTATR_INET :
+ case FN_INSERT_HYPERLINK:
+ {
+ const sal_uInt16 nWhich = GetPool().GetWhich( nSlot );
+ if ( pArgs && pArgs->GetItemState( nWhich ) == SfxItemState::SET )
+ bUseDialog = false;
+ [[fallthrough]];
+ }
+ case SID_CHAR_DLG:
+ case SID_CHAR_DLG_EFFECT:
+ case SID_CHAR_DLG_POSITION:
+ {
+ sw_CharDialog(rWrtSh, bUseDialog, /*ApplyToParagraph*/false, nSlot, pArgs, &rReq);
+ }
+ break;
+ case SID_CHAR_DLG_FOR_PARAGRAPH:
+ {
+ sw_CharDialog(rWrtSh, /*UseDialog*/true, /*ApplyToParagraph*/true, nSlot, pArgs, &rReq);
+ }
+ break;
+ case SID_ATTR_LRSPACE :
+ case SID_ATTR_ULSPACE :
+ case SID_ATTR_BRUSH :
+ case SID_PARA_VERTALIGN :
+ case SID_ATTR_PARA_NUMRULE :
+ case SID_ATTR_PARA_REGISTER :
+ case SID_ATTR_PARA_PAGENUM :
+ case FN_FORMAT_LINENUMBER :
+ case FN_NUMBER_NEWSTART :
+ case FN_NUMBER_NEWSTART_AT :
+ case FN_FORMAT_DROPCAPS :
+ case FN_DROP_TEXT:
+ case SID_ATTR_PARA_LRSPACE:
+ {
+ const sal_uInt16 nWhich = GetPool().GetWhich( nSlot );
+ if ( pArgs && pArgs->GetItemState( nWhich ) == SfxItemState::SET )
+ bUseDialog = false;
+ [[fallthrough]];
+ }
+ case SID_PARA_DLG:
+ {
+ SwPaM* pPaM = nullptr;
+
+ if ( pArgs )
+ {
+ const SwPaMItem* pPaMItem = pArgs->GetItemIfSet( GetPool().GetWhich( FN_PARAM_PAM ), false );
+ if ( pPaMItem )
+ pPaM = pPaMItem->GetValue( );
+ }
+
+ if ( !pPaM )
+ pPaM = rWrtSh.GetCursor();
+
+ FieldUnit eMetric = ::GetDfltMetric( dynamic_cast<SwWebView*>( &GetView()) != nullptr );
+ SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)));
+
+ bool bApplyCharUnit = ::HasCharUnit( dynamic_cast<SwWebView*>( &GetView()) != nullptr );
+ SW_MOD()->PutItem(SfxBoolItem(SID_ATTR_APPLYCHARUNIT, bApplyCharUnit));
+
+ SfxItemSetFixed<
+ RES_PARATR_BEGIN, RES_FRMATR_END - 1,
+ // FillAttribute support:
+ XATTR_FILL_FIRST, XATTR_FILL_LAST,
+ // Includes SID_ATTR_TABSTOP_POS:
+ SID_ATTR_TABSTOP_DEFAULTS, SID_ATTR_TABSTOP_OFFSET,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
+ SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP,
+ // Items to hand over XPropertyList things like XColorList,
+ // XHatchList, XGradientList, and XBitmapList to the Area
+ // TabPage:
+ SID_COLOR_TABLE, SID_PATTERN_LIST,
+ SID_HTML_MODE, SID_HTML_MODE,
+ SID_ATTR_PARA_PAGENUM, SID_ATTR_PARA_PAGENUM,
+ FN_PARAM_1, FN_PARAM_1,
+ FN_NUMBER_NEWSTART, FN_NUMBER_NEWSTART_AT,
+ FN_DROP_TEXT, FN_DROP_CHAR_STYLE_NAME> aCoreSet( GetPool() );
+
+ // get also the list level indent values merged as LR-SPACE item, if needed.
+ rWrtSh.GetPaMAttr( pPaM, aCoreSet, true );
+
+ // create needed items for XPropertyList entries from the DrawModel so that
+ // the Area TabPage can access them
+ // Do this after GetCurAttr, this resets the ItemSet content again
+ SwDrawModel* pDrawModel = GetView().GetDocShell()->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
+
+ aCoreSet.Put(SvxColorListItem(pDrawModel->GetColorList(), SID_COLOR_TABLE));
+ aCoreSet.Put(SvxGradientListItem(pDrawModel->GetGradientList(), SID_GRADIENT_LIST));
+ aCoreSet.Put(SvxHatchListItem(pDrawModel->GetHatchList(), SID_HATCH_LIST));
+ aCoreSet.Put(SvxBitmapListItem(pDrawModel->GetBitmapList(), SID_BITMAP_LIST));
+ aCoreSet.Put(SvxPatternListItem(pDrawModel->GetPatternList(), SID_PATTERN_LIST));
+ aCoreSet.Put(SfxUInt16Item(SID_HTML_MODE,
+ ::GetHtmlMode(GetView().GetDocShell())));
+
+ // Tabulators: Put DefaultTabs into ItemSet
+ const SvxTabStopItem& rDefTabs =
+ GetPool().GetDefaultItem(RES_PARATR_TABSTOP);
+
+ const sal_uInt16 nDefDist = o3tl::narrowing<sal_uInt16>(::GetTabDist( rDefTabs ));
+ SfxUInt16Item aDefDistItem( SID_ATTR_TABSTOP_DEFAULTS, nDefDist );
+ aCoreSet.Put( aDefDistItem );
+
+ // Current tabulator
+ SfxUInt16Item aTabPos( SID_ATTR_TABSTOP_POS, 0 );
+ aCoreSet.Put( aTabPos );
+
+ // Left border as offset
+ //#i24363# tab stops relative to indent
+ const tools::Long nOff = rWrtSh.getIDocumentSettingAccess().get(DocumentSettingId::TABS_RELATIVE_TO_INDENT)
+ ? aCoreSet.Get(RES_MARGIN_TEXTLEFT).GetTextLeft() : 0;
+ SfxInt32Item aOff( SID_ATTR_TABSTOP_OFFSET, nOff );
+ aCoreSet.Put( aOff );
+
+ // Setting the BoxInfo
+ ::PrepareBoxInfo( aCoreSet, rWrtSh );
+
+ // Current page format
+ ::SwToSfxPageDescAttr( aCoreSet );
+
+ // Properties of numbering
+ if (rWrtSh.GetNumRuleAtCurrCursorPos())
+ {
+ SfxBoolItem aStart( FN_NUMBER_NEWSTART, rWrtSh.IsNumRuleStart( pPaM ) );
+ aCoreSet.Put(aStart);
+ SfxUInt16Item aStartAt( FN_NUMBER_NEWSTART_AT,
+ rWrtSh.GetNodeNumStart( pPaM ) );
+ aCoreSet.Put(aStartAt);
+ }
+ VclPtr<SfxAbstractTabDialog> pDlg;
+
+ if ( bUseDialog && GetActiveView() )
+ {
+ OUString sDefPage;
+ if (pItem)
+ sDefPage = static_cast<const SfxStringItem*>(pItem)->GetValue();
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ pDlg.reset(pFact->CreateSwParaDlg(GetView().GetFrameWeld(), GetView(), aCoreSet, false, sDefPage));
+ }
+
+ if ( !bUseDialog )
+ {
+ if ( nSlot == SID_ATTR_PARA_LRSPACE)
+ {
+ SvxLRSpaceItem aParaMargin(static_cast<const SvxLRSpaceItem&>(pArgs->Get(nSlot)));
+ SvxFirstLineIndentItem firstLine(RES_MARGIN_FIRSTLINE);
+ SvxTextLeftMarginItem leftMargin(RES_MARGIN_TEXTLEFT);
+ SvxRightMarginItem rightMargin(RES_MARGIN_RIGHT);
+ firstLine.SetTextFirstLineOffset(aParaMargin.GetTextFirstLineOffset(), aParaMargin.GetPropTextFirstLineOffset());
+ firstLine.SetAutoFirst(aParaMargin.IsAutoFirst());
+ leftMargin.SetTextLeft(aParaMargin.GetTextLeft(), aParaMargin.GetPropLeft());
+ rightMargin.SetRight(aParaMargin.GetRight(), aParaMargin.GetPropRight());
+ aCoreSet.Put(firstLine);
+ aCoreSet.Put(leftMargin);
+ aCoreSet.Put(rightMargin);
+
+ sw_ParagraphDialogResult(&aCoreSet, rWrtSh, rReq, pPaM);
+ }
+ else
+ sw_ParagraphDialogResult(const_cast<SfxItemSet*>(pArgs), rWrtSh, rReq, pPaM);
+ }
+ else if (pDlg)
+ {
+ auto pRequest = std::make_shared<SfxRequest>(rReq);
+ rReq.Ignore(); // the 'old' request is not relevant any more
+
+ auto vCursors = CopyPaMRing(*pPaM); // tdf#134439 make a copy to use at later apply
+ pDlg->StartExecuteAsync([pDlg, &rWrtSh, pDrawModel, pRequest, nDefDist, vCursors](sal_Int32 nResult){
+ if (nResult == RET_OK)
+ {
+ // Apply defaults if necessary.
+ SfxItemSet* pSet = const_cast<SfxItemSet*>(pDlg->GetOutputItemSet());
+ sal_uInt16 nNewDist;
+ const SfxUInt16Item* pDefaultsItem = pSet->GetItemIfSet(SID_ATTR_TABSTOP_DEFAULTS, false);
+ if (pDefaultsItem && nDefDist != (nNewDist = pDefaultsItem->GetValue()) )
+ {
+ SvxTabStopItem aDefTabs( 0, 0, SvxTabAdjust::Default, RES_PARATR_TABSTOP );
+ MakeDefTabs( nNewDist, aDefTabs );
+ rWrtSh.SetDefault( aDefTabs );
+ pSet->ClearItem( SID_ATTR_TABSTOP_DEFAULTS );
+ }
+
+ const SfxPoolItem* pItem2 = nullptr;
+ if (SfxItemState::SET == pSet->GetItemState(FN_PARAM_1, false, &pItem2))
+ {
+ pSet->Put(SfxStringItem(FN_DROP_TEXT, static_cast<const SfxStringItem*>(pItem2)->GetValue()));
+ pSet->ClearItem(FN_PARAM_1);
+ }
+
+ if (const SwFormatDrop* pDropItem = pSet->GetItemIfSet(RES_PARATR_DROP, false))
+ {
+ OUString sCharStyleName;
+ if (pDropItem->GetCharFormat())
+ sCharStyleName = pDropItem->GetCharFormat()->GetName();
+ pSet->Put(SfxStringItem(FN_DROP_CHAR_STYLE_NAME, sCharStyleName));
+ }
+
+ const XFillStyleItem* pFS = pSet->GetItem<XFillStyleItem>(XATTR_FILLSTYLE);
+ bool bSet = pFS && pFS->GetValue() == drawing::FillStyle_GRADIENT;
+ const XFillGradientItem* pTempGradItem
+ = bSet ? pSet->GetItem<XFillGradientItem>(XATTR_FILLGRADIENT) : nullptr;
+ if (pTempGradItem && pTempGradItem->GetName().isEmpty())
+ {
+ // MigrateItemSet guarantees unique gradient names
+ SfxItemSetFixed<XATTR_FILLGRADIENT, XATTR_FILLGRADIENT> aMigrateSet(rWrtSh.GetView().GetPool());
+ aMigrateSet.Put(XFillGradientItem("gradient", pTempGradItem->GetGradientValue()));
+ SdrModel::MigrateItemSet(&aMigrateSet, pSet, pDrawModel);
+ }
+
+ bSet = pFS && pFS->GetValue() == drawing::FillStyle_HATCH;
+ const XFillHatchItem* pTempHatchItem
+ = bSet ? pSet->GetItem<XFillHatchItem>(XATTR_FILLHATCH) : nullptr;
+ if (pTempHatchItem && pTempHatchItem->GetName().isEmpty())
+ {
+ SfxItemSetFixed<XATTR_FILLHATCH, XATTR_FILLHATCH> aMigrateSet(rWrtSh.GetView().GetPool());
+ aMigrateSet.Put(XFillHatchItem("hatch", pTempHatchItem->GetHatchValue()));
+ SdrModel::MigrateItemSet(&aMigrateSet, pSet, pDrawModel);
+ }
+
+ sw_ParagraphDialogResult(pSet, rWrtSh, *pRequest, vCursors->front().get());
+ }
+ pDlg->disposeOnce();
+ });
+ }
+ }
+ break;
+ case FN_NUM_CONTINUE:
+ {
+ OUString sContinuedListId;
+ const SwNumRule* pRule =
+ rWrtSh.SearchNumRule( true, sContinuedListId );
+ // #i86492#
+ // Search also for bullet list
+ if ( !pRule )
+ {
+ pRule = rWrtSh.SearchNumRule( false, sContinuedListId );
+ }
+ if ( pRule )
+ {
+ rWrtSh.SetCurNumRule( *pRule, false, sContinuedListId );
+ }
+ }
+ break;
+
+ case FN_SELECT_PARA:
+ {
+ if ( !rWrtSh.IsSttOfPara() )
+ rWrtSh.SttPara();
+ else
+ rWrtSh.EnterStdMode();
+ rWrtSh.EndPara( true );
+ }
+ break;
+
+ case SID_DEC_INDENT:
+ case SID_INC_INDENT:
+ //According to the requirement, modified the behavior when user
+ //using the indent button on the toolbar. Now if we increase/decrease indent for a
+ //paragraph which has bullet style it will increase/decrease the bullet level.
+ {
+ //If the current paragraph has bullet call the function to
+ //increase or decrease the bullet level.
+ //Why could I know whether a paragraph has bullet or not by checking the below conditions?
+ //Please refer to the "case KEY_TAB:" section in SwEditWin::KeyInput(..) :
+ // if( rSh.GetCurNumRule() && rSh.IsSttOfPara() &&
+ // !rSh.HasReadonlySel() )
+ // eKeyState = KS_NumDown;
+ //Above code demonstrates that when the cursor is at the start of a paragraph which has bullet,
+ //press TAB will increase the bullet level.
+ //So I copied from that ^^
+ if ( rWrtSh.GetNumRuleAtCurrCursorPos() && !rWrtSh.HasReadonlySel() )
+ {
+ rWrtSh.NumUpDown( SID_INC_INDENT == nSlot );
+ }
+ else //execute the original processing functions
+ {
+ //below is copied of the old codes
+ rWrtSh.MoveLeftMargin( SID_INC_INDENT == nSlot, rReq.GetModifier() != KEY_MOD1 );
+ }
+ }
+ rReq.Done();
+ break;
+
+ case FN_DEC_INDENT_OFFSET:
+ case FN_INC_INDENT_OFFSET:
+ rWrtSh.MoveLeftMargin( FN_INC_INDENT_OFFSET == nSlot, rReq.GetModifier() == KEY_MOD1 );
+ rReq.Done();
+ break;
+
+ case SID_ATTR_CHAR_COLOR2:
+ {
+ if (pItem)
+ {
+ auto* pColorItem = static_cast<const SvxColorItem*>(pItem);
+ SwEditWin& rEditWin = GetView().GetEditWin();
+ rEditWin.SetWaterCanTextColor(pColorItem->GetValue());
+ SwApplyTemplate* pApply = rEditWin.GetApplyTemplate();
+
+ // If there is a selection, then set the color on it
+ // otherwise, it'll be the color for the next text to be typed
+ if (!pApply || pApply->nColor != SID_ATTR_CHAR_COLOR_EXT)
+ {
+ rWrtSh.SetAttrItem(SvxColorItem(pColorItem->GetValue(), pColorItem->getComplexColor(), RES_CHRATR_COLOR));
+ }
+
+ rReq.Done();
+ }
+ }
+ break;
+ case SID_ATTR_CHAR_BACK_COLOR:
+ case SID_ATTR_CHAR_COLOR_BACKGROUND: // deprecated
+ case SID_ATTR_CHAR_COLOR_EXT:
+ {
+ Color aColor;
+ model::ComplexColor aComplexColor;
+
+ if (pItem)
+ {
+ auto* pColorItem = static_cast<const SvxColorItem*>(pItem);
+ aColor = pColorItem->GetValue();
+ aComplexColor = pColorItem->getComplexColor();
+ }
+ else
+ aColor = COL_TRANSPARENT;
+
+ SwEditWin& rEdtWin = GetView().GetEditWin();
+ if (nSlot != SID_ATTR_CHAR_COLOR_EXT)
+ rEdtWin.SetWaterCanTextBackColor(aColor);
+ else if (pItem)
+ rEdtWin.SetWaterCanTextColor(aColor);
+
+ SwApplyTemplate* pApply = rEdtWin.GetApplyTemplate();
+ SwApplyTemplate aTempl;
+ if (!pApply && (rWrtSh.HasSelection() || rReq.IsAPI()))
+ {
+ if (nSlot != SID_ATTR_CHAR_COLOR_EXT)
+ {
+ SfxItemSetFixed<RES_CHRATR_BACKGROUND, RES_CHRATR_BACKGROUND> aCoreSet( rWrtSh.GetView().GetPool() );
+
+ rWrtSh.GetCurAttr(aCoreSet);
+
+ // Remove highlight if already set of the same color
+ const SvxBrushItem& rBrushItem = aCoreSet.Get(RES_CHRATR_BACKGROUND);
+ if (aColor == rBrushItem.GetColor())
+ {
+ aComplexColor = model::ComplexColor();
+ aColor = COL_TRANSPARENT;
+ }
+ ApplyCharBackground(aColor, aComplexColor, rWrtSh);
+ }
+ else
+ rWrtSh.SetAttrItem(SvxColorItem(aColor, aComplexColor, RES_CHRATR_COLOR));
+ }
+ else
+ {
+ if(!pApply || pApply->nColor != nSlot)
+ aTempl.nColor = nSlot;
+ rEdtWin.SetApplyTemplate(aTempl);
+ }
+
+ rReq.Done();
+ }
+ break;
+
+ case FN_NUM_BULLET_MOVEDOWN:
+ if (!rWrtSh.IsAddMode())
+ rWrtSh.MoveParagraph();
+ rReq.Done();
+ break;
+
+ case FN_NUM_BULLET_MOVEUP:
+ if (!rWrtSh.IsAddMode())
+ rWrtSh.MoveParagraph(SwNodeOffset(-1));
+ rReq.Done();
+ break;
+ case SID_RUBY_DIALOG:
+ case SID_HYPERLINK_DIALOG:
+ {
+ SfxRequest aReq(nSlot, SfxCallMode::SLOT, SfxGetpApp()->GetPool());
+ GetView().GetViewFrame().ExecuteSlot( aReq);
+ rReq.Ignore();
+ }
+ break;
+ case FN_INSERT_PAGEHEADER:
+ case FN_INSERT_PAGEFOOTER:
+ if(pArgs && pArgs->Count())
+ {
+ OUString sStyleName;
+ if(pItem)
+ sStyleName = static_cast<const SfxStringItem*>(pItem)->GetValue();
+ bool bOn = true;
+ if( SfxItemState::SET == pArgs->GetItemState(FN_PARAM_1, false, &pItem))
+ bOn = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ rWrtSh.ChangeHeaderOrFooter(sStyleName, FN_INSERT_PAGEHEADER == nSlot, bOn, !rReq.IsAPI());
+ rReq.Done();
+ }
+ break;
+ case FN_READONLY_SELECTION_MODE :
+ if(GetView().GetDocShell()->IsReadOnly())
+ {
+ rWrtSh.SetReadonlySelectionOption(
+ !rWrtSh.GetViewOptions()->IsSelectionInReadonly());
+ rWrtSh.ShowCursor();
+ }
+ break;
+ case FN_SELECTION_MODE_DEFAULT:
+ case FN_SELECTION_MODE_BLOCK :
+ {
+ bool bSetBlockMode = !rWrtSh.IsBlockMode();
+ if( pArgs && SfxItemState::SET == pArgs->GetItemState(nSlot, false, &pItem))
+ bSetBlockMode = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ if( ( nSlot == FN_SELECTION_MODE_DEFAULT ) != bSetBlockMode )
+ rWrtSh.EnterBlockMode();
+ else
+ rWrtSh.EnterStdMode();
+ SfxBindings &rBnd = GetView().GetViewFrame().GetBindings();
+ rBnd.Invalidate(FN_STAT_SELMODE);
+ rBnd.Update(FN_STAT_SELMODE);
+ }
+ break;
+ case SID_OPEN_HYPERLINK:
+ case SID_COPY_HYPERLINK_LOCATION:
+ {
+ SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
+ rWrtSh.GetCurAttr(aSet);
+ if(SfxItemState::SET <= aSet.GetItemState( RES_TXTATR_INETFMT ))
+ {
+ const SwFormatINetFormat& rINetFormat = aSet.Get(RES_TXTATR_INETFMT);
+
+ if (nSlot == SID_OPEN_HYPERLINK)
+ {
+ rWrtSh.ClickToINetAttr(rINetFormat);
+ }
+ else if (nSlot == SID_COPY_HYPERLINK_LOCATION)
+ {
+ OUString hyperlinkLocation = rINetFormat.GetValue();
+ ::uno::Reference< datatransfer::clipboard::XClipboard > xClipboard = GetView().GetEditWin().GetClipboard();
+ vcl::unohelper::TextDataObject::CopyStringTo(hyperlinkLocation, xClipboard, SfxViewShell::Current());
+ }
+ }
+ else
+ {
+ SwField* pField = rWrtSh.GetCurField();
+ if (pField && pField->GetTyp()->Which() == SwFieldIds::TableOfAuthorities)
+ {
+ const auto& rAuthorityField = *static_cast<const SwAuthorityField*>(pField);
+ OUString targetURL = "";
+
+ if (auto targetType = rAuthorityField.GetTargetType();
+ targetType == SwAuthorityField::TargetType::UseDisplayURL
+ || targetType == SwAuthorityField::TargetType::UseTargetURL)
+ {
+ // Bibliography entry with URL also provides a hyperlink.
+ targetURL = rAuthorityField.GetAbsoluteURL();
+ }
+
+ if (targetURL.getLength() > 0)
+ {
+ if (nSlot == SID_OPEN_HYPERLINK)
+ {
+ ::LoadURL(rWrtSh, targetURL, LoadUrlFlags::NewView, /*rTargetFrameName=*/OUString());
+ }
+ else if (nSlot == SID_COPY_HYPERLINK_LOCATION)
+ {
+ ::uno::Reference< datatransfer::clipboard::XClipboard > xClipboard = GetView().GetEditWin().GetClipboard();
+ vcl::unohelper::TextDataObject::CopyStringTo(targetURL, xClipboard, SfxViewShell::Current());
+ }
+ }
+ }
+ }
+ }
+ break;
+ case FN_OPEN_LOCAL_URL:
+ {
+ OUString aLocalURL = GetLocalURL(rWrtSh);
+ if (!aLocalURL.isEmpty())
+ {
+ ::LoadURL(rWrtSh, aLocalURL, LoadUrlFlags::NewView, /*rTargetFrameName=*/OUString());
+ }
+ }
+ break;
+ case SID_OPEN_XML_FILTERSETTINGS:
+ {
+ HandleOpenXmlFilterSettings(rReq);
+ }
+ break;
+ case FN_FORMAT_APPLY_HEAD1:
+ {
+ }
+ break;
+ case FN_FORMAT_APPLY_HEAD2:
+ {
+ }
+ break;
+ case FN_FORMAT_APPLY_HEAD3:
+ {
+ }
+ break;
+ case FN_FORMAT_APPLY_DEFAULT:
+ {
+ }
+ break;
+ case FN_FORMAT_APPLY_TEXTBODY:
+ {
+ }
+ break;
+ case FN_WORDCOUNT_DIALOG:
+ {
+ GetView().UpdateWordCount(this, nSlot);
+ }
+ break;
+ case FN_PROTECT_FIELDS:
+ case FN_PROTECT_BOOKMARKS:
+ {
+ IDocumentSettingAccess& rIDSA = rWrtSh.getIDocumentSettingAccess();
+ DocumentSettingId aSettingId = nSlot == FN_PROTECT_FIELDS
+ ? DocumentSettingId::PROTECT_FIELDS
+ : DocumentSettingId::PROTECT_BOOKMARKS;
+ rIDSA.set(aSettingId, !rIDSA.get(aSettingId));
+ // Invalidate so that toggle state gets updated
+ SfxViewFrame& rViewFrame = GetView().GetViewFrame();
+ rViewFrame.GetBindings().Invalidate(nSlot);
+ rViewFrame.GetBindings().Update(nSlot);
+ }
+ break;
+ case SID_FM_CTL_PROPERTIES:
+ {
+ SwPosition aPos(*GetShell().GetCursor()->GetPoint());
+ sw::mark::IFieldmark* pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos);
+ if ( !pFieldBM )
+ {
+ aPos.AdjustContent(-1);
+ pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos);
+ }
+
+ if ( pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDROPDOWN
+ && !(rWrtSh.GetCurrSection() && rWrtSh.GetCurrSection()->IsProtect()) )
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateDropDownFormFieldDialog(rWrtSh.GetView().GetFrameWeld(), pFieldBM));
+ if (pDlg->Execute() == RET_OK)
+ {
+ pFieldBM->Invalidate();
+ rWrtSh.InvalidateWindows( SwRect(rWrtSh.GetView().GetVisArea()) );
+ rWrtSh.UpdateCursor(); // cursor position might be invalid
+ }
+ }
+ else if ( pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDATE )
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ sw::mark::DateFieldmark& rDateField = dynamic_cast<sw::mark::DateFieldmark&>(*pFieldBM);
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateDateFormFieldDialog(rWrtSh.GetView().GetFrameWeld(), &rDateField, *GetView().GetDocShell()->GetDoc()));
+ if (pDlg->Execute() == RET_OK)
+ {
+ rDateField.Invalidate();
+ rWrtSh.InvalidateWindows( SwRect(rWrtSh.GetView().GetVisArea()) );
+ rWrtSh.UpdateCursor(); // cursor position might be invalid
+ }
+ }
+ else
+ {
+ SfxRequest aReq(GetView().GetViewFrame(), SID_FM_CTL_PROPERTIES);
+ aReq.AppendItem( SfxBoolItem( SID_FM_CTL_PROPERTIES, true ) );
+ rWrtSh.GetView().GetFormShell()->Execute( aReq );
+ }
+ }
+ break;
+ case SID_FM_TRANSLATE:
+ {
+#if HAVE_FEATURE_CURL && !ENABLE_WASM_STRIP_EXTRA
+ const SfxPoolItem* pTargetLangStringItem = nullptr;
+ if (pArgs && SfxItemState::SET == pArgs->GetItemState(SID_ATTR_TARGETLANG_STR, false, &pTargetLangStringItem))
+ {
+ std::optional<OUString> oDeeplAPIUrl = officecfg::Office::Linguistic::Translation::Deepl::ApiURL::get();
+ std::optional<OUString> oDeeplKey = officecfg::Office::Linguistic::Translation::Deepl::AuthKey::get();
+ if (!oDeeplAPIUrl || oDeeplAPIUrl->isEmpty() || !oDeeplKey || oDeeplKey->isEmpty())
+ {
+ SAL_WARN("sw.ui", "SID_FM_TRANSLATE: API options are not set");
+ break;
+ }
+ const OString aAPIUrl = OUStringToOString(rtl::Concat2View(*oDeeplAPIUrl + "?tag_handling=html"), RTL_TEXTENCODING_UTF8).trim();
+ const OString aAuthKey = OUStringToOString(*oDeeplKey, RTL_TEXTENCODING_UTF8).trim();
+ OString aTargetLang = OUStringToOString(static_cast<const SfxStringItem*>(pTargetLangStringItem)->GetValue(), RTL_TEXTENCODING_UTF8);
+ SwTranslateHelper::TranslateAPIConfig aConfig({aAPIUrl, aAuthKey, aTargetLang});
+ SwTranslateHelper::TranslateDocument(rWrtSh, aConfig);
+ }
+ else
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ std::shared_ptr<AbstractSwTranslateLangSelectDlg> pAbstractDialog(pFact->CreateSwTranslateLangSelectDlg(GetView().GetFrameWeld(), rWrtSh));
+ std::shared_ptr<weld::DialogController> pDialogController(pAbstractDialog->getDialogController());
+ weld::DialogController::runAsync(pDialogController, [] (sal_Int32 /*nResult*/) { });
+ }
+#endif // HAVE_FEATURE_CURL && ENABLE_WASM_STRIP_EXTRA
+ }
+ break;
+ case SID_SPELLCHECK_IGNORE:
+ {
+ SwPaM *pPaM = rWrtSh.GetCursor();
+ if (pPaM)
+ SwEditShell::IgnoreGrammarErrorAt( *pPaM );
+ }
+ break;
+ case SID_SPELLCHECK_IGNORE_ALL:
+ {
+ OUString sApplyText;
+ const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if (pItem2)
+ sApplyText = pItem2->GetValue();
+
+ if(sApplyText == "Grammar")
+ {
+ linguistic2::ProofreadingResult aGrammarCheckRes;
+ sal_Int32 nErrorInResult = -1;
+ uno::Sequence< OUString > aSuggestions;
+ sal_Int32 nErrorPosInText = -1;
+ SwRect aToFill;
+ bool bCorrectionRes = rWrtSh.GetGrammarCorrection( aGrammarCheckRes, nErrorPosInText, nErrorInResult, aSuggestions, nullptr, aToFill );
+ if(bCorrectionRes)
+ {
+ try {
+ uno::Reference< linguistic2::XDictionary > xDictionary = LinguMgr::GetIgnoreAllList();
+ aGrammarCheckRes.xProofreader->ignoreRule(
+ aGrammarCheckRes.aErrors[ nErrorInResult ].aRuleIdentifier,
+ aGrammarCheckRes.aLocale );
+ // refresh the layout of the actual paragraph (faster)
+ SwPaM *pPaM = rWrtSh.GetCursor();
+ if (pPaM)
+ SwEditShell::IgnoreGrammarErrorAt( *pPaM );
+ if (xDictionary.is())
+ {
+ // refresh the layout of all paragraphs (workaround to launch a dictionary event)
+ xDictionary->setActive(false);
+ xDictionary->setActive(true);
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ }
+ }
+ }
+ else if (sApplyText == "Spelling")
+ {
+ SwRect aToFill;
+ uno::Reference<linguistic2::XSpellAlternatives> xSpellAlt(rWrtSh.GetCorrection(nullptr, aToFill));
+ if (!xSpellAlt.is())
+ return;
+ uno::Reference< linguistic2::XDictionary > xDictionary = LinguMgr::GetIgnoreAllList();
+ OUString sWord(xSpellAlt->getWord());
+ linguistic::DictionaryError nAddRes = linguistic::AddEntryToDic( xDictionary,
+ sWord, false, OUString() );
+ if (linguistic::DictionaryError::NONE != nAddRes && xDictionary.is() && !xDictionary->getEntry(sWord).is())
+ {
+ SvxDicError(rWrtSh.GetView().GetFrameWeld(), nAddRes);
+ }
+ }
+ }
+ break;
+ case SID_SPELLCHECK_APPLY_SUGGESTION:
+ {
+ OUString sApplyText;
+ const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if (pItem2)
+ sApplyText = pItem2->GetValue();
+
+ static constexpr OUString sSpellingRule(u"Spelling_"_ustr);
+ static constexpr OUString sGrammarRule(u"Grammar_"_ustr);
+
+ bool bGrammar = false;
+ sal_Int32 nPos = 0;
+ uno::Reference< linguistic2::XSpellAlternatives > xSpellAlt;
+ if(-1 != (nPos = sApplyText.indexOf( sGrammarRule )))
+ {
+ sApplyText = sApplyText.replaceAt(nPos, sGrammarRule.getLength(), u"");
+ bGrammar = true;
+ }
+ else if (-1 != (nPos = sApplyText.indexOf( sSpellingRule )))
+ {
+ sApplyText = sApplyText.replaceAt(nPos, sSpellingRule.getLength(), u"");
+ SwRect aToFill;
+ xSpellAlt.set(rWrtSh.GetCorrection(nullptr, aToFill));
+ bGrammar = false;
+ }
+
+ if (!bGrammar && !xSpellAlt.is())
+ return;
+
+ bool bOldIns = rWrtSh.IsInsMode();
+ rWrtSh.SetInsMode();
+
+ OUString aTmp( sApplyText );
+ OUString aOrig( bGrammar ? OUString() : xSpellAlt->getWord() );
+
+ // if original word has a trailing . (likely the end of a sentence)
+ // and the replacement text hasn't, then add it to the replacement
+ if (!aTmp.isEmpty() && !aOrig.isEmpty() &&
+ aOrig.endsWith(".") && /* !IsAlphaNumeric ??*/
+ !aTmp.endsWith("."))
+ {
+ aTmp += ".";
+ }
+
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UndoArg1, rWrtSh.GetCursorDescr()
+ // don't show the hidden control character of the comment
+ .replaceAll(OUStringChar(CH_TXTATR_INWORD), "") );
+ aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
+
+ OUString aTmpStr = SwResId(STR_START_QUOTE) +
+ aTmp + SwResId(STR_END_QUOTE);
+ aRewriter.AddRule(UndoArg3, aTmpStr);
+
+ rWrtSh.StartUndo(SwUndoId::UI_REPLACE, &aRewriter);
+ rWrtSh.StartAction();
+
+ // keep comments at the end of the replacement in case spelling correction is
+ // invoked via the context menu. The spell check dialog does the correction in edlingu.cxx.
+ rWrtSh.ReplaceKeepComments(aTmp);
+
+ rWrtSh.EndAction();
+ rWrtSh.EndUndo();
+
+ rWrtSh.SetInsMode( bOldIns );
+ }
+ break;
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ return;
+ }
+}
+
+void SwTextShell::GetState( SfxItemSet &rSet )
+{
+ SwWrtShell &rSh = GetShell();
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while ( nWhich )
+ {
+ const sal_uInt16 nSlotId = GetPool().GetSlotId(nWhich);
+ switch (nSlotId)
+ {
+ case FN_FORMAT_CURRENT_FOOTNOTE_DLG:
+ if( !rSh.IsCursorInFootnote() )
+ rSet.DisableItem( nWhich );
+ break;
+
+ case SID_LANGUAGE_STATUS:
+ {
+ // the value of used script types
+ OUString aScriptTypesInUse( OUString::number( static_cast<int>(rSh.GetScriptType()) ) );
+
+ // get keyboard language
+ OUString aKeyboardLang;
+ SwEditWin& rEditWin = GetView().GetEditWin();
+ LanguageType nLang = rEditWin.GetInputLanguage();
+ if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
+ aKeyboardLang = SvtLanguageTable::GetLanguageString( nLang );
+
+ // get the language that is in use
+ OUString aCurrentLang = "*";
+ nLang = SwLangHelper::GetCurrentLanguage( rSh );
+ if (nLang != LANGUAGE_DONTKNOW)
+ {
+ aCurrentLang = SvtLanguageTable::GetLanguageString( nLang );
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ if (nLang == LANGUAGE_NONE)
+ {
+ aCurrentLang += ";-";
+ }
+ else
+ {
+ aCurrentLang += ";" + LanguageTag(nLang).getBcp47(false);
+ }
+ }
+ }
+
+ // build sequence for status value
+ uno::Sequence< OUString > aSeq{ aCurrentLang,
+ aScriptTypesInUse,
+ aKeyboardLang,
+ SwLangHelper::GetTextForLanguageGuessing( rSh ) };
+
+ // set sequence as status value
+ SfxStringListItem aItem( SID_LANGUAGE_STATUS );
+ aItem.SetStringList( aSeq );
+ rSet.Put( aItem );
+ }
+ break;
+
+ case SID_THES:
+ {
+ // is there a valid selection to get text from?
+ OUString aText;
+ bool bValid = !rSh.HasSelection() ||
+ (rSh.IsSelOnePara() && !rSh.IsMultiSelection());
+ // prevent context menu from showing when cursor is not in or at the end of a word
+ // (GetCurWord will return the next word if there is none at the current position...)
+ const sal_Int16 nWordType = ::i18n::WordType::DICTIONARY_WORD;
+ bool bWord = rSh.IsInWord( nWordType ) || rSh.IsStartWord( nWordType ) || rSh.IsEndWord( nWordType );
+ if (bValid && bWord)
+ aText = rSh.HasSelection()? rSh.GetSelText() : rSh.GetCurWord();
+
+ LanguageType nLang = rSh.GetCurLang();
+ LanguageTag aLanguageTag( nLang);
+ const lang::Locale& aLocale( aLanguageTag.getLocale());
+
+ // disable "Thesaurus" context menu entry if there is nothing to look up
+ uno::Reference< linguistic2::XThesaurus > xThes( ::GetThesaurus() );
+ if (aText.isEmpty() ||
+ !xThes.is() || nLang == LANGUAGE_NONE || !xThes->hasLocale( aLocale ))
+ rSet.DisableItem( SID_THES );
+ else
+ {
+ // set word and locale to look up as status value
+ OUString aStatusVal = aText + "#" + aLanguageTag.getBcp47();
+ rSet.Put( SfxStringItem( SID_THES, aStatusVal ) );
+ }
+ }
+ break;
+
+ case FN_NUMBER_NEWSTART :
+ if(!rSh.GetNumRuleAtCurrCursorPos())
+ rSet.DisableItem(nWhich);
+ else
+ rSet.Put(SfxBoolItem(FN_NUMBER_NEWSTART,
+ rSh.IsNumRuleStart()));
+ break;
+
+ case FN_EDIT_FORMULA:
+ case SID_CHARMAP:
+ case SID_CHARMAP_CONTROL:
+ {
+ const SelectionType nType = rSh.GetSelectionType();
+ if (!(nType & SelectionType::Text) &&
+ !(nType & SelectionType::Table) &&
+ !(nType & SelectionType::NumberList))
+ {
+ rSet.DisableItem(nWhich);
+ }
+ else if ( nWhich == FN_EDIT_FORMULA
+ && rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ }
+ break;
+
+ case FN_INSERT_ENDNOTE:
+ case FN_INSERT_FOOTNOTE:
+ case FN_INSERT_FOOTNOTE_DLG:
+ {
+ const FrameTypeFlags nNoType =
+ FrameTypeFlags::FLY_ANY | FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER | FrameTypeFlags::FOOTNOTE;
+ FrameTypeFlags eType = rSh.GetFrameType(nullptr, true);
+ bool bSplitFly = false;
+ if (eType & FrameTypeFlags::FLY_ATCNT)
+ {
+ SwContentFrame* pContentFrame = rSh.GetCurrFrame(/*bCalcFrame=*/false);
+ if (pContentFrame)
+ {
+ SwFlyFrame* pFlyFrame = pContentFrame->FindFlyFrame();
+ bSplitFly = pFlyFrame && pFlyFrame->IsFlySplitAllowed();
+ }
+ }
+ if (eType & nNoType && !bSplitFly)
+ rSet.DisableItem(nWhich);
+
+ if ( rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ }
+ break;
+
+ case FN_INSERT_HYPERLINK:
+ case SID_INSERTDOC:
+ case FN_INSERT_GLOSSARY:
+ case FN_EXPAND_GLOSSARY:
+ if ( rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case FN_INSERT_TABLE:
+ if ( rSh.CursorInsideInputField()
+ || rSh.GetTableFormat()
+ || (rSh.GetFrameType(nullptr,true) & FrameTypeFlags::FOOTNOTE) )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case FN_CALCULATE:
+ if ( !rSh.IsSelection() )
+ rSet.DisableItem(nWhich);
+ break;
+ case FN_GOTO_REFERENCE:
+ {
+ SwField *pField = rSh.GetCurField();
+ if ( !pField || (pField->GetTypeId() != SwFieldTypesEnum::GetRef) )
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case FN_AUTOFORMAT_AUTO:
+ {
+ rSet.Put( SfxBoolItem( nWhich, SvxAutoCorrCfg::Get().IsAutoFormatByInput() ));
+ }
+ break;
+
+ case SID_DEC_INDENT:
+ case SID_INC_INDENT:
+ {
+ //if the paragraph has bullet we'll do the following things:
+ //1: if the bullet level is the first level, disable the decrease-indent button
+ //2: if the bullet level is the last level, disable the increase-indent button
+ if ( rSh.GetNumRuleAtCurrCursorPos() && !rSh.HasReadonlySel() )
+ {
+ const sal_uInt8 nLevel = rSh.GetNumLevel();
+ if ( ( nLevel == ( MAXLEVEL - 1 ) && nWhich == SID_INC_INDENT )
+ || ( nLevel == 0 && nWhich == SID_DEC_INDENT ) )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ }
+ else
+ {
+ sal_uInt16 nHtmlMode = ::GetHtmlMode( GetView().GetDocShell() );
+ nHtmlMode &= HTMLMODE_ON | HTMLMODE_SOME_STYLES;
+ if ( ( nHtmlMode == HTMLMODE_ON )
+ || !rSh.IsMoveLeftMargin( SID_INC_INDENT == nWhich ) )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ }
+ }
+ break;
+
+ case FN_DEC_INDENT_OFFSET:
+ case FN_INC_INDENT_OFFSET:
+ {
+ sal_uInt16 nHtmlMode = ::GetHtmlMode(GetView().GetDocShell());
+ nHtmlMode &= HTMLMODE_ON|HTMLMODE_SOME_STYLES;
+ if( (nHtmlMode == HTMLMODE_ON) ||
+ !rSh.IsMoveLeftMargin( FN_INC_INDENT_OFFSET == nWhich,
+ false ))
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case SID_ATTR_CHAR_COLOR2:
+ {
+ SfxItemSet aSet( GetPool() );
+ rSh.GetCurAttr( aSet );
+ const SvxColorItem& aColorItem = aSet.Get(RES_CHRATR_COLOR);
+ rSet.Put( aColorItem.CloneSetWhich(SID_ATTR_CHAR_COLOR2) );
+ }
+ break;
+ case SID_ATTR_CHAR_BACK_COLOR:
+ case SID_ATTR_CHAR_COLOR_BACKGROUND:
+ {
+ // Always use the visible background
+ SfxItemSet aSet( GetPool() );
+ rSh.GetCurAttr( aSet );
+ const SvxBrushItem& aBrushItem = aSet.Get(RES_CHRATR_HIGHLIGHT);
+ if( aBrushItem.GetColor() != COL_TRANSPARENT )
+ {
+ rSet.Put(SvxColorItem(aBrushItem.GetColor(), aBrushItem.getComplexColor(), nWhich));
+ }
+ else
+ {
+ const SvxBrushItem& aBrushItem2 = aSet.Get(RES_CHRATR_BACKGROUND);
+ rSet.Put(SvxColorItem(aBrushItem2.GetColor(), aBrushItem2.getComplexColor(), nWhich));
+ }
+ }
+ break;
+ case SID_ATTR_CHAR_COLOR_BACKGROUND_EXT:
+ {
+ SwEditWin& rEdtWin = GetView().GetEditWin();
+ SwApplyTemplate* pApply = rEdtWin.GetApplyTemplate();
+ const sal_uInt32 nColWhich = pApply ? pApply->nColor : 0;
+ const bool bUseTemplate = nColWhich == SID_ATTR_CHAR_BACK_COLOR
+ || nColWhich == SID_ATTR_CHAR_COLOR_BACKGROUND;
+ rSet.Put(SfxBoolItem(nWhich, bUseTemplate));
+ }
+ break;
+ case SID_ATTR_CHAR_COLOR_EXT:
+ {
+ SwEditWin& rEdtWin = GetView().GetEditWin();
+ SwApplyTemplate* pApply = rEdtWin.GetApplyTemplate();
+ rSet.Put(SfxBoolItem(nWhich, pApply && pApply->nColor == nWhich));
+ }
+ break;
+ case FN_SET_REMINDER:
+ case FN_INSERT_BOOKMARK:
+ if( rSh.IsTableMode()
+ || rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case FN_INSERT_BREAK:
+ if ( rSh.HasReadonlySel()
+ && !rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case FN_INSERT_BREAK_DLG:
+ case FN_INSERT_COLUMN_BREAK:
+ case FN_INSERT_PAGEBREAK:
+ if( rSh.CursorInsideInputField() || rSh.CursorInsideContentControl() )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case FN_INSERT_PAGEHEADER:
+ case FN_INSERT_PAGEFOOTER:
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ bool bState = false;
+ bool bAllState = true;
+ bool bIsPhysical = false;
+
+ OUString aStyleName;
+ std::vector<OUString> aList;
+ static constexpr OUStringLiteral sPhysical(u"IsPhysical");
+ static constexpr OUStringLiteral sDisplay(u"DisplayName");
+ const OUString sHeaderOn(nWhich == FN_INSERT_PAGEHEADER ? OUString("HeaderIsOn") : OUString("FooterIsOn"));
+
+ uno::Reference< XStyleFamiliesSupplier > xSupplier(GetView().GetDocShell()->GetBaseModel(), uno::UNO_QUERY);
+ if (xSupplier.is())
+ {
+ uno::Reference< XNameContainer > xContainer;
+ uno::Reference< XNameAccess > xFamilies = xSupplier->getStyleFamilies();
+ if (xFamilies->getByName("PageStyles") >>= xContainer)
+ {
+ const uno::Sequence< OUString > aSeqNames = xContainer->getElementNames();
+ for (const auto& rName : aSeqNames)
+ {
+ aStyleName = rName;
+ uno::Reference<XPropertySet> xPropSet(xContainer->getByName(aStyleName), uno::UNO_QUERY);
+ if (xPropSet.is() && (xPropSet->getPropertyValue(sPhysical) >>= bIsPhysical) && bIsPhysical)
+ {
+ xPropSet->getPropertyValue(sDisplay) >>= aStyleName;
+ if ((xPropSet->getPropertyValue(sHeaderOn)>>= bState) && bState)
+ aList.push_back(aStyleName);
+ else
+ bState = false;
+
+ // Check if all entries have the same state
+ bAllState &= bState;
+ }
+ else
+ bIsPhysical = false;
+ }
+ }
+ }
+
+ if (bAllState && aList.size() > 1)
+ aList.push_back("_ALL_");
+
+ rSet.Put(SfxStringListItem(nWhich, &aList));
+ }
+ else
+ {
+ rSet.Put( SfxObjectShellItem( nWhich, GetView().GetDocShell() ));
+ }
+ break;
+ case FN_TABLE_SORT_DIALOG:
+ case FN_SORTING_DLG:
+ if(!rSh.HasSelection() ||
+ (FN_TABLE_SORT_DIALOG == nWhich && !rSh.GetTableFormat()))
+ rSet.DisableItem( nWhich );
+ break;
+
+ case SID_RUBY_DIALOG:
+ {
+ if( !SvtCJKOptions::IsRubyEnabled()
+ || rSh.CursorInsideInputField() )
+ {
+ GetView().GetViewFrame().GetBindings().SetVisibleState( nWhich, false );
+ rSet.DisableItem(nWhich);
+ }
+ else
+ GetView().GetViewFrame().GetBindings().SetVisibleState( nWhich, true );
+ }
+ break;
+
+ case SID_FM_TRANSLATE:
+ {
+#if HAVE_FEATURE_CURL && !ENABLE_WASM_STRIP_EXTRA
+ if (!officecfg::Office::Common::Misc::ExperimentalMode::get()
+ && !comphelper::LibreOfficeKit::isActive())
+ {
+ rSet.Put(SfxVisibilityItem(nWhich, false));
+ break;
+ }
+ std::optional<OUString> oDeeplAPIUrl = officecfg::Office::Linguistic::Translation::Deepl::ApiURL::get();
+ std::optional<OUString> oDeeplKey = officecfg::Office::Linguistic::Translation::Deepl::AuthKey::get();
+ if (!oDeeplAPIUrl || oDeeplAPIUrl->isEmpty() || !oDeeplKey || oDeeplKey->isEmpty())
+ {
+ rSet.DisableItem(nWhich);
+ }
+#endif
+ }
+ break;
+
+ case SID_HYPERLINK_DIALOG:
+ if( GetView().GetDocShell()->IsReadOnly()
+ || ( !GetView().GetViewFrame().HasChildWindow(nWhich)
+ && rSh.HasReadonlySel() )
+ || rSh.CursorInsideInputField() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ else
+ {
+ rSet.Put(SfxBoolItem( nWhich, nullptr != GetView().GetViewFrame().GetChildWindow( nWhich ) ));
+ }
+ break;
+
+ case SID_EDIT_HYPERLINK:
+ {
+ SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
+ rSh.GetCurAttr(aSet);
+ if(SfxItemState::SET > aSet.GetItemState( RES_TXTATR_INETFMT ) || rSh.HasReadonlySel())
+ {
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+ case SID_REMOVE_HYPERLINK:
+ {
+ SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
+ rSh.GetCurAttr(aSet);
+
+ // If a hyperlink is selected, either alone or along with other text...
+ if ((aSet.GetItemState(RES_TXTATR_INETFMT) < SfxItemState::SET &&
+ aSet.GetItemState(RES_TXTATR_INETFMT) != SfxItemState::DONTCARE) ||
+ rSh.HasReadonlySel())
+ {
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+ case SID_TRANSLITERATE_HALFWIDTH:
+ case SID_TRANSLITERATE_FULLWIDTH:
+ case SID_TRANSLITERATE_HIRAGANA:
+ case SID_TRANSLITERATE_KATAKANA:
+ {
+ if(!SvtCJKOptions::IsChangeCaseMapEnabled())
+ {
+ GetView().GetViewFrame().GetBindings().SetVisibleState( nWhich, false );
+ rSet.DisableItem(nWhich);
+ }
+ else
+ GetView().GetViewFrame().GetBindings().SetVisibleState( nWhich, true );
+ }
+ break;
+ case FN_READONLY_SELECTION_MODE :
+ if(!GetView().GetDocShell()->IsReadOnly())
+ rSet.DisableItem( nWhich );
+ else
+ {
+ rSet.Put(SfxBoolItem(nWhich, rSh.GetViewOptions()->IsSelectionInReadonly()));
+ }
+ break;
+ case FN_SELECTION_MODE_DEFAULT:
+ case FN_SELECTION_MODE_BLOCK :
+ rSet.Put(SfxBoolItem(nWhich, (nWhich == FN_SELECTION_MODE_DEFAULT) != rSh.IsBlockMode()));
+ break;
+ case SID_COPY_HYPERLINK_LOCATION:
+ case SID_OPEN_HYPERLINK:
+ {
+ SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
+ rSh.GetCurAttr(aSet);
+
+ bool bAuthorityFieldURL = false;
+ SwField* pField = rSh.GetCurField();
+ if (pField && pField->GetTyp()->Which() == SwFieldIds::TableOfAuthorities)
+ {
+ const auto& rAuthorityField = *static_cast<const SwAuthorityField*>(pField);
+ if (auto targetType = rAuthorityField.GetTargetType();
+ targetType == SwAuthorityField::TargetType::UseDisplayURL
+ || targetType == SwAuthorityField::TargetType::UseTargetURL)
+ {
+ // Check if the Bibliography entry has a target URL
+ bAuthorityFieldURL = rAuthorityField.GetAbsoluteURL().getLength() > 0;
+ }
+ }
+ if (SfxItemState::SET > aSet.GetItemState(RES_TXTATR_INETFMT, false)
+ && !bAuthorityFieldURL)
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case FN_OPEN_LOCAL_URL:
+ {
+ if (GetLocalURL(rSh).isEmpty())
+ {
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+ case SID_OPEN_SMARTTAGMENU:
+ {
+ std::vector< OUString > aSmartTagTypes;
+ uno::Sequence< uno::Reference< container::XStringKeyMap > > aStringKeyMaps;
+ uno::Reference<text::XTextRange> xRange;
+
+ rSh.GetSmartTagTerm( aSmartTagTypes, aStringKeyMaps, xRange );
+
+ if ( xRange.is() && !aSmartTagTypes.empty() )
+ {
+ uno::Sequence < uno::Sequence< uno::Reference< smarttags::XSmartTagAction > > > aActionComponentsSequence;
+ uno::Sequence < uno::Sequence< sal_Int32 > > aActionIndicesSequence;
+
+ const SmartTagMgr& rSmartTagMgr = SwSmartTagMgr::Get();
+ rSmartTagMgr.GetActionSequences( aSmartTagTypes,
+ aActionComponentsSequence,
+ aActionIndicesSequence );
+
+ uno::Reference <frame::XController> xController = GetView().GetController();
+ lang::Locale aLocale( SW_BREAKITER()->GetLocale( GetAppLanguageTag() ) );
+ const OUString& aApplicationName( rSmartTagMgr.GetApplicationName() );
+ const OUString aRangeText = xRange->getString();
+
+ const SvxSmartTagItem aItem( SID_OPEN_SMARTTAGMENU,
+ aActionComponentsSequence,
+ aActionIndicesSequence,
+ aStringKeyMaps,
+ xRange,
+ xController,
+ std::move(aLocale),
+ aApplicationName,
+ aRangeText );
+
+ rSet.Put( aItem );
+ }
+ else
+ rSet.DisableItem(nWhich);
+ }
+ break;
+
+ case FN_NUM_NUMBERING_ON:
+ rSet.Put(SfxBoolItem(FN_NUM_NUMBERING_ON,rSh.SelectionHasNumber()));
+ break;
+
+ case FN_NUM_BULLET_ON:
+ rSet.Put(SfxBoolItem(FN_NUM_BULLET_ON,rSh.SelectionHasBullet()));
+ break;
+
+ case FN_NUM_BULLET_OFF:
+ rSet.Put(SfxBoolItem(FN_NUM_BULLET_OFF, !rSh.GetNumRuleAtCurrCursorPos() &&
+ !rSh.GetNumRuleAtCurrentSelection()));
+ break;
+
+ case FN_SVX_SET_OUTLINE:
+ {
+ NBOTypeMgrBase* pOutline = NBOutlineTypeMgrFact::CreateInstance(NBOType::Outline);
+ auto pCurRule = const_cast<SwNumRule*>(rSh.GetNumRuleAtCurrCursorPos());
+ if (pOutline && pCurRule)
+ {
+ SvxNumRule aSvxRule = pCurRule->MakeSvxNumRule();
+ const sal_uInt16 nIndex = pOutline->GetNBOIndexForNumRule(aSvxRule, 0);
+ rSet.Put(SfxBoolItem(FN_SVX_SET_OUTLINE, nIndex < USHRT_MAX));
+ }
+ break;
+ }
+ case FN_BUL_NUM_RULE_INDEX:
+ case FN_NUM_NUM_RULE_INDEX:
+ case FN_OUTLINE_RULE_INDEX:
+ {
+ SwNumRule* pCurRule = const_cast<SwNumRule*>(GetShell().GetNumRuleAtCurrCursorPos());
+ if( pCurRule )
+ {
+ sal_uInt16 nActNumLvl = GetShell().GetNumLevel();
+ if( nActNumLvl < MAXLEVEL )
+ {
+ nActNumLvl = 1<<nActNumLvl;
+ }
+ SvxNumRule aSvxRule = pCurRule->MakeSvxNumRule();
+ if ( GetShell().HasBullet())
+ {
+ rSet.Put(SfxUInt16Item(FN_BUL_NUM_RULE_INDEX, USHRT_MAX));
+ rSet.Put(SfxUInt16Item(FN_NUM_NUM_RULE_INDEX, USHRT_MAX));
+ NBOTypeMgrBase* pBullets = NBOutlineTypeMgrFact::CreateInstance(NBOType::Bullets);
+ if ( pBullets )
+ {
+ const sal_uInt16 nBulIndex = pBullets->GetNBOIndexForNumRule(aSvxRule,nActNumLvl);
+ rSet.Put(SfxUInt16Item(FN_BUL_NUM_RULE_INDEX,nBulIndex));
+ }
+ }else if ( GetShell().HasNumber() )
+ {
+ rSet.Put(SfxUInt16Item(FN_BUL_NUM_RULE_INDEX, USHRT_MAX));
+ rSet.Put(SfxUInt16Item(FN_NUM_NUM_RULE_INDEX, USHRT_MAX));
+ NBOTypeMgrBase* pNumbering = NBOutlineTypeMgrFact::CreateInstance(NBOType::Numbering);
+ if ( pNumbering )
+ {
+ const sal_uInt16 nBulIndex = pNumbering->GetNBOIndexForNumRule(aSvxRule,nActNumLvl);
+ rSet.Put(SfxUInt16Item(FN_NUM_NUM_RULE_INDEX,nBulIndex));
+ }
+ }
+
+ if ( nWhich == FN_OUTLINE_RULE_INDEX )
+ {
+ rSet.Put(SfxUInt16Item(FN_OUTLINE_RULE_INDEX, USHRT_MAX));
+ NBOTypeMgrBase* pOutline = NBOutlineTypeMgrFact::CreateInstance(NBOType::Outline);
+ if ( pOutline )
+ {
+ const sal_uInt16 nIndex = pOutline->GetNBOIndexForNumRule(aSvxRule,nActNumLvl);
+ rSet.Put(SfxUInt16Item(FN_OUTLINE_RULE_INDEX,nIndex));
+ }
+ }
+ }
+ }
+ break;
+ case FN_NUM_CONTINUE:
+ {
+ // #i86492#
+ // Search also for bullet list
+ OUString aDummy;
+ const SwNumRule* pRule =
+ rSh.SearchNumRule( true, aDummy );
+ if ( !pRule )
+ {
+ pRule = rSh.SearchNumRule( false, aDummy );
+ }
+ if ( !pRule )
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_INSERT_RLM :
+ case SID_INSERT_LRM :
+ {
+ bool bEnabled = SvtCTLOptions::IsCTLFontEnabled();
+ GetView().GetViewFrame().GetBindings().SetVisibleState( nWhich, bEnabled );
+ if(!bEnabled)
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_FM_CTL_PROPERTIES:
+ {
+ bool bDisable = false;
+
+ // First get the state from the form shell
+ SfxItemSetFixed<SID_FM_CTL_PROPERTIES, SID_FM_CTL_PROPERTIES> aSet(GetShell().GetAttrPool());
+ aSet.Put(SfxBoolItem( SID_FM_CTL_PROPERTIES, true ));
+ GetShell().GetView().GetFormShell()->GetState( aSet );
+
+ if(SfxItemState::DISABLED == aSet.GetItemState(SID_FM_CTL_PROPERTIES))
+ {
+ bDisable = true;
+ }
+
+ // Enable it if we have a valid object other than what form shell knows
+ SwPosition aPos(*GetShell().GetCursor()->GetPoint());
+ sw::mark::IFieldmark* pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos);
+ if ( !pFieldBM && aPos.GetContentIndex() > 0)
+ {
+ aPos.AdjustContent(-1);
+ pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos);
+ }
+ if ( pFieldBM && (pFieldBM->GetFieldname() == ODF_FORMDROPDOWN || pFieldBM->GetFieldname() == ODF_FORMDATE) )
+ {
+ bDisable = false;
+ }
+
+ if(bDisable)
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_COPY:
+ case SID_CUT:
+ {
+ if (GetObjectShell()->isContentExtractionLocked())
+ rSet.DisableItem(nWhich);
+ break;
+ }
+ case FN_PROTECT_FIELDS:
+ case FN_PROTECT_BOOKMARKS:
+ {
+ DocumentSettingId aSettingId = nWhich == FN_PROTECT_FIELDS
+ ? DocumentSettingId::PROTECT_FIELDS
+ : DocumentSettingId::PROTECT_BOOKMARKS;
+ bool bProtected = rSh.getIDocumentSettingAccess().get(aSettingId);
+ rSet.Put(SfxBoolItem(nWhich, bProtected));
+ }
+ break;
+ case FN_CONTENT_CONTROL_PROPERTIES:
+ {
+ if (!GetShell().CursorInsideContentControl())
+ {
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/textsh2.cxx b/sw/source/uibase/shells/textsh2.cxx
new file mode 100644
index 0000000000..8a62f401fe
--- /dev/null
+++ b/sw/source/uibase/shells/textsh2.cxx
@@ -0,0 +1,252 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/stritem.hxx>
+#include <svl/itemset.hxx>
+#include <sfx2/request.hxx>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <comphelper/types.hxx>
+#include <sfx2/frame.hxx>
+#include <fldmgr.hxx>
+#include <fldbas.hxx>
+#include <dbmgr.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#include <osl/diagnose.h>
+
+#include <vcl/svapp.hxx>
+
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <swtypes.hxx>
+#include <cmdid.h>
+#include <textsh.hxx>
+#include <swabstdlg.hxx>
+
+using namespace ::svx;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::frame;
+
+struct DBTextStruct_Impl
+{
+ SwDBData aDBData;
+ Sequence<Any> aSelection;
+ Reference<XResultSet> xCursor;
+ Reference<XConnection> xConnection;
+};
+
+void SwTextShell::ExecDB(SfxRequest const &rReq)
+{
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ SwDBManager* pDBManager = GetShell().GetDBManager();
+ OUString sSourceArg, sCommandArg;
+ sal_Int32 nCommandTypeArg = 0;
+ const SfxUnoAnyItem* pSourceItem = nullptr;
+ const SfxUnoAnyItem* pCommandItem = nullptr;
+ const SfxUnoAnyItem* pCommandTypeItem = nullptr;
+ const SfxUnoAnyItem* pConnectionItem = nullptr;
+
+ // first get the selection of rows to be inserted
+
+ Sequence<Any> aSelection;
+ if(const SfxUnoAnyItem* pSelectionItem = pArgs->GetItemIfSet(FN_DB_DATA_SELECTION_ANY, false))
+ pSelectionItem->GetValue() >>= aSelection;
+
+ // get the data source name
+ pSourceItem = pArgs->GetItemIfSet(FN_DB_DATA_SOURCE_ANY, false);
+ if(pSourceItem)
+ pSourceItem->GetValue() >>= sSourceArg;
+
+ // get the command
+ pCommandItem = pArgs->GetItemIfSet(FN_DB_DATA_COMMAND_ANY, false);
+ if(pCommandItem)
+ pCommandItem->GetValue() >>= sCommandArg;
+
+ // get the command type
+ pCommandTypeItem = pArgs->GetItemIfSet(FN_DB_DATA_COMMAND_TYPE_ANY, false);
+ if(pCommandTypeItem)
+ pCommandTypeItem->GetValue() >>= nCommandTypeArg;
+
+ Reference<XConnection> xConnection;
+ pConnectionItem = pArgs->GetItemIfSet(FN_DB_CONNECTION_ANY, false);
+ if(pConnectionItem)
+ pConnectionItem->GetValue() >>= xConnection;
+ // may be we even get no connection
+ if ( !xConnection.is() )
+ {
+ Reference<XDataSource> xSource;
+ SwView &rSwView = GetView();
+ xConnection = SwDBManager::GetConnection(sSourceArg, xSource, &rSwView);
+ }
+ if(!xConnection.is())
+ return ;
+
+ // get the cursor, we use to travel, may be NULL
+ Reference<XResultSet> xCursor;
+ if ( const SfxUnoAnyItem* pCursorItem = pArgs->GetItemIfSet(FN_DB_DATA_CURSOR_ANY, false) )
+ pCursorItem->GetValue() >>= xCursor;
+
+ switch (rReq.GetSlot())
+ {
+ case FN_QRY_INSERT:
+ {
+ if(pSourceItem && pCommandItem && pCommandTypeItem)
+ {
+ DBTextStruct_Impl* pNew = new DBTextStruct_Impl;
+ pNew->aDBData.sDataSource = sSourceArg;
+ pNew->aDBData.sCommand = sCommandArg;
+ pNew->aDBData.nCommandType = nCommandTypeArg;
+ pNew->aSelection = aSelection;
+ //if the cursor is NULL, it must be created inside InsertDBTextHdl
+ // because it called via a PostUserEvent
+ pNew->xCursor = xCursor;
+ pNew->xConnection = xConnection;
+
+ Application::PostUserEvent( LINK( this, SwBaseShell, InsertDBTextHdl ), pNew );
+ // the pNew will be removed in InsertDBTextHdl !!
+ }
+ }
+ break;
+
+ case FN_QRY_MERGE_FIELD:
+ {
+ // we don't get any cursor, so we must create our own
+ bool bDisposeResultSet = false;
+ if ( !xCursor.is() )
+ {
+ SwView &rSwView = GetView();
+ xCursor = SwDBManager::createCursor(sSourceArg,sCommandArg,nCommandTypeArg,xConnection,&rSwView);
+ bDisposeResultSet = xCursor.is();
+ }
+
+ ODataAccessDescriptor aDescriptor;
+ aDescriptor.setDataSource(sSourceArg);
+ aDescriptor[DataAccessDescriptorProperty::Command] <<= sCommandArg;
+ aDescriptor[DataAccessDescriptorProperty::Cursor] <<= xCursor;
+ aDescriptor[DataAccessDescriptorProperty::Selection] <<= aSelection;
+ aDescriptor[DataAccessDescriptorProperty::CommandType] <<= nCommandTypeArg;
+
+ SwMergeDescriptor aMergeDesc( DBMGR_MERGE, *GetShellPtr(), aDescriptor );
+ pDBManager->Merge(aMergeDesc);
+
+ if ( bDisposeResultSet )
+ ::comphelper::disposeComponent(xCursor);
+ }
+ break;
+
+ case FN_QRY_INSERT_FIELD:
+ {
+ const SfxUnoAnyItem* pColumnItem = pArgs->GetItemIfSet(FN_DB_COLUMN_ANY, false);
+ const SfxUnoAnyItem* pColumnNameItem =
+ pArgs->GetItemIfSet(FN_DB_DATA_COLUMN_NAME_ANY, false);
+
+ OUString sColumnName;
+ if(pColumnNameItem)
+ pColumnNameItem->GetValue() >>= sColumnName;
+ OUString sDBName = sSourceArg + OUStringChar(DB_DELIM)
+ + sCommandArg + OUStringChar(DB_DELIM)
+ + OUString::number(nCommandTypeArg)
+ + OUStringChar(DB_DELIM) + sColumnName;
+
+ SwFieldMgr aFieldMgr(GetShellPtr());
+ SwInsertField_Data aData(SwFieldTypesEnum::Database, 0, sDBName, OUString(), 0);
+ if(pConnectionItem)
+ aData.m_aDBConnection = pConnectionItem->GetValue();
+ if(pColumnItem)
+ aData.m_aDBColumn = pColumnItem->GetValue();
+ aFieldMgr.InsertField(aData);
+ SfxViewFrame& rViewFrame = GetView().GetViewFrame();
+ uno::Reference< XDispatchRecorder > xRecorder =
+ rViewFrame.GetBindings().GetRecorder();
+ if ( xRecorder.is() )
+ {
+ SfxRequest aReq(rViewFrame, FN_INSERT_DBFIELD);
+ aReq.AppendItem( SfxUInt16Item(FN_PARAM_FIELD_TYPE, static_cast<sal_uInt16>(SwFieldTypesEnum::Database)));
+ aReq.AppendItem( SfxStringItem( FN_INSERT_DBFIELD, sDBName ));
+ aReq.AppendItem( SfxStringItem( FN_PARAM_1, sCommandArg ));
+ aReq.AppendItem( SfxStringItem( FN_PARAM_2, sColumnName ));
+ aReq.AppendItem( SfxInt32Item( FN_PARAM_3, nCommandTypeArg));
+ aReq.Done();
+ }
+ }
+ break;
+
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ return;
+ }
+}
+
+IMPL_LINK( SwBaseShell, InsertDBTextHdl, void*, p, void )
+{
+ DBTextStruct_Impl* pDBStruct = static_cast<DBTextStruct_Impl*>(p);
+ if( pDBStruct )
+ {
+ bool bDispose = false;
+ Reference< sdbc::XConnection> xConnection = pDBStruct->xConnection;
+ Reference<XDataSource> xSource = SwDBManager::getDataSourceAsParent(xConnection,pDBStruct->aDBData.sDataSource);
+ // #111987# the connection is disposed and so no parent has been found
+ if(xConnection.is() && !xSource.is())
+ return;
+
+ if ( !xConnection.is() )
+ {
+ SwView &rSwView = GetView();
+ xConnection = SwDBManager::GetConnection(pDBStruct->aDBData.sDataSource, xSource, &rSwView);
+ bDispose = true;
+ }
+
+ Reference< XColumnsSupplier> xColSupp;
+ if(xConnection.is())
+ xColSupp = SwDBManager::GetColumnSupplier(xConnection,
+ pDBStruct->aDBData.sCommand,
+ pDBStruct->aDBData.nCommandType == CommandType::QUERY ?
+ SwDBSelect::QUERY : SwDBSelect::TABLE);
+
+ if( xColSupp.is() )
+ {
+ SwDBData aDBData = pDBStruct->aDBData;
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractSwInsertDBColAutoPilot>pDlg (pFact->CreateSwInsertDBColAutoPilot(GetView(),
+ xSource,
+ xColSupp,
+ aDBData));
+ if( RET_OK == pDlg->Execute() )
+ {
+ pDlg->DataToDoc(pDBStruct->aSelection, xSource, xConnection, pDBStruct->xCursor);
+ }
+ }
+ if ( bDispose )
+ ::comphelper::disposeComponent(xConnection);
+ }
+
+ delete pDBStruct;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/translatehelper.cxx b/sw/source/uibase/shells/translatehelper.cxx
new file mode 100644
index 0000000000..eb9bcaedbb
--- /dev/null
+++ b/sw/source/uibase/shells/translatehelper.cxx
@@ -0,0 +1,216 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <config_features.h>
+#include <config_wasm_strip.h>
+#include <wrtsh.hxx>
+#include <pam.hxx>
+#include <node.hxx>
+#include <ndtxt.hxx>
+#include <translatehelper.hxx>
+#include <sal/log.hxx>
+#include <rtl/string.h>
+#include <shellio.hxx>
+#include <vcl/scheduler.hxx>
+#include <vcl/svapp.hxx>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/json_parser.hpp>
+#include <vcl/htmltransferable.hxx>
+#include <vcl/transfer.hxx>
+#include <swdtflvr.hxx>
+#include <linguistic/translate.hxx>
+#include <com/sun/star/task/XStatusIndicator.hpp>
+#include <sfx2/viewfrm.hxx>
+#include <com/sun/star/task/XStatusIndicatorFactory.hpp>
+#include <strings.hrc>
+
+namespace SwTranslateHelper
+{
+OString ExportPaMToHTML(SwPaM* pCursor)
+{
+ SolarMutexGuard gMutex;
+ OString aResult;
+ WriterRef xWrt;
+ GetHTMLWriter(u"NoLineLimit,SkipHeaderFooter,NoPrettyPrint", OUString(), xWrt);
+ if (pCursor != nullptr)
+ {
+ SvMemoryStream aMemoryStream;
+ SwWriter aWriter(aMemoryStream, *pCursor);
+ ErrCodeMsg nError = aWriter.Write(xWrt);
+ if (nError.IsError())
+ {
+ SAL_WARN("sw.ui", "ExportPaMToHTML: failed to export selection to HTML " << nError);
+ return {};
+ }
+ aResult
+ = OString(static_cast<const char*>(aMemoryStream.GetData()), aMemoryStream.GetSize());
+ aResult = aResult.replaceAll("<p"_ostr, "<span"_ostr);
+ aResult = aResult.replaceAll("</p>"_ostr, "</span>"_ostr);
+
+ // HTML has for that <br> and <p> also does new line
+ aResult = aResult.replaceAll("<ul>"_ostr, ""_ostr);
+ aResult = aResult.replaceAll("</ul>"_ostr, ""_ostr);
+ aResult = aResult.replaceAll("<ol>"_ostr, ""_ostr);
+ aResult = aResult.replaceAll("</ol>"_ostr, ""_ostr);
+ aResult = aResult.replaceAll("\n"_ostr, ""_ostr).trim();
+ return aResult;
+ }
+ return {};
+}
+
+void PasteHTMLToPaM(SwWrtShell& rWrtSh, SwPaM* pCursor, const OString& rData)
+{
+ SolarMutexGuard gMutex;
+ rtl::Reference<vcl::unohelper::HtmlTransferable> pHtmlTransferable
+ = new vcl::unohelper::HtmlTransferable(rData);
+ if (pHtmlTransferable.is())
+ {
+ TransferableDataHelper aDataHelper(pHtmlTransferable);
+ if (aDataHelper.GetXTransferable().is()
+ && SwTransferable::IsPasteSpecial(rWrtSh, aDataHelper))
+ {
+ rWrtSh.SetSelection(*pCursor);
+ SwTransferable::Paste(rWrtSh, aDataHelper);
+ rWrtSh.KillSelection(nullptr, false);
+ }
+ }
+}
+
+#if HAVE_FEATURE_CURL && !ENABLE_WASM_STRIP_EXTRA
+void TranslateDocument(SwWrtShell& rWrtSh, const TranslateAPIConfig& rConfig)
+{
+ bool bCancel = false;
+ TranslateDocumentCancellable(rWrtSh, rConfig, bCancel);
+}
+
+void TranslateDocumentCancellable(SwWrtShell& rWrtSh, const TranslateAPIConfig& rConfig,
+ bool& rCancelTranslation)
+{
+ auto m_pCurrentPam = rWrtSh.GetCursor();
+ bool bHasSelection = rWrtSh.HasSelection();
+
+ if (bHasSelection)
+ {
+ // iteration will start top to bottom
+ if (m_pCurrentPam->GetPoint()->nNode > m_pCurrentPam->GetMark()->nNode)
+ m_pCurrentPam->Exchange();
+ }
+
+ auto const& pNodes = rWrtSh.GetNodes();
+ SwPosition aPoint = *m_pCurrentPam->GetPoint();
+ SwPosition aMark = *m_pCurrentPam->GetMark();
+ auto startNode = bHasSelection ? aPoint.nNode.GetIndex() : SwNodeOffset(0);
+ auto endNode = bHasSelection ? aMark.nNode.GetIndex() : pNodes.Count() - 1;
+
+ sal_Int32 nCount(0);
+ sal_Int32 nProgress(0);
+
+ for (SwNodeOffset n(startNode); n <= endNode; ++n)
+ {
+ if (pNodes[n] && pNodes[n]->IsTextNode())
+ {
+ if (pNodes[n]->GetTextNode()->GetText().isEmpty())
+ continue;
+ nCount++;
+ }
+ }
+
+ SfxViewFrame* pFrame = SfxViewFrame::Current();
+ uno::Reference<frame::XFrame> xFrame(pFrame ? pFrame->GetFrame().GetFrameInterface() : nullptr);
+ uno::Reference<task::XStatusIndicatorFactory> xProgressFactory(xFrame, uno::UNO_QUERY);
+ uno::Reference<task::XStatusIndicator> xStatusIndicator;
+
+ if (xProgressFactory.is())
+ {
+ xStatusIndicator = xProgressFactory->createStatusIndicator();
+ }
+
+ if (xStatusIndicator.is())
+ xStatusIndicator->start(SwResId(STR_STATSTR_SWTRANSLATE), nCount);
+
+ for (SwNodeOffset n(startNode); n <= endNode; ++n)
+ {
+ if (rCancelTranslation)
+ break;
+
+ if (n >= rWrtSh.GetNodes().Count())
+ break;
+
+ if (!pNodes[n])
+ break;
+
+ SwNode* pNode = pNodes[n];
+ if (pNode->IsTextNode())
+ {
+ if (pNode->GetTextNode()->GetText().isEmpty())
+ continue;
+
+ auto cursor
+ = Writer::NewUnoCursor(*rWrtSh.GetDoc(), pNode->GetIndex(), pNode->GetIndex());
+
+ // set edges (start, end) for nodes inside the selection.
+ if (bHasSelection)
+ {
+ if (startNode == endNode)
+ {
+ cursor->SetMark();
+ cursor->GetPoint()->nContent = aPoint.nContent;
+ cursor->GetMark()->nContent = aMark.nContent;
+ }
+ else if (n == startNode)
+ {
+ cursor->SetMark();
+ cursor->GetPoint()->nContent = aPoint.nContent;
+ }
+ else if (n == endNode)
+ {
+ cursor->SetMark();
+ cursor->GetMark()->nContent = aMark.nContent;
+ cursor->GetPoint()->nContent = 0;
+ }
+ }
+
+ const auto aOut = SwTranslateHelper::ExportPaMToHTML(cursor.get());
+ const auto aTranslatedOut = linguistic::Translate(
+ rConfig.m_xTargetLanguage, rConfig.m_xAPIUrl, rConfig.m_xAuthKey, aOut);
+ SwTranslateHelper::PasteHTMLToPaM(rWrtSh, cursor.get(), aTranslatedOut);
+
+ if (xStatusIndicator.is() && nCount)
+ xStatusIndicator->setValue((100 * ++nProgress) / nCount);
+
+ Idle aIdle("ProgressBar::SetValue aIdle");
+ aIdle.SetPriority(TaskPriority::POST_PAINT);
+ aIdle.Start();
+
+ rWrtSh.LockView(true);
+ while (aIdle.IsActive() && !Application::IsQuit())
+ {
+ Application::Yield();
+ }
+ rWrtSh.LockView(false);
+ }
+ }
+
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+}
+#endif // HAVE_FEATURE_CURL && !ENABLE_WASM_STRIP_EXTRA
+}
diff --git a/sw/source/uibase/shells/txtattr.cxx b/sw/source/uibase/shells/txtattr.cxx
new file mode 100644
index 0000000000..68f4197f54
--- /dev/null
+++ b/sw/source/uibase/shells/txtattr.cxx
@@ -0,0 +1,849 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+
+#include <svl/whiter.hxx>
+#include <svl/stritem.hxx>
+#include <svl/ctloptions.hxx>
+#include <swmodule.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/adjustitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/escapementitem.hxx>
+#include <editeng/pmdlitem.hxx>
+#include <sfx2/htmlmode.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <osl/diagnose.h>
+#include <paratr.hxx>
+
+#include <fmtinfmt.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <viewopt.hxx>
+#include <uitool.hxx>
+#include <textsh.hxx>
+#include <swundo.hxx>
+#include <fmtcol.hxx>
+
+#include <cmdid.h>
+#include <globals.h>
+#include <SwStyleNameMapper.hxx>
+#include <swabstdlg.hxx>
+#include <memory>
+
+const sal_uInt32 nFontInc = 40; // 2pt
+const sal_uInt32 nFontMaxSz = 19998; // 999.9pt
+
+void SwTextShell::ExecCharAttr(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ int eState = STATE_TOGGLE;
+ sal_uInt16 nWhich = rReq.GetSlot();
+
+ if(pArgs )
+ {
+ const SfxPoolItem* pItem;
+ pArgs->GetItemState(nWhich, false, &pItem);
+ eState = static_cast<const SfxBoolItem &>( pArgs->
+ Get( nWhich )).GetValue() ? STATE_ON : STATE_OFF;
+ }
+
+ SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END-1> aSet( GetPool() );
+ if (STATE_TOGGLE == eState)
+ rSh.GetCurAttr( aSet );
+
+ switch ( nWhich )
+ {
+ case FN_SET_SUB_SCRIPT:
+ case FN_SET_SUPER_SCRIPT:
+ {
+ SvxEscapement eEscape = SvxEscapement::Subscript;
+ switch (eState)
+ {
+ case STATE_TOGGLE:
+ {
+ short nTmpEsc = aSet.Get( RES_CHRATR_ESCAPEMENT ).GetEsc();
+ eEscape = nWhich == FN_SET_SUPER_SCRIPT ?
+ SvxEscapement::Superscript:
+ SvxEscapement::Subscript;
+ if( (nWhich == FN_SET_SUB_SCRIPT && nTmpEsc < 0) ||
+ (nWhich == FN_SET_SUPER_SCRIPT && nTmpEsc > 0) )
+ eEscape = SvxEscapement::Off;
+
+ SfxBindings& rBind = GetView().GetViewFrame().GetBindings();
+ if( nWhich == FN_SET_SUB_SCRIPT )
+ rBind.SetState( SfxBoolItem( FN_SET_SUPER_SCRIPT,
+ false ) );
+ else
+ rBind.SetState( SfxBoolItem( FN_SET_SUB_SCRIPT,
+ false ) );
+
+ }
+ break;
+ case STATE_ON:
+ eEscape = nWhich == FN_SET_SUPER_SCRIPT ?
+ SvxEscapement::Superscript:
+ SvxEscapement::Subscript;
+ break;
+ case STATE_OFF:
+ eEscape = SvxEscapement::Off;
+ break;
+ }
+ SvxEscapementItem aEscape( eEscape, RES_CHRATR_ESCAPEMENT );
+ rSh.SetAttrItem( aEscape );
+ rReq.AppendItem( aEscape );
+ rReq.Done();
+ }
+ break;
+
+ case FN_SET_SMALL_CAPS:
+ {
+ SvxCaseMap eCaseMap = SvxCaseMap::SmallCaps;
+ switch (eState)
+ {
+ case STATE_TOGGLE:
+ {
+ SvxCaseMap eTmpCaseMap = aSet.Get(RES_CHRATR_CASEMAP).GetCaseMap();
+ if (eTmpCaseMap == SvxCaseMap::SmallCaps)
+ eCaseMap = SvxCaseMap::NotMapped;
+ }
+ break;
+ case STATE_ON:
+ // Nothing to do, already set.
+ break;
+ case STATE_OFF:
+ eCaseMap = SvxCaseMap::NotMapped;
+ break;
+ }
+ SvxCaseMapItem aCaseMap(eCaseMap, RES_CHRATR_CASEMAP);
+ rSh.SetAttrItem(aCaseMap);
+ rReq.AppendItem(aCaseMap);
+ rReq.Done();
+ }
+ break;
+
+ case FN_UPDATE_STYLE_BY_EXAMPLE:
+ rSh.QuickUpdateStyle();
+ rReq.Done();
+ break;
+
+ case SID_ULINE_VAL_NONE:
+ {
+ SvxUnderlineItem aUnderline(LINESTYLE_NONE, RES_CHRATR_UNDERLINE );
+ rSh.SetAttrItem( aUnderline );
+ rReq.AppendItem( aUnderline );
+ rReq.Done();
+ break;
+ }
+
+ case SID_ULINE_VAL_SINGLE:
+ case SID_ULINE_VAL_DOUBLE:
+ case SID_ULINE_VAL_DOTTED:
+ {
+ FontLineStyle eOld = aSet.Get(RES_CHRATR_UNDERLINE).GetLineStyle();
+ FontLineStyle eNew = eOld;
+
+ switch (nWhich)
+ {
+ case SID_ULINE_VAL_SINGLE:
+ eNew = ( eOld == LINESTYLE_SINGLE ) ? LINESTYLE_NONE : LINESTYLE_SINGLE;
+ break;
+ case SID_ULINE_VAL_DOUBLE:
+ eNew = ( eOld == LINESTYLE_DOUBLE ) ? LINESTYLE_NONE : LINESTYLE_DOUBLE;
+ break;
+ case SID_ULINE_VAL_DOTTED:
+ eNew = ( eOld == LINESTYLE_DOTTED ) ? LINESTYLE_NONE : LINESTYLE_DOTTED;
+ break;
+ }
+
+ SvxUnderlineItem aUnderline(eNew, RES_CHRATR_UNDERLINE );
+ rSh.SetAttrItem( aUnderline );
+ rReq.AppendItem( aUnderline );
+ rReq.Done();
+ }
+ break;
+ case FN_REMOVE_DIRECT_CHAR_FORMATS:
+ if( !rSh.HasReadonlySel() && rSh.IsEndPara())
+ rSh.DontExpandFormat();
+ break;
+ default:
+ OSL_FAIL("wrong dispatcher");
+ return;
+ }
+}
+
+void SwTextShell::ExecCharAttrArgs(SfxRequest &rReq)
+{
+ sal_uInt16 nSlot = rReq.GetSlot();
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ bool bArgs = pArgs != nullptr && pArgs->Count() > 0;
+ SwWrtShell& rWrtSh = GetShell();
+ SwTextFormatColl* pColl = nullptr;
+
+ // Is only set if the whole paragraph is selected and AutoUpdateFormat is set.
+ if (rWrtSh.HasSelection() && rWrtSh.IsSelFullPara())
+ {
+ pColl = rWrtSh.GetCurTextFormatColl();
+ if ( pColl && !pColl->IsAutoUpdateOnDirectFormat() )
+ pColl = nullptr;
+ }
+ SfxItemPool& rPool = GetPool();
+ sal_uInt16 nWhich = rPool.GetWhich( nSlot );
+ switch (nSlot)
+ {
+ case FN_TXTATR_INET:
+ // Special treatment of the PoolId of the SwFormatInetFormat
+ if(bArgs)
+ {
+ const SfxPoolItem& rItem = pArgs->Get( nWhich );
+
+ SwFormatINetFormat aINetFormat( static_cast<const SwFormatINetFormat&>(rItem) );
+ if ( USHRT_MAX == aINetFormat.GetVisitedFormatId() )
+ {
+ OSL_ENSURE( false, "<SwTextShell::ExecCharAttrArgs(..)> - unexpected visited character format ID at hyperlink attribute" );
+ aINetFormat.SetVisitedFormatAndId(
+ aINetFormat.GetVisitedFormat(),
+ SwStyleNameMapper::GetPoolIdFromUIName( aINetFormat.GetVisitedFormat(), SwGetPoolIdFromName::ChrFmt ) );
+ }
+ if ( USHRT_MAX == aINetFormat.GetINetFormatId() )
+ {
+ OSL_ENSURE( false, "<SwTextShell::ExecCharAttrArgs(..)> - unexpected unvisited character format ID at hyperlink attribute" );
+ aINetFormat.SetINetFormatAndId(
+ aINetFormat.GetINetFormat(),
+ SwStyleNameMapper::GetPoolIdFromUIName( aINetFormat.GetINetFormat(), SwGetPoolIdFromName::ChrFmt ) );
+ }
+
+ if ( pColl )
+ pColl->SetFormatAttr( aINetFormat );
+ else
+ rWrtSh.SetAttrItem( aINetFormat );
+ rReq.Done();
+ }
+ break;
+
+ case FN_GROW_FONT_SIZE:
+ case FN_SHRINK_FONT_SIZE:
+ {
+ SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONTHEIGHT, rPool );
+ rWrtSh.GetCurAttr( aSetItem.GetItemSet() );
+ SfxItemSet aAttrSet( rPool, aSetItem.GetItemSet().GetRanges() );
+
+ SvtScriptType nScriptTypes = rWrtSh.GetScriptType();
+ const SvxFontHeightItem* pSize( static_cast<const SvxFontHeightItem*>(
+ aSetItem.GetItemOfScript( nScriptTypes ) ) );
+ std::vector<std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM> >> vItems;
+ // simple case where selected text has one size and
+ // (tdf#124919) selection is not multiple table cells
+ if (pSize && !rWrtSh.IsTableMode())
+ {
+ // must create new one, otherwise document is without pam
+ SwPaM* pPaM = rWrtSh.GetCursor();
+ vItems.emplace_back( pSize, std::make_unique<SwPaM>( *(pPaM->GetMark()), *(pPaM->GetPoint())) );
+ }
+ else
+ vItems = rWrtSh.GetItemWithPaM( RES_CHRATR_FONTSIZE );
+
+ rWrtSh.StartUndo( SwUndoId::INSATTR );
+ for( std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM> >& iPair : vItems )
+ {
+ std::unique_ptr<SwPaM> pPaM = std::move(iPair.second);
+ const SfxPoolItem* pItem = iPair.first;
+ aSetItem.GetItemSet().ClearItem();
+ rWrtSh.GetPaMAttr( pPaM.get(), aSetItem.GetItemSet() );
+ aAttrSet.SetRanges( aSetItem.GetItemSet().GetRanges() );
+
+ pSize = static_cast<const SvxFontHeightItem*>( pItem );
+ if (pSize)
+ {
+ SvxFontHeightItem aSize(*pSize);
+
+ sal_uInt32 nSize = aSize.GetHeight();
+
+ if ( nSlot == FN_GROW_FONT_SIZE && ( nSize += nFontInc ) > nFontMaxSz )
+ nSize = nFontMaxSz;
+ else if ( nSlot == FN_SHRINK_FONT_SIZE && ( nSize -= nFontInc ) < nFontInc )
+ nSize = nFontInc;
+
+ aSize.SetHeight( nSize );
+ aSetItem.PutItemForScriptType( nScriptTypes, aSize );
+ aAttrSet.Put( aSetItem.GetItemSet() );
+ if( pColl )
+ pColl->SetFormatAttr( aAttrSet );
+ else
+ rWrtSh.SetAttrSet( aAttrSet, SetAttrMode::DEFAULT, pPaM.get() );
+ }
+ }
+ rWrtSh.EndUndo( SwUndoId::INSATTR );
+ rReq.Done();
+ }
+ break;
+
+ default:
+ OSL_FAIL("wrong dispatcher");
+ return;
+ }
+}
+
+void SwTextShell::ExecParaAttr(SfxRequest &rReq)
+{
+ SvxAdjust eAdjst;
+ sal_uInt16 ePropL;
+ const SfxItemSet* pArgs = rReq.GetArgs();
+
+ // Get both attributes immediately isn't more expensive!!
+ SfxItemSetFixed
+ <RES_PARATR_LINESPACING, RES_PARATR_ADJUST,
+ RES_FRAMEDIR, RES_FRAMEDIR> aSet( GetPool() );
+
+ sal_uInt16 nSlot = rReq.GetSlot();
+ switch (nSlot)
+ {
+ case SID_ATTR_PARA_ADJUST:
+ {
+ if( pArgs && SfxItemState::SET == pArgs->GetItemState(RES_PARATR_ADJUST) )
+ {
+ const SvxAdjustItem& rAdj = pArgs->Get(RES_PARATR_ADJUST);
+ SvxAdjustItem aAdj( rAdj.GetAdjust(), RES_PARATR_ADJUST );
+ if ( rAdj.GetAdjust() == SvxAdjust::Block )
+ {
+ aAdj.SetLastBlock( rAdj.GetLastBlock() );
+ aAdj.SetOneWord( rAdj.GetOneWord() );
+ }
+
+ aSet.Put(aAdj);
+ }
+ }
+ break;
+ case SID_ATTR_PARA_ADJUST_LEFT: eAdjst = SvxAdjust::Left; goto SET_ADJUST;
+ case SID_ATTR_PARA_ADJUST_RIGHT: eAdjst = SvxAdjust::Right; goto SET_ADJUST;
+ case SID_ATTR_PARA_ADJUST_CENTER: eAdjst = SvxAdjust::Center; goto SET_ADJUST;
+ case SID_ATTR_PARA_ADJUST_BLOCK: eAdjst = SvxAdjust::Block; goto SET_ADJUST;
+SET_ADJUST:
+ {
+ aSet.Put(SvxAdjustItem(eAdjst,RES_PARATR_ADJUST));
+ rReq.AppendItem( SfxBoolItem( GetPool().GetWhich(nSlot), true ) );
+ }
+ break;
+
+ case SID_ATTR_PARA_LINESPACE:
+ if(pArgs && SfxItemState::SET == pArgs->GetItemState( GetPool().GetWhich(nSlot) ))
+ {
+ SvxLineSpacingItem aLineSpace = static_cast<const SvxLineSpacingItem&>( pArgs->Get(
+ GetPool().GetWhich(nSlot)));
+ aSet.Put( aLineSpace );
+ }
+ break;
+ case SID_ATTR_PARA_LINESPACE_10: ePropL = 100; goto SET_LINESPACE;
+ case SID_ATTR_PARA_LINESPACE_15: ePropL = 150; goto SET_LINESPACE;
+ case SID_ATTR_PARA_LINESPACE_115: ePropL = 115; goto SET_LINESPACE;
+ case SID_ATTR_PARA_LINESPACE_20: ePropL = 200; goto SET_LINESPACE;
+
+SET_LINESPACE:
+ {
+
+ SvxLineSpacingItem aLineSpacing(ePropL, RES_PARATR_LINESPACING );
+ aLineSpacing.SetLineSpaceRule( SvxLineSpaceRule::Auto );
+ if( 100 == ePropL )
+ aLineSpacing.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off );
+ else
+ aLineSpacing.SetPropLineSpace(ePropL);
+ aSet.Put( aLineSpacing );
+ }
+ break;
+
+ case SID_ATTR_PARA_LEFT_TO_RIGHT :
+ case SID_ATTR_PARA_RIGHT_TO_LEFT :
+ {
+ SfxItemSetFixed<RES_PARATR_ADJUST, RES_PARATR_ADJUST> aAdjustSet( GetPool() );
+ GetShell().GetCurAttr(aAdjustSet);
+ bool bChgAdjust = false;
+ SfxItemState eAdjustState = aAdjustSet.GetItemState(RES_PARATR_ADJUST, false);
+ if(eAdjustState >= SfxItemState::DEFAULT)
+ {
+ SvxAdjust eAdjust =
+ aAdjustSet.Get(RES_PARATR_ADJUST).GetAdjust();
+ bChgAdjust = (SvxAdjust::Left == eAdjust && SID_ATTR_PARA_RIGHT_TO_LEFT == nSlot) ||
+ (SvxAdjust::Right == eAdjust && SID_ATTR_PARA_LEFT_TO_RIGHT == nSlot);
+ }
+ else
+ bChgAdjust = true;
+
+ SvxFrameDirection eFrameDirection =
+ (SID_ATTR_PARA_LEFT_TO_RIGHT == nSlot) ?
+ SvxFrameDirection::Horizontal_LR_TB : SvxFrameDirection::Horizontal_RL_TB;
+ aSet.Put( SvxFrameDirectionItem( eFrameDirection, RES_FRAMEDIR ) );
+
+ if (bChgAdjust)
+ {
+ SvxAdjust eAdjust = (SID_ATTR_PARA_LEFT_TO_RIGHT == nSlot) ?
+ SvxAdjust::Left : SvxAdjust::Right;
+ SvxAdjustItem aAdjust( eAdjust, RES_PARATR_ADJUST );
+ aSet.Put( aAdjust );
+ aAdjust.SetWhich(SID_ATTR_PARA_ADJUST);
+ GetView().GetViewFrame().GetBindings().SetState( aAdjust );
+ // Toggle numbering alignment
+ const SwNumRule* pCurRule = GetShell().GetNumRuleAtCurrCursorPos();
+ if( pCurRule )
+ {
+ SvxNumRule aRule = pCurRule->MakeSvxNumRule();
+
+ for(sal_uInt16 i = 0; i < aRule.GetLevelCount(); i++)
+ {
+ SvxNumberFormat aFormat(aRule.GetLevel(i));
+ if(SvxAdjust::Left == aFormat.GetNumAdjust())
+ aFormat.SetNumAdjust( SvxAdjust::Right );
+
+ else if(SvxAdjust::Right == aFormat.GetNumAdjust())
+ aFormat.SetNumAdjust( SvxAdjust::Left );
+
+ aRule.SetLevel(i, aFormat, aRule.Get(i) != nullptr);
+ }
+ SwNumRule aSetRule( pCurRule->GetName(),
+ pCurRule->Get( 0 ).GetPositionAndSpaceMode() );
+ aSetRule.SetSvxRule( aRule, GetShell().GetDoc());
+ aSetRule.SetAutoRule( true );
+ // no start or continuation of a list - list style is only changed
+ GetShell().SetCurNumRule( aSetRule, false );
+ }
+ }
+ }
+ break;
+
+ default:
+ OSL_FAIL("wrong dispatcher");
+ return;
+ }
+ SwWrtShell& rWrtSh = GetShell();
+ SwTextFormatColl* pColl = rWrtSh.GetCurTextFormatColl();
+ if(pColl && pColl->IsAutoUpdateOnDirectFormat())
+ {
+ rWrtSh.AutoUpdatePara(pColl, aSet);
+ }
+ else
+ rWrtSh.SetAttrSet( aSet, SetAttrMode::DEFAULT, nullptr, true);
+ rReq.Done();
+}
+
+void SwTextShell::ExecParaAttrArgs(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ const SfxPoolItem *pItem = nullptr;
+
+ sal_uInt16 nSlot = rReq.GetSlot();
+ if(pArgs)
+ pArgs->GetItemState(GetPool().GetWhich(nSlot), false, &pItem);
+ switch ( nSlot )
+ {
+ case FN_DROP_CHAR_STYLE_NAME:
+ if( pItem )
+ {
+ OUString sCharStyleName = static_cast<const SfxStringItem*>(pItem)->GetValue();
+ SfxItemSetFixed<RES_PARATR_DROP, RES_PARATR_DROP> aSet(GetPool());
+ rSh.GetCurAttr(aSet);
+ SwFormatDrop aDropItem(aSet.Get(RES_PARATR_DROP));
+ SwCharFormat* pFormat = nullptr;
+ if(!sCharStyleName.isEmpty())
+ pFormat = rSh.FindCharFormatByName( sCharStyleName );
+ aDropItem.SetCharFormat( pFormat );
+ aSet.Put(aDropItem);
+ rSh.SetAttrSet(aSet);
+ }
+ break;
+ case FN_FORMAT_DROPCAPS:
+ {
+ if(pItem)
+ {
+ rSh.SetAttrItem(*pItem);
+ rReq.Done();
+ }
+ else
+ {
+ SfxItemSetFixed<RES_PARATR_DROP, RES_PARATR_DROP,
+ HINT_END, HINT_END> aSet(GetPool());
+ rSh.GetCurAttr(aSet);
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateSwDropCapsDialog(GetView().GetFrameWeld(), aSet));
+ if (pDlg->Execute() == RET_OK)
+ {
+ rSh.StartAction();
+ rSh.StartUndo( SwUndoId::START );
+ if ( const SfxStringItem* pHintItem = aSet.GetItemIfSet(HINT_END,false) )
+ {
+ if ( !pHintItem->GetValue().isEmpty() )
+ rSh.ReplaceDropText(pHintItem->GetValue());
+ }
+ rSh.SetAttrSet(*pDlg->GetOutputItemSet());
+ rSh.EndUndo( SwUndoId::END );
+ rSh.EndAction();
+ rReq.Done(*pDlg->GetOutputItemSet());
+ }
+ }
+ }
+ break;
+ case SID_ATTR_PARA_PAGEBREAK:
+ if(pItem)
+ {
+ rSh.SetAttrItem( *pItem );
+ rReq.Done();
+ }
+ break;
+ case SID_ATTR_PARA_MODEL:
+ {
+ if(pItem)
+ {
+ SfxItemSetFixed<RES_PAGEDESC, RES_PAGEDESC,
+ SID_ATTR_PARA_MODEL, SID_ATTR_PARA_MODEL> aCoreSet( GetPool() );
+ aCoreSet.Put(*pItem);
+ SfxToSwPageDescAttr( rSh, aCoreSet);
+ rSh.SetAttrSet(aCoreSet);
+ rReq.Done();
+ }
+ }
+ break;
+
+ default:
+ OSL_FAIL("wrong dispatcher");
+ return;
+ }
+}
+
+void SwTextShell::GetAttrState(SfxItemSet &rSet)
+{
+ SwWrtShell &rSh = GetShell();
+ SfxItemPool& rPool = GetPool();
+ SfxItemSet aCoreSet(rPool, aTextFormatCollSetRange);
+ // Request *all* text attributes from the core.
+ // fdo#78737: this is called from SvxRuler, which requires the list indents!
+ rSh.GetCurAttr(aCoreSet, /* bMergeIndentValuesOfNumRule = */ true);
+
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nSlot = aIter.FirstWhich();
+ bool bFlag = false;
+ SfxBoolItem aFlagItem;
+ const SfxPoolItem* pItem = nullptr;
+ SvxAdjust eAdjust = SvxAdjust::Left;
+ bool bAdjustGood = false;
+ SfxItemState eState = aCoreSet.GetItemState(RES_PARATR_ADJUST, false, &pItem);
+
+ if( SfxItemState::DEFAULT == eState )
+ pItem = &rPool.GetDefaultItem(RES_PARATR_ADJUST);
+ if( SfxItemState::DEFAULT <= eState )
+ {
+ eAdjust = static_cast<const SvxAdjustItem* >( pItem)->GetAdjust();
+ bAdjustGood = true;
+ }
+
+ short nEsc = 0;
+ eState = aCoreSet.GetItemState(RES_CHRATR_ESCAPEMENT, false, &pItem);
+ if( SfxItemState::DEFAULT == eState )
+ pItem = &rPool.GetDefaultItem(RES_CHRATR_ESCAPEMENT);
+ if( eState >= SfxItemState::DEFAULT )
+ nEsc = static_cast<const SvxEscapementItem* >(pItem)->GetEsc();
+
+ sal_uInt16 nLineSpace = 0;
+ eState = aCoreSet.GetItemState(RES_PARATR_LINESPACING, false, &pItem);
+ if( SfxItemState::DEFAULT == eState )
+ pItem = &rPool.GetDefaultItem(RES_PARATR_LINESPACING);
+ if( SfxItemState::DEFAULT <= eState &&
+ static_cast<const SvxLineSpacingItem* >(pItem)->GetLineSpaceRule() == SvxLineSpaceRule::Auto )
+ {
+ if(SvxInterLineSpaceRule::Off ==
+ static_cast<const SvxLineSpacingItem* >(pItem)->GetInterLineSpaceRule())
+ nLineSpace = 100;
+ else
+ nLineSpace = static_cast<const SvxLineSpacingItem* >(pItem)->GetPropLineSpace();
+ }
+
+ SvxCaseMap eCaseMap = SvxCaseMap::NotMapped;
+ eState = aCoreSet.GetItemState(RES_CHRATR_CASEMAP, false, &pItem);
+ if (eState == SfxItemState::DEFAULT)
+ pItem = &rPool.GetDefaultItem(RES_CHRATR_CASEMAP);
+ if (eState >= SfxItemState::DEFAULT)
+ eCaseMap = static_cast<const SvxCaseMapItem*>(pItem)->GetCaseMap();
+
+ while (nSlot)
+ {
+ switch(nSlot)
+ {
+ case FN_SET_SUPER_SCRIPT:
+ bFlag = 0 < nEsc;
+ break;
+ case FN_SET_SUB_SCRIPT:
+ bFlag = 0 > nEsc;
+ break;
+ case FN_SET_SMALL_CAPS:
+ bFlag = eCaseMap == SvxCaseMap::SmallCaps;
+ break;
+ case SID_ATTR_PARA_ADJUST_LEFT:
+ if (!bAdjustGood)
+ {
+ rSet.InvalidateItem( nSlot );
+ nSlot = 0;
+ }
+ else
+ bFlag = SvxAdjust::Left == eAdjust;
+ break;
+ case SID_ATTR_PARA_ADJUST_RIGHT:
+ if (!bAdjustGood)
+ {
+ rSet.InvalidateItem( nSlot );
+ nSlot = 0;
+ }
+ else
+ bFlag = SvxAdjust::Right == eAdjust;
+ break;
+ case SID_ATTR_PARA_ADJUST_CENTER:
+ if (!bAdjustGood)
+ {
+ rSet.InvalidateItem( nSlot );
+ nSlot = 0;
+ }
+ else
+ bFlag = SvxAdjust::Center == eAdjust;
+ break;
+ case SID_ATTR_PARA_ADJUST_BLOCK:
+ {
+ if (!bAdjustGood)
+ {
+ rSet.InvalidateItem( nSlot );
+ nSlot = 0;
+ }
+ else
+ {
+ bFlag = SvxAdjust::Block == eAdjust;
+ sal_uInt16 nHtmlMode = GetHtmlMode(rSh.GetView().GetDocShell());
+ if((nHtmlMode & HTMLMODE_ON) && !(nHtmlMode & HTMLMODE_FULL_STYLES ))
+ {
+ rSet.DisableItem( nSlot );
+ nSlot = 0;
+ }
+ }
+ }
+ break;
+ case SID_ATTR_PARA_LINESPACE_10:
+ bFlag = nLineSpace == 100;
+ break;
+ case SID_ATTR_PARA_LINESPACE_115:
+ bFlag = nLineSpace == 115;
+ break;
+ case SID_ATTR_PARA_LINESPACE_15:
+ bFlag = nLineSpace == 150;
+ break;
+ case SID_ATTR_PARA_LINESPACE_20:
+ bFlag = nLineSpace == 200;
+ break;
+ case FN_GROW_FONT_SIZE:
+ case FN_SHRINK_FONT_SIZE:
+ {
+ SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONTHEIGHT,
+ *rSet.GetPool() );
+ aSetItem.GetItemSet().Put( aCoreSet, false );
+ const SvxFontHeightItem* pSize( static_cast<const SvxFontHeightItem*>(
+ aSetItem.GetItemOfScript( rSh.GetScriptType() ) ) );
+
+ if( pSize ) // selection is of one size
+ {
+ sal_uInt32 nSize = pSize->GetHeight();
+ if( nSize == nFontMaxSz )
+ rSet.DisableItem( FN_GROW_FONT_SIZE );
+ else if( nSize == nFontInc )
+ rSet.DisableItem( FN_SHRINK_FONT_SIZE );
+ }
+ else
+ {
+ std::vector<std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM> >>
+ vFontHeight = rSh.GetItemWithPaM( RES_CHRATR_FONTSIZE );
+ for ( const std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM>>& aIt : vFontHeight )
+ {
+ if (!aIt.first)
+ {
+ rSet.DisableItem(FN_GROW_FONT_SIZE);
+ rSet.DisableItem(FN_SHRINK_FONT_SIZE);
+ break;
+ }
+ pSize = static_cast<const SvxFontHeightItem*>( aIt.first );
+ sal_uInt32 nSize = pSize->GetHeight();
+ if( nSize == nFontMaxSz )
+ rSet.DisableItem( FN_GROW_FONT_SIZE );
+ else if( nSize == nFontInc )
+ rSet.DisableItem( FN_SHRINK_FONT_SIZE );
+ }
+ }
+ nSlot = 0;
+ }
+ break;
+ case SID_ULINE_VAL_NONE:
+ case SID_ULINE_VAL_SINGLE:
+ case SID_ULINE_VAL_DOUBLE:
+ case SID_ULINE_VAL_DOTTED:
+ {
+ eState = aCoreSet.GetItemState(RES_CHRATR_UNDERLINE);
+ if( eState >= SfxItemState::DEFAULT )
+ {
+ FontLineStyle eLineStyle = aCoreSet.Get(RES_CHRATR_UNDERLINE).GetLineStyle();
+
+ switch (nSlot)
+ {
+ case SID_ULINE_VAL_NONE:
+ rSet.Put(SfxBoolItem(nSlot, eLineStyle == LINESTYLE_NONE));
+ break;
+ case SID_ULINE_VAL_SINGLE:
+ rSet.Put(SfxBoolItem(nSlot, eLineStyle == LINESTYLE_SINGLE));
+ break;
+ case SID_ULINE_VAL_DOUBLE:
+ rSet.Put(SfxBoolItem(nSlot, eLineStyle == LINESTYLE_DOUBLE));
+ break;
+ case SID_ULINE_VAL_DOTTED:
+ rSet.Put(SfxBoolItem(nSlot, eLineStyle == LINESTYLE_DOTTED));
+ break;
+ }
+ }
+ else
+ rSet.InvalidateItem(nSlot);
+ nSlot = 0;
+ }
+ break;
+ case SID_ATTR_PARA_ADJUST:
+ if (!bAdjustGood)
+ rSet.InvalidateItem( nSlot );
+ else
+ rSet.Put(SvxAdjustItem(eAdjust, SID_ATTR_PARA_ADJUST ));
+ nSlot = 0;
+ break;
+ case SID_ATTR_PARA_LRSPACE:
+ case SID_ATTR_PARA_LEFTSPACE:
+ case SID_ATTR_PARA_RIGHTSPACE:
+ case SID_ATTR_PARA_FIRSTLINESPACE:
+ {
+ eState = aCoreSet.GetItemState(RES_MARGIN_FIRSTLINE);
+ eState = std::min(aCoreSet.GetItemState(RES_MARGIN_TEXTLEFT), eState);
+ eState = std::min(aCoreSet.GetItemState(RES_MARGIN_RIGHT), eState);
+ if( eState >= SfxItemState::DEFAULT )
+ {
+ SvxLRSpaceItem aLR(RES_LR_SPACE);
+ SvxFirstLineIndentItem const& rFirstLine(aCoreSet.Get(RES_MARGIN_FIRSTLINE));
+ SvxTextLeftMarginItem const& rLeftMargin(aCoreSet.Get(RES_MARGIN_TEXTLEFT));
+ SvxRightMarginItem const& rRightMargin(aCoreSet.Get(RES_MARGIN_RIGHT));
+ aLR.SetTextFirstLineOffset(rFirstLine.GetTextFirstLineOffset(), rFirstLine.GetPropTextFirstLineOffset());
+ aLR.SetAutoFirst(rFirstLine.IsAutoFirst());
+ aLR.SetTextLeft(rLeftMargin.GetTextLeft(), rLeftMargin.GetPropLeft());
+ aLR.SetRight(rRightMargin.GetRight(), rRightMargin.GetPropRight());
+ aLR.SetWhich(nSlot);
+ rSet.Put(aLR);
+ }
+ else
+ rSet.InvalidateItem(nSlot);
+ nSlot = 0;
+ }
+ break;
+
+ case SID_ATTR_PARA_LEFT_TO_RIGHT :
+ case SID_ATTR_PARA_RIGHT_TO_LEFT :
+ {
+ if ( !SvtCTLOptions::IsCTLFontEnabled() )
+ {
+ rSet.DisableItem( nSlot );
+ nSlot = 0;
+ }
+ else
+ {
+ // is the item set?
+ sal_uInt16 nHtmlMode = GetHtmlMode(rSh.GetView().GetDocShell());
+ if((!(nHtmlMode & HTMLMODE_ON) || (0 != (nHtmlMode & HTMLMODE_SOME_STYLES))) &&
+ aCoreSet.GetItemState( RES_FRAMEDIR, false ) >= SfxItemState::DEFAULT)
+ {
+ SvxFrameDirection eFrameDir =
+ aCoreSet.Get(RES_FRAMEDIR).GetValue();
+ if (SvxFrameDirection::Environment == eFrameDir)
+ {
+ eFrameDir = rSh.IsInRightToLeftText() ?
+ SvxFrameDirection::Horizontal_RL_TB : SvxFrameDirection::Horizontal_LR_TB;
+ }
+ bFlag = (SID_ATTR_PARA_LEFT_TO_RIGHT == nSlot &&
+ SvxFrameDirection::Horizontal_LR_TB == eFrameDir) ||
+ (SID_ATTR_PARA_RIGHT_TO_LEFT == nSlot &&
+ SvxFrameDirection::Horizontal_RL_TB == eFrameDir);
+ }
+ else
+ {
+ rSet.InvalidateItem(nSlot);
+ nSlot = 0;
+ }
+ }
+ }
+ break;
+
+ case SID_ATTR_CHAR_LANGUAGE:
+ case SID_ATTR_CHAR_KERNING:
+ case RES_PARATR_DROP:
+ {
+ rSet.Put(aCoreSet.Get( GetPool().GetWhich(nSlot)));
+ nSlot = 0;
+ }
+ break;
+ case SID_ATTR_PARA_MODEL:
+ {
+ SfxItemSetFixed
+ <RES_PAGEDESC,RES_PAGEDESC,
+ SID_ATTR_PARA_MODEL,SID_ATTR_PARA_MODEL> aTemp(GetPool());
+ aTemp.Put(aCoreSet);
+ ::SwToSfxPageDescAttr(aTemp);
+ rSet.Put(aTemp.Get(SID_ATTR_PARA_MODEL));
+ nSlot = 0;
+ }
+ break;
+ case RES_TXTATR_INETFMT:
+ {
+ SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
+ rSh.GetCurAttr(aSet);
+ const SfxPoolItem& rItem = aSet.Get(RES_TXTATR_INETFMT);
+ rSet.Put(rItem);
+ nSlot = 0;
+ }
+ break;
+
+ default:
+ // Do nothing
+ nSlot = 0;
+ break;
+
+ }
+ if( nSlot )
+ {
+ aFlagItem.SetWhich( nSlot );
+ aFlagItem.SetValue( bFlag );
+ rSet.Put( aFlagItem );
+ }
+ nSlot = aIter.NextWhich();
+ }
+
+ rSet.Put(aCoreSet,false);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/txtcrsr.cxx b/sw/source/uibase/shells/txtcrsr.cxx
new file mode 100644
index 0000000000..6dc161cb1e
--- /dev/null
+++ b/sw/source/uibase/shells/txtcrsr.cxx
@@ -0,0 +1,464 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include <sfx2/request.hxx>
+#include <svl/eitem.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/bindings.hxx>
+#include <osl/diagnose.h>
+
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <textsh.hxx>
+#include <edtwin.hxx>
+#include <doc.hxx>
+#include <docsh.hxx>
+
+#include <cmdid.h>
+#include <globals.hrc>
+
+#include <svx/svdouno.hxx>
+#include <svx/fmshell.hxx>
+#include <svx/sdrobjectfilter.hxx>
+
+using namespace ::com::sun::star;
+
+void SwTextShell::ExecBasicMove(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ GetView().GetEditWin().FlushInBuffer();
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ bool bSelect = false;
+ sal_Int32 nCount = 1;
+ if(pArgs)
+ {
+ if(const SfxInt32Item* pCountItem = pArgs->GetItemIfSet(FN_PARAM_MOVE_COUNT))
+ nCount = pCountItem->GetValue();
+ if(const SfxBoolItem* pSelectionItem = pArgs->GetItemIfSet(FN_PARAM_MOVE_SELECTION))
+ bSelect = pSelectionItem->GetValue();
+ }
+ switch(rReq.GetSlot())
+ {
+ case FN_CHAR_LEFT_SEL:
+ rReq.SetSlot( FN_CHAR_LEFT );
+ bSelect = true;
+ break;
+ case FN_CHAR_RIGHT_SEL:
+ rReq.SetSlot( FN_CHAR_RIGHT );
+ bSelect = true;
+ break;
+ case FN_LINE_UP_SEL:
+ rReq.SetSlot( FN_LINE_UP );
+ bSelect = true;
+ break;
+ case FN_LINE_DOWN_SEL:
+ rReq.SetSlot( FN_LINE_DOWN );
+ bSelect = true;
+ break;
+ }
+
+ uno::Reference< frame::XDispatchRecorder > xRecorder =
+ GetView().GetViewFrame().GetBindings().GetRecorder();
+ if ( xRecorder.is() )
+ {
+ rReq.AppendItem( SfxInt32Item(FN_PARAM_MOVE_COUNT, nCount) );
+ rReq.AppendItem( SfxBoolItem(FN_PARAM_MOVE_SELECTION, bSelect) );
+ }
+ const sal_uInt16 nSlot = rReq.GetSlot();
+ rReq.Done();
+ // Get EditWin before calling the move functions (shell change may occur!)
+ SwEditWin& rTmpEditWin = GetView().GetEditWin();
+ for( sal_Int32 i = 0; i < nCount; i++ )
+ {
+ switch(nSlot)
+ {
+ case FN_CHAR_LEFT:
+ rSh.Left( SwCursorSkipMode::Cells, bSelect, 1, false, true );
+ break;
+ case FN_CHAR_RIGHT:
+ rSh.Right( SwCursorSkipMode::Cells, bSelect, 1, false, true );
+ break;
+ case FN_LINE_UP:
+ rSh.Up( bSelect );
+ break;
+ case FN_LINE_DOWN:
+ rSh.Down( bSelect );
+ break;
+ default:
+ OSL_FAIL("wrong Dispatcher");
+ return;
+ }
+ }
+
+ //#i42732# - notify the edit window that from now on we do not use the input language
+ rTmpEditWin.SetUseInputLanguage( false );
+}
+
+void SwTextShell::ExecMove(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ rSh.addCurrentPosition();
+ SwEditWin& rTmpEditWin = GetView().GetEditWin();
+ rTmpEditWin.FlushInBuffer();
+
+ bool bRet = false;
+ switch ( rReq.GetSlot() )
+ {
+ case FN_START_OF_LINE_SEL:
+ bRet = rSh.LeftMargin( true, false );
+ break;
+ case FN_START_OF_LINE:
+ bRet = rSh.LeftMargin( false, false );
+ break;
+ case FN_END_OF_LINE_SEL:
+ bRet = rSh.RightMargin( true, false );
+ break;
+ case FN_END_OF_LINE:
+ bRet = rSh.RightMargin( false, false );
+ break;
+ case FN_START_OF_DOCUMENT_SEL:
+ bRet = rSh.StartOfSection( true );
+ break;
+ case FN_START_OF_DOCUMENT:
+ bRet = rSh.StartOfSection();
+ break;
+ case FN_END_OF_DOCUMENT_SEL:
+ bRet = rSh.EndOfSection( true );
+ break;
+ case FN_END_OF_DOCUMENT:
+ bRet = rSh.EndOfSection();
+ break;
+ case FN_SELECT_WORD:
+ bRet = rSh.SelNearestWrd();
+ break;
+ case FN_SELECT_SENTENCE:
+ rSh.SelSentence( nullptr );
+ bRet = true;
+ break;
+ case SID_SELECTALL:
+ rSh.SelAll();
+ bRet = true;
+ break;
+ default:
+ OSL_FAIL("wrong dispatcher");
+ return;
+ }
+
+ if ( bRet )
+ rReq.Done();
+ else
+ rReq.Ignore();
+
+ //#i42732# - notify the edit window that from now on we do not use the input language
+ rTmpEditWin.SetUseInputLanguage( false );
+}
+
+void SwTextShell::ExecMovePage(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ rSh.addCurrentPosition();
+ GetView().GetEditWin().FlushInBuffer();
+
+ switch( rReq.GetSlot() )
+ {
+ case FN_START_OF_NEXT_PAGE_SEL :
+ rSh.SttNxtPg( true );
+ break;
+ case FN_START_OF_NEXT_PAGE:
+ rSh.SttNxtPg();
+ break;
+ case FN_END_OF_NEXT_PAGE_SEL:
+ rSh.EndNxtPg( true );
+ break;
+ case FN_END_OF_NEXT_PAGE:
+ rSh.EndNxtPg();
+ break;
+ case FN_START_OF_PREV_PAGE_SEL:
+ rSh.SttPrvPg( true );
+ break;
+ case FN_START_OF_PREV_PAGE:
+ rSh.SttPrvPg();
+ break;
+ case FN_END_OF_PREV_PAGE_SEL:
+ rSh.EndPrvPg( true );
+ break;
+ case FN_END_OF_PREV_PAGE:
+ rSh.EndPrvPg();
+ break;
+ case FN_START_OF_PAGE_SEL:
+ rSh.SttPg( true );
+ break;
+ case FN_START_OF_PAGE:
+ rSh.SttPg();
+ break;
+ case FN_END_OF_PAGE_SEL:
+ rSh.EndPg( true );
+ break;
+ case FN_END_OF_PAGE:
+ rSh.EndPg();
+ break;
+ default:
+ OSL_FAIL("wrong dispatcher");
+ return;
+ }
+ rReq.Done();
+}
+
+void SwTextShell::ExecMoveCol(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ rSh.addCurrentPosition();
+ switch ( rReq.GetSlot() )
+ {
+ case FN_START_OF_COLUMN:
+ rSh.StartOfColumn();
+ break;
+ case FN_END_OF_COLUMN:
+ rSh.EndOfColumn();
+ break;
+ case FN_START_OF_NEXT_COLUMN:
+ rSh.StartOfNextColumn() ;
+ break;
+ case FN_END_OF_NEXT_COLUMN:
+ rSh.EndOfNextColumn();
+ break;
+ case FN_START_OF_PREV_COLUMN:
+ rSh.StartOfPrevColumn();
+ break;
+ case FN_END_OF_PREV_COLUMN:
+ rSh.EndOfPrevColumn();
+ break;
+ default:
+ OSL_FAIL("wrong dispatcher");
+ return;
+ }
+ rReq.Done();
+}
+
+void SwTextShell::ExecMoveLingu(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ rSh.addCurrentPosition();
+ GetView().GetEditWin().FlushInBuffer();
+
+ switch ( rReq.GetSlot() )
+ {
+ case FN_NEXT_WORD_SEL:
+ rSh.NxtWrd( true );
+ break;
+ case FN_NEXT_WORD:
+ rSh.NxtWrd();
+ break;
+ case FN_START_OF_PARA_SEL:
+ rSh.SttPara( true );
+ break;
+ case FN_START_OF_PARA:
+ rSh.SttPara();
+ break;
+ case FN_END_OF_PARA_SEL:
+ rSh.EndPara( true );
+ break;
+ case FN_END_OF_PARA:
+ rSh.EndPara();
+ break;
+ case FN_PREV_WORD_SEL:
+ rSh.PrvWrd( true );
+ break;
+ case FN_PREV_WORD:
+ rSh.PrvWrd();
+ break;
+ case FN_NEXT_SENT_SEL:
+ rSh.FwdSentence( true );
+ break;
+ case FN_NEXT_SENT:
+ rSh.FwdSentence();
+ break;
+ case FN_PREV_SENT_SEL:
+ rSh.BwdSentence( true );
+ break;
+ case FN_PREV_SENT:
+ rSh.BwdSentence();
+ break;
+ case FN_NEXT_PARA:
+ rSh.FwdPara();
+ break;
+ case FN_PREV_PARA:
+ rSh.BwdPara();
+ break;
+ default:
+ OSL_FAIL("wrong dispatcher");
+ return;
+ }
+ rReq.Done();
+}
+
+void SwTextShell::ExecMoveMisc(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetShell();
+ rSh.addCurrentPosition();
+ const sal_uInt16 nSlot = rReq.GetSlot();
+ bool bSetRetVal = true, bRet = true;
+ switch ( nSlot )
+ {
+ case SID_FM_TOGGLECONTROLFOCUS:
+ {
+ const SwDoc* pDoc = rSh.GetDoc();
+ const SwDocShell* pDocShell = pDoc ? pDoc->GetDocShell() : nullptr;
+ const SwView* pView = pDocShell ? pDocShell->GetView() : nullptr;
+ const FmFormShell* pFormShell = pView ? pView->GetFormShell() : nullptr;
+ SdrView* pDrawView = pView ? pView->GetDrawView() : nullptr;
+ vcl::Window* pWindow = pView ? pView->GetWrtShell().GetWin() : nullptr;
+
+ OSL_ENSURE( pFormShell && pDrawView && pWindow, "SwXTextView::ExecMoveMisc: no chance!" );
+ if ( !pFormShell || !pDrawView || !pWindow )
+ break;
+
+ std::unique_ptr< svx::ISdrObjectFilter > pFilter( FmFormShell::CreateFocusableControlFilter(
+ *pDrawView, *pWindow->GetOutDev() ) );
+ if (!pFilter)
+ break;
+
+ const SdrObject* pNearestControl = rSh.GetBestObject( true, GotoObjFlags::DrawControl, false, pFilter.get() );
+ if ( !pNearestControl )
+ break;
+
+ const SdrUnoObj* pUnoObject = dynamic_cast< const SdrUnoObj* >( pNearestControl );
+ OSL_ENSURE( pUnoObject, "SwTextShell::ExecMoveMisc: GetBestObject returned nonsense!" );
+ if ( !pUnoObject )
+ break;
+
+ pFormShell->ToggleControlFocus( *pUnoObject, *pDrawView, *pWindow->GetOutDev() );
+ }
+ break;
+ case FN_CNTNT_TO_NEXT_FRAME:
+ bRet = rSh.GotoObj(true, GotoObjFlags::Any);
+ if(bRet)
+ {
+ rSh.HideCursor();
+ rSh.EnterSelFrameMode();
+ }
+ break;
+ case FN_NEXT_FOOTNOTE:
+ rSh.MoveCursor();
+ bRet = rSh.GotoNextFootnoteAnchor();
+ break;
+ case FN_PREV_FOOTNOTE:
+ rSh.MoveCursor();
+ bRet = rSh.GotoPrevFootnoteAnchor();
+ break;
+ case FN_TO_HEADER:
+ rSh.MoveCursor();
+ if ( FrameTypeFlags::HEADER & rSh.GetFrameType(nullptr,false) )
+ rSh.SttPg();
+ else
+ {
+ bool bMoved = rSh.GotoHeaderText();
+ if ( !bMoved )
+ rSh.SttPg();
+ }
+ bSetRetVal = false;
+ break;
+ case FN_TO_FOOTER:
+ rSh.MoveCursor();
+ if ( FrameTypeFlags::FOOTER & rSh.GetFrameType(nullptr,false) )
+ rSh.EndPg();
+ else
+ {
+ bool bMoved = rSh.GotoFooterText();
+ if ( !bMoved )
+ rSh.EndPg();
+ }
+ bSetRetVal = false;
+ break;
+ case FN_FOOTNOTE_TO_ANCHOR:
+ rSh.MoveCursor();
+ if ( FrameTypeFlags::FOOTNOTE & rSh.GetFrameType(nullptr,false) )
+ rSh.GotoFootnoteAnchor();
+ else
+ rSh.GotoFootnoteText();
+ bSetRetVal = false;
+ break;
+ case FN_TO_FOOTNOTE_AREA :
+ rSh.GotoFootnoteText();
+ break;
+ case FN_PREV_TABLE:
+ bRet = rSh.MoveTable( GotoPrevTable, fnTableStart);
+ break;
+ case FN_NEXT_TABLE:
+ bRet = rSh.MoveTable(GotoNextTable, fnTableStart);
+ break;
+ case FN_GOTO_NEXT_REGION :
+ bRet = rSh.MoveRegion(GotoNextRegion, fnRegionStart);
+ break;
+ case FN_GOTO_PREV_REGION :
+ bRet = rSh.MoveRegion(GotoPrevRegion, fnRegionStart);
+ break;
+ case FN_NEXT_TOXMARK:
+ bRet = rSh.GotoNxtPrvTOXMark();
+ break;
+ case FN_PREV_TOXMARK:
+ bRet = rSh.GotoNxtPrvTOXMark( false );
+ break;
+ case FN_NEXT_TBLFML:
+ bRet = rSh.GotoNxtPrvTableFormula();
+ break;
+ case FN_PREV_TBLFML:
+ bRet = rSh.GotoNxtPrvTableFormula( false );
+ break;
+ case FN_NEXT_TBLFML_ERR:
+ bRet = rSh.GotoNxtPrvTableFormula( true, true );
+ break;
+ case FN_PREV_TBLFML_ERR:
+ bRet = rSh.GotoNxtPrvTableFormula( false, true );
+ break;
+ default:
+ OSL_FAIL("wrong dispatcher");
+ return;
+ }
+
+ if( bSetRetVal )
+ rReq.SetReturnValue(SfxBoolItem( nSlot, bRet ));
+ rReq.Done();
+
+ bool bInHeader = true;
+ if ( rSh.IsInHeaderFooter( &bInHeader ) )
+ {
+ if ( !bInHeader )
+ {
+ rSh.SetShowHeaderFooterSeparator( FrameControlType::Footer, true );
+ rSh.SetShowHeaderFooterSeparator( FrameControlType::Header, false );
+ }
+ else
+ {
+ rSh.SetShowHeaderFooterSeparator( FrameControlType::Header, true );
+ rSh.SetShowHeaderFooterSeparator( FrameControlType::Footer, false );
+ }
+
+ // Force repaint
+ rSh.GetWin()->Invalidate();
+ }
+ if ( rSh.IsInHeaderFooter() != rSh.IsHeaderFooterEdit() )
+ rSh.ToggleHeaderFooterEdit();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/txtnum.cxx b/sw/source/uibase/shells/txtnum.cxx
new file mode 100644
index 0000000000..e769b7f463
--- /dev/null
+++ b/sw/source/uibase/shells/txtnum.cxx
@@ -0,0 +1,330 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/request.hxx>
+#include <svl/eitem.hxx>
+#include <svl/stritem.hxx>
+#include <editeng/numitem.hxx>
+#include <editeng/brushitem.hxx>
+#include <osl/diagnose.h>
+#include <numrule.hxx>
+
+#include <cmdid.h>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <viewopt.hxx>
+#include <wdocsh.hxx>
+#include <poolfmt.hxx>
+#include <textsh.hxx>
+#include <swabstdlg.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <sfx2/tabdlg.hxx>
+#include <svx/nbdtmg.hxx>
+#include <svx/nbdtmgfact.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/bindings.hxx>
+#include <memory>
+
+void SwTextShell::ExecEnterNum(SfxRequest &rReq)
+{
+ //Because the record before any shell exchange.
+ switch(rReq.GetSlot())
+ {
+ case FN_NUM_NUMBERING_ON:
+ {
+ GetShell().StartAllAction();
+ const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(FN_PARAM_1);
+ bool bMode = !GetShell().SelectionHasNumber(); // #i29560#
+ if ( pItem )
+ bMode = pItem->GetValue();
+ else
+ rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bMode ) );
+
+ if ( bMode != (GetShell().SelectionHasNumber()) ) // #i29560#
+ {
+ rReq.Done();
+ if( bMode )
+ GetShell().NumOn();
+ else
+ GetShell().NumOrBulletOff(); // #i29560#
+ }
+ bool bNewResult = GetShell().SelectionHasNumber();
+ if (bNewResult!=bMode) {
+ SfxBindings& rBindings = GetView().GetViewFrame().GetBindings();
+ SfxBoolItem aItem(FN_NUM_NUMBERING_ON,!bNewResult);
+ rBindings.SetState(aItem);
+ SfxBoolItem aNewItem(FN_NUM_NUMBERING_ON,bNewResult);
+ rBindings.SetState(aNewItem);
+ }
+ GetShell().EndAllAction();
+ }
+ break;
+ case FN_NUM_BULLET_ON:
+ {
+ GetShell().StartAllAction();
+ const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(FN_PARAM_1);
+ bool bMode = !GetShell().SelectionHasBullet(); // #i29560#
+ if ( pItem )
+ bMode = pItem->GetValue();
+ else
+ rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bMode ) );
+
+ if ( bMode != (GetShell().SelectionHasBullet()) ) // #i29560#
+ {
+ rReq.Done();
+ if( bMode )
+ GetShell().BulletOn();
+ else
+ GetShell().NumOrBulletOff(); // #i29560#
+ }
+ bool bNewResult = GetShell().SelectionHasBullet();
+ if (bNewResult!=bMode) {
+ SfxBindings& rBindings = GetView().GetViewFrame().GetBindings();
+ SfxBoolItem aItem(FN_NUM_BULLET_ON,!bNewResult);
+ rBindings.SetState(aItem);
+ SfxBoolItem aNewItem(FN_NUM_BULLET_ON,bNewResult);
+ rBindings.SetState(aNewItem);
+ }
+ GetShell().EndAllAction();
+ }
+ break;
+
+ case FN_NUM_BULLET_OFF:
+ {
+ GetShell().StartAllAction();
+ SfxRequest aReq(GetView().GetViewFrame(), FN_NUM_BULLET_ON);
+ aReq.AppendItem(SfxBoolItem(FN_PARAM_1, false));
+ aReq.Done();
+ GetShell().NumOrBulletOff();
+ GetShell().DelNumRules();
+ GetShell().EndAllAction();
+ }
+ break;
+
+ case FN_NUMBER_BULLETS:
+ case SID_OUTLINE_BULLET:
+ {
+ SfxItemSetFixed<SID_HTML_MODE, SID_HTML_MODE,
+ SID_ATTR_NUMBERING_RULE, SID_PARAM_CUR_NUM_LEVEL> aSet( GetPool() );
+ SwDocShell* pDocSh = GetView().GetDocShell();
+ const bool bHtml = dynamic_cast<SwWebDocShell*>( pDocSh ) != nullptr;
+ const SwNumRule* pNumRuleAtCurrentSelection = GetShell().GetNumRuleAtCurrentSelection();
+ if ( pNumRuleAtCurrentSelection != nullptr )
+ {
+ SvxNumRule aRule = pNumRuleAtCurrentSelection->MakeSvxNumRule();
+
+ //convert type of linked bitmaps from SVX_NUM_BITMAP to (SVX_NUM_BITMAP|LINK_TOKEN)
+ for ( sal_uInt16 i = 0; i < aRule.GetLevelCount(); i++ )
+ {
+ SvxNumberFormat aFormat( aRule.GetLevel( i ) );
+ if ( SVX_NUM_BITMAP == aFormat.GetNumberingType() )
+ {
+ const SvxBrushItem* pBrush = aFormat.GetBrush();
+ if(pBrush && !pBrush->GetGraphicLink().isEmpty())
+ aFormat.SetNumberingType(SvxNumType(SVX_NUM_BITMAP|LINK_TOKEN));
+ aRule.SetLevel(i, aFormat, aRule.Get(i) != nullptr);
+ }
+ }
+ if(bHtml)
+ aRule.SetFeatureFlag(SvxNumRuleFlags::ENABLE_EMBEDDED_BMP, false);
+
+ aSet.Put(SvxNumBulletItem(aRule));
+ OSL_ENSURE( GetShell().GetNumLevel() < MAXLEVEL,
+ "<SwTextShell::ExecEnterNum()> - numbered node without valid list level. Serious defect." );
+ sal_uInt16 nLevel = GetShell().GetNumLevel();
+ if( nLevel < MAXLEVEL )
+ {
+ nLevel = 1 << nLevel;
+ aSet.Put( SfxUInt16Item( SID_PARAM_CUR_NUM_LEVEL, nLevel ) );
+ }
+ }
+ else
+ {
+ SwNumRule aRule( GetShell().GetUniqueNumRuleName(),
+ // #i89178#
+ numfunc::GetDefaultPositionAndSpaceMode() );
+ SvxNumRule aSvxRule = aRule.MakeSvxNumRule();
+ const bool bRightToLeft = GetShell().IsInRightToLeftText();
+
+ if ( bHtml || bRightToLeft )
+ {
+ for ( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
+ {
+ SvxNumberFormat aFormat( aSvxRule.GetLevel( n ) );
+ if ( n && bHtml )
+ {
+ // 1/2" for HTML
+ aFormat.SetAbsLSpace(n * 720);
+ }
+ // #i38904# Default alignment for
+ // numbering/bullet should be rtl in rtl paragraph:
+ if ( bRightToLeft )
+ {
+ aFormat.SetNumAdjust( SvxAdjust::Right );
+ }
+ aSvxRule.SetLevel( n, aFormat, false );
+ }
+ aSvxRule.SetFeatureFlag(SvxNumRuleFlags::ENABLE_EMBEDDED_BMP, false);
+ }
+ aSet.Put( SvxNumBulletItem( std::move(aSvxRule) ) );
+ }
+
+ aSet.Put( SfxBoolItem( SID_PARAM_NUM_PRESET,false ));
+
+ // Before the dialogue of the HTML mode will be dropped at the Docshell.
+ pDocSh->PutItem(SfxUInt16Item(SID_HTML_MODE, ::GetHtmlMode(pDocSh)));
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ weld::Window *pParent = rReq.GetFrameWeld();
+ VclPtr<AbstractNumBulletDialog> pDlg(pFact->CreateSvxNumBulletTabDialog(pParent, aSet, GetShell()));
+ const SfxStringItem* pPageItem = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if ( pPageItem )
+ pDlg->SetCurPageId( pPageItem->GetValue() );
+
+ auto pRequest = std::make_shared<SfxRequest>(rReq);
+ rReq.Ignore(); // the 'old' request is not relevant any more
+
+ pDlg->StartExecuteAsync([pDlg, pNumRuleAtCurrentSelection, pRequest, this](sal_Int32 nResult){
+ if (RET_OK == nResult)
+ {
+ const SvxNumBulletItem* pBulletItem = pDlg->GetOutputItemSet()->GetItemIfSet(SID_ATTR_NUMBERING_RULE, false);
+ if (pBulletItem)
+ {
+ pRequest->AppendItem(*pBulletItem);
+ pRequest->Done();
+ SvxNumRule& rSetRule = const_cast<SvxNumRule&>(pBulletItem->GetNumRule());
+ rSetRule.UnLinkGraphics();
+ SwNumRule aSetRule(pNumRuleAtCurrentSelection != nullptr
+ ? pNumRuleAtCurrentSelection->GetName()
+ : GetShell().GetUniqueNumRuleName(),
+ numfunc::GetDefaultPositionAndSpaceMode());
+ aSetRule.SetSvxRule(rSetRule, GetShell().GetDoc());
+ aSetRule.SetAutoRule(true);
+ // No start of new list, if an existing list style is edited.
+ // Otherwise start a new list.
+ const bool bCreateList = (pNumRuleAtCurrentSelection == nullptr);
+ GetShell().SetCurNumRule(aSetRule, bCreateList);
+ }
+ // If the Dialog was leaved with OK but nothing was chosen then the
+ // numbering must be at least activated, if it is not already.
+ else if (pNumRuleAtCurrentSelection == nullptr
+ && (pBulletItem = pDlg->GetInputItemSet()->GetItemIfSet(SID_ATTR_NUMBERING_RULE, false)))
+ {
+ pRequest->AppendItem(*pBulletItem);
+ pRequest->Done();
+ const SvxNumRule& rSetRule = pBulletItem->GetNumRule();
+ SwNumRule aSetRule(
+ GetShell().GetUniqueNumRuleName(),
+ numfunc::GetDefaultPositionAndSpaceMode());
+ aSetRule.SetSvxRule(rSetRule, GetShell().GetDoc());
+ aSetRule.SetAutoRule(true);
+ // start new list
+ GetShell().SetCurNumRule(aSetRule, true);
+ }
+ }
+ else if (RET_USER == nResult)
+ GetShell().DelNumRules();
+ pDlg->disposeOnce();
+ });
+ }
+ break;
+
+ default:
+ OSL_FAIL("wrong dispatcher");
+ return;
+ }
+}
+
+
+void SwTextShell::ExecSetNumber(SfxRequest const &rReq)
+{
+ const sal_uInt16 nSlot = rReq.GetSlot();
+ switch ( nSlot )
+ {
+ case FN_SVX_SET_NUMBER:
+ case FN_SVX_SET_BULLET:
+ case FN_SVX_SET_OUTLINE:
+ {
+ const SfxUInt16Item* pItem = rReq.GetArg<SfxUInt16Item>(nSlot);
+ if ( pItem != nullptr )
+ {
+ const sal_uInt16 nChosenItemIdx = pItem->GetValue();
+ svx::sidebar::NBOType nNBOType = svx::sidebar::NBOType::Bullets;
+ if ( nSlot == FN_SVX_SET_NUMBER )
+ nNBOType = svx::sidebar::NBOType::Numbering;
+ else if ( nSlot == FN_SVX_SET_OUTLINE )
+ nNBOType = svx::sidebar::NBOType::Outline;
+
+ svx::sidebar::NBOTypeMgrBase* pNBOTypeMgr = svx::sidebar::NBOutlineTypeMgrFact::CreateInstance( nNBOType );
+
+ if ( pNBOTypeMgr != nullptr )
+ {
+ const SwNumRule* pNumRuleAtCurrentSelection = GetShell().GetNumRuleAtCurrentSelection();
+ sal_uInt16 nActNumLvl = USHRT_MAX;
+ if ( pNumRuleAtCurrentSelection != nullptr )
+ {
+ const sal_uInt16 nLevel = GetShell().GetNumLevel();
+ if ( nLevel < MAXLEVEL )
+ {
+ nActNumLvl = 1 << nLevel;
+ }
+ }
+ SwNumRule aNewNumRule(
+ pNumRuleAtCurrentSelection != nullptr ? pNumRuleAtCurrentSelection->GetName() : GetShell().GetUniqueNumRuleName(),
+ numfunc::GetDefaultPositionAndSpaceMode() );
+ SvxNumRule aNewSvxNumRule = pNumRuleAtCurrentSelection != nullptr
+ ? pNumRuleAtCurrentSelection->MakeSvxNumRule()
+ : aNewNumRule.MakeSvxNumRule();
+
+ OUString aNumCharFormat, aBulletCharFormat;
+ SwStyleNameMapper::FillUIName( RES_POOLCHR_NUM_LEVEL, aNumCharFormat );
+ SwStyleNameMapper::FillUIName( RES_POOLCHR_BULLET_LEVEL, aBulletCharFormat );
+
+ SfxAllItemSet aSet( GetPool() );
+ aSet.Put( SfxStringItem( SID_NUM_CHAR_FMT, aNumCharFormat ) );
+ aSet.Put( SfxStringItem( SID_BULLET_CHAR_FMT, aBulletCharFormat ) );
+ aSet.Put( SvxNumBulletItem( aNewSvxNumRule, SID_ATTR_NUMBERING_RULE ) );
+
+ pNBOTypeMgr->SetItems( &aSet );
+ pNBOTypeMgr->ApplyNumRule( aNewSvxNumRule, nChosenItemIdx - 1, nActNumLvl );
+
+ aNewNumRule.SetSvxRule( aNewSvxNumRule, GetShell().GetDoc() );
+ aNewNumRule.SetAutoRule( true );
+ const bool bCreateNewList = ( pNumRuleAtCurrentSelection == nullptr );
+ GetShell().SetCurNumRule( aNewNumRule, bCreateNewList );
+ }
+ }
+ else if (nSlot == FN_SVX_SET_OUTLINE)
+ {
+ // no outline provided: launch dialog to request a specific outline
+ SfxBindings& rBindings = GetView().GetViewFrame().GetBindings();
+ const SfxStringItem aPage(FN_PARAM_1, "outlinenum");
+ const SfxPoolItem* aItems[] = { &aPage, nullptr };
+ rBindings.Execute(SID_OUTLINE_BULLET, aItems);
+ }
+ }
+ break;
+
+ default:
+ OSL_ENSURE(false, "wrong Dispatcher");
+ return;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/A11yCheckIssuesPanel.cxx b/sw/source/uibase/sidebar/A11yCheckIssuesPanel.cxx
new file mode 100644
index 0000000000..a1907c9b63
--- /dev/null
+++ b/sw/source/uibase/sidebar/A11yCheckIssuesPanel.cxx
@@ -0,0 +1,377 @@
+/* -*- 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 <AccessibilityCheck.hxx>
+#include <AccessibilityIssue.hxx>
+#include <cmdid.h>
+#include <doc.hxx>
+#include <docsh.hxx>
+#include <ndtxt.hxx>
+#include <wrtsh.hxx>
+
+#include <officecfg/Office/Common.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/AccessibilityIssue.hxx>
+#include <unotools/configmgr.hxx>
+#include <vcl/svapp.hxx>
+
+#include "A11yCheckIssuesPanel.hxx"
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+namespace sw::sidebar
+{
+AccessibilityCheckEntry::AccessibilityCheckEntry(
+ weld::Container* pParent, std::shared_ptr<sfx::AccessibilityIssue> const& rAccessibilityIssue)
+ : m_xBuilder(Application::CreateBuilder(pParent, "svx/ui/accessibilitycheckentry.ui"))
+ , m_xContainer(m_xBuilder->weld_container("accessibilityCheckEntryBox"))
+ , m_xLabel(m_xBuilder->weld_label("accessibilityCheckEntryLabel"))
+ , m_xGotoButton(m_xBuilder->weld_link_button("accessibilityCheckEntryLinkButton"))
+ , m_xFixButton(m_xBuilder->weld_button("accessibilityCheckEntryFixButton"))
+ , m_pAccessibilityIssue(rAccessibilityIssue)
+{
+ // lock in the height as including the button so all rows are the same height
+ m_xContainer->set_size_request(-1, m_xContainer->get_preferred_size().Height());
+
+ if (m_pAccessibilityIssue->canGotoIssue())
+ {
+ m_xGotoButton->set_label(m_pAccessibilityIssue->m_aIssueText);
+
+ // tdf#156137 allow LinkButton label to wrap
+ int nMaxWidth = m_xGotoButton->get_approximate_digit_width() * 10;
+ m_xGotoButton->set_label_wrap(true);
+ m_xGotoButton->set_size_request(nMaxWidth, -1);
+
+ m_xGotoButton->connect_activate_link(
+ LINK(this, AccessibilityCheckEntry, GotoButtonClicked));
+
+ // add full path of linked graphic as tooltip,
+ if (m_pAccessibilityIssue->m_eIssueID == sfx::AccessibilityIssueID::LINKED_GRAPHIC)
+ {
+ auto pSwIssue = std::static_pointer_cast<sw::AccessibilityIssue>(m_pAccessibilityIssue);
+ auto aInfo = pSwIssue->getAdditionalInfo();
+ if (aInfo.size() > 0)
+ {
+ m_xGotoButton->set_tooltip_text(aInfo[0]);
+ }
+ }
+
+ m_xLabel->set_visible(false);
+ }
+ else
+ {
+ m_xLabel->set_label(m_pAccessibilityIssue->m_aIssueText);
+ m_xGotoButton->set_visible(false);
+ }
+
+ m_xFixButton->set_visible(m_pAccessibilityIssue->canQuickFixIssue());
+ m_xFixButton->connect_clicked(LINK(this, AccessibilityCheckEntry, FixButtonClicked));
+
+ m_pAccessibilityIssue->setParent(dynamic_cast<weld::Window*>(get_widget()));
+}
+
+IMPL_LINK_NOARG(AccessibilityCheckEntry, GotoButtonClicked, weld::LinkButton&, bool)
+{
+ m_pAccessibilityIssue->gotoIssue();
+ return true;
+}
+
+IMPL_LINK_NOARG(AccessibilityCheckEntry, FixButtonClicked, weld::Button&, void)
+{
+ m_pAccessibilityIssue->quickFixIssue();
+}
+
+std::unique_ptr<PanelLayout> A11yCheckIssuesPanel::Create(weld::Widget* pParent,
+ SfxBindings* pBindings)
+{
+ if (pParent == nullptr)
+ throw ::com::sun::star::lang::IllegalArgumentException(
+ "no parent window given to A11yCheckIssuesPanel::Create", nullptr, 0);
+ return std::make_unique<A11yCheckIssuesPanel>(pParent, pBindings);
+}
+
+A11yCheckIssuesPanel::A11yCheckIssuesPanel(weld::Widget* pParent, SfxBindings* pBindings)
+ : PanelLayout(pParent, "A11yCheckIssuesPanel", "modules/swriter/ui/a11ycheckissuespanel.ui")
+ , m_xExpanderDocument(m_xBuilder->weld_expander("expand_document"))
+ , m_xExpanderStyles(m_xBuilder->weld_expander("expand_styles"))
+ , m_xExpanderLinked(m_xBuilder->weld_expander("expand_linked"))
+ , m_xExpanderNoAlt(m_xBuilder->weld_expander("expand_no_alt"))
+ , m_xExpanderTable(m_xBuilder->weld_expander("expand_table"))
+ , m_xExpanderFormatting(m_xBuilder->weld_expander("expand_formatting"))
+ , m_xExpanderHyperlink(m_xBuilder->weld_expander("expand_hyperlink"))
+ , m_xExpanderFakes(m_xBuilder->weld_expander("expand_fakes"))
+ , m_xExpanderNumbering(m_xBuilder->weld_expander("expand_numbering"))
+ , m_xExpanderOther(m_xBuilder->weld_expander("expand_other"))
+ , m_xBoxDocument(m_xBuilder->weld_box("box_document"))
+ , m_xBoxStyles(m_xBuilder->weld_box("box_styles"))
+ , m_xBoxLinked(m_xBuilder->weld_box("box_linked"))
+ , m_xBoxNoAlt(m_xBuilder->weld_box("box_no_alt"))
+ , m_xBoxTable(m_xBuilder->weld_box("box_table"))
+ , m_xBoxFormatting(m_xBuilder->weld_box("box_formatting"))
+ , m_xBoxHyperlink(m_xBuilder->weld_box("box_hyperlink"))
+ , m_xBoxFakes(m_xBuilder->weld_box("box_fakes"))
+ , m_xBoxNumbering(m_xBuilder->weld_box("box_numbering"))
+ , m_xBoxOther(m_xBuilder->weld_box("box_other"))
+ , mpBindings(pBindings)
+ , mpDoc(nullptr)
+ , maA11yCheckController(FN_STAT_ACCESSIBILITY_CHECK, *pBindings, *this)
+ , mnIssueCount(0)
+ , mbAutomaticCheckEnabled(false)
+{
+ SwDocShell* pDocSh = dynamic_cast<SwDocShell*>(SfxObjectShell::Current());
+ if (!pDocSh)
+ return;
+
+ // Automatic a11y checking must be enabled for this panel to work properly
+ mbAutomaticCheckEnabled
+ = officecfg::Office::Common::Accessibility::OnlineAccessibilityCheck::get();
+ if (!mbAutomaticCheckEnabled)
+ {
+ std::shared_ptr<comphelper::ConfigurationChanges> batch(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Accessibility::OnlineAccessibilityCheck::set(true, batch);
+ batch->commit();
+ pBindings->Invalidate(SID_ACCESSIBILITY_CHECK_ONLINE);
+ }
+
+ mpDoc = pDocSh->GetDoc();
+
+ populateIssues();
+}
+
+void A11yCheckIssuesPanel::ImplDestroy()
+{
+ // Restore state when this panel is no longer used
+ if (!mbAutomaticCheckEnabled)
+ {
+ std::shared_ptr<comphelper::ConfigurationChanges> batch(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Accessibility::OnlineAccessibilityCheck::set(false, batch);
+ batch->commit();
+ mpBindings->Invalidate(SID_ACCESSIBILITY_CHECK_ONLINE);
+ }
+ m_xExpanderDocument.reset();
+ m_xExpanderStyles.reset();
+ m_xExpanderLinked.reset();
+ m_xExpanderNoAlt.reset();
+ m_xExpanderTable.reset();
+ m_xExpanderFormatting.reset();
+ m_xExpanderHyperlink.reset();
+ m_xExpanderFakes.reset();
+ m_xExpanderNumbering.reset();
+ m_xExpanderOther.reset();
+ m_xBoxDocument.reset();
+ m_xBoxStyles.reset();
+ m_xBoxLinked.reset();
+ m_xBoxNoAlt.reset();
+ m_xBoxTable.reset();
+ m_xBoxFormatting.reset();
+ m_xBoxHyperlink.reset();
+ m_xBoxFakes.reset();
+ m_xBoxNumbering.reset();
+ m_xBoxOther.reset();
+}
+
+A11yCheckIssuesPanel::~A11yCheckIssuesPanel() { suppress_fun_call_w_exception(ImplDestroy()); }
+
+void A11yCheckIssuesPanel::removeOldWidgets()
+{
+ for (auto const& xEntry : m_aDocumentEntries)
+ m_xBoxDocument->move(xEntry->get_widget(), nullptr);
+ m_xExpanderDocument->set_visible(false);
+
+ for (auto const& xEntry : m_aStylesEntries)
+ m_xBoxStyles->move(xEntry->get_widget(), nullptr);
+ m_xExpanderStyles->set_visible(false);
+
+ for (auto const& xEntry : m_aLinkedEntries)
+ m_xBoxLinked->move(xEntry->get_widget(), nullptr);
+ m_xExpanderLinked->set_visible(false);
+
+ for (auto const& xEntry : m_aNoAltEntries)
+ m_xBoxNoAlt->move(xEntry->get_widget(), nullptr);
+ m_xExpanderNoAlt->set_visible(false);
+
+ for (auto const& xEntry : m_aTableEntries)
+ m_xBoxTable->move(xEntry->get_widget(), nullptr);
+ m_xExpanderTable->set_visible(false);
+
+ for (auto const& xEntry : m_aFormattingEntries)
+ m_xBoxFormatting->move(xEntry->get_widget(), nullptr);
+ m_xExpanderFormatting->set_visible(false);
+
+ for (auto const& xEntry : m_aHyperlinkEntries)
+ m_xBoxHyperlink->move(xEntry->get_widget(), nullptr);
+ m_xExpanderHyperlink->set_visible(false);
+
+ for (auto const& xEntry : m_aFakesEntries)
+ m_xBoxFakes->move(xEntry->get_widget(), nullptr);
+ m_xExpanderFakes->set_visible(false);
+
+ for (auto const& xEntry : m_aNumberingEntries)
+ m_xBoxNumbering->move(xEntry->get_widget(), nullptr);
+ m_xExpanderNumbering->set_visible(false);
+
+ for (auto const& xEntry : m_aOtherEntries)
+ m_xBoxOther->move(xEntry->get_widget(), nullptr);
+ m_xExpanderOther->set_visible(false);
+}
+
+void A11yCheckIssuesPanel::populateIssues()
+{
+ if (!mpDoc)
+ return;
+ sw::AccessibilityCheck aCheck(mpDoc);
+ aCheck.check();
+ m_aIssueCollection = aCheck.getIssueCollection();
+
+ removeOldWidgets();
+
+ sal_Int32 iDocument = 0;
+ sal_Int32 iStyles = 0;
+ sal_Int32 iLinked = 0;
+ sal_Int32 iNoAlt = 0;
+ sal_Int32 iTable = 0;
+ sal_Int32 iFormatting = 0;
+ sal_Int32 iHyperlink = 0;
+ sal_Int32 iFakes = 0;
+ sal_Int32 iNumbering = 0;
+ sal_Int32 iOther = 0;
+ for (std::shared_ptr<sfx::AccessibilityIssue> const& pIssue : m_aIssueCollection.getIssues())
+ {
+ switch (pIssue->m_eIssueID)
+ {
+ case sfx::AccessibilityIssueID::DOCUMENT_TITLE:
+ case sfx::AccessibilityIssueID::DOCUMENT_LANGUAGE:
+ case sfx::AccessibilityIssueID::DOCUMENT_BACKGROUND:
+ {
+ auto xEntry
+ = std::make_unique<AccessibilityCheckEntry>(m_xBoxDocument.get(), pIssue);
+ m_xBoxDocument->reorder_child(xEntry->get_widget(), iDocument++);
+ m_xExpanderDocument->set_visible(true);
+ m_aDocumentEntries.push_back(std::move(xEntry));
+ }
+ break;
+ case sfx::AccessibilityIssueID::STYLE_LANGUAGE:
+ {
+ auto xEntry = std::make_unique<AccessibilityCheckEntry>(m_xBoxStyles.get(), pIssue);
+ m_xBoxStyles->reorder_child(xEntry->get_widget(), iStyles++);
+ m_xExpanderStyles->set_visible(true);
+ m_aStylesEntries.push_back(std::move(xEntry));
+ }
+ break;
+ case sfx::AccessibilityIssueID::LINKED_GRAPHIC:
+ {
+ auto xEntry = std::make_unique<AccessibilityCheckEntry>(m_xBoxLinked.get(), pIssue);
+ m_xBoxLinked->reorder_child(xEntry->get_widget(), iLinked++);
+ m_xExpanderLinked->set_visible(true);
+ m_aLinkedEntries.push_back(std::move(xEntry));
+ }
+ break;
+ case sfx::AccessibilityIssueID::NO_ALT_OLE:
+ case sfx::AccessibilityIssueID::NO_ALT_GRAPHIC:
+ case sfx::AccessibilityIssueID::NO_ALT_SHAPE:
+ {
+ auto xEntry = std::make_unique<AccessibilityCheckEntry>(m_xBoxNoAlt.get(), pIssue);
+ m_xBoxNoAlt->reorder_child(xEntry->get_widget(), iNoAlt++);
+ m_xExpanderNoAlt->set_visible(true);
+ m_aNoAltEntries.push_back(std::move(xEntry));
+ }
+ break;
+ case sfx::AccessibilityIssueID::TABLE_MERGE_SPLIT:
+ {
+ auto xEntry = std::make_unique<AccessibilityCheckEntry>(m_xBoxTable.get(), pIssue);
+ m_xBoxTable->reorder_child(xEntry->get_widget(), iTable++);
+ m_xExpanderTable->set_visible(true);
+ m_aTableEntries.push_back(std::move(xEntry));
+ }
+ break;
+ case sfx::AccessibilityIssueID::TEXT_FORMATTING:
+ case sfx::AccessibilityIssueID::TABLE_FORMATTING:
+ {
+ auto xEntry
+ = std::make_unique<AccessibilityCheckEntry>(m_xBoxFormatting.get(), pIssue);
+ m_xBoxFormatting->reorder_child(xEntry->get_widget(), iFormatting++);
+ m_xExpanderFormatting->set_visible(true);
+ m_aFormattingEntries.push_back(std::move(xEntry));
+ }
+ break;
+ case sfx::AccessibilityIssueID::HYPERLINK_IS_TEXT:
+ case sfx::AccessibilityIssueID::HYPERLINK_SHORT:
+ {
+ auto xEntry
+ = std::make_unique<AccessibilityCheckEntry>(m_xBoxHyperlink.get(), pIssue);
+ m_xBoxHyperlink->reorder_child(xEntry->get_widget(), iHyperlink++);
+ m_xExpanderHyperlink->set_visible(true);
+ m_aHyperlinkEntries.push_back(std::move(xEntry));
+ }
+ break;
+ case sfx::AccessibilityIssueID::FAKE_FOOTNOTE:
+ case sfx::AccessibilityIssueID::FAKE_CAPTION:
+ {
+ auto xEntry = std::make_unique<AccessibilityCheckEntry>(m_xBoxFakes.get(), pIssue);
+ m_xBoxFakes->reorder_child(xEntry->get_widget(), iFakes++);
+ m_xExpanderFakes->set_visible(true);
+ m_aFakesEntries.push_back(std::move(xEntry));
+ }
+ break;
+ case sfx::AccessibilityIssueID::MANUAL_NUMBERING:
+ {
+ auto xEntry
+ = std::make_unique<AccessibilityCheckEntry>(m_xBoxNumbering.get(), pIssue);
+ m_xBoxNumbering->reorder_child(xEntry->get_widget(), iNumbering++);
+ m_xExpanderNumbering->set_visible(true);
+ m_aNumberingEntries.push_back(std::move(xEntry));
+ }
+ break;
+ case sfx::AccessibilityIssueID::UNSPECIFIED:
+ {
+ auto xEntry = std::make_unique<AccessibilityCheckEntry>(m_xBoxOther.get(), pIssue);
+ m_xBoxOther->reorder_child(xEntry->get_widget(), iOther++);
+ m_xExpanderOther->set_visible(true);
+ m_aOtherEntries.push_back(std::move(xEntry));
+ }
+ break;
+ default:
+ {
+ SAL_WARN("sw.a11y", "Invalid issue ID.");
+ continue;
+ }
+ break;
+ };
+ }
+}
+
+void A11yCheckIssuesPanel::NotifyItemUpdate(const sal_uInt16 nSid, const SfxItemState /* eState */,
+ const SfxPoolItem* pState)
+{
+ if (!pState) //disposed
+ return;
+
+ switch (nSid)
+ {
+ case FN_STAT_ACCESSIBILITY_CHECK:
+ {
+ sal_Int32 nIssueCount = static_cast<const SfxInt32Item*>(pState)->GetValue();
+ if (nIssueCount != mnIssueCount)
+ {
+ mnIssueCount = nIssueCount;
+ populateIssues();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/source/uibase/sidebar/A11yCheckIssuesPanel.hxx b/sw/source/uibase/sidebar/A11yCheckIssuesPanel.hxx
new file mode 100644
index 0000000000..7f569e16ef
--- /dev/null
+++ b/sw/source/uibase/sidebar/A11yCheckIssuesPanel.hxx
@@ -0,0 +1,106 @@
+/* -*- 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 <memory>
+
+#include <sfx2/AccessibilityIssue.hxx>
+#include <sfx2/sidebar/ControllerItem.hxx>
+#include <sfx2/sidebar/PanelLayout.hxx>
+#include <svl/poolitem.hxx>
+#include <tools/link.hxx>
+#include <vcl/weld.hxx>
+
+#include <doc.hxx>
+
+namespace sw::sidebar
+{
+class AccessibilityCheckEntry final
+{
+private:
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Container> m_xContainer;
+ std::unique_ptr<weld::Label> m_xLabel;
+ std::unique_ptr<weld::LinkButton> m_xGotoButton;
+ std::unique_ptr<weld::Button> m_xFixButton;
+
+ std::shared_ptr<sfx::AccessibilityIssue> const& m_pAccessibilityIssue;
+
+public:
+ AccessibilityCheckEntry(weld::Container* pParent,
+ std::shared_ptr<sfx::AccessibilityIssue> const& pAccessibilityIssue);
+
+ weld::Widget* get_widget() const { return m_xContainer.get(); }
+
+ DECL_LINK(GotoButtonClicked, weld::LinkButton&, bool);
+ DECL_LINK(FixButtonClicked, weld::Button&, void);
+};
+
+class A11yCheckIssuesPanel : public PanelLayout,
+ public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface
+{
+public:
+ static std::unique_ptr<PanelLayout> Create(weld::Widget* pParent, SfxBindings* pBindings);
+
+ virtual void NotifyItemUpdate(const sal_uInt16 nSId, const SfxItemState eState,
+ const SfxPoolItem* pState) override;
+
+ virtual void GetControlState(const sal_uInt16 /*nSId*/,
+ boost::property_tree::ptree& /*rState*/) override{};
+
+ A11yCheckIssuesPanel(weld::Widget* pParent, SfxBindings* pBindings);
+ void ImplDestroy();
+ virtual ~A11yCheckIssuesPanel() override;
+
+private:
+ std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aDocumentEntries;
+ std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aStylesEntries;
+ std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aLinkedEntries;
+ std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aNoAltEntries;
+ std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aTableEntries;
+ std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aFormattingEntries;
+ std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aHyperlinkEntries;
+ std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aFakesEntries;
+ std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aNumberingEntries;
+ std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aOtherEntries;
+ std::unique_ptr<weld::Expander> m_xExpanderDocument;
+ std::unique_ptr<weld::Expander> m_xExpanderStyles;
+ std::unique_ptr<weld::Expander> m_xExpanderLinked;
+ std::unique_ptr<weld::Expander> m_xExpanderNoAlt;
+ std::unique_ptr<weld::Expander> m_xExpanderTable;
+ std::unique_ptr<weld::Expander> m_xExpanderFormatting;
+ std::unique_ptr<weld::Expander> m_xExpanderHyperlink;
+ std::unique_ptr<weld::Expander> m_xExpanderFakes;
+ std::unique_ptr<weld::Expander> m_xExpanderNumbering;
+ std::unique_ptr<weld::Expander> m_xExpanderOther;
+ std::unique_ptr<weld::Box> m_xBoxDocument;
+ std::unique_ptr<weld::Box> m_xBoxStyles;
+ std::unique_ptr<weld::Box> m_xBoxLinked;
+ std::unique_ptr<weld::Box> m_xBoxNoAlt;
+ std::unique_ptr<weld::Box> m_xBoxTable;
+ std::unique_ptr<weld::Box> m_xBoxFormatting;
+ std::unique_ptr<weld::Box> m_xBoxHyperlink;
+ std::unique_ptr<weld::Box> m_xBoxFakes;
+ std::unique_ptr<weld::Box> m_xBoxNumbering;
+ std::unique_ptr<weld::Box> m_xBoxOther;
+ sfx::AccessibilityIssueCollection m_aIssueCollection;
+ void removeOldWidgets();
+ void populateIssues();
+
+ SfxBindings* mpBindings;
+ SwDoc* mpDoc;
+ ::sfx2::sidebar::ControllerItem maA11yCheckController;
+ sal_Int32 mnIssueCount;
+ bool mbAutomaticCheckEnabled;
+};
+
+} //end of namespace sw::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/source/uibase/sidebar/PageColumnControl.cxx b/sw/source/uibase/sidebar/PageColumnControl.cxx
new file mode 100644
index 0000000000..6afb22a819
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageColumnControl.cxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include "PageColumnControl.hxx"
+#include <PageColumnPopup.hxx>
+
+#include <cmdid.h>
+
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/intitem.hxx>
+#include <svx/pageitem.hxx>
+
+namespace sw::sidebar {
+
+PageColumnControl::PageColumnControl(PageColumnPopup* pControl, weld::Widget* pParent)
+ : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "modules/swriter/ui/pagecolumncontrol.ui", "PageColumnControl")
+ , m_xMoreButton(m_xBuilder->weld_button("moreoptions"))
+ , m_xControl(pControl)
+{
+ bool bLandscape = false;
+ if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
+ {
+ SfxPoolItemHolder aResult;
+ pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE, aResult);
+ const SvxPageItem* pPageItem(static_cast<const SvxPageItem*>(aResult.getItem()));
+ bLandscape = pPageItem->IsLandscape();
+ }
+
+ if ( bLandscape )
+ {
+ m_xOneColumn = m_xBuilder->weld_button("column1L");
+ m_xTwoColumns = m_xBuilder->weld_button("column2L");
+ m_xThreeColumns = m_xBuilder->weld_button("column3L");
+ m_xLeft = m_xBuilder->weld_button("columnleftL");
+ m_xRight = m_xBuilder->weld_button("columnrightL");
+ }
+ else
+ {
+ m_xOneColumn = m_xBuilder->weld_button("column1");
+ m_xTwoColumns = m_xBuilder->weld_button( "column2");
+ m_xThreeColumns = m_xBuilder->weld_button("column3");
+ m_xLeft = m_xBuilder->weld_button("columnleft");
+ m_xRight = m_xBuilder->weld_button("columnright");
+ }
+
+ m_xOneColumn->show();
+ m_xTwoColumns->show();
+ m_xThreeColumns->show();
+ m_xLeft->show();
+ m_xRight->show();
+
+ m_xOneColumn->connect_clicked( LINK( this, PageColumnControl, ColumnButtonClickHdl_Impl ) );
+ m_xTwoColumns->connect_clicked( LINK( this, PageColumnControl, ColumnButtonClickHdl_Impl ) );
+ m_xThreeColumns->connect_clicked( LINK( this, PageColumnControl, ColumnButtonClickHdl_Impl ) );
+ m_xLeft->connect_clicked( LINK( this, PageColumnControl, ColumnButtonClickHdl_Impl ) );
+ m_xRight->connect_clicked( LINK( this, PageColumnControl, ColumnButtonClickHdl_Impl ) );
+
+ m_xMoreButton->connect_clicked( LINK( this, PageColumnControl, MoreButtonClickHdl_Impl ) );
+}
+
+void PageColumnControl::GrabFocus()
+{
+ m_xMoreButton->grab_focus();
+}
+
+PageColumnControl::~PageColumnControl()
+{
+}
+
+void PageColumnControl::ExecuteColumnChange( const sal_uInt16 nColumnType )
+{
+ SfxInt16Item aPageColumnTypeItem(SID_ATTR_PAGE_COLUMN);
+ aPageColumnTypeItem.SetValue( nColumnType );
+ if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
+ pViewFrm->GetBindings().GetDispatcher()->ExecuteList(SID_ATTR_PAGE_COLUMN,
+ SfxCallMode::RECORD, { &aPageColumnTypeItem });
+}
+
+IMPL_LINK( PageColumnControl, ColumnButtonClickHdl_Impl, weld::Button&, rButton, void )
+{
+ if ( &rButton == m_xOneColumn.get() )
+ ExecuteColumnChange( 1 );
+ else if ( &rButton == m_xTwoColumns.get() )
+ ExecuteColumnChange( 2 );
+ else if ( &rButton == m_xThreeColumns.get() )
+ ExecuteColumnChange( 3 );
+ else if ( &rButton == m_xLeft.get() )
+ ExecuteColumnChange( 4 );
+ else if ( &rButton == m_xRight.get() )
+ ExecuteColumnChange( 5 );
+
+ m_xControl->EndPopupMode();
+}
+
+IMPL_LINK_NOARG( PageColumnControl, MoreButtonClickHdl_Impl, weld::Button&, void )
+{
+ if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
+ pViewFrm->GetBindings().GetDispatcher()->Execute( FN_FORMAT_PAGE_COLUMN_DLG, SfxCallMode::ASYNCHRON );
+ m_xControl->EndPopupMode();
+}
+
+} // end of namespace sw::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageColumnControl.hxx b/sw/source/uibase/sidebar/PageColumnControl.hxx
new file mode 100644
index 0000000000..f4e35291b7
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageColumnControl.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGECOLUMNCONTROL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGECOLUMNCONTROL_HXX
+
+#include <svtools/toolbarmenu.hxx>
+#include <vcl/weld.hxx>
+
+class PageColumnPopup;
+
+namespace sw::sidebar
+{
+class PageColumnControl final : public WeldToolbarPopup
+{
+public:
+ explicit PageColumnControl(PageColumnPopup* pControl, weld::Widget* pParent);
+ virtual void GrabFocus() override;
+ virtual ~PageColumnControl() override;
+
+private:
+ std::unique_ptr<weld::Button> m_xOneColumn;
+ std::unique_ptr<weld::Button> m_xTwoColumns;
+ std::unique_ptr<weld::Button> m_xThreeColumns;
+ std::unique_ptr<weld::Button> m_xLeft;
+ std::unique_ptr<weld::Button> m_xRight;
+ std::unique_ptr<weld::Button> m_xMoreButton;
+
+ rtl::Reference<PageColumnPopup> m_xControl;
+
+ static void ExecuteColumnChange(const sal_uInt16 nColumnType);
+
+ DECL_LINK(ColumnButtonClickHdl_Impl, weld::Button&, void);
+ DECL_LINK(MoreButtonClickHdl_Impl, weld::Button&, void);
+};
+
+} // end of namespace sw::sidebar
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageColumnPopup.cxx b/sw/source/uibase/sidebar/PageColumnPopup.cxx
new file mode 100644
index 0000000000..da64a484d3
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageColumnPopup.cxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include <PageColumnPopup.hxx>
+#include "PageColumnControl.hxx"
+#include <vcl/toolbox.hxx>
+
+PageColumnPopup::PageColumnPopup(const css::uno::Reference<css::uno::XComponentContext>& rContext)
+ : PopupWindowController(rContext, nullptr, OUString())
+{
+}
+
+void PageColumnPopup::initialize( const css::uno::Sequence< css::uno::Any >& rArguments )
+{
+ PopupWindowController::initialize(rArguments);
+
+ ToolBox* pToolBox = nullptr;
+ ToolBoxItemId nId;
+ if (getToolboxId(nId, &pToolBox))
+ pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWNONLY | pToolBox->GetItemBits(nId));
+}
+
+PageColumnPopup::~PageColumnPopup()
+{
+}
+
+std::unique_ptr<WeldToolbarPopup> PageColumnPopup::weldPopupWindow()
+{
+ return std::make_unique<sw::sidebar::PageColumnControl>(this, m_pToolbar);
+}
+
+VclPtr<vcl::Window> PageColumnPopup::createVclPopupWindow( vcl::Window* pParent )
+{
+ mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent,
+ std::make_unique<sw::sidebar::PageColumnControl>(this, pParent->GetFrameWeld()));
+
+ mxInterimPopover->Show();
+
+ return mxInterimPopover;
+}
+
+OUString PageColumnPopup::getImplementationName()
+{
+ return "lo.writer.PageColumnToolBoxControl";
+}
+
+css::uno::Sequence<OUString> PageColumnPopup::getSupportedServiceNames()
+{
+ return { "com.sun.star.frame.ToolbarController" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+lo_writer_PageColumnToolBoxControl_get_implementation(
+ css::uno::XComponentContext* rContext,
+ css::uno::Sequence<css::uno::Any> const & )
+{
+ return cppu::acquire(new PageColumnPopup(rContext));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageFooterPanel.cxx b/sw/source/uibase/sidebar/PageFooterPanel.cxx
new file mode 100644
index 0000000000..1a2f049dce
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageFooterPanel.cxx
@@ -0,0 +1,285 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include <sal/config.h>
+#include <svl/intitem.hxx>
+#include <svl/eitem.hxx>
+#include <svl/itemset.hxx>
+#include <svx/dlgutil.hxx>
+#include <svx/rulritem.hxx>
+#include <svx/svdtrans.hxx>
+#include <svx/spacinglistbox.hxx>
+#include <svx/samecontentlistbox.hxx>
+#include "PageFooterPanel.hxx"
+#include <sfx2/dispatch.hxx>
+#include <sfx2/bindings.hxx>
+#include <cmdid.h>
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+namespace sw::sidebar{
+
+std::unique_ptr<PanelLayout> PageFooterPanel::Create(
+ weld::Widget* pParent,
+ SfxBindings* pBindings)
+{
+ if( pParent == nullptr )
+ throw ::com::sun::star::lang::IllegalArgumentException("no parent window given to PageFooterPanel::Create", nullptr, 0);
+ return std::make_unique<PageFooterPanel>(pParent, pBindings);
+}
+
+void PageFooterPanel::SetMarginsAndSpacingFieldUnit()
+{
+ SpacingListBox::Fill(IsInch(meFUnit) ? SpacingType::SPACING_INCH : SpacingType::SPACING_CM, *mxFooterSpacingLB);
+ SpacingListBox::Fill(IsInch(meFUnit) ? SpacingType::MARGINS_INCH : SpacingType::MARGINS_CM, *mxFooterMarginPresetLB);
+}
+
+PageFooterPanel::PageFooterPanel(
+ weld::Widget* pParent,
+ SfxBindings* pBindings) :
+ PanelLayout(pParent, "PageFooterPanel", "modules/swriter/ui/pagefooterpanel.ui"),
+ mpBindings( pBindings ),
+ maHFToggleController(SID_ATTR_PAGE_FOOTER, *pBindings, *this),
+ maMetricController(SID_ATTR_METRIC, *pBindings,*this),
+ maFooterLRMarginController(SID_ATTR_PAGE_FOOTER_LRMARGIN, *pBindings, *this),
+ maFooterSpacingController(SID_ATTR_PAGE_FOOTER_SPACING, *pBindings, *this),
+ maFooterLayoutController(SID_ATTR_PAGE_FOOTER_LAYOUT, *pBindings, *this),
+ meFUnit(GetModuleFieldUnit()),
+ mpFooterItem( new SfxBoolItem(SID_ATTR_PAGE_FOOTER) ),
+ mpFooterLRMarginItem( new SvxLongLRSpaceItem(0, 0, SID_ATTR_PAGE_FOOTER_LRMARGIN)),
+ mpFooterSpacingItem( new SvxLongULSpaceItem(0, 0, SID_ATTR_PAGE_FOOTER_SPACING)),
+ mpFooterLayoutItem( new SfxInt16Item(SID_ATTR_PAGE_FOOTER_LAYOUT)),
+ mxFooterToggle(m_xBuilder->weld_check_button("footertoggle")),
+ mxFooterSpacingLB(m_xBuilder->weld_combo_box("spacingpreset")),
+ mxFooterMarginPresetLB(m_xBuilder->weld_combo_box("footermarginpreset")),
+ mxFooterLayoutLB(m_xBuilder->weld_combo_box("samecontentLB")),
+ mxCustomEntry(m_xBuilder->weld_label("customlabel"))
+{
+ Initialize();
+}
+
+PageFooterPanel::~PageFooterPanel()
+{
+ mxFooterToggle.reset();
+ maMetricController.dispose();
+ mxFooterSpacingLB.reset();
+ mxFooterLayoutLB.reset();
+ mxFooterMarginPresetLB.reset();
+ mxCustomEntry.reset();
+}
+
+FieldUnit PageFooterPanel::GetCurrentUnit(SfxItemState eState, const SfxPoolItem* pState)
+{
+ FieldUnit eUnit;
+
+ if (pState && eState >= SfxItemState::DEFAULT)
+ eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pState)->GetValue());
+ else
+ eUnit = GetModuleFieldUnit();
+
+ return eUnit;
+}
+
+void PageFooterPanel::Initialize()
+{
+ SameContentListBox::Fill(*mxFooterLayoutLB);
+
+ SetMarginsAndSpacingFieldUnit();
+
+ m_aCustomEntry = mxCustomEntry->get_label();
+ mxFooterToggle->connect_toggled( LINK(this, PageFooterPanel, FooterToggleHdl) );
+ mxFooterMarginPresetLB->connect_changed( LINK(this, PageFooterPanel, FooterLRMarginHdl));
+ mxFooterSpacingLB->connect_changed( LINK(this, PageFooterPanel, FooterSpacingHdl));
+ mxFooterLayoutLB->connect_changed( LINK(this, PageFooterPanel, FooterLayoutHdl));
+
+ mpBindings->Invalidate(SID_ATTR_METRIC);
+ mpBindings->Invalidate(SID_ATTR_PAGE_FOOTER);
+ mpBindings->Invalidate(SID_ATTR_PAGE_FOOTER_LRMARGIN);
+ mpBindings->Invalidate(SID_ATTR_PAGE_FOOTER_SPACING);
+ mpBindings->Invalidate(SID_ATTR_PAGE_FOOTER_LAYOUT);
+}
+
+void PageFooterPanel::UpdateFooterCheck()
+{
+ if (mxFooterToggle->get_active())
+ {
+ mxFooterSpacingLB->set_sensitive(true);
+ mxFooterLayoutLB->set_sensitive(true);
+ mxFooterMarginPresetLB->set_sensitive(true);
+ }
+ else
+ {
+ mxFooterSpacingLB->set_sensitive(false);
+ mxFooterLayoutLB->set_sensitive(false);
+ mxFooterMarginPresetLB->set_sensitive(false);
+ }
+}
+
+void PageFooterPanel::UpdateMarginControl()
+{
+ sal_uInt16 nLeft = mpFooterLRMarginItem->GetLeft();
+ sal_uInt16 nRight = mpFooterLRMarginItem->GetRight();
+ sal_uInt16 nCount = mxFooterMarginPresetLB->get_count();
+ if(nLeft == nRight)
+ {
+ for (sal_uInt16 i = 0; i < nCount; ++i)
+ {
+ if (mxFooterMarginPresetLB->get_id(i).toUInt32() == nLeft)
+ {
+ mxFooterMarginPresetLB->set_active(i);
+ int nCustomEntry = mxFooterMarginPresetLB->find_text(m_aCustomEntry);
+ if (nCustomEntry != -1)
+ mxFooterMarginPresetLB->remove(nCustomEntry);
+ return;
+ }
+ }
+ }
+ mxFooterMarginPresetLB->append_text(m_aCustomEntry);
+ mxFooterMarginPresetLB->set_active_text(m_aCustomEntry);
+}
+
+void PageFooterPanel::UpdateSpacingControl()
+{
+ sal_uInt16 nBottom = mpFooterSpacingItem->GetUpper();
+ sal_uInt16 nCount = mxFooterSpacingLB->get_count();
+ for (sal_uInt16 i = 0; i < nCount; ++i)
+ {
+ if (mxFooterSpacingLB->get_id(i).toUInt32() == nBottom)
+ {
+ mxFooterSpacingLB->set_active(i);
+ int nCustomEntry = mxFooterSpacingLB->find_text(m_aCustomEntry);
+ if (nCustomEntry != -1)
+ mxFooterSpacingLB->remove(nCustomEntry);
+ return;
+ }
+ }
+ mxFooterSpacingLB->append_text(m_aCustomEntry);
+ mxFooterSpacingLB->set_active_text(m_aCustomEntry);
+}
+
+void PageFooterPanel::UpdateLayoutControl()
+{
+ sal_uInt16 nLayout = mpFooterLayoutItem->GetValue();
+ mxFooterLayoutLB->set_active(nLayout);
+}
+
+void PageFooterPanel::NotifyItemUpdate(
+ const sal_uInt16 nSid,
+ const SfxItemState eState,
+ const SfxPoolItem* pState)
+{
+ if (!mxFooterToggle) //disposed
+ return;
+
+ switch(nSid)
+ {
+ case SID_ATTR_PAGE_FOOTER:
+ {
+ if(eState >= SfxItemState::DEFAULT &&
+ dynamic_cast<const SfxBoolItem*>( pState) )
+ {
+ mpFooterItem.reset( static_cast<SfxBoolItem*>(pState->Clone()) );
+ mxFooterToggle->set_active(mpFooterItem->GetValue());
+ UpdateFooterCheck();
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_FOOTER_LRMARGIN:
+ {
+ if(eState >= SfxItemState::DEFAULT &&
+ dynamic_cast<const SvxLongLRSpaceItem*>( pState) )
+ {
+ mpFooterLRMarginItem.reset( static_cast<SvxLongLRSpaceItem*>(pState->Clone()) );
+ UpdateMarginControl();
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_FOOTER_SPACING:
+ {
+ if(eState >= SfxItemState::DEFAULT &&
+ dynamic_cast<const SvxLongULSpaceItem*>( pState) )
+ {
+ mpFooterSpacingItem.reset(static_cast<SvxLongULSpaceItem*>(pState->Clone()) );
+ UpdateSpacingControl();
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_FOOTER_LAYOUT:
+ {
+ if(eState >= SfxItemState::DEFAULT &&
+ dynamic_cast<const SfxInt16Item*>( pState) )
+ {
+ mpFooterLayoutItem.reset(static_cast<SfxInt16Item*>(pState->Clone()) );
+ UpdateLayoutControl();
+ }
+ }
+ break;
+ case SID_ATTR_METRIC:
+ {
+ FieldUnit eFUnit = GetCurrentUnit(eState, pState);
+ if (meFUnit != eFUnit)
+ {
+ meFUnit = eFUnit;
+ SetMarginsAndSpacingFieldUnit();
+ UpdateSpacingControl();
+ UpdateMarginControl();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+IMPL_LINK_NOARG( PageFooterPanel, FooterToggleHdl, weld::Toggleable&, void )
+{
+ bool IsChecked = mxFooterToggle->get_active();
+ mpFooterItem->SetValue(IsChecked);
+ GetBindings()->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_FOOTER, SfxCallMode::RECORD, { mpFooterItem.get() } );
+ UpdateFooterCheck();
+}
+
+IMPL_LINK_NOARG( PageFooterPanel, FooterLRMarginHdl, weld::ComboBox&, void )
+{
+ sal_uInt16 nVal = mxFooterMarginPresetLB->get_active_id().toUInt32();
+ mpFooterLRMarginItem->SetLeft(nVal);
+ mpFooterLRMarginItem->SetRight(nVal);
+ GetBindings()->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_FOOTER_LRMARGIN,
+ SfxCallMode::RECORD, { mpFooterLRMarginItem.get() } );
+}
+
+IMPL_LINK_NOARG( PageFooterPanel, FooterSpacingHdl, weld::ComboBox&, void )
+{
+ sal_uInt16 nVal = mxFooterSpacingLB->get_active_id().toUInt32();
+ mpFooterSpacingItem->SetUpper(nVal);
+ GetBindings()->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_FOOTER_SPACING,
+ SfxCallMode::RECORD, { mpFooterSpacingItem.get() } );
+
+}
+IMPL_LINK_NOARG( PageFooterPanel, FooterLayoutHdl, weld::ComboBox&, void )
+{
+ sal_uInt16 nVal = mxFooterLayoutLB->get_active();
+ mpFooterLayoutItem->SetValue(nVal);
+ GetBindings()->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_FOOTER_LAYOUT,
+ SfxCallMode::RECORD, { mpFooterLayoutItem.get() } );
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageFooterPanel.hxx b/sw/source/uibase/sidebar/PageFooterPanel.hxx
new file mode 100644
index 0000000000..6f5397a16c
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageFooterPanel.hxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGEFOOTERPANEL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGEFOOTERPANEL_HXX
+
+#include <memory>
+
+#include <sfx2/sidebar/PanelLayout.hxx>
+#include <sfx2/sidebar/ControllerItem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/poolitem.hxx>
+#include <svl/eitem.hxx>
+#include <svx/rulritem.hxx>
+
+namespace sw::sidebar {
+
+class PageFooterPanel :
+ public PanelLayout,
+ public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface
+{
+public:
+ static std::unique_ptr<PanelLayout> Create(
+ weld::Widget* pParent,
+ SfxBindings* pBindings);
+
+ virtual void NotifyItemUpdate(
+ const sal_uInt16 nSId,
+ const SfxItemState eState,
+ const SfxPoolItem* pState) override;
+
+ virtual void GetControlState(
+ const sal_uInt16 /*nSId*/,
+ boost::property_tree::ptree& /*rState*/) override {};
+
+ SfxBindings* GetBindings() const { return mpBindings; }
+ PageFooterPanel(
+ weld::Widget* pParent,
+ SfxBindings* pBindings);
+ virtual ~PageFooterPanel() override;
+
+private:
+
+ SfxBindings* mpBindings;
+
+ ::sfx2::sidebar::ControllerItem maHFToggleController;
+ ::sfx2::sidebar::ControllerItem maMetricController;
+ ::sfx2::sidebar::ControllerItem maFooterLRMarginController;
+ ::sfx2::sidebar::ControllerItem maFooterSpacingController;
+ ::sfx2::sidebar::ControllerItem maFooterLayoutController;
+
+ FieldUnit meFUnit;
+
+ OUString m_aCustomEntry;
+
+ void Initialize();
+ void SetMarginsAndSpacingFieldUnit();
+ void UpdateFooterCheck();
+ void UpdateMarginControl();
+ void UpdateSpacingControl();
+ void UpdateLayoutControl();
+
+ ::std::unique_ptr<SfxBoolItem> mpFooterItem;
+ ::std::unique_ptr<SvxLongLRSpaceItem> mpFooterLRMarginItem;
+ ::std::unique_ptr<SvxLongULSpaceItem> mpFooterSpacingItem;
+ ::std::unique_ptr<SfxInt16Item> mpFooterLayoutItem;
+
+ std::unique_ptr<weld::CheckButton> mxFooterToggle;
+ std::unique_ptr<weld::ComboBox> mxFooterSpacingLB;
+ std::unique_ptr<weld::ComboBox> mxFooterMarginPresetLB;
+ std::unique_ptr<weld::ComboBox> mxFooterLayoutLB;
+ std::unique_ptr<weld::Label> mxCustomEntry;
+
+ static FieldUnit GetCurrentUnit(SfxItemState eState, const SfxPoolItem* pState);
+
+ DECL_LINK( FooterToggleHdl, weld::Toggleable&, void );
+ DECL_LINK( FooterLRMarginHdl, weld::ComboBox&, void);
+ DECL_LINK( FooterSpacingHdl, weld::ComboBox&, void);
+ DECL_LINK( FooterLayoutHdl, weld::ComboBox&, void);
+};
+
+} //end of namespace sw::sidebar
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageFormatPanel.cxx b/sw/source/uibase/sidebar/PageFormatPanel.cxx
new file mode 100644
index 0000000000..fdfa9ce661
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageFormatPanel.cxx
@@ -0,0 +1,418 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include <sal/config.h>
+#include <sal/log.hxx>
+#include <swtypes.hxx>
+#include <svl/intitem.hxx>
+#include <editeng/sizeitem.hxx>
+#include <editeng/paperinf.hxx>
+#include <svx/dlgutil.hxx>
+#include <svx/rulritem.hxx>
+#include <svx/svdtrans.hxx>
+#include "PageFormatPanel.hxx"
+#include "PageMarginUtils.hxx"
+#include <sfx2/dispatch.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/module.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <pageformatpanel.hrc>
+#include <cmdid.h>
+#include <svtools/optionsdrawinglayer.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+namespace sw::sidebar{
+
+std::unique_ptr<PanelLayout> PageFormatPanel::Create(
+ weld::Widget* pParent,
+ SfxBindings* pBindings)
+{
+ if( pParent == nullptr )
+ throw ::com::sun::star::lang::IllegalArgumentException("no parent window given to PageFormatPanel::Create", nullptr, 0);
+
+ return std::make_unique<PageFormatPanel>(pParent, pBindings);
+}
+
+void PageFormatPanel::SetMarginFieldUnit()
+{
+ auto nSelected = mxMarginSelectBox->get_active();
+ mxMarginSelectBox->clear();
+
+ const LocaleDataWrapper& rLocaleData = Application::GetSettings().GetLocaleDataWrapper();
+ if (IsInch(meFUnit))
+ {
+ OUString sSuffix = weld::MetricSpinButton::MetricToString(FieldUnit::INCH);
+ for (auto const& [aName, nSize] : RID_PAGEFORMATPANEL_MARGINS_INCH)
+ {
+ OUString sStr = rLocaleData.getNum(nSize, 2, true, false) + sSuffix;
+ mxMarginSelectBox->append_text(SwResId(aName).replaceFirst("%1", sStr));
+ }
+ }
+ else
+ {
+ OUString sSuffix = weld::MetricSpinButton::MetricToString(FieldUnit::CM);
+ for (auto const& [aName, nSize] : RID_PAGEFORMATPANEL_MARGINS_CM)
+ {
+ OUString sStr = rLocaleData.getNum(nSize, 2, true, false) + " " + sSuffix;
+ mxMarginSelectBox->append_text(SwResId(aName).replaceFirst("%1", sStr));
+ }
+ }
+ mxMarginSelectBox->set_active(nSelected);
+}
+
+PageFormatPanel::PageFormatPanel(weld::Widget* pParent, SfxBindings* pBindings) :
+ PanelLayout(pParent, "PageFormatPanel", "modules/swriter/ui/pageformatpanel.ui"),
+ mpBindings( pBindings ),
+ mxPaperSizeBox(new SvxPaperSizeListBox(m_xBuilder->weld_combo_box("papersize"))),
+ mxPaperWidth(new SvxRelativeField(m_xBuilder->weld_metric_spin_button("paperwidth", FieldUnit::CM))),
+ mxPaperHeight(new SvxRelativeField(m_xBuilder->weld_metric_spin_button("paperheight", FieldUnit::CM))),
+ mxPaperOrientation(m_xBuilder->weld_combo_box("paperorientation")),
+ mxMarginSelectBox(m_xBuilder->weld_combo_box("marginLB")),
+ mxCustomEntry(m_xBuilder->weld_label("customlabel")),
+ maPaperSizeController(SID_ATTR_PAGE_SIZE, *pBindings, *this),
+ maPaperOrientationController(SID_ATTR_PAGE, *pBindings, *this),
+ maMetricController(SID_ATTR_METRIC, *pBindings,*this),
+ maSwPageLRControl(SID_ATTR_PAGE_LRSPACE, *pBindings, *this),
+ maSwPageULControl(SID_ATTR_PAGE_ULSPACE, *pBindings, *this),
+ mpPageItem( new SvxPageItem(SID_ATTR_PAGE) ),
+ mpPageLRMarginItem( new SvxLongLRSpaceItem( 0, 0, SID_ATTR_PAGE_LRSPACE ) ),
+ mpPageULMarginItem( new SvxLongULSpaceItem( 0, 0, SID_ATTR_PAGE_ULSPACE ) ),
+ meFUnit(GetModuleFieldUnit()),
+ meUnit()
+{
+ Initialize();
+}
+
+PageFormatPanel::~PageFormatPanel()
+{
+ mxPaperSizeBox.reset();
+ mxPaperWidth.reset();
+ mxPaperHeight.reset();
+ mxPaperOrientation.reset();
+ mxMarginSelectBox.reset();
+ mxCustomEntry.reset();
+
+ maMetricController.dispose();
+ maPaperOrientationController.dispose();
+ maPaperSizeController.dispose();
+ maSwPageLRControl.dispose();
+ maSwPageULControl.dispose();
+ mpPageULMarginItem.reset();
+ mpPageLRMarginItem.reset();
+ mpPageItem.reset();
+}
+
+void PageFormatPanel::Initialize()
+{
+ mxPaperSizeBox->FillPaperSizeEntries( PaperSizeApp::Std );
+ maPaperSizeController.SetFallbackCoreMetric(MapUnit::MapTwip);
+ meUnit = maPaperSizeController.GetCoreMetric();
+ mxPaperWidth->SetFieldUnit(meFUnit);
+ mxPaperHeight->SetFieldUnit(meFUnit);
+ SetMarginFieldUnit();
+ m_aCustomEntry = mxCustomEntry->get_label();
+
+ mxPaperWidth->set_max(mxPaperWidth->normalize(SvtOptionsDrawinglayer::GetMaximumPaperWidth()), FieldUnit::CM);
+ mxPaperHeight->set_max(mxPaperHeight->normalize(SvtOptionsDrawinglayer::GetMaximumPaperHeight()), FieldUnit::CM);
+
+ mxPaperSizeBox->connect_changed( LINK(this, PageFormatPanel, PaperFormatModifyHdl ));
+ mxPaperOrientation->connect_changed( LINK(this, PageFormatPanel, PaperFormatModifyHdl ));
+ mxPaperHeight->connect_value_changed( LINK(this, PageFormatPanel, PaperSizeModifyHdl ));
+ mxPaperWidth->connect_value_changed( LINK(this, PageFormatPanel, PaperSizeModifyHdl ));
+ mxMarginSelectBox->connect_changed( LINK(this, PageFormatPanel, PaperModifyMarginHdl));
+
+ mpBindings->Update(SID_ATTR_METRIC);
+ mpBindings->Update(SID_ATTR_PAGE);
+ mpBindings->Update(SID_ATTR_PAGE_SIZE);
+ mpBindings->Update(SID_ATTR_PAGE_LRSPACE);
+ mpBindings->Update(SID_ATTR_PAGE_ULSPACE);
+
+ UpdateMarginBox();
+}
+
+void PageFormatPanel::NotifyItemUpdate(
+ const sal_uInt16 nSId,
+ const SfxItemState eState,
+ const SfxPoolItem* pState)
+{
+ switch(nSId)
+ {
+ case SID_ATTR_PAGE_SIZE:
+ {
+ const SvxSizeItem* pSizeItem = nullptr;
+ if (eState >= SfxItemState::DEFAULT)
+ pSizeItem = dynamic_cast< const SvxSizeItem* >(pState);
+ if (pSizeItem)
+ {
+ Size aPaperSize = pSizeItem->GetSize();
+
+ mxPaperWidth->set_value(mxPaperWidth->normalize(aPaperSize.Width()), FieldUnit::TWIP);
+ mxPaperHeight->set_value(mxPaperHeight->normalize(aPaperSize.Height()), FieldUnit::TWIP);
+
+ if(mxPaperOrientation->get_active() == 1)
+ Swap(aPaperSize);
+
+ Paper ePaper = SvxPaperInfo::GetSvxPaper(aPaperSize, meUnit);
+ mxPaperSizeBox->set_active_id( ePaper );
+ }
+ }
+ break;
+ case SID_ATTR_METRIC:
+ {
+ meUnit = maPaperSizeController.GetCoreMetric();
+ FieldUnit eFUnit = GetCurrentUnit(eState, pState);
+ if (eFUnit != meFUnit)
+ {
+ meFUnit = eFUnit;
+ mxPaperHeight->SetFieldUnit(meFUnit);
+ mxPaperWidth->SetFieldUnit(meFUnit);
+ SetMarginFieldUnit();
+ UpdateMarginBox();
+ }
+ }
+ break;
+ case SID_ATTR_PAGE:
+ {
+ if ( eState >= SfxItemState::DEFAULT &&
+ dynamic_cast< const SvxPageItem *>( pState ) )
+ {
+ mpPageItem.reset( static_cast<SvxPageItem*>(pState->Clone()) );
+ if ( mpPageItem->IsLandscape() )
+ mxPaperOrientation->set_active(1);
+ else
+ mxPaperOrientation->set_active(0);
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_LRSPACE:
+ {
+ if ( eState >= SfxItemState::DEFAULT &&
+ dynamic_cast< const SvxLongLRSpaceItem *>( pState ) )
+ {
+ mpPageLRMarginItem.reset( static_cast<SvxLongLRSpaceItem*>(pState->Clone()) );
+ UpdateMarginBox();
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_ULSPACE:
+ {
+ if ( eState >= SfxItemState::DEFAULT &&
+ dynamic_cast< const SvxLongULSpaceItem *>( pState ) )
+ {
+ mpPageULMarginItem.reset( static_cast<SvxLongULSpaceItem*>(pState->Clone()) );
+ UpdateMarginBox();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+IMPL_LINK_NOARG(PageFormatPanel, PaperFormatModifyHdl, weld::ComboBox&, void)
+{
+ Paper ePaper = mxPaperSizeBox->get_active_id();
+ Size aSize;
+
+ if(ePaper!=PAPER_USER)
+ aSize = SvxPaperInfo::GetPaperSize(ePaper, meUnit);
+ else
+ aSize = Size(mxPaperWidth->GetCoreValue(meUnit), mxPaperHeight->GetCoreValue(meUnit));
+
+ if (mxPaperOrientation->get_active() == 1 || ePaper==PAPER_USER)
+ Swap(aSize);
+
+ mpPageItem->SetLandscape(mxPaperOrientation->get_active() == 1);
+ SvxSizeItem aSizeItem(SID_ATTR_PAGE_SIZE, aSize);
+ mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_SIZE, SfxCallMode::RECORD, { &aSizeItem, mpPageItem.get() });
+}
+
+IMPL_LINK_NOARG(PageFormatPanel, PaperSizeModifyHdl, weld::MetricSpinButton&, void)
+{
+ Size aSize(mxPaperWidth->GetCoreValue(meUnit), mxPaperHeight->GetCoreValue(meUnit));
+ SvxSizeItem aSizeItem(SID_ATTR_PAGE_SIZE, aSize);
+ mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_SIZE, SfxCallMode::RECORD, { &aSizeItem });
+}
+
+IMPL_LINK_NOARG(PageFormatPanel, PaperModifyMarginHdl, weld::ComboBox&, void)
+{
+ bool bMirrored = false;
+ bool bApplyNewPageMargins = true;
+ switch (mxMarginSelectBox->get_active())
+ {
+ case 0:
+ SetNone(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored);
+ break;
+ case 1:
+ SetNarrow(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored);
+ break;
+ case 2:
+ SetModerate(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored);
+ break;
+ case 3:
+ SetNormal075(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored);
+ break;
+ case 4:
+ SetNormal100(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored);
+ break;
+ case 5:
+ SetNormal125(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored);
+ break;
+ case 6:
+ SetWide(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored);
+ break;
+ case 7:
+ SetMirrored(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored);
+ break;
+ default:
+ bApplyNewPageMargins = false;
+ break;
+ }
+
+ if(bApplyNewPageMargins)
+ {
+ ExecuteMarginLRChange( mnPageLeftMargin, mnPageRightMargin );
+ ExecuteMarginULChange( mnPageTopMargin, mnPageBottomMargin );
+ if(bMirrored != (mpPageItem->GetPageUsage() == SvxPageUsage::Mirror))
+ {
+ mpPageItem->SetPageUsage( bMirrored ? SvxPageUsage::Mirror : SvxPageUsage::All );
+ mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_PAGE,
+ SfxCallMode::RECORD, { mpPageItem.get() });
+ }
+ }
+}
+
+FieldUnit PageFormatPanel::GetCurrentUnit( SfxItemState eState, const SfxPoolItem* pState )
+{
+ FieldUnit eUnit = FieldUnit::NONE;
+
+ if ( pState && eState >= SfxItemState::DEFAULT )
+ eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pState)->GetValue());
+ else
+ {
+ SfxViewFrame* pFrame = SfxViewFrame::Current();
+ SfxObjectShell* pSh = nullptr;
+ if ( pFrame )
+ pSh = pFrame->GetObjectShell();
+ if ( pSh )
+ {
+ SfxModule* pModule = pSh->GetModule();
+ if ( pModule )
+ {
+ const SfxPoolItem* pItem = pModule->GetItem( SID_ATTR_METRIC );
+ if ( pItem )
+ eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pItem)->GetValue());
+ }
+ else
+ {
+ SAL_WARN("sw.ui", "GetModuleFieldUnit(): no module found");
+ }
+ }
+ }
+
+ return eUnit;
+}
+
+void PageFormatPanel::ExecuteMarginLRChange( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin )
+{
+ mpPageLRMarginItem->SetLeft( nPageLeftMargin );
+ mpPageLRMarginItem->SetRight( nPageRightMargin );
+ mpBindings->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_LRSPACE, SfxCallMode::RECORD, { mpPageLRMarginItem.get() });
+}
+
+void PageFormatPanel::ExecuteMarginULChange(const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin)
+{
+ mpPageULMarginItem->SetUpper( nPageTopMargin );
+ mpPageULMarginItem->SetLower( nPageBottomMargin );
+ mpBindings->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_ULSPACE, SfxCallMode::RECORD, { mpPageULMarginItem.get() });
+}
+
+void PageFormatPanel::UpdateMarginBox()
+{
+ mnPageLeftMargin = mpPageLRMarginItem->GetLeft();
+ mnPageRightMargin = mpPageLRMarginItem->GetRight();
+ mnPageTopMargin = mpPageULMarginItem->GetUpper();
+ mnPageBottomMargin = mpPageULMarginItem->GetLower();
+
+ int nCustomEntry = mxMarginSelectBox->find_text(m_aCustomEntry);
+
+ bool bMirrored = (mpPageItem->GetPageUsage() == SvxPageUsage::Mirror);
+ if( IsNone(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored) )
+ {
+ mxMarginSelectBox->set_active(0);
+ if (nCustomEntry != -1)
+ mxMarginSelectBox->remove(nCustomEntry);
+ }
+ else if( IsNarrow(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored) )
+ {
+ mxMarginSelectBox->set_active(1);
+ if (nCustomEntry != -1)
+ mxMarginSelectBox->remove(nCustomEntry);
+ }
+ else if( IsModerate(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored) )
+ {
+ mxMarginSelectBox->set_active(2);
+ if (nCustomEntry != -1)
+ mxMarginSelectBox->remove(nCustomEntry);
+ }
+ else if( IsNormal075(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored) )
+ {
+ mxMarginSelectBox->set_active(3);
+ if (nCustomEntry != -1)
+ mxMarginSelectBox->remove(nCustomEntry);
+ }
+ else if( IsNormal100(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored) )
+ {
+ mxMarginSelectBox->set_active(4);
+ if (nCustomEntry != -1)
+ mxMarginSelectBox->remove(nCustomEntry);
+ }
+ else if( IsNormal125(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored) )
+ {
+ mxMarginSelectBox->set_active(5);
+ if (nCustomEntry != -1)
+ mxMarginSelectBox->remove(nCustomEntry);
+ }
+ else if( IsWide(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored) )
+ {
+ mxMarginSelectBox->set_active(6);
+ if (nCustomEntry != -1)
+ mxMarginSelectBox->remove(nCustomEntry);
+ }
+ else if( IsMirrored(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored) )
+ {
+ mxMarginSelectBox->set_active(7);
+ if (nCustomEntry != -1)
+ mxMarginSelectBox->remove(nCustomEntry);
+ }
+ else
+ {
+ if (nCustomEntry == -1)
+ mxMarginSelectBox->append_text(m_aCustomEntry);
+ mxMarginSelectBox->set_active_text(m_aCustomEntry);
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageFormatPanel.hxx b/sw/source/uibase/sidebar/PageFormatPanel.hxx
new file mode 100644
index 0000000000..a1eb2f109b
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageFormatPanel.hxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/sidebar/PanelLayout.hxx>
+#include <sfx2/sidebar/ControllerItem.hxx>
+
+#include <svx/pageitem.hxx>
+#include <svx/rulritem.hxx>
+#include <svx/papersizelistbox.hxx>
+
+#include <tools/fldunit.hxx>
+#include <svl/poolitem.hxx>
+#include <svx/relfld.hxx>
+
+#include <memory>
+
+namespace sw::sidebar {
+
+class PageFormatPanel :
+ public PanelLayout,
+ public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface
+{
+public:
+ static std::unique_ptr<PanelLayout> Create(
+ weld::Widget* pParent,
+ SfxBindings* pBindings);
+
+ virtual void NotifyItemUpdate(
+ const sal_uInt16 nSId,
+ const SfxItemState eState,
+ const SfxPoolItem* pState) override;
+
+ virtual void GetControlState(
+ const sal_uInt16 /*nSId*/,
+ boost::property_tree::ptree& /*rState*/) override {};
+
+ PageFormatPanel(
+ weld::Widget* pParent,
+ SfxBindings* pBindings);
+ virtual ~PageFormatPanel() override;
+
+ static FieldUnit GetCurrentUnit( SfxItemState eState, const SfxPoolItem* pState );
+
+private:
+
+ SfxBindings* mpBindings;
+
+ std::unique_ptr<SvxPaperSizeListBox> mxPaperSizeBox;
+ std::unique_ptr<SvxRelativeField> mxPaperWidth;
+ std::unique_ptr<SvxRelativeField> mxPaperHeight;
+ std::unique_ptr<weld::ComboBox> mxPaperOrientation;
+ std::unique_ptr<weld::ComboBox> mxMarginSelectBox;
+ std::unique_ptr<weld::Label> mxCustomEntry;
+
+ ::sfx2::sidebar::ControllerItem maPaperSizeController;
+ ::sfx2::sidebar::ControllerItem maPaperOrientationController;
+ ::sfx2::sidebar::ControllerItem maMetricController;
+ ::sfx2::sidebar::ControllerItem maSwPageLRControl;
+ ::sfx2::sidebar::ControllerItem maSwPageULControl;
+
+ std::unique_ptr<SvxPageItem> mpPageItem;
+ std::unique_ptr<SvxLongLRSpaceItem> mpPageLRMarginItem;
+ std::unique_ptr<SvxLongULSpaceItem> mpPageULMarginItem;
+
+ FieldUnit meFUnit;
+ MapUnit meUnit;
+
+ tools::Long mnPageLeftMargin;
+ tools::Long mnPageRightMargin;
+ tools::Long mnPageTopMargin;
+ tools::Long mnPageBottomMargin;
+ OUString m_aCustomEntry;
+
+ void Initialize();
+ void SetMarginFieldUnit();
+ void UpdateMarginBox();
+ void ExecuteMarginLRChange( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin );
+ void ExecuteMarginULChange( const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin);
+ DECL_LINK(PaperFormatModifyHdl, weld::ComboBox&, void);
+ DECL_LINK(PaperSizeModifyHdl, weld::MetricSpinButton&, void);
+ DECL_LINK(PaperModifyMarginHdl, weld::ComboBox&, void );
+};
+
+} //end of namespace sw::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageHeaderPanel.cxx b/sw/source/uibase/sidebar/PageHeaderPanel.cxx
new file mode 100644
index 0000000000..e0706f9c76
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageHeaderPanel.cxx
@@ -0,0 +1,287 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include <sal/config.h>
+#include <svl/intitem.hxx>
+#include <svl/eitem.hxx>
+#include <svl/itemset.hxx>
+#include <svx/dlgutil.hxx>
+#include <svx/rulritem.hxx>
+#include <svx/svdtrans.hxx>
+#include <svx/spacinglistbox.hxx>
+#include <svx/samecontentlistbox.hxx>
+#include "PageHeaderPanel.hxx"
+#include <sfx2/dispatch.hxx>
+#include <sfx2/bindings.hxx>
+#include <cmdid.h>
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+namespace sw::sidebar{
+
+std::unique_ptr<PanelLayout> PageHeaderPanel::Create(
+ weld::Widget* pParent,
+ SfxBindings* pBindings)
+{
+ if( pParent == nullptr )
+ throw ::com::sun::star::lang::IllegalArgumentException("no parent window given to PageHeaderPanel::Create", nullptr, 0);
+ if( pBindings == nullptr )
+ throw ::com::sun::star::lang::IllegalArgumentException("no SfxBindings given to PageHeaderPanel::Create", nullptr, 0);
+
+ return std::make_unique<PageHeaderPanel>(pParent, pBindings);
+}
+
+void PageHeaderPanel::SetMarginsAndSpacingFieldUnit()
+{
+ SpacingListBox::Fill(IsInch(meFUnit) ? SpacingType::SPACING_INCH : SpacingType::SPACING_CM, *mxHeaderSpacingLB);
+ SpacingListBox::Fill(IsInch(meFUnit) ? SpacingType::MARGINS_INCH : SpacingType::MARGINS_CM, *mxHeaderMarginPresetLB);
+}
+
+PageHeaderPanel::PageHeaderPanel(
+ weld::Widget* pParent,
+ SfxBindings* pBindings
+ ) :
+ PanelLayout(pParent, "PageHeaderPanel", "modules/swriter/ui/pageheaderpanel.ui"),
+ mpBindings( pBindings ),
+ maHFToggleController(SID_ATTR_PAGE_HEADER, *pBindings, *this),
+ maMetricController(SID_ATTR_METRIC, *pBindings,*this),
+ maHeaderLRMarginController(SID_ATTR_PAGE_HEADER_LRMARGIN, *pBindings, *this),
+ maHeaderSpacingController(SID_ATTR_PAGE_HEADER_SPACING, *pBindings, *this),
+ maHeaderLayoutController(SID_ATTR_PAGE_HEADER_LAYOUT, *pBindings, *this),
+ meFUnit(GetModuleFieldUnit()),
+ mpHeaderItem( new SfxBoolItem(SID_ATTR_PAGE_HEADER) ),
+ mpHeaderLRMarginItem( new SvxLongLRSpaceItem(0, 0, SID_ATTR_PAGE_HEADER_LRMARGIN)),
+ mpHeaderSpacingItem( new SvxLongULSpaceItem(0, 0, SID_ATTR_PAGE_HEADER_SPACING)),
+ mpHeaderLayoutItem( new SfxInt16Item(SID_ATTR_PAGE_HEADER_LAYOUT)),
+ mxHeaderToggle(m_xBuilder->weld_check_button("headertoggle")),
+ mxHeaderSpacingLB(m_xBuilder->weld_combo_box("spacingpreset")),
+ mxHeaderMarginPresetLB(m_xBuilder->weld_combo_box("headermarginpreset")),
+ mxHeaderLayoutLB(m_xBuilder->weld_combo_box("samecontentLB")),
+ mxCustomEntry(m_xBuilder->weld_label("customlabel"))
+{
+ Initialize();
+}
+
+PageHeaderPanel::~PageHeaderPanel()
+{
+ mxHeaderToggle.reset();
+ mxHeaderSpacingLB.reset();
+ mxHeaderLayoutLB.reset();
+ mxHeaderMarginPresetLB.reset();
+ mxCustomEntry.reset();
+}
+
+FieldUnit PageHeaderPanel::GetCurrentUnit(SfxItemState eState, const SfxPoolItem* pState)
+{
+ FieldUnit eUnit;
+
+ if (pState && eState >= SfxItemState::DEFAULT)
+ eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pState)->GetValue());
+ else
+ eUnit = GetModuleFieldUnit();
+
+ return eUnit;
+}
+
+void PageHeaderPanel::Initialize()
+{
+ SameContentListBox::Fill(*mxHeaderLayoutLB);
+
+ SetMarginsAndSpacingFieldUnit();
+
+ m_aCustomEntry = mxCustomEntry->get_label();
+ mxHeaderToggle->connect_toggled( LINK(this, PageHeaderPanel, HeaderToggleHdl) );
+ mxHeaderMarginPresetLB->connect_changed( LINK(this, PageHeaderPanel, HeaderLRMarginHdl));
+ mxHeaderSpacingLB->connect_changed( LINK(this, PageHeaderPanel, HeaderSpacingHdl));
+ mxHeaderLayoutLB->connect_changed( LINK(this, PageHeaderPanel, HeaderLayoutHdl));
+
+ mpBindings->Invalidate(SID_ATTR_METRIC);
+ mpBindings->Invalidate(SID_ATTR_PAGE_HEADER);
+ mpBindings->Invalidate(SID_ATTR_PAGE_HEADER_LRMARGIN);
+ mpBindings->Invalidate(SID_ATTR_PAGE_HEADER_SPACING);
+ mpBindings->Invalidate(SID_ATTR_PAGE_HEADER_LAYOUT);
+}
+
+void PageHeaderPanel::UpdateHeaderCheck()
+{
+ if (mxHeaderToggle->get_active())
+ {
+ mxHeaderSpacingLB->set_sensitive(true);
+ mxHeaderLayoutLB->set_sensitive(true);
+ mxHeaderMarginPresetLB->set_sensitive(true);
+ }
+ else
+ {
+ mxHeaderSpacingLB->set_sensitive(false);
+ mxHeaderLayoutLB->set_sensitive(false);
+ mxHeaderMarginPresetLB->set_sensitive(false);
+ }
+}
+
+void PageHeaderPanel::UpdateMarginControl()
+{
+ sal_uInt16 nLeft = mpHeaderLRMarginItem->GetLeft();
+ sal_uInt16 nRight = mpHeaderLRMarginItem->GetRight();
+ sal_uInt16 nCount = mxHeaderMarginPresetLB->get_count();
+ if(nLeft == nRight)
+ {
+ for (sal_uInt16 i = 0; i < nCount; ++i)
+ {
+ if (mxHeaderMarginPresetLB->get_id(i).toUInt32() == nLeft)
+ {
+ mxHeaderMarginPresetLB->set_active(i);
+ int nCustomEntry = mxHeaderMarginPresetLB->find_text(m_aCustomEntry);
+ if (nCustomEntry != -1)
+ mxHeaderMarginPresetLB->remove(nCustomEntry);
+ return;
+ }
+ }
+ }
+ mxHeaderMarginPresetLB->append_text(m_aCustomEntry);
+ mxHeaderMarginPresetLB->set_active_text(m_aCustomEntry);
+}
+
+void PageHeaderPanel::UpdateSpacingControl()
+{
+ sal_uInt16 nBottom = mpHeaderSpacingItem->GetLower();
+ sal_uInt16 nCount = mxHeaderSpacingLB->get_count();
+ for (sal_uInt16 i = 0; i < nCount; ++i)
+ {
+ if (mxHeaderSpacingLB->get_id(i).toUInt32() == nBottom)
+ {
+ mxHeaderSpacingLB->set_active(i);
+ int nCustomEntry = mxHeaderSpacingLB->find_text(m_aCustomEntry);
+ if (nCustomEntry != -1)
+ mxHeaderSpacingLB->remove(nCustomEntry);
+ return;
+ }
+ }
+ mxHeaderSpacingLB->append_text(m_aCustomEntry);
+ mxHeaderSpacingLB->set_active_text(m_aCustomEntry);
+}
+
+void PageHeaderPanel::UpdateLayoutControl()
+{
+ sal_uInt16 nLayout = mpHeaderLayoutItem->GetValue();
+ mxHeaderLayoutLB->set_active(nLayout);
+}
+
+void PageHeaderPanel::NotifyItemUpdate(
+ const sal_uInt16 nSid,
+ const SfxItemState eState,
+ const SfxPoolItem* pState)
+{
+ if (!mxHeaderToggle) //disposed
+ return;
+
+ switch(nSid)
+ {
+ case SID_ATTR_PAGE_HEADER:
+ {
+ if(eState >= SfxItemState::DEFAULT &&
+ dynamic_cast<const SfxBoolItem*>( pState) )
+ {
+ mpHeaderItem.reset( static_cast<SfxBoolItem*>(pState->Clone()) );
+ mxHeaderToggle->set_active(mpHeaderItem->GetValue());
+ UpdateHeaderCheck();
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_HEADER_LRMARGIN:
+ {
+ if(eState >= SfxItemState::DEFAULT &&
+ dynamic_cast<const SvxLongLRSpaceItem*>( pState) )
+ {
+ mpHeaderLRMarginItem.reset( static_cast<SvxLongLRSpaceItem*>(pState->Clone()) );
+ UpdateMarginControl();
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_HEADER_SPACING:
+ {
+ if(eState >= SfxItemState::DEFAULT &&
+ dynamic_cast<const SvxLongULSpaceItem*>( pState) )
+ {
+ mpHeaderSpacingItem.reset(static_cast<SvxLongULSpaceItem*>(pState->Clone()) );
+ UpdateSpacingControl();
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_HEADER_LAYOUT:
+ {
+ if(eState >= SfxItemState::DEFAULT &&
+ dynamic_cast<const SfxInt16Item*>( pState) )
+ {
+ mpHeaderLayoutItem.reset(static_cast<SfxInt16Item*>(pState->Clone()) );
+ UpdateLayoutControl();
+ }
+ }
+ break;
+ case SID_ATTR_METRIC:
+ {
+ FieldUnit eFUnit = GetCurrentUnit(eState, pState);
+ if (meFUnit != eFUnit)
+ {
+ meFUnit = eFUnit;
+ SetMarginsAndSpacingFieldUnit();
+ UpdateSpacingControl();
+ UpdateMarginControl();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+IMPL_LINK_NOARG( PageHeaderPanel, HeaderToggleHdl, weld::Toggleable&, void )
+{
+ bool IsChecked = mxHeaderToggle->get_active();
+ mpHeaderItem->SetValue(IsChecked);
+ GetBindings()->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_HEADER, SfxCallMode::RECORD, { mpHeaderItem.get() } );
+ UpdateHeaderCheck();
+}
+
+IMPL_LINK_NOARG( PageHeaderPanel, HeaderLRMarginHdl, weld::ComboBox&, void )
+{
+ sal_uInt16 nVal = mxHeaderMarginPresetLB->get_active_id().toUInt32();
+ mpHeaderLRMarginItem->SetLeft(nVal);
+ mpHeaderLRMarginItem->SetRight(nVal);
+ GetBindings()->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_HEADER_LRMARGIN,
+ SfxCallMode::RECORD, { mpHeaderLRMarginItem.get() } );
+}
+
+IMPL_LINK_NOARG( PageHeaderPanel, HeaderSpacingHdl, weld::ComboBox&, void )
+{
+ sal_uInt16 nVal = mxHeaderSpacingLB->get_active_id().toUInt32();
+ mpHeaderSpacingItem->SetLower(nVal);
+ GetBindings()->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_HEADER_SPACING,
+ SfxCallMode::RECORD, { mpHeaderSpacingItem.get() } );
+}
+IMPL_LINK_NOARG( PageHeaderPanel, HeaderLayoutHdl, weld::ComboBox&, void )
+{
+ sal_uInt16 nVal = mxHeaderLayoutLB->get_active();
+ mpHeaderLayoutItem->SetValue(nVal);
+ GetBindings()->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_HEADER_LAYOUT,
+ SfxCallMode::RECORD, { mpHeaderLayoutItem.get() } );
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageHeaderPanel.hxx b/sw/source/uibase/sidebar/PageHeaderPanel.hxx
new file mode 100644
index 0000000000..7ccd7268c8
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageHeaderPanel.hxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+#include <sfx2/sidebar/PanelLayout.hxx>
+#include <sfx2/sidebar/ControllerItem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/poolitem.hxx>
+#include <svl/eitem.hxx>
+#include <svx/rulritem.hxx>
+
+namespace sw::sidebar {
+
+class PageHeaderPanel :
+ public PanelLayout,
+ public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface
+{
+public:
+ static std::unique_ptr<PanelLayout> Create(
+ weld::Widget* pParent,
+ SfxBindings* pBindings);
+
+ virtual void NotifyItemUpdate(
+ const sal_uInt16 nSId,
+ const SfxItemState eState,
+ const SfxPoolItem* pState) override;
+
+ virtual void GetControlState(
+ const sal_uInt16 /*nSId*/,
+ boost::property_tree::ptree& /*rState*/) override {};
+
+ SfxBindings* GetBindings() const { return mpBindings; }
+ PageHeaderPanel(
+ weld::Widget* pParent,
+ SfxBindings* pBindings);
+ virtual ~PageHeaderPanel() override;
+
+private:
+
+ SfxBindings* mpBindings;
+
+ ::sfx2::sidebar::ControllerItem maHFToggleController;
+ ::sfx2::sidebar::ControllerItem maMetricController;
+ ::sfx2::sidebar::ControllerItem maHeaderLRMarginController;
+ ::sfx2::sidebar::ControllerItem maHeaderSpacingController;
+ ::sfx2::sidebar::ControllerItem maHeaderLayoutController;
+
+ FieldUnit meFUnit;
+
+ OUString m_aCustomEntry;
+
+ void Initialize();
+ void SetMarginsAndSpacingFieldUnit();
+ void UpdateHeaderCheck();
+ void UpdateMarginControl();
+ void UpdateSpacingControl();
+ void UpdateLayoutControl();
+
+ ::std::unique_ptr<SfxBoolItem> mpHeaderItem;
+ ::std::unique_ptr<SvxLongLRSpaceItem> mpHeaderLRMarginItem;
+ ::std::unique_ptr<SvxLongULSpaceItem> mpHeaderSpacingItem;
+ ::std::unique_ptr<SfxInt16Item> mpHeaderLayoutItem;
+
+ std::unique_ptr<weld::CheckButton> mxHeaderToggle;
+ std::unique_ptr<weld::ComboBox> mxHeaderSpacingLB;
+ std::unique_ptr<weld::ComboBox> mxHeaderMarginPresetLB;
+ std::unique_ptr<weld::ComboBox> mxHeaderLayoutLB;
+ std::unique_ptr<weld::Label> mxCustomEntry;
+
+ static FieldUnit GetCurrentUnit(SfxItemState eState, const SfxPoolItem* pState);
+
+ DECL_LINK( HeaderToggleHdl, weld::Toggleable&, void );
+ DECL_LINK( HeaderLRMarginHdl, weld::ComboBox&, void);
+ DECL_LINK( HeaderSpacingHdl, weld::ComboBox&, void);
+ DECL_LINK( HeaderLayoutHdl, weld::ComboBox&, void);
+};
+
+} //end of namespace sw::sidebar
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageMarginControl.cxx b/sw/source/uibase/sidebar/PageMarginControl.cxx
new file mode 100644
index 0000000000..2b9bb36cd7
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageMarginControl.cxx
@@ -0,0 +1,597 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <sal/config.h>
+
+#include "PageMarginControl.hxx"
+#include <strings.hrc>
+
+#include <editeng/sizeitem.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/module.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svx/pageitem.hxx>
+#include <svx/rulritem.hxx>
+#include <svl/itempool.hxx>
+#include <svl/intitem.hxx>
+#include <svtools/unitconv.hxx>
+#include <unotools/viewoptions.hxx>
+
+#include <swtypes.hxx>
+#include <cmdid.h>
+#include <PageMarginPopup.hxx>
+
+#include <com/sun/star/document/XUndoManagerSupplier.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+
+constexpr OUString SWPAGE_LEFT_GVALUE = u"Sw_Page_Left"_ustr;
+constexpr OUString SWPAGE_RIGHT_GVALUE = u"Sw_Page_Right"_ustr;
+constexpr OUString SWPAGE_TOP_GVALUE = u"Sw_Page_Top"_ustr;
+constexpr OUString SWPAGE_DOWN_GVALUE = u"Sw_Page_Down"_ustr;
+constexpr OUString SWPAGE_MIRROR_GVALUE = u"Sw_Page_Mirrored"_ustr;
+
+namespace
+{
+ FieldUnit lcl_GetFieldUnit()
+ {
+ if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
+ {
+ SfxPoolItemHolder aResult;
+ const SfxItemState eState(pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_METRIC, aResult));
+ const SfxUInt16Item* pItem(static_cast<const SfxUInt16Item*>(aResult.getItem()));
+ if (pItem && eState >= SfxItemState::DEFAULT)
+ return static_cast<FieldUnit>(pItem->GetValue());
+ }
+ return SfxModule::GetCurrentFieldUnit();
+ }
+
+ MapUnit lcl_GetUnit()
+ {
+ SfxItemPool &rPool = SfxGetpApp()->GetPool();
+ sal_uInt16 nWhich = rPool.GetWhich( SID_ATTR_PAGE_SIZE );
+ return rPool.GetMetric( nWhich );
+ }
+
+ css::uno::Reference< css::document::XUndoManager > getUndoManager( const css::uno::Reference< css::frame::XFrame >& rxFrame )
+ {
+ const css::uno::Reference< css::frame::XController >& xController = rxFrame->getController();
+ if ( xController.is() )
+ {
+ const css::uno::Reference< css::frame::XModel >& xModel = xController->getModel();
+ if ( xModel.is() )
+ {
+ const css::uno::Reference< css::document::XUndoManagerSupplier > xSuppUndo( xModel, css::uno::UNO_QUERY_THROW );
+ return css::uno::Reference< css::document::XUndoManager >( xSuppUndo->getUndoManager(), css::uno::UNO_SET_THROW );
+ }
+ }
+
+ return css::uno::Reference< css::document::XUndoManager > ();
+ }
+}
+
+namespace sw::sidebar {
+
+PageMarginControl::PageMarginControl(PageMarginPopup* pControl, weld::Widget* pParent)
+ : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "modules/swriter/ui/pagemargincontrol.ui", "PageMarginControl")
+ , m_xMoreButton(m_xBuilder->weld_button("moreoptions"))
+ , m_xLeft(m_xBuilder->weld_label("leftLabel"))
+ , m_xRight(m_xBuilder->weld_label("rightLabel"))
+ , m_xInner(m_xBuilder->weld_label("innerLabel"))
+ , m_xOuter(m_xBuilder->weld_label("outerLabel"))
+ , m_xLeftMarginEdit(m_xBuilder->weld_metric_spin_button("left", FieldUnit::CM))
+ , m_xRightMarginEdit(m_xBuilder->weld_metric_spin_button("right", FieldUnit::CM))
+ , m_xTopMarginEdit(m_xBuilder->weld_metric_spin_button("top", FieldUnit::CM))
+ , m_xBottomMarginEdit(m_xBuilder->weld_metric_spin_button("bottom", FieldUnit::CM))
+ , m_xWidthHeightField(m_xBuilder->weld_metric_spin_button("hidden", FieldUnit::CM))
+ , m_xControl(pControl)
+ , m_nPageLeftMargin(0)
+ , m_nPageRightMargin(0)
+ , m_nPageTopMargin(0)
+ , m_nPageBottomMargin(0)
+ , m_bMirrored(false)
+ , m_eUnit( lcl_GetUnit() )
+ , m_bUserCustomValuesAvailable( false )
+ , m_nUserCustomPageLeftMargin( 0 )
+ , m_nUserCustomPageRightMargin( 0 )
+ , m_nUserCustomPageTopMargin( 0 )
+ , m_nUserCustomPageBottomMargin( 0 )
+ , m_bUserCustomMirrored( false )
+ , m_bCustomValuesUsed( false )
+{
+ m_xWidthHeightField->set_unit(FieldUnit::CM);
+ m_xWidthHeightField->set_range(0, 9999, FieldUnit::NONE);
+ m_xWidthHeightField->set_digits(2);
+ m_xWidthHeightField->set_increments(10, 100, FieldUnit::NONE);
+ SetFieldUnit( *m_xWidthHeightField, lcl_GetFieldUnit() );
+
+ bool bLandscape = false;
+ const SvxSizeItem* pSize = nullptr;
+ const SvxLongLRSpaceItem* pLRItem = nullptr;
+ const SvxLongULSpaceItem* pULItem = nullptr;
+ if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
+ {
+ SfxPoolItemHolder aResult;
+ pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE, aResult);
+ const SvxPageItem* pPageItem(static_cast<const SvxPageItem*>(aResult.getItem()));
+ bLandscape = pPageItem->IsLandscape();
+ m_bMirrored = pPageItem->GetPageUsage() == SvxPageUsage::Mirror;
+
+ pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_SIZE, aResult);
+ pSize = static_cast<const SvxSizeItem*>(aResult.getItem());
+
+ pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_LRSPACE, aResult);
+ pLRItem = static_cast<const SvxLongLRSpaceItem*>(aResult.getItem());
+
+ pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_ULSPACE, aResult);
+ pULItem = static_cast<const SvxLongULSpaceItem*>(aResult.getItem());
+ }
+
+ if ( pLRItem )
+ {
+ m_nPageLeftMargin = pLRItem->GetLeft();
+ m_nPageRightMargin = pLRItem->GetRight();
+ }
+
+ if ( pULItem )
+ {
+ m_nPageTopMargin = pULItem->GetUpper();
+ m_nPageBottomMargin = pULItem->GetLower();
+ }
+
+ if ( bLandscape )
+ {
+ m_xNarrow = m_xBuilder->weld_button("narrowL");
+ m_xNormal = m_xBuilder->weld_button("normalL");
+ m_xWide = m_xBuilder->weld_button("wideL");
+ m_xMirrored = m_xBuilder->weld_button("mirroredL");
+ m_xLast = m_xBuilder->weld_button("lastL");
+ }
+ else
+ {
+ m_xNarrow = m_xBuilder->weld_button("narrow");
+ m_xNormal = m_xBuilder->weld_button("normal");
+ m_xWide = m_xBuilder->weld_button("wide");
+ m_xMirrored = m_xBuilder->weld_button("mirrored");
+ m_xLast = m_xBuilder->weld_button("last");
+ }
+
+ m_xNarrow->show();
+ m_xNormal->show();
+ m_xWide->show();
+ m_xMirrored->show();
+ m_xLast->show();
+ m_xMoreButton->show();
+
+ m_xNarrow->connect_clicked( LINK( this, PageMarginControl, SelectMarginHdl ) );
+ m_xNormal->connect_clicked( LINK( this, PageMarginControl, SelectMarginHdl ) );
+ m_xWide->connect_clicked( LINK( this, PageMarginControl, SelectMarginHdl ) );
+ m_xMirrored->connect_clicked( LINK( this, PageMarginControl, SelectMarginHdl ) );
+ m_xLast->connect_clicked( LINK( this, PageMarginControl, SelectMarginHdl ) );
+ m_xMoreButton->connect_clicked( LINK(this, PageMarginControl, MoreButtonClickHdl_Impl));
+
+ m_bUserCustomValuesAvailable = GetUserCustomValues();
+
+ FillHelpText( m_bUserCustomValuesAvailable );
+
+ Link<weld::MetricSpinButton&,void> aLinkLR = LINK( this, PageMarginControl, ModifyLRMarginHdl );
+ m_xLeftMarginEdit->connect_value_changed( aLinkLR );
+ SetMetricValue( *m_xLeftMarginEdit, m_nPageLeftMargin, m_eUnit );
+ SetFieldUnit( *m_xLeftMarginEdit, lcl_GetFieldUnit() );
+
+ m_xRightMarginEdit->connect_value_changed( aLinkLR );
+ SetMetricValue( *m_xRightMarginEdit, m_nPageRightMargin, m_eUnit );
+ SetFieldUnit( *m_xRightMarginEdit, lcl_GetFieldUnit() );
+
+ Link<weld::MetricSpinButton&,void> aLinkUL = LINK( this, PageMarginControl, ModifyULMarginHdl );
+ m_xTopMarginEdit->connect_value_changed( aLinkUL );
+ SetMetricValue( *m_xTopMarginEdit, m_nPageTopMargin, m_eUnit );
+ SetFieldUnit( *m_xTopMarginEdit, lcl_GetFieldUnit() );
+
+ m_xBottomMarginEdit->connect_value_changed( aLinkUL );
+ SetMetricValue( *m_xBottomMarginEdit, m_nPageBottomMargin, m_eUnit );
+ SetFieldUnit( *m_xBottomMarginEdit, lcl_GetFieldUnit() );
+
+ if (pSize)
+ {
+ m_aPageSize = pSize->GetSize();
+ SetMetricFieldMaxValues( m_aPageSize );
+ }
+
+ if ( m_bMirrored )
+ {
+ m_xLeft->hide();
+ m_xRight->hide();
+ m_xInner->show();
+ m_xOuter->show();
+ }
+ else
+ {
+ m_xLeft->show();
+ m_xRight->show();
+ m_xInner->hide();
+ m_xOuter->hide();
+ }
+}
+
+void PageMarginControl::GrabFocus()
+{
+ m_xMoreButton->grab_focus();
+}
+
+PageMarginControl::~PageMarginControl()
+{
+ StoreUserCustomValues();
+}
+
+void PageMarginControl::SetMetricFieldMaxValues( const Size& rPageSize )
+{
+ const tools::Long nML = m_xLeftMarginEdit->denormalize( m_xLeftMarginEdit->get_value( FieldUnit::TWIP ) );
+ const tools::Long nMR = m_xRightMarginEdit->denormalize( m_xRightMarginEdit->get_value( FieldUnit::TWIP ) );
+ const tools::Long nMT = m_xTopMarginEdit->denormalize( m_xTopMarginEdit->get_value( FieldUnit::TWIP ) );
+ const tools::Long nMB = m_xBottomMarginEdit->denormalize( m_xBottomMarginEdit->get_value( FieldUnit::TWIP ) );
+
+ const tools::Long nPH = OutputDevice::LogicToLogic( rPageSize.Height(), m_eUnit, MapUnit::MapTwip );
+ const tools::Long nPW = OutputDevice::LogicToLogic( rPageSize.Width(), m_eUnit, MapUnit::MapTwip );
+
+ // Left
+ tools::Long nMax = nPW - nMR - MINBODY;
+ m_xLeftMarginEdit->set_max( m_xLeftMarginEdit->normalize( nMax ), FieldUnit::TWIP );
+
+ // Right
+ nMax = nPW - nML - MINBODY;
+ m_xRightMarginEdit->set_max( m_xRightMarginEdit->normalize( nMax ), FieldUnit::TWIP );
+
+ //Top
+ nMax = nPH - nMB - MINBODY;
+ m_xTopMarginEdit->set_max( m_xTopMarginEdit->normalize( nMax ), FieldUnit::TWIP );
+
+ //Bottom
+ nMax = nPH - nMT - MINBODY;
+ m_xBottomMarginEdit->set_max( m_xTopMarginEdit->normalize( nMax ), FieldUnit::TWIP );
+}
+
+void PageMarginControl::FillHelpText( const bool bUserCustomValuesAvailable )
+{
+ const OUString aLeft = SwResId( STR_MARGIN_TOOLTIP_LEFT );
+ const OUString aRight = SwResId( STR_MARGIN_TOOLTIP_RIGHT );
+ const OUString aTop = SwResId( STR_MARGIN_TOOLTIP_TOP );
+ const OUString aBottom = SwResId( STR_MARGIN_TOOLTIP_BOT );
+
+ SetMetricValue( *m_xWidthHeightField, SWPAGE_NARROW_VALUE, m_eUnit );
+ const OUString aNarrowValText = m_xWidthHeightField->get_text();
+ OUString aHelpText = aLeft +
+ aNarrowValText +
+ aRight +
+ aNarrowValText +
+ aTop +
+ aNarrowValText +
+ aBottom +
+ aNarrowValText;
+ m_xNarrow->set_tooltip_text( aHelpText );
+
+ SetMetricValue( *m_xWidthHeightField, SWPAGE_NORMAL_VALUE, m_eUnit );
+ const OUString aNormalValText = m_xWidthHeightField->get_text();
+ aHelpText = aLeft +
+ aNormalValText +
+ aRight +
+ aNormalValText +
+ aTop +
+ aNormalValText +
+ aBottom +
+ aNormalValText;
+ m_xNormal->set_tooltip_text( aHelpText );
+
+ SetMetricValue( *m_xWidthHeightField, SWPAGE_WIDE_VALUE1, m_eUnit );
+ const OUString aWide1ValText = m_xWidthHeightField->get_text();
+ SetMetricValue( *m_xWidthHeightField, SWPAGE_WIDE_VALUE2, m_eUnit );
+ const OUString aWide2ValText = m_xWidthHeightField->get_text();
+ aHelpText = aLeft +
+ aWide2ValText +
+ aRight +
+ aWide2ValText +
+ aTop +
+ aWide1ValText +
+ aBottom +
+ aWide1ValText;
+ m_xWide->set_tooltip_text( aHelpText );
+
+ const OUString aInner = SwResId( STR_MARGIN_TOOLTIP_INNER );
+ const OUString aOuter = SwResId( STR_MARGIN_TOOLTIP_OUTER );
+
+ SetMetricValue( *m_xWidthHeightField, SWPAGE_WIDE_VALUE3, m_eUnit );
+ const OUString aWide3ValText = m_xWidthHeightField->get_text();
+ aHelpText = aInner +
+ aWide3ValText +
+ aOuter +
+ aWide1ValText +
+ aTop +
+ aWide1ValText +
+ aBottom +
+ aWide1ValText;
+ m_xMirrored->set_tooltip_text( aHelpText );
+
+ if ( bUserCustomValuesAvailable )
+ {
+ aHelpText = m_bUserCustomMirrored ? aInner : aLeft;
+ SetMetricValue( *m_xWidthHeightField, m_nUserCustomPageLeftMargin, m_eUnit );
+ aHelpText += m_xWidthHeightField->get_text();
+ aHelpText += m_bUserCustomMirrored ? aOuter : aRight;
+ SetMetricValue( *m_xWidthHeightField, m_nUserCustomPageRightMargin, m_eUnit );
+ aHelpText += m_xWidthHeightField->get_text() + aTop;
+ SetMetricValue( *m_xWidthHeightField, m_nUserCustomPageTopMargin, m_eUnit );
+ aHelpText += m_xWidthHeightField->get_text() + aBottom;
+ SetMetricValue( *m_xWidthHeightField, m_nUserCustomPageBottomMargin, m_eUnit );
+ aHelpText += m_xWidthHeightField->get_text();
+ }
+ else
+ {
+ aHelpText.clear();
+ }
+ m_xLast->set_tooltip_text( aHelpText );
+}
+
+IMPL_LINK( PageMarginControl, SelectMarginHdl, weld::Button&, rControl, void )
+{
+ bool bMirrored = false;
+ bool bApplyNewPageMargins = true;
+ if( &rControl == m_xNarrow.get() )
+ {
+ m_nPageLeftMargin = SWPAGE_NARROW_VALUE;
+ m_nPageRightMargin = SWPAGE_NARROW_VALUE;
+ m_nPageTopMargin = SWPAGE_NARROW_VALUE;
+ m_nPageBottomMargin = SWPAGE_NARROW_VALUE;
+ bMirrored = false;
+ }
+ if( &rControl == m_xNormal.get() )
+ {
+ m_nPageLeftMargin = SWPAGE_NORMAL_VALUE;
+ m_nPageRightMargin = SWPAGE_NORMAL_VALUE;
+ m_nPageTopMargin = SWPAGE_NORMAL_VALUE;
+ m_nPageBottomMargin = SWPAGE_NORMAL_VALUE;
+ bMirrored = false;
+ }
+ if( &rControl == m_xWide.get() )
+ {
+ m_nPageLeftMargin = SWPAGE_WIDE_VALUE2;
+ m_nPageRightMargin = SWPAGE_WIDE_VALUE2;
+ m_nPageTopMargin = SWPAGE_WIDE_VALUE1;
+ m_nPageBottomMargin = SWPAGE_WIDE_VALUE1;
+ bMirrored = false;
+ }
+ if( &rControl == m_xMirrored.get() )
+ {
+ m_nPageLeftMargin = SWPAGE_WIDE_VALUE3;
+ m_nPageRightMargin = SWPAGE_WIDE_VALUE1;
+ m_nPageTopMargin = SWPAGE_WIDE_VALUE1;
+ m_nPageBottomMargin = SWPAGE_WIDE_VALUE1;
+ bMirrored = true;
+ }
+ if( &rControl == m_xLast.get() )
+ {
+ if ( m_bUserCustomValuesAvailable )
+ {
+ m_nPageLeftMargin = m_nUserCustomPageLeftMargin;
+ m_nPageRightMargin = m_nUserCustomPageRightMargin;
+ m_nPageTopMargin = m_nUserCustomPageTopMargin;
+ m_nPageBottomMargin = m_nUserCustomPageBottomMargin;
+ bMirrored = m_bUserCustomMirrored;
+ }
+ else
+ {
+ bApplyNewPageMargins = false;
+ }
+ }
+
+ if ( !bApplyNewPageMargins )
+ return;
+
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ const css::uno::Reference<css::document::XUndoManager> xUndoManager(pViewFrm ? getUndoManager(pViewFrm->GetFrame().GetFrameInterface()) : nullptr);
+ if ( xUndoManager.is() )
+ xUndoManager->enterUndoContext( "" );
+
+ ExecuteMarginLRChange( m_nPageLeftMargin, m_nPageRightMargin );
+ ExecuteMarginULChange( m_nPageTopMargin, m_nPageBottomMargin );
+ if ( m_bMirrored != bMirrored )
+ {
+ m_bMirrored = bMirrored;
+ ExecutePageLayoutChange( m_bMirrored );
+ }
+
+ if ( xUndoManager.is() )
+ xUndoManager->leaveUndoContext();
+
+ m_bCustomValuesUsed = false;
+ m_xControl->EndPopupMode();
+}
+
+void PageMarginControl::ExecuteMarginLRChange(
+ const tools::Long nPageLeftMargin,
+ const tools::Long nPageRightMargin )
+{
+ if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
+ {
+ SvxLongLRSpaceItem aPageLRMarginItem( 0, 0, SID_ATTR_PAGE_LRSPACE );
+ aPageLRMarginItem.SetLeft( nPageLeftMargin );
+ aPageLRMarginItem.SetRight( nPageRightMargin );
+ pViewFrm->GetBindings().GetDispatcher()->ExecuteList( SID_ATTR_PAGE_LRSPACE,
+ SfxCallMode::RECORD, { &aPageLRMarginItem } );
+ }
+}
+
+void PageMarginControl::ExecuteMarginULChange(
+ const tools::Long nPageTopMargin,
+ const tools::Long nPageBottomMargin )
+{
+ if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
+ {
+ SvxLongULSpaceItem aPageULMarginItem( 0, 0, SID_ATTR_PAGE_ULSPACE );
+ aPageULMarginItem.SetUpper( nPageTopMargin );
+ aPageULMarginItem.SetLower( nPageBottomMargin );
+ pViewFrm->GetBindings().GetDispatcher()->ExecuteList( SID_ATTR_PAGE_ULSPACE,
+ SfxCallMode::RECORD, { &aPageULMarginItem } );
+ }
+}
+
+void PageMarginControl::ExecutePageLayoutChange( const bool bMirrored )
+{
+ if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
+ {
+ SvxPageItem aPageItem( SID_ATTR_PAGE );
+ aPageItem.SetPageUsage( bMirrored ? SvxPageUsage::Mirror : SvxPageUsage::All );
+ pViewFrm->GetBindings().GetDispatcher()->ExecuteList( SID_ATTR_PAGE,
+ SfxCallMode::RECORD, { &aPageItem } );
+ }
+}
+
+IMPL_LINK_NOARG( PageMarginControl, ModifyLRMarginHdl, weld::MetricSpinButton&, void )
+{
+ m_nPageLeftMargin = GetCoreValue( *m_xLeftMarginEdit, m_eUnit );
+ m_nPageRightMargin = GetCoreValue( *m_xRightMarginEdit, m_eUnit );
+ ExecuteMarginLRChange( m_nPageLeftMargin, m_nPageRightMargin );
+ SetMetricFieldMaxValues( m_aPageSize );
+ m_bCustomValuesUsed = true;
+}
+
+IMPL_LINK_NOARG( PageMarginControl, ModifyULMarginHdl, weld::MetricSpinButton&, void )
+{
+ m_nPageTopMargin = GetCoreValue( *m_xTopMarginEdit, m_eUnit );
+ m_nPageBottomMargin = GetCoreValue( *m_xBottomMarginEdit, m_eUnit );
+ ExecuteMarginULChange( m_nPageTopMargin, m_nPageBottomMargin );
+ SetMetricFieldMaxValues( m_aPageSize );
+ m_bCustomValuesUsed = true;
+}
+
+IMPL_LINK_NOARG(PageMarginControl, MoreButtonClickHdl_Impl, weld::Button&, void)
+{
+ if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
+ pViewFrm->GetBindings().GetDispatcher()->Execute(FN_FORMAT_PAGE_SETTING_DLG,
+ SfxCallMode::ASYNCHRON);
+ m_xControl->EndPopupMode();
+}
+
+bool PageMarginControl::GetUserCustomValues()
+{
+ bool bUserCustomValuesAvailable = false;
+
+ SvtViewOptions aWinOpt( EViewType::Window, SWPAGE_LEFT_GVALUE );
+ if ( aWinOpt.Exists() )
+ {
+ css::uno::Sequence < css::beans::NamedValue > aSeq = aWinOpt.GetUserData();
+ OUString aTmp;
+ if ( aSeq.hasElements())
+ aSeq[0].Value >>= aTmp;
+ OUString aWinData( aTmp );
+ m_nUserCustomPageLeftMargin = aWinData.toInt32();
+ bUserCustomValuesAvailable = true;
+ }
+
+ SvtViewOptions aWinOpt2( EViewType::Window, SWPAGE_RIGHT_GVALUE );
+ if ( aWinOpt2.Exists() )
+ {
+ css::uno::Sequence < css::beans::NamedValue > aSeq = aWinOpt2.GetUserData();
+ OUString aTmp;
+ if ( aSeq.hasElements())
+ aSeq[0].Value >>= aTmp;
+ OUString aWinData( aTmp );
+ m_nUserCustomPageRightMargin = aWinData.toInt32();
+ bUserCustomValuesAvailable = true;
+ }
+
+ SvtViewOptions aWinOpt3( EViewType::Window, SWPAGE_TOP_GVALUE );
+ if ( aWinOpt3.Exists() )
+ {
+ css::uno::Sequence < css::beans::NamedValue > aSeq = aWinOpt3.GetUserData();
+ OUString aTmp;
+ if ( aSeq.hasElements() )
+ aSeq[0].Value >>= aTmp;
+ OUString aWinData( aTmp );
+ m_nUserCustomPageTopMargin = aWinData.toInt32();
+ bUserCustomValuesAvailable = true;
+ }
+
+ SvtViewOptions aWinOpt4( EViewType::Window, SWPAGE_DOWN_GVALUE );
+ if ( aWinOpt4.Exists() )
+ {
+ css::uno::Sequence < css::beans::NamedValue > aSeq = aWinOpt4.GetUserData();
+ OUString aTmp;
+ if ( aSeq.hasElements())
+ aSeq[0].Value >>= aTmp;
+ OUString aWinData( aTmp );
+ m_nUserCustomPageBottomMargin = aWinData.toInt32();
+ bUserCustomValuesAvailable = true;
+ }
+
+ SvtViewOptions aWinOpt5( EViewType::Window, SWPAGE_MIRROR_GVALUE );
+ if ( aWinOpt5.Exists() )
+ {
+ css::uno::Sequence < css::beans::NamedValue > aSeq = aWinOpt5.GetUserData();
+ OUString aTmp;
+ if ( aSeq.hasElements())
+ aSeq[0].Value >>= aTmp;
+ OUString aWinData( aTmp );
+ m_bUserCustomMirrored = aWinData.toInt32() != 0;
+ bUserCustomValuesAvailable = true;
+ }
+
+ return bUserCustomValuesAvailable;
+}
+
+void PageMarginControl::StoreUserCustomValues()
+{
+ if ( !m_bCustomValuesUsed )
+ {
+ return;
+ }
+
+ css::uno::Sequence < css::beans::NamedValue > aSeq( 1 );
+ auto pSeq = aSeq.getArray();
+ SvtViewOptions aWinOpt( EViewType::Window, SWPAGE_LEFT_GVALUE );
+
+ pSeq[0].Name = "mnPageLeftMargin";
+ pSeq[0].Value <<= OUString::number( m_nPageLeftMargin );
+ aWinOpt.SetUserData( aSeq );
+
+ SvtViewOptions aWinOpt2( EViewType::Window, SWPAGE_RIGHT_GVALUE );
+ pSeq[0].Name = "mnPageRightMargin";
+ pSeq[0].Value <<= OUString::number( m_nPageRightMargin );
+ aWinOpt2.SetUserData( aSeq );
+
+ SvtViewOptions aWinOpt3( EViewType::Window, SWPAGE_TOP_GVALUE );
+ pSeq[0].Name = "mnPageTopMargin";
+ pSeq[0].Value <<= OUString::number( m_nPageTopMargin );
+ aWinOpt3.SetUserData( aSeq );
+
+ SvtViewOptions aWinOpt4( EViewType::Window, SWPAGE_DOWN_GVALUE );
+ pSeq[0].Name = "mnPageBottomMargin";
+ pSeq[0].Value <<= OUString::number( m_nPageBottomMargin );
+ aWinOpt4.SetUserData( aSeq );
+
+ SvtViewOptions aWinOpt5( EViewType::Window, SWPAGE_MIRROR_GVALUE );
+ pSeq[0].Name = "mbMirrored";
+ pSeq[0].Value <<= OUString::number( m_bMirrored ? 1 : 0 );
+ aWinOpt5.SetUserData( aSeq );
+}
+
+} // end of namespace sw::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageMarginControl.hxx b/sw/source/uibase/sidebar/PageMarginControl.hxx
new file mode 100644
index 0000000000..6cfb7b05bf
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageMarginControl.hxx
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGEMARGINCONTROL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGEMARGINCONTROL_HXX
+
+#include <sal/config.h>
+
+#include <o3tl/unit_conversion.hxx>
+#include <svtools/toolbarmenu.hxx>
+
+#define SWPAGE_NARROW_VALUE 720
+#define SWPAGE_NORMAL_VALUE 1136
+#define SWPAGE_WIDE_VALUE1 1440
+#define SWPAGE_WIDE_VALUE2 2880
+#define SWPAGE_WIDE_VALUE3 1800
+
+// #i19922# - tdf#126051 see cui/source/tabpages/page.cxx and svx/source/dialog/hdft.cxx
+constexpr tools::Long MINBODY = o3tl::toTwips(1, o3tl::Length::mm); // 1mm in twips rounded
+
+class PageMarginPopup;
+
+namespace sw::sidebar {
+
+class PageMarginControl final : public WeldToolbarPopup
+{
+public:
+ explicit PageMarginControl(PageMarginPopup* pControl, weld::Widget* pParent);
+ virtual void GrabFocus() override;
+ virtual ~PageMarginControl() override;
+
+private:
+ std::unique_ptr<weld::Button> m_xNarrow;
+ std::unique_ptr<weld::Button> m_xNormal;
+ std::unique_ptr<weld::Button> m_xWide;
+ std::unique_ptr<weld::Button> m_xMirrored;
+ std::unique_ptr<weld::Button> m_xLast;
+ std::unique_ptr<weld::Button> m_xMoreButton;
+
+ std::unique_ptr<weld::Label> m_xLeft;
+ std::unique_ptr<weld::Label> m_xRight;
+ std::unique_ptr<weld::Label> m_xInner;
+ std::unique_ptr<weld::Label> m_xOuter;
+
+ std::unique_ptr<weld::MetricSpinButton> m_xLeftMarginEdit;
+ std::unique_ptr<weld::MetricSpinButton> m_xRightMarginEdit;
+ std::unique_ptr<weld::MetricSpinButton> m_xTopMarginEdit;
+ std::unique_ptr<weld::MetricSpinButton> m_xBottomMarginEdit;
+
+ // hidden metric field
+ std::unique_ptr<weld::MetricSpinButton> m_xWidthHeightField;
+
+ rtl::Reference<PageMarginPopup> m_xControl;
+
+ tools::Long m_nPageLeftMargin;
+ tools::Long m_nPageRightMargin;
+ tools::Long m_nPageTopMargin;
+ tools::Long m_nPageBottomMargin;
+ bool m_bMirrored;
+
+ const MapUnit m_eUnit;
+
+ Size m_aPageSize;
+
+ bool m_bUserCustomValuesAvailable;
+ tools::Long m_nUserCustomPageLeftMargin;
+ tools::Long m_nUserCustomPageRightMargin;
+ tools::Long m_nUserCustomPageTopMargin;
+ tools::Long m_nUserCustomPageBottomMargin;
+ bool m_bUserCustomMirrored;
+
+ bool m_bCustomValuesUsed;
+
+ DECL_LINK( SelectMarginHdl, weld::Button&, void );
+ DECL_LINK( ModifyLRMarginHdl, weld::MetricSpinButton&, void );
+ DECL_LINK( ModifyULMarginHdl, weld::MetricSpinButton&, void );
+ DECL_LINK(MoreButtonClickHdl_Impl, weld::Button&, void);
+
+ static void ExecuteMarginLRChange(
+ const tools::Long nPageLeftMargin,
+ const tools::Long nPageRightMargin );
+ static void ExecuteMarginULChange(
+ const tools::Long nPageTopMargin,
+ const tools::Long nPageBottomMargin );
+ static void ExecutePageLayoutChange( const bool bMirrored );
+
+ void SetMetricFieldMaxValues(const Size& rPageSize);
+
+ bool GetUserCustomValues();
+ void StoreUserCustomValues();
+
+ void FillHelpText( const bool bUserCustomValuesAvailable );
+};
+
+} // end of namespace sw::sidebar
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageMarginPopup.cxx b/sw/source/uibase/sidebar/PageMarginPopup.cxx
new file mode 100644
index 0000000000..67f13acc01
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageMarginPopup.cxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include <PageMarginPopup.hxx>
+#include "PageMarginControl.hxx"
+#include <vcl/toolbox.hxx>
+
+PageMarginPopup::PageMarginPopup(const css::uno::Reference<css::uno::XComponentContext>& rContext)
+ : PopupWindowController(rContext, nullptr, OUString())
+{
+}
+
+void PageMarginPopup::initialize( const css::uno::Sequence< css::uno::Any >& rArguments )
+{
+ PopupWindowController::initialize(rArguments);
+
+ ToolBox* pToolBox = nullptr;
+ ToolBoxItemId nId;
+ if (getToolboxId(nId, &pToolBox))
+ pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWNONLY | pToolBox->GetItemBits(nId));
+}
+
+PageMarginPopup::~PageMarginPopup()
+{
+}
+
+std::unique_ptr<WeldToolbarPopup> PageMarginPopup::weldPopupWindow()
+{
+ return std::make_unique<sw::sidebar::PageMarginControl>(this, m_pToolbar);
+}
+
+VclPtr<vcl::Window> PageMarginPopup::createVclPopupWindow( vcl::Window* pParent )
+{
+ mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent,
+ std::make_unique<sw::sidebar::PageMarginControl>(this, pParent->GetFrameWeld()));
+
+ mxInterimPopover->Show();
+
+ return mxInterimPopover;
+}
+
+OUString PageMarginPopup::getImplementationName()
+{
+ return "lo.writer.PageMarginToolBoxControl";
+}
+
+css::uno::Sequence<OUString> PageMarginPopup::getSupportedServiceNames()
+{
+ return { "com.sun.star.frame.ToolbarController" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+lo_writer_PageMarginToolBoxControl_get_implementation(
+ css::uno::XComponentContext* rContext,
+ css::uno::Sequence<css::uno::Any> const & )
+{
+ return cppu::acquire(new PageMarginPopup(rContext));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageMarginUtils.hxx b/sw/source/uibase/sidebar/PageMarginUtils.hxx
new file mode 100644
index 0000000000..ce7d5f65ee
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageMarginUtils.hxx
@@ -0,0 +1,194 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include <cmath>
+#include <tools/long.hxx>
+
+#define SWPAGE_NO_MARGIN 0
+#define SWPAGE_NARROW_VALUE 720
+#define SWPAGE_MODERATE_LR 1080
+#define SWPAGE_NORMAL_VALUE 1136
+#define SWPAGE_WIDE_VALUE1 1440
+#define SWPAGE_WIDE_VALUE2 2880
+#define SWPAGE_WIDE_VALUE3 1800
+#define SWPAGE_UNIT_THRESHOLD 5
+
+namespace sw::sidebar{
+
+bool IsNone( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin,
+ const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored)
+{
+ return( std::abs(nPageLeftMargin - SWPAGE_NO_MARGIN) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageRightMargin - SWPAGE_NO_MARGIN ) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageTopMargin - SWPAGE_NO_MARGIN) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageBottomMargin - SWPAGE_NO_MARGIN) <= SWPAGE_UNIT_THRESHOLD &&
+ !bMirrored );
+}
+
+void SetNone( tools::Long& nPageLeftMargin, tools::Long& nPageRightMargin,
+ tools::Long& nPageTopMargin, tools::Long& nPageBottomMargin, bool& bMirrored)
+{
+ nPageLeftMargin = SWPAGE_NO_MARGIN;
+ nPageRightMargin = SWPAGE_NO_MARGIN;
+ nPageTopMargin = SWPAGE_NO_MARGIN;
+ nPageBottomMargin = SWPAGE_NO_MARGIN;
+ bMirrored = false;
+}
+
+bool IsNarrow( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin,
+ const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored)
+{
+ return( std::abs(nPageLeftMargin - SWPAGE_NARROW_VALUE) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageRightMargin - SWPAGE_NARROW_VALUE) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageTopMargin - SWPAGE_NARROW_VALUE) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageBottomMargin - SWPAGE_NARROW_VALUE) <= SWPAGE_UNIT_THRESHOLD &&
+ !bMirrored );
+}
+
+void SetNarrow( tools::Long& nPageLeftMargin, tools::Long& nPageRightMargin,
+ tools::Long& nPageTopMargin, tools::Long& nPageBottomMargin, bool& bMirrored)
+{
+ nPageLeftMargin = SWPAGE_NARROW_VALUE;
+ nPageRightMargin = SWPAGE_NARROW_VALUE;
+ nPageTopMargin = SWPAGE_NARROW_VALUE;
+ nPageBottomMargin = SWPAGE_NARROW_VALUE;
+ bMirrored = false;
+}
+
+bool IsModerate( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin,
+ const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored)
+{
+ return( std::abs(nPageLeftMargin - SWPAGE_MODERATE_LR) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageRightMargin - SWPAGE_MODERATE_LR) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageTopMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageBottomMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD &&
+ !bMirrored );
+}
+
+void SetModerate( tools::Long& nPageLeftMargin, tools::Long& nPageRightMargin,
+ tools::Long& nPageTopMargin, tools::Long& nPageBottomMargin, bool& bMirrored)
+{
+ nPageLeftMargin = SWPAGE_MODERATE_LR;
+ nPageRightMargin = SWPAGE_MODERATE_LR;
+ nPageTopMargin = SWPAGE_WIDE_VALUE1;
+ nPageBottomMargin = SWPAGE_WIDE_VALUE1;
+ bMirrored = false;
+}
+
+bool IsNormal075( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin,
+ const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored)
+{
+ return( std::abs(nPageLeftMargin - SWPAGE_NORMAL_VALUE) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageRightMargin - SWPAGE_NORMAL_VALUE) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageTopMargin - SWPAGE_NORMAL_VALUE) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageBottomMargin - SWPAGE_NORMAL_VALUE) <= SWPAGE_UNIT_THRESHOLD &&
+ !bMirrored );
+}
+
+void SetNormal075( tools::Long& nPageLeftMargin, tools::Long& nPageRightMargin,
+ tools::Long& nPageTopMargin, tools::Long& nPageBottomMargin, bool& bMirrored)
+{
+ nPageLeftMargin = SWPAGE_NORMAL_VALUE;
+ nPageRightMargin = SWPAGE_NORMAL_VALUE;
+ nPageTopMargin = SWPAGE_NORMAL_VALUE;
+ nPageBottomMargin = SWPAGE_NORMAL_VALUE;
+ bMirrored = false;
+}
+
+bool IsNormal100( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin,
+ const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored)
+{
+ return( std::abs(nPageLeftMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageRightMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageTopMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageBottomMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD &&
+ !bMirrored );
+}
+
+void SetNormal100( tools::Long& nPageLeftMargin, tools::Long& nPageRightMargin,
+ tools::Long& nPageTopMargin, tools::Long& nPageBottomMargin, bool& bMirrored)
+{
+ nPageLeftMargin = SWPAGE_WIDE_VALUE1;
+ nPageRightMargin = SWPAGE_WIDE_VALUE1;
+ nPageTopMargin = SWPAGE_WIDE_VALUE1;
+ nPageBottomMargin = SWPAGE_WIDE_VALUE1;
+ bMirrored = false;
+}
+
+bool IsNormal125( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin,
+ const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored)
+{
+ return( std::abs(nPageLeftMargin - SWPAGE_WIDE_VALUE3) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageRightMargin - SWPAGE_WIDE_VALUE3) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageTopMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageBottomMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD &&
+ !bMirrored );
+}
+
+void SetNormal125( tools::Long& nPageLeftMargin, tools::Long& nPageRightMargin,
+ tools::Long& nPageTopMargin, tools::Long& nPageBottomMargin, bool& bMirrored)
+{
+ nPageLeftMargin = SWPAGE_WIDE_VALUE3;
+ nPageRightMargin = SWPAGE_WIDE_VALUE3;
+ nPageTopMargin = SWPAGE_WIDE_VALUE1;
+ nPageBottomMargin = SWPAGE_WIDE_VALUE1;
+ bMirrored = false;
+}
+
+bool IsWide( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin,
+ const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored)
+{
+ return( std::abs(nPageLeftMargin - SWPAGE_WIDE_VALUE2) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageRightMargin - SWPAGE_WIDE_VALUE2) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageTopMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageBottomMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD &&
+ !bMirrored );
+}
+
+void SetWide( tools::Long& nPageLeftMargin, tools::Long& nPageRightMargin,
+ tools::Long& nPageTopMargin, tools::Long& nPageBottomMargin, bool& bMirrored)
+{
+ nPageLeftMargin = SWPAGE_WIDE_VALUE2;
+ nPageRightMargin = SWPAGE_WIDE_VALUE2;
+ nPageTopMargin = SWPAGE_WIDE_VALUE1;
+ nPageBottomMargin = SWPAGE_WIDE_VALUE1;
+ bMirrored = false;
+}
+
+bool IsMirrored( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin,
+ const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored)
+{
+ return( std::abs(nPageLeftMargin - SWPAGE_WIDE_VALUE3) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageRightMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageTopMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD &&
+ std::abs(nPageBottomMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD &&
+ bMirrored );
+}
+
+void SetMirrored( tools::Long& nPageLeftMargin, tools::Long& nPageRightMargin,
+ tools::Long& nPageTopMargin, tools::Long& nPageBottomMargin, bool& bMirrored)
+{
+ nPageLeftMargin = SWPAGE_WIDE_VALUE3;
+ nPageRightMargin = SWPAGE_WIDE_VALUE1;
+ nPageTopMargin = SWPAGE_WIDE_VALUE1;
+ nPageBottomMargin = SWPAGE_WIDE_VALUE1;
+ bMirrored = true;
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageOrientationControl.cxx b/sw/source/uibase/sidebar/PageOrientationControl.cxx
new file mode 100644
index 0000000000..6f0a45d268
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageOrientationControl.cxx
@@ -0,0 +1,197 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "PageOrientationControl.hxx"
+#include "PageMarginControl.hxx"
+#include <PageOrientationPopup.hxx>
+#include <com/sun/star/document/XUndoManager.hpp>
+#include <com/sun/star/document/XUndoManagerSupplier.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+
+#include <sfx2/viewsh.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <cmdid.h>
+
+namespace {
+ css::uno::Reference< css::document::XUndoManager > getUndoManager( const css::uno::Reference< css::frame::XFrame >& rxFrame )
+ {
+ const css::uno::Reference< css::frame::XController >& xController = rxFrame->getController();
+ if ( xController.is() )
+ {
+ const css::uno::Reference< css::frame::XModel >& xModel = xController->getModel();
+ if ( xModel.is() )
+ {
+ const css::uno::Reference< css::document::XUndoManagerSupplier > xSuppUndo( xModel, css::uno::UNO_QUERY_THROW );
+ return css::uno::Reference< css::document::XUndoManager >( xSuppUndo->getUndoManager(), css::uno::UNO_SET_THROW );
+ }
+ }
+
+ return css::uno::Reference< css::document::XUndoManager > ();
+ }
+}
+
+namespace sw::sidebar {
+
+PageOrientationControl::PageOrientationControl(PageOrientationPopup* pControl, weld::Widget* pParent)
+ : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "modules/swriter/ui/pageorientationcontrol.ui", "PageOrientationControl")
+ , m_xPortrait(m_xBuilder->weld_button("portrait"))
+ , m_xLandscape(m_xBuilder->weld_button("landscape"))
+ , m_xControl(pControl)
+ , mpPageItem( new SvxPageItem(SID_ATTR_PAGE) )
+ , mpPageSizeItem( new SvxSizeItem(SID_ATTR_PAGE_SIZE) )
+ , mpPageLRMarginItem( new SvxLongLRSpaceItem( 0, 0, SID_ATTR_PAGE_LRSPACE ) )
+ , mpPageULMarginItem( new SvxLongULSpaceItem( 0, 0, SID_ATTR_PAGE_ULSPACE ) )
+{
+ m_xPortrait->connect_clicked( LINK( this, PageOrientationControl,ImplOrientationHdl ) );
+ m_xLandscape->connect_clicked( LINK( this, PageOrientationControl,ImplOrientationHdl ) );
+}
+
+void PageOrientationControl::GrabFocus()
+{
+ m_xPortrait->grab_focus();
+}
+
+PageOrientationControl::~PageOrientationControl()
+{
+}
+
+void PageOrientationControl::ExecuteMarginLRChange(
+ const tools::Long nPageLeftMargin,
+ const tools::Long nPageRightMargin )
+{
+ mpPageLRMarginItem->SetLeft( nPageLeftMargin );
+ mpPageLRMarginItem->SetRight( nPageRightMargin );
+ if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
+ pViewFrm->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_LRSPACE,
+ SfxCallMode::RECORD, { mpPageLRMarginItem.get() });
+}
+
+void PageOrientationControl::ExecuteMarginULChange(
+ const tools::Long nPageTopMargin,
+ const tools::Long nPageBottomMargin )
+{
+ mpPageULMarginItem->SetUpper( nPageTopMargin );
+ mpPageULMarginItem->SetLower( nPageBottomMargin );
+ if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
+ pViewFrm->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_ULSPACE,
+ SfxCallMode::RECORD, { mpPageULMarginItem.get() });
+}
+
+void PageOrientationControl::ExecuteOrientationChange( const bool bLandscape )
+{
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if (!pViewFrm)
+ return;
+
+ css::uno::Reference< css::document::XUndoManager > mxUndoManager(
+ getUndoManager( pViewFrm->GetFrame().GetFrameInterface() ) );
+
+ if ( mxUndoManager.is() )
+ mxUndoManager->enterUndoContext( "" );
+
+ SfxPoolItemHolder aResult;
+ pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_SIZE, aResult);
+ mpPageSizeItem.reset(static_cast<const SvxSizeItem*>(aResult.getItem())->Clone());
+
+ // Prevent accidental toggling of page orientation
+ if ((mpPageSizeItem->GetWidth() > mpPageSizeItem->GetHeight()) == bLandscape)
+ {
+ if ( mxUndoManager.is() )
+ mxUndoManager->leaveUndoContext();
+ return;
+ }
+
+ pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_LRSPACE, aResult);
+ mpPageLRMarginItem.reset(static_cast<const SvxLongLRSpaceItem*>(aResult.getItem())->Clone());
+
+ pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_ULSPACE, aResult);
+ mpPageULMarginItem.reset(static_cast<const SvxLongULSpaceItem*>(aResult.getItem())->Clone());
+
+ {
+ // set new page orientation
+ mpPageItem->SetLandscape( bLandscape );
+
+ // swap the width and height of the page size
+ const tools::Long nRotatedWidth = mpPageSizeItem->GetSize().Height();
+ const tools::Long nRotatedHeight = mpPageSizeItem->GetSize().Width();
+ mpPageSizeItem->SetSize(Size(nRotatedWidth, nRotatedHeight));
+
+ // apply changed attributes
+ pViewFrm->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_SIZE,
+ SfxCallMode::RECORD, { mpPageSizeItem.get(), mpPageItem.get() });
+ }
+
+ // check, if margin values still fit to the changed page size.
+ // if not, adjust margin values
+ {
+ const tools::Long nML = mpPageLRMarginItem->GetLeft();
+ const tools::Long nMR = mpPageLRMarginItem->GetRight();
+ const tools::Long nTmpPW = nML + nMR + MINBODY;
+
+ const tools::Long nPW = mpPageSizeItem->GetSize().Width();
+
+ if ( nTmpPW > nPW )
+ {
+ if ( nML <= nMR )
+ {
+ ExecuteMarginLRChange( mpPageLRMarginItem->GetLeft(), nMR - (nTmpPW - nPW ) );
+ }
+ else
+ {
+ ExecuteMarginLRChange( nML - (nTmpPW - nPW ), mpPageLRMarginItem->GetRight() );
+ }
+ }
+
+ const tools::Long nMT = mpPageULMarginItem->GetUpper();
+ const tools::Long nMB = mpPageULMarginItem->GetLower();
+ const tools::Long nTmpPH = nMT + nMB + MINBODY;
+
+ const tools::Long nPH = mpPageSizeItem->GetSize().Height();
+
+ if ( nTmpPH > nPH )
+ {
+ if ( nMT <= nMB )
+ {
+ ExecuteMarginULChange( mpPageULMarginItem->GetUpper(), nMB - ( nTmpPH - nPH ) );
+ }
+ else
+ {
+ ExecuteMarginULChange( nMT - ( nTmpPH - nPH ), mpPageULMarginItem->GetLower() );
+ }
+ }
+ }
+
+ if ( mxUndoManager.is() )
+ mxUndoManager->leaveUndoContext();
+}
+
+IMPL_LINK(PageOrientationControl, ImplOrientationHdl, weld::Button&, rControl, void)
+{
+ if (&rControl == m_xPortrait.get())
+ ExecuteOrientationChange( false );
+ else
+ ExecuteOrientationChange( true );
+
+ m_xControl->EndPopupMode();
+}
+
+} // end of namespace sw::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageOrientationControl.hxx b/sw/source/uibase/sidebar/PageOrientationControl.hxx
new file mode 100644
index 0000000000..da82474b08
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageOrientationControl.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <memory>
+#include <svtools/toolbarmenu.hxx>
+#include <svx/pageitem.hxx>
+#include <svx/rulritem.hxx>
+#include <editeng/sizeitem.hxx>
+
+class PageOrientationPopup;
+
+namespace sw::sidebar {
+
+class PageOrientationControl final : public WeldToolbarPopup
+{
+public:
+ explicit PageOrientationControl(PageOrientationPopup* pControl, weld::Widget* pParent);
+ virtual void GrabFocus() override;
+ virtual ~PageOrientationControl() override;
+
+private:
+ std::unique_ptr<weld::Button> m_xPortrait;
+ std::unique_ptr<weld::Button> m_xLandscape;
+ rtl::Reference<PageOrientationPopup> m_xControl;
+
+ std::unique_ptr<SvxPageItem> mpPageItem;
+ std::unique_ptr<SvxSizeItem> mpPageSizeItem;
+ std::unique_ptr<SvxLongLRSpaceItem> mpPageLRMarginItem;
+ std::unique_ptr<SvxLongULSpaceItem> mpPageULMarginItem;
+
+ void ExecuteMarginULChange(const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin);
+ void ExecuteMarginLRChange(const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin);
+ void ExecuteOrientationChange(const bool bLandscape);
+
+ DECL_LINK(ImplOrientationHdl, weld::Button&, void);
+};
+
+} // end of namespace sw::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageOrientationPopup.cxx b/sw/source/uibase/sidebar/PageOrientationPopup.cxx
new file mode 100644
index 0000000000..ca506c83a6
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageOrientationPopup.cxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include <PageOrientationPopup.hxx>
+#include "PageOrientationControl.hxx"
+#include <vcl/toolbox.hxx>
+
+PageOrientationPopup::PageOrientationPopup(const css::uno::Reference<css::uno::XComponentContext>& rContext)
+ : PopupWindowController(rContext, nullptr, OUString())
+{
+}
+
+void PageOrientationPopup::initialize( const css::uno::Sequence< css::uno::Any >& rArguments )
+{
+ PopupWindowController::initialize(rArguments);
+
+ ToolBox* pToolBox = nullptr;
+ ToolBoxItemId nId;
+ if (getToolboxId(nId, &pToolBox))
+ pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWNONLY | pToolBox->GetItemBits(nId));
+}
+
+PageOrientationPopup::~PageOrientationPopup()
+{
+}
+
+std::unique_ptr<WeldToolbarPopup> PageOrientationPopup::weldPopupWindow()
+{
+ return std::make_unique<sw::sidebar::PageOrientationControl>(this, m_pToolbar);
+}
+
+VclPtr<vcl::Window> PageOrientationPopup::createVclPopupWindow( vcl::Window* pParent )
+{
+ mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent,
+ std::make_unique<sw::sidebar::PageOrientationControl>(this, pParent->GetFrameWeld()));
+
+ mxInterimPopover->Show();
+
+ return mxInterimPopover;
+}
+
+OUString PageOrientationPopup::getImplementationName()
+{
+ return "lo.writer.PageOrientationToolBoxControl";
+}
+
+css::uno::Sequence<OUString> PageOrientationPopup::getSupportedServiceNames()
+{
+ return { "com.sun.star.frame.ToolbarController" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+lo_writer_PageOrientationToolBoxControl_get_implementation(
+ css::uno::XComponentContext* rContext,
+ css::uno::Sequence<css::uno::Any> const & )
+{
+ return cppu::acquire(new PageOrientationPopup(rContext));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageSizeControl.cxx b/sw/source/uibase/sidebar/PageSizeControl.cxx
new file mode 100644
index 0000000000..4ea5995c09
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageSizeControl.cxx
@@ -0,0 +1,237 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include "PageSizeControl.hxx"
+
+#include <cmdid.h>
+#include <svx/pageitem.hxx>
+#include <svx/sidebar/ValueSetWithTextControl.hxx>
+
+#include <unotools/localedatawrapper.hxx>
+#include <rtl/character.hxx>
+#include <editeng/paperinf.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/module.hxx>
+#include <sfx2/viewfrm.hxx>
+
+#include <vcl/settings.hxx>
+#include <svl/itempool.hxx>
+#include <svl/intitem.hxx>
+#include <svtools/unitconv.hxx>
+#include <editeng/sizeitem.hxx>
+
+#include <PageSizePopup.hxx>
+
+namespace
+{
+ FieldUnit lcl_GetFieldUnit()
+ {
+ if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
+ {
+ SfxPoolItemHolder aResult;
+ const SfxItemState eState(pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_METRIC, aResult));
+ const SfxUInt16Item* pItem(static_cast<const SfxUInt16Item*>(aResult.getItem()));
+
+ if (pItem && eState >= SfxItemState::DEFAULT)
+ return static_cast<FieldUnit>(pItem->GetValue());
+ }
+ return SfxModule::GetCurrentFieldUnit();
+ }
+
+ MapUnit lcl_GetUnit()
+ {
+ SfxItemPool &rPool = SfxGetpApp()->GetPool();
+ sal_uInt16 nWhich = rPool.GetWhich( SID_ATTR_PAGE_SIZE );
+ return rPool.GetMetric( nWhich );
+ }
+}
+
+namespace sw::sidebar {
+
+PageSizeControl::PageSizeControl(PageSizePopup* pControl, weld::Widget* pParent)
+ : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "modules/swriter/ui/pagesizecontrol.ui", "PageSizeControl")
+ , mxMoreButton(m_xBuilder->weld_button("moreoptions"))
+ , mxWidthHeightField(m_xBuilder->weld_metric_spin_button("metric", FieldUnit::CM))
+ , mxSizeValueSet(new svx::sidebar::ValueSetWithTextControl)
+ , mxSizeValueSetWin(new weld::CustomWeld(*m_xBuilder, "pagesizevalueset", *mxSizeValueSet))
+ , mxControl(pControl)
+{
+ mxWidthHeightField->set_unit(FieldUnit::CM);
+ mxWidthHeightField->set_range(0, 9999, FieldUnit::NONE);
+ mxWidthHeightField->set_digits(2);
+ mxWidthHeightField->set_increments(10, 100, FieldUnit::NONE);
+ SetFieldUnit( *mxWidthHeightField, lcl_GetFieldUnit() );
+
+ maPaperList.push_back( PAPER_A3 );
+ maPaperList.push_back( PAPER_A4 );
+ maPaperList.push_back( PAPER_A5 );
+ maPaperList.push_back( PAPER_B4_ISO );
+ maPaperList.push_back( PAPER_B5_ISO );
+ maPaperList.push_back( PAPER_ENV_C5 );
+ maPaperList.push_back( PAPER_LETTER );
+ maPaperList.push_back( PAPER_LEGAL );
+
+ mxSizeValueSet->SetStyle( mxSizeValueSet->GetStyle() | WB_3DLOOK | WB_NO_DIRECTSELECT );
+ mxSizeValueSet->SetColor( Application::GetSettings().GetStyleSettings().GetMenuColor() );
+
+ sal_uInt16 nSelectedItem = 0;
+ {
+ OUString aMetricStr;
+ {
+ const OUString aText = mxWidthHeightField->get_text();
+ for (short i = aText.getLength() - 1; i >= 0; i--)
+ {
+ sal_Unicode c = aText[i];
+ if ( rtl::isAsciiAlpha(c) || (c == '\'') || (c == '\"') || (c == '%') )
+ {
+ aMetricStr = OUStringChar(c) + aMetricStr;
+ }
+ else
+ {
+ if (!aMetricStr.isEmpty())
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ bool bLandscape = false;
+ const SvxSizeItem* pSize(nullptr);
+ if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
+ {
+ SfxPoolItemHolder aResult;
+ pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE, aResult );
+ bLandscape = static_cast<const SvxPageItem*>(aResult.getItem())->IsLandscape();
+ pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_SIZE, aResult);
+ pSize = static_cast<const SvxSizeItem*>(aResult.getItem());
+ }
+
+ const LocaleDataWrapper& localeDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
+ OUString aWidthStr;
+ OUString aHeightStr;
+ OUString aItemText2;
+ for ( std::vector< Paper >::size_type nPaperIdx = 0;
+ nPaperIdx < maPaperList.size();
+ ++nPaperIdx )
+ {
+ Size aPaperSize = SvxPaperInfo::GetPaperSize( maPaperList[ nPaperIdx ] );
+ if ( bLandscape )
+ {
+ Swap( aPaperSize );
+ }
+
+ mxWidthHeightField->set_value( mxWidthHeightField->normalize( aPaperSize.Width() ), FieldUnit::TWIP );
+ aWidthStr = localeDataWrapper.getNum(
+ mxWidthHeightField->get_value(FieldUnit::NONE),
+ mxWidthHeightField->get_digits(),
+ true,
+ true );
+
+ mxWidthHeightField->set_value( mxWidthHeightField->normalize( aPaperSize.Height() ), FieldUnit::TWIP);
+ aHeightStr = localeDataWrapper.getNum(
+ mxWidthHeightField->get_value(FieldUnit::NONE),
+ mxWidthHeightField->get_digits(),
+ true,
+ true );
+
+ aItemText2 = aWidthStr + " x " + aHeightStr + " " + aMetricStr;
+
+ mxSizeValueSet->AddItem(
+ SvxPaperInfo::GetName( maPaperList[ nPaperIdx ] ),
+ aItemText2 );
+
+ if ( pSize && aPaperSize == pSize->GetSize() )
+ {
+ nSelectedItem = nPaperIdx + 1;
+ }
+ }
+ }
+ mxSizeValueSet->SetNoSelection();
+ mxSizeValueSet->SetSelectHdl( LINK(this, PageSizeControl, ImplSizeHdl ) );
+ mxSizeValueSet->SetOptimalDrawingAreaHeight();
+ mxSizeValueSet->Show();
+ mxSizeValueSet->Resize();
+
+ mxSizeValueSet->SelectItem( nSelectedItem );
+ mxSizeValueSet->SetFormat();
+ mxSizeValueSet->Invalidate();
+
+ mxMoreButton->connect_clicked( LINK( this, PageSizeControl, MoreButtonClickHdl_Impl ) );
+ mxMoreButton->grab_focus();
+}
+
+void PageSizeControl::GrabFocus()
+{
+ mxSizeValueSet->GrabFocus();
+}
+
+PageSizeControl::~PageSizeControl()
+{
+}
+
+void PageSizeControl::ExecuteSizeChange( const Paper ePaper )
+{
+ bool bLandscape = false;
+ MapUnit eUnit = lcl_GetUnit();
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if (!pViewFrm)
+ return;
+
+ SfxPoolItemHolder aResult;
+ pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE, aResult);
+ const SvxPageItem* pItem(static_cast<const SvxPageItem*>(aResult.getItem()));
+ bLandscape = pItem->IsLandscape();
+
+ SvxSizeItem aPageSizeItem(SID_ATTR_PAGE_SIZE);
+ Size aPageSize = SvxPaperInfo::GetPaperSize( ePaper, eUnit );
+ if ( bLandscape )
+ {
+ Swap( aPageSize );
+ }
+ aPageSizeItem.SetSize( aPageSize );
+
+ pViewFrm->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_SIZE,
+ SfxCallMode::RECORD, { &aPageSizeItem });
+}
+
+
+IMPL_LINK_NOARG(PageSizeControl, ImplSizeHdl, ValueSet*, void)
+{
+ mxSizeValueSet->SetNoSelection();
+ const sal_uInt16 nSelectedPaper = mxSizeValueSet->GetSelectedItemId();
+ const Paper ePaper = maPaperList[nSelectedPaper - 1];
+ ExecuteSizeChange( ePaper );
+
+ mxControl->EndPopupMode();
+}
+
+IMPL_LINK_NOARG(PageSizeControl, MoreButtonClickHdl_Impl, weld::Button&, void)
+{
+ if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
+ pViewFrm->GetDispatcher()->Execute( FN_FORMAT_PAGE_SETTING_DLG, SfxCallMode::ASYNCHRON );
+ mxControl->EndPopupMode();
+}
+
+} // end of namespace sw::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageSizeControl.hxx b/sw/source/uibase/sidebar/PageSizeControl.hxx
new file mode 100644
index 0000000000..bbeaa1b198
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageSizeControl.hxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGESIZECONTROL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGESIZECONTROL_HXX
+
+#include <i18nutil/paper.hxx>
+
+#include <svtools/toolbarmenu.hxx>
+#include <svtools/valueset.hxx>
+
+#include <vector>
+
+namespace svx::sidebar
+{
+class ValueSetWithTextControl;
+}
+class PageSizePopup;
+class ValueSet;
+
+namespace sw::sidebar
+{
+class PageSizeControl final : public WeldToolbarPopup
+{
+public:
+ explicit PageSizeControl(PageSizePopup* pControl, weld::Widget* pParent);
+ virtual void GrabFocus() override;
+ virtual ~PageSizeControl() override;
+
+private:
+ std::unique_ptr<weld::Button> mxMoreButton;
+ // hidden metric field
+ std::unique_ptr<weld::MetricSpinButton> mxWidthHeightField;
+ std::unique_ptr<svx::sidebar::ValueSetWithTextControl> mxSizeValueSet;
+ std::unique_ptr<weld::CustomWeld> mxSizeValueSetWin;
+ rtl::Reference<PageSizePopup> mxControl;
+
+ std::vector<Paper> maPaperList;
+
+ static void ExecuteSizeChange(const Paper ePaper);
+
+ DECL_LINK(ImplSizeHdl, ValueSet*, void);
+ DECL_LINK(MoreButtonClickHdl_Impl, weld::Button&, void);
+};
+
+} // end of namespace sw::sidebar
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageSizePopup.cxx b/sw/source/uibase/sidebar/PageSizePopup.cxx
new file mode 100644
index 0000000000..7e2f7e7a4f
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageSizePopup.cxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include <PageSizePopup.hxx>
+#include "PageSizeControl.hxx"
+#include <vcl/toolbox.hxx>
+
+PageSizePopup::PageSizePopup(const css::uno::Reference<css::uno::XComponentContext>& rContext)
+ : PopupWindowController(rContext, nullptr, OUString())
+{
+}
+
+void PageSizePopup::initialize( const css::uno::Sequence< css::uno::Any >& rArguments )
+{
+ PopupWindowController::initialize(rArguments);
+
+ ToolBox* pToolBox = nullptr;
+ ToolBoxItemId nId;
+ if (getToolboxId(nId, &pToolBox))
+ pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWNONLY | pToolBox->GetItemBits(nId));
+}
+
+PageSizePopup::~PageSizePopup()
+{
+}
+
+std::unique_ptr<WeldToolbarPopup> PageSizePopup::weldPopupWindow()
+{
+ return std::make_unique<sw::sidebar::PageSizeControl>(this, m_pToolbar);
+}
+
+VclPtr<vcl::Window> PageSizePopup::createVclPopupWindow( vcl::Window* pParent )
+{
+ mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent,
+ std::make_unique<sw::sidebar::PageSizeControl>(this, pParent->GetFrameWeld()));
+
+ mxInterimPopover->Show();
+
+ return mxInterimPopover;
+}
+
+OUString PageSizePopup::getImplementationName()
+{
+ return "lo.writer.PageSizeToolBoxControl";
+}
+
+css::uno::Sequence<OUString> PageSizePopup::getSupportedServiceNames()
+{
+ return { "com.sun.star.frame.ToolbarController" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+lo_writer_PageSizeToolBoxControl_get_implementation(
+ css::uno::XComponentContext* rContext,
+ css::uno::Sequence<css::uno::Any> const & )
+{
+ return cppu::acquire(new PageSizePopup(rContext));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageStylesPanel.cxx b/sw/source/uibase/sidebar/PageStylesPanel.cxx
new file mode 100644
index 0000000000..53cf43fb74
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageStylesPanel.cxx
@@ -0,0 +1,619 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include <sal/config.h>
+#include <svl/intitem.hxx>
+#include <svx/colorbox.hxx>
+#include <svx/drawitem.hxx>
+#include <svx/xfillit0.hxx>
+#include <svx/xflclit.hxx>
+#include <svx/xflgrit.hxx>
+#include <svx/xflhtit.hxx>
+#include <svx/xbtmpit.hxx>
+#include <svx/itemwin.hxx>
+#include <svx/SvxNumOptionsTabPageHelper.hxx>
+#include "PageStylesPanel.hxx"
+#include <sfx2/sidebar/Panel.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/objsh.hxx>
+#include <cmdid.h>
+
+using namespace ::com::sun::star;
+
+namespace sw::sidebar{
+
+namespace {
+
+enum eFillStyle
+{
+ NONE,
+ SOLID,
+ GRADIENT,
+ HATCH,
+ BITMAP,
+ PATTERN
+};
+
+}
+
+const SvxPageUsage aArr[] =
+{
+ SvxPageUsage::All,
+ SvxPageUsage::Mirror,
+ SvxPageUsage::Right,
+ SvxPageUsage::Left
+};
+
+
+static sal_uInt16 PageUsageToPos_Impl( SvxPageUsage nUsage )
+{
+ for ( size_t i = 0; i < SAL_N_ELEMENTS(aArr); ++i )
+ if ( aArr[i] == nUsage )
+ return i;
+ return 3;
+}
+
+static SvxPageUsage PosToPageUsage_Impl( sal_uInt16 nPos )
+{
+ if ( nPos >= SAL_N_ELEMENTS(aArr) )
+ return SvxPageUsage::NONE;
+ return aArr[nPos];
+}
+
+std::unique_ptr<PanelLayout> PageStylesPanel::Create(weld::Widget* pParent, SfxBindings* pBindings)
+{
+ if( pParent == nullptr )
+ throw ::com::sun::star::lang::IllegalArgumentException("no parent window given to PageStylesPanel::Create", nullptr, 0);
+ if( pBindings == nullptr )
+ throw ::com::sun::star::lang::IllegalArgumentException("no SfxBindings given to PageStylesPanel::Create", nullptr, 0);
+
+ return std::make_unique<PageStylesPanel>(pParent, pBindings);
+}
+
+PageStylesPanel::PageStylesPanel(
+ weld::Widget* pParent,
+ SfxBindings* pBindings
+ ) :
+ PanelLayout(pParent, "PageStylesPanel", "modules/swriter/ui/pagestylespanel.ui"),
+ mpBindings( pBindings ),
+ mpPageColumnItem( new SfxInt16Item(SID_ATTR_PAGE_COLUMN) ),
+ mpPageItem( new SvxPageItem(SID_ATTR_PAGE) ),
+ maPageColumnControl(SID_ATTR_PAGE_COLUMN, *pBindings, *this),
+ maPageNumFormatControl( SID_ATTR_PAGE, *pBindings, *this ),
+ maBgColorControl( SID_ATTR_PAGE_COLOR, *pBindings, *this ),
+ maBgHatchingControl( SID_ATTR_PAGE_HATCH, *pBindings, *this ),
+ maBgGradientControl( SID_ATTR_PAGE_GRADIENT, *pBindings, *this ),
+ maBgBitmapControl( SID_ATTR_PAGE_BITMAP, *pBindings, *this ),
+ maBgFillStyleControl(SID_ATTR_PAGE_FILLSTYLE, *pBindings, *this),
+ mxBgColorLB(new ColorListBox(m_xBuilder->weld_menu_button("lbcolor"), [this]{ return GetFrameWeld(); })),
+ mxBgHatchingLB(m_xBuilder->weld_combo_box("lbhatching")),
+ mxBgGradientLB(new ColorListBox(m_xBuilder->weld_menu_button("lbgradient"), [this]{ return GetFrameWeld(); })),
+ mxBgBitmapLB(m_xBuilder->weld_combo_box("lbbitmap")),
+ mxLayoutSelectLB(m_xBuilder->weld_combo_box("layoutbox")),
+ mxColumnCount(m_xBuilder->weld_combo_box("columnbox")),
+ mxNumberSelectLB(new SvxPageNumberListBox(m_xBuilder->weld_combo_box("numberbox"))),
+ mxBgFillType(m_xBuilder->weld_combo_box("bgselect")),
+ mxCustomEntry(m_xBuilder->weld_label("customlabel"))
+{
+ Initialize();
+}
+
+PageStylesPanel::~PageStylesPanel()
+{
+ mxColumnCount.reset();
+ mxNumberSelectLB.reset();
+ mxBgFillType.reset();
+ mxBgColorLB.reset();
+ mxBgHatchingLB.reset();
+ mxBgGradientLB.reset();
+ mxBgBitmapLB.reset();
+ mxLayoutSelectLB.reset();
+ mxCustomEntry.reset();
+
+ maBgBitmapControl.dispose();
+ maBgColorControl.dispose();
+ maBgFillStyleControl.dispose();
+ maBgGradientControl.dispose();
+ maBgHatchingControl.dispose();
+ maPageColumnControl.dispose();
+ maPageNumFormatControl.dispose();
+}
+
+void PageStylesPanel::Initialize()
+{
+ SvxFillTypeBox::Fill(*mxBgFillType);
+
+ m_aCustomEntry = mxCustomEntry->get_label();
+ mpBindings->Invalidate(SID_ATTR_PAGE_COLUMN);
+ mpBindings->Invalidate(SID_ATTR_PAGE);
+ mpBindings->Invalidate(SID_ATTR_PAGE_FILLSTYLE);
+ Update();
+
+ mxColumnCount->connect_changed( LINK(this, PageStylesPanel, ModifyColumnCountHdl) );
+ SvxNumOptionsTabPageHelper::GetI18nNumbering(mxNumberSelectLB->get_widget(), ::std::numeric_limits<sal_uInt16>::max());
+ mxNumberSelectLB->connect_changed( LINK(this, PageStylesPanel, ModifyNumberingHdl) );
+ mxLayoutSelectLB->connect_changed( LINK(this, PageStylesPanel, ModifyLayoutHdl) );
+ mxBgFillType->connect_changed( LINK(this, PageStylesPanel, ModifyFillStyleHdl));
+ mxBgColorLB->SetSelectHdl( LINK(this, PageStylesPanel, ModifyFillColorListHdl));
+ mxBgGradientLB->SetSelectHdl( LINK(this, PageStylesPanel, ModifyFillColorListHdl));
+ mxBgHatchingLB->connect_changed( LINK(this, PageStylesPanel, ModifyFillColorHdl));
+ mxBgBitmapLB->connect_changed( LINK(this, PageStylesPanel, ModifyFillColorHdl));
+}
+
+void PageStylesPanel::Update()
+{
+ const eFillStyle eXFS = static_cast<eFillStyle>(mxBgFillType->get_active());
+ SfxObjectShell* pSh = SfxObjectShell::Current();
+ if (!pSh)
+ {
+ SAL_WARN("sw.ui", "PageStylesPanel::Update(): no SfxObjectShell found");
+ return;
+ }
+ switch(eXFS)
+ {
+ case NONE:
+ {
+ mxBgColorLB->hide();
+ mxBgHatchingLB->hide();
+ mxBgGradientLB->hide();
+ mxBgBitmapLB->hide();
+ }
+ break;
+ case SOLID:
+ {
+ mxBgBitmapLB->hide();
+ mxBgGradientLB->hide();
+ mxBgHatchingLB->hide();
+ mxBgColorLB->show();
+ const Color aColor = GetColorSetOrDefault();
+ mxBgColorLB->SelectEntry(aColor);
+ }
+ break;
+ case GRADIENT:
+ {
+ mxBgBitmapLB->hide();
+ mxBgHatchingLB->hide();
+ mxBgColorLB->show();
+ mxBgGradientLB->show();
+
+ const basegfx::BGradient aBGradient = GetGradientSetOrDefault();
+ const Color aStartColor(aBGradient.GetColorStops().front().getStopColor());
+ mxBgColorLB->SelectEntry(aStartColor);
+ const Color aEndColor(aBGradient.GetColorStops().back().getStopColor());
+ mxBgGradientLB->SelectEntry(aEndColor);
+ }
+ break;
+
+ case HATCH:
+ {
+ mxBgColorLB->hide();
+ mxBgGradientLB->hide();
+ mxBgBitmapLB->hide();
+ mxBgHatchingLB->show();
+ mxBgHatchingLB->clear();
+ SvxFillAttrBox::Fill(*mxBgHatchingLB, pSh->GetItem(SID_HATCH_LIST)->GetHatchList());
+
+ const OUString aHatchName = GetHatchingSetOrDefault();
+ mxBgHatchingLB->set_active_text( aHatchName );
+ }
+ break;
+
+ case BITMAP:
+ case PATTERN:
+ {
+ mxBgColorLB->hide();
+ mxBgGradientLB->hide();
+ mxBgHatchingLB->hide();
+ mxBgBitmapLB->show();
+ mxBgBitmapLB->clear();
+ OUString aBitmapName;
+
+ if( eXFS == BITMAP )
+ {
+ SvxFillAttrBox::Fill(*mxBgBitmapLB, pSh->GetItem(SID_BITMAP_LIST)->GetBitmapList());
+ aBitmapName = GetBitmapSetOrDefault();
+ }
+ else
+ {
+ SvxFillAttrBox::Fill(*mxBgBitmapLB, pSh->GetItem(SID_PATTERN_LIST)->GetPatternList());
+ aBitmapName = GetPatternSetOrDefault();
+ }
+
+ mxBgBitmapLB->set_active_text( aBitmapName );
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // Need to do a relayouting, otherwise the panel size is not updated after show / hide controls
+ if (m_pPanel)
+ m_pPanel->TriggerDeckLayouting();
+}
+
+Color const & PageStylesPanel::GetColorSetOrDefault()
+{
+ if ( !mpBgColorItem )
+ mpBgColorItem.reset( new XFillColorItem( OUString(), Color(0x72, 0x9f, 0xcf) ) );
+
+ return mpBgColorItem->GetColorValue();
+}
+
+basegfx::BGradient const & PageStylesPanel::GetGradientSetOrDefault()
+{
+ if( !mpBgGradientItem )
+ {
+ basegfx::BGradient aGradient;
+ OUString aGradientName;
+ if (SfxObjectShell* pSh = SfxObjectShell::Current())
+ {
+ const SvxGradientListItem* pGradListItem = pSh->GetItem(SID_GRADIENT_LIST);
+ aGradient = pGradListItem->GetGradientList()->GetGradient(0)->GetGradient();
+ aGradientName = pGradListItem->GetGradientList()->GetGradient(0)->GetName();
+ }
+ mpBgGradientItem.reset( new XFillGradientItem( aGradientName, aGradient ) );
+ }
+
+ return mpBgGradientItem->GetGradientValue();
+}
+
+OUString const & PageStylesPanel::GetHatchingSetOrDefault()
+{
+ if( !mpBgHatchItem )
+ {
+ XHatch aHatch;
+ OUString aHatchName;
+ if (SfxObjectShell* pSh = SfxObjectShell::Current())
+ {
+ const SvxHatchListItem * pHatchListItem = pSh->GetItem(SID_HATCH_LIST);
+ aHatch = pHatchListItem->GetHatchList()->GetHatch(0)->GetHatch();
+ aHatchName = pHatchListItem->GetHatchList()->GetHatch(0)->GetName();
+ }
+ mpBgHatchItem.reset( new XFillHatchItem( aHatchName, aHatch ) );
+ }
+
+ return mpBgHatchItem->GetName();
+}
+
+OUString const & PageStylesPanel::GetBitmapSetOrDefault()
+{
+ if( !mpBgBitmapItem || mpBgBitmapItem->isPattern() )
+ {
+ GraphicObject aGraphObj;
+ OUString aBmpName;
+ if (SfxObjectShell* pSh = SfxObjectShell::Current())
+ {
+ const SvxBitmapListItem * pBmpListItem = pSh->GetItem(SID_BITMAP_LIST);
+ aGraphObj = pBmpListItem->GetBitmapList()->GetBitmap(0)->GetGraphicObject();
+ aBmpName = pBmpListItem->GetBitmapList()->GetBitmap(0)->GetName();
+ }
+ mpBgBitmapItem.reset( new XFillBitmapItem( aBmpName, aGraphObj ) );
+ }
+
+ return mpBgBitmapItem->GetName();
+}
+
+OUString const & PageStylesPanel::GetPatternSetOrDefault()
+{
+ if( !mpBgBitmapItem || !mpBgBitmapItem->isPattern() )
+ {
+ GraphicObject aGraphObj;
+ OUString aPatternName;
+ if (SfxObjectShell* pSh = SfxObjectShell::Current())
+ {
+ const SvxPatternListItem * pPatternListItem = pSh->GetItem(SID_PATTERN_LIST);
+ aGraphObj = pPatternListItem->GetPatternList()->GetBitmap(0)->GetGraphicObject();
+ aPatternName = pPatternListItem->GetPatternList()->GetBitmap(0)->GetName();
+ }
+ mpBgBitmapItem.reset( new XFillBitmapItem( aPatternName, aGraphObj ) );
+ }
+
+ return mpBgBitmapItem->GetName();
+}
+
+void PageStylesPanel::NotifyItemUpdate(
+ const sal_uInt16 nSid,
+ const SfxItemState eState,
+ const SfxPoolItem* pState)
+{
+ if (!mxColumnCount) //disposed
+ return;
+
+ switch(nSid)
+ {
+ case SID_ATTR_PAGE_COLUMN:
+ {
+ if ( eState >= SfxItemState::DEFAULT &&
+ dynamic_cast< const SfxInt16Item *>( pState ) )
+ {
+ mpPageColumnItem.reset( static_cast<SfxInt16Item*>(pState->Clone()) );
+ if(mpPageColumnItem->GetValue() <= 5)
+ {
+ mxColumnCount->set_active(mpPageColumnItem->GetValue() - 1);
+ int nIndex = mxColumnCount->find_text(m_aCustomEntry);
+ if (nIndex != -1)
+ mxColumnCount->remove(nIndex);
+ }
+ else
+ {
+ if (mxColumnCount->find_text(m_aCustomEntry) == -1)
+ mxColumnCount->append_text(m_aCustomEntry);
+ mxColumnCount->set_active_text(m_aCustomEntry);
+ }
+ }
+ }
+ break;
+
+ case SID_ATTR_PAGE:
+ {
+ if( eState >= SfxItemState::DEFAULT &&
+ dynamic_cast< const SvxPageItem*>( pState ) )
+ {
+ mpPageItem.reset( static_cast<SvxPageItem*>(pState->Clone()) );
+ SvxNumType eNumType = mpPageItem->GetNumType();
+ mxNumberSelectLB->set_active_id(eNumType);
+
+ SvxPageUsage nUse = mpPageItem->GetPageUsage();
+ mxLayoutSelectLB->set_active( PageUsageToPos_Impl( nUse ) );
+ }
+ }
+ break;
+
+ case SID_ATTR_PAGE_COLOR:
+ {
+ if(eState >= SfxItemState::DEFAULT)
+ {
+ mxBgFillType->set_active( static_cast<sal_Int32>(SOLID) );
+ mpBgColorItem.reset(pState ? static_cast< XFillColorItem* >(pState->Clone()) : nullptr);
+ Update();
+ }
+ }
+ break;
+
+ case SID_ATTR_PAGE_HATCH:
+ {
+ if(eState >= SfxItemState::DEFAULT)
+ {
+ mxBgFillType->set_active( static_cast<sal_Int32>(HATCH) );
+ mpBgHatchItem.reset(pState ? static_cast < XFillHatchItem* >(pState->Clone()) : nullptr);
+ Update();
+ }
+ }
+ break;
+
+ case SID_ATTR_PAGE_GRADIENT:
+ {
+ if(eState >= SfxItemState::DEFAULT)
+ {
+ mxBgFillType->set_active( static_cast<sal_Int32>(GRADIENT) );
+ mpBgGradientItem.reset(pState ? static_cast< XFillGradientItem* >(pState->Clone()) : nullptr);
+ Update();
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_BITMAP:
+ {
+ if(eState >= SfxItemState::DEFAULT)
+ {
+ mpBgBitmapItem.reset(pState ? static_cast< XFillBitmapItem* >(pState->Clone()) : nullptr);
+ if (mpBgBitmapItem)
+ {
+ if (mpBgBitmapItem->isPattern())
+ mxBgFillType->set_active( static_cast<sal_Int32>(PATTERN) );
+ else
+ mxBgFillType->set_active( static_cast<sal_Int32>(BITMAP) );
+ }
+ Update();
+ }
+ }
+ break;
+
+ case SID_ATTR_PAGE_FILLSTYLE:
+ {
+ const XFillStyleItem* pFillStyleItem = nullptr;
+ if (eState >= SfxItemState::DEFAULT)
+ pFillStyleItem = dynamic_cast< const XFillStyleItem* >(pState);
+ if (pFillStyleItem)
+ {
+ css::drawing::FillStyle eXFS = pFillStyleItem->GetValue();
+ switch(eXFS)
+ {
+ case drawing::FillStyle_NONE:
+ mxBgFillType->set_active( static_cast<sal_Int32>(NONE) );
+ break;
+ case drawing::FillStyle_SOLID:
+ mxBgFillType->set_active( static_cast<sal_Int32>(SOLID) );
+ break;
+ case drawing::FillStyle_GRADIENT:
+ mxBgFillType->set_active( static_cast<sal_Int32>(GRADIENT) );
+ break;
+ case drawing::FillStyle_HATCH:
+ mxBgFillType->set_active( static_cast<sal_Int32>(HATCH) );
+ break;
+ case drawing::FillStyle_BITMAP:
+ if (mpBgBitmapItem->isPattern())
+ mxBgFillType->set_active( static_cast<sal_Int32>(PATTERN) );
+ else
+ mxBgFillType->set_active( static_cast<sal_Int32>(BITMAP) );
+ break;
+ default:
+ break;
+ }
+ Update();
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+IMPL_LINK_NOARG( PageStylesPanel, ModifyColumnCountHdl, weld::ComboBox&, void )
+{
+ sal_uInt16 nColumnType = mxColumnCount->get_active() + 1;
+ mpPageColumnItem->SetValue( nColumnType );
+ mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_COLUMN,
+ SfxCallMode::RECORD, { mpPageColumnItem.get() });
+}
+
+IMPL_LINK_NOARG( PageStylesPanel, ModifyNumberingHdl, weld::ComboBox&, void )
+{
+ SvxNumType nEntryData = mxNumberSelectLB->get_active_id();
+ mpPageItem->SetNumType(nEntryData);
+ mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_PAGE, SfxCallMode::RECORD, { mpPageItem.get() });
+}
+
+IMPL_LINK_NOARG( PageStylesPanel, ModifyLayoutHdl, weld::ComboBox&, void )
+{
+ sal_uInt16 nUse = mxLayoutSelectLB->get_active();
+ mpPageItem->SetPageUsage(PosToPageUsage_Impl(nUse));
+ mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_PAGE, SfxCallMode::RECORD, { mpPageItem.get() });
+}
+
+IMPL_LINK_NOARG(PageStylesPanel, ModifyFillStyleHdl, weld::ComboBox&, void)
+{
+ const eFillStyle eXFS = static_cast<eFillStyle>(mxBgFillType->get_active());
+ Update();
+
+ switch (eXFS)
+ {
+ case NONE:
+ {
+ const XFillStyleItem aXFillStyleItem(drawing::FillStyle_NONE);
+ GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_FILLSTYLE, SfxCallMode::RECORD, { &aXFillStyleItem });
+ }
+ break;
+
+ case SOLID:
+ {
+ XFillColorItem aItem( OUString(), mpBgColorItem->GetColorValue() );
+ GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_COLOR, SfxCallMode::RECORD, { &aItem });
+ }
+ break;
+
+ case GRADIENT:
+ {
+ XFillGradientItem aItem( mpBgGradientItem->GetName(), mpBgGradientItem->GetGradientValue() );
+ GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_GRADIENT, SfxCallMode::RECORD, { &aItem });
+ }
+ break;
+
+ case HATCH:
+ {
+ XFillHatchItem aItem( mpBgHatchItem->GetName(), mpBgHatchItem->GetHatchValue() );
+ GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_HATCH, SfxCallMode::RECORD, { &aItem });
+ }
+ break;
+
+ case BITMAP:
+ case PATTERN:
+ {
+ XFillBitmapItem aItem( mpBgBitmapItem->GetName(), mpBgBitmapItem->GetGraphicObject() );
+ GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_BITMAP, SfxCallMode::RECORD, { &aItem });
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void PageStylesPanel::ModifyFillColor()
+{
+ const eFillStyle eXFS = static_cast<eFillStyle>(mxBgFillType->get_active());
+ SfxObjectShell* pSh = SfxObjectShell::Current();
+ switch(eXFS)
+ {
+ case SOLID:
+ {
+ auto aNamedColor = mxBgColorLB->GetSelectedEntry();
+ XFillColorItem aItem(OUString(), aNamedColor.m_aColor);
+ aItem.setComplexColor(aNamedColor.getComplexColor());
+ aItem.setComplexColor(mxBgColorLB->GetSelectedEntry().getComplexColor());
+ GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_COLOR, SfxCallMode::RECORD, { &aItem });
+ }
+ break;
+ case GRADIENT:
+ {
+ basegfx::BGradient aGradient(
+ basegfx::BColorStops(
+ mxBgColorLB->GetSelectEntryColor().getBColor(),
+ mxBgGradientLB->GetSelectEntryColor().getBColor()));
+
+ XFillGradientItem aItem(aGradient);
+ GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_GRADIENT, SfxCallMode::RECORD, { &aItem });
+ }
+ break;
+ case HATCH:
+ if (pSh)
+ {
+ const SvxHatchListItem * pHatchListItem = pSh->GetItem(SID_HATCH_LIST);
+ sal_uInt16 nPos = mxBgHatchingLB->get_active();
+ XHatch aHatch = pHatchListItem->GetHatchList()->GetHatch(nPos)->GetHatch();
+ const OUString aHatchName = pHatchListItem->GetHatchList()->GetHatch(nPos)->GetName();
+
+ XFillHatchItem aItem(aHatchName, aHatch);
+ GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_HATCH, SfxCallMode::RECORD, { &aItem });
+ }
+ break;
+ case BITMAP:
+ case PATTERN:
+ if (pSh)
+ {
+ sal_Int16 nPos = mxBgBitmapLB->get_active();
+ GraphicObject aBitmap;
+ OUString aBitmapName;
+
+ if ( eXFS == BITMAP )
+ {
+ SvxBitmapListItem const * pBitmapListItem = pSh->GetItem(SID_BITMAP_LIST);
+ aBitmap = pBitmapListItem->GetBitmapList()->GetBitmap(nPos)->GetGraphicObject();
+ aBitmapName = pBitmapListItem->GetBitmapList()->GetBitmap(nPos)->GetName();
+ }
+ else
+ {
+ SvxPatternListItem const * pPatternListItem = pSh->GetItem(SID_PATTERN_LIST);
+ aBitmap = pPatternListItem->GetPatternList()->GetBitmap(nPos)->GetGraphicObject();
+ aBitmapName = pPatternListItem->GetPatternList()->GetBitmap(nPos)->GetName();
+ }
+
+ XFillBitmapItem aItem(aBitmapName, aBitmap);
+ GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_BITMAP, SfxCallMode::RECORD, { &aItem });
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+IMPL_LINK_NOARG(PageStylesPanel, ModifyFillColorHdl, weld::ComboBox&, void)
+{
+ ModifyFillColor();
+}
+
+IMPL_LINK_NOARG(PageStylesPanel, ModifyFillColorListHdl, ColorListBox&, void)
+{
+ ModifyFillColor();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/PageStylesPanel.hxx b/sw/source/uibase/sidebar/PageStylesPanel.hxx
new file mode 100644
index 0000000000..5395b2784e
--- /dev/null
+++ b/sw/source/uibase/sidebar/PageStylesPanel.hxx
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGESTYLESPANEL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGESTYLESPANEL_HXX
+
+#include <memory>
+
+#include <sfx2/sidebar/PanelLayout.hxx>
+#include <sfx2/sidebar/ControllerItem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/poolitem.hxx>
+#include <svx/xbtmpit.hxx>
+#include <svx/xflclit.hxx>
+#include <svx/xflgrit.hxx>
+#include <svx/xflhtit.hxx>
+#include <svx/pageitem.hxx>
+#include <svx/pagenumberlistbox.hxx>
+
+class List;
+class ColorListBox;
+namespace sw::sidebar {
+
+class PageStylesPanel:
+ public PanelLayout,
+ public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface
+{
+public:
+ static std::unique_ptr<PanelLayout> Create(
+ weld::Widget* pParent,
+ SfxBindings* pBindings);
+
+ virtual void NotifyItemUpdate(
+ const sal_uInt16 nSId,
+ const SfxItemState eState,
+ const SfxPoolItem* pState) override;
+
+ virtual void GetControlState(
+ const sal_uInt16 /*nSId*/,
+ boost::property_tree::ptree& /*rState*/) override {};
+
+ SfxBindings* GetBindings() const { return mpBindings; }
+ PageStylesPanel(
+ weld::Widget* pParent,
+ SfxBindings* pBindings);
+ virtual ~PageStylesPanel() override;
+
+private:
+
+ SfxBindings* mpBindings;
+
+ ::std::unique_ptr<SfxInt16Item> mpPageColumnItem;
+ ::std::unique_ptr<SvxPageItem> mpPageItem;
+ ::std::unique_ptr<XFillColorItem> mpBgColorItem;
+ ::std::unique_ptr<XFillGradientItem> mpBgGradientItem;
+ ::std::unique_ptr<XFillHatchItem> mpBgHatchItem;
+ ::std::unique_ptr<XFillBitmapItem> mpBgBitmapItem;
+
+ ::sfx2::sidebar::ControllerItem maPageColumnControl;
+ ::sfx2::sidebar::ControllerItem maPageNumFormatControl;
+ ::sfx2::sidebar::ControllerItem maBgColorControl;
+ ::sfx2::sidebar::ControllerItem maBgHatchingControl;
+ ::sfx2::sidebar::ControllerItem maBgGradientControl;
+ ::sfx2::sidebar::ControllerItem maBgBitmapControl;
+ ::sfx2::sidebar::ControllerItem maBgFillStyleControl;
+
+ std::unique_ptr<ColorListBox> mxBgColorLB;
+ std::unique_ptr<weld::ComboBox> mxBgHatchingLB;
+ std::unique_ptr<ColorListBox> mxBgGradientLB;
+ std::unique_ptr<weld::ComboBox> mxBgBitmapLB;
+ std::unique_ptr<weld::ComboBox> mxLayoutSelectLB;
+ std::unique_ptr<weld::ComboBox> mxColumnCount;
+ std::unique_ptr<SvxPageNumberListBox> mxNumberSelectLB;
+ std::unique_ptr<weld::ComboBox> mxBgFillType;
+ std::unique_ptr<weld::Label> mxCustomEntry;
+ OUString m_aCustomEntry;
+
+ void Initialize();
+ void Update();
+ Color const & GetColorSetOrDefault();
+ basegfx::BGradient const & GetGradientSetOrDefault();
+ OUString const & GetHatchingSetOrDefault();
+ OUString const & GetBitmapSetOrDefault();
+ OUString const & GetPatternSetOrDefault();
+
+ void ModifyFillColor();
+
+ DECL_LINK( ModifyColumnCountHdl, weld::ComboBox&, void );
+ DECL_LINK( ModifyNumberingHdl, weld::ComboBox&, void );
+ DECL_LINK( ModifyLayoutHdl, weld::ComboBox&, void );
+ DECL_LINK( ModifyFillStyleHdl, weld::ComboBox&, void );
+ DECL_LINK( ModifyFillColorHdl, weld::ComboBox&, void );
+ DECL_LINK( ModifyFillColorListHdl, ColorListBox&, void );
+};
+
+} //end of namespace sw::sidebar
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/StylePresetsPanel.cxx b/sw/source/uibase/sidebar/StylePresetsPanel.cxx
new file mode 100644
index 0000000000..ff05d11cfe
--- /dev/null
+++ b/sw/source/uibase/sidebar/StylePresetsPanel.cxx
@@ -0,0 +1,205 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 "StylePresetsPanel.hxx"
+
+#include <vcl/image.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/virdev.hxx>
+
+#include <sfx2/objsh.hxx>
+#include <sfx2/StylePreviewRenderer.hxx>
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+#include <sfx2/doctempl.hxx>
+
+#include <shellio.hxx>
+#include <docsh.hxx>
+
+#include <sfx2/docfile.hxx>
+
+namespace sw::sidebar {
+
+namespace {
+
+void renderPreview(sfx2::StyleManager* pStyleManager, OutputDevice& aOutputDevice,
+ std::u16string_view sName, sal_Int32 nHeight, tools::Rectangle const & aRect)
+{
+ SfxStyleSheetBase* pStyleSheet = pStyleManager->Search(sName, SfxStyleFamily::Para);
+
+ if (pStyleSheet)
+ {
+ std::unique_ptr<sfx2::StylePreviewRenderer> pStylePreviewRenderer
+ = pStyleManager->CreateStylePreviewRenderer(aOutputDevice, pStyleSheet, nHeight);
+ pStylePreviewRenderer->recalculate();
+ pStylePreviewRenderer->render(aRect, sfx2::StylePreviewRenderer::RenderAlign::TOP);
+ }
+}
+
+BitmapEx GenerateStylePreview(SfxObjectShell& rSource, OUString const & aName)
+{
+ sfx2::StyleManager* pStyleManager = rSource.GetStyleManager();
+
+ ScopedVclPtrInstance<VirtualDevice> pVirtualDev(*Application::GetDefaultDevice());
+
+ float fScalingFactor = pVirtualDev->GetDPIScaleFactor();
+
+ sal_Int32 nMargin = 6 * fScalingFactor;
+
+ sal_Int32 nPreviewWidth = 144 * fScalingFactor;
+
+ sal_Int32 nNameHeight = 16 * fScalingFactor;
+ sal_Int32 nTitleHeight = 32 * fScalingFactor;
+ sal_Int32 nHeadingHeight = 24 * fScalingFactor;
+ sal_Int32 nTextBodyHeight = 16 * fScalingFactor;
+ sal_Int32 nBottomMargin = 2 * fScalingFactor;
+
+ sal_Int32 nNameFontSize = 12 * fScalingFactor;
+
+ sal_Int32 nPreviewHeight = nNameHeight + nTitleHeight + nHeadingHeight + nTextBodyHeight + nBottomMargin;
+
+ Size aSize(nPreviewWidth, nPreviewHeight);
+
+ pVirtualDev->SetOutputSizePixel(aSize);
+
+ pVirtualDev->SetLineColor(COL_LIGHTGRAY);
+ pVirtualDev->SetFillColor();
+
+ tools::Long y = 0;
+ {
+ pVirtualDev->SetFillColor(COL_LIGHTGRAY);
+ tools::Rectangle aNameRect(0, y, nPreviewWidth, nNameHeight);
+ pVirtualDev->DrawRect(aNameRect);
+
+ vcl::Font aFont;
+ aFont.SetFontSize(Size(0, nNameFontSize));
+
+ pVirtualDev->SetFont(aFont);
+
+ Size aTextSize(pVirtualDev->GetTextWidth(aName), pVirtualDev->GetTextHeight());
+
+ Point aPoint((aNameRect.GetWidth() / 2.0) - (aTextSize.Width() / 2.0),
+ y + (aNameRect.GetHeight() / 2.0) - (aTextSize.Height() / 2.0));
+
+ pVirtualDev->DrawText(aPoint, aName);
+
+ y += nNameHeight;
+ }
+
+ {
+ tools::Rectangle aRenderRect(Point(nMargin, y), aSize);
+ renderPreview(pStyleManager, *pVirtualDev, u"Title", nTitleHeight, aRenderRect);
+ y += nTitleHeight;
+ }
+
+ {
+ tools::Rectangle aRenderRect(Point(nMargin, y), aSize);
+ renderPreview(pStyleManager, *pVirtualDev, u"Heading 1", nHeadingHeight, aRenderRect);
+ y += nHeadingHeight;
+ }
+ {
+ tools::Rectangle aRenderRect(Point(nMargin, y), aSize);
+ renderPreview(pStyleManager, *pVirtualDev, u"Body Text", nTextBodyHeight, aRenderRect);
+ }
+
+ return pVirtualDev->GetBitmapEx(Point(), aSize);
+}
+
+BitmapEx CreatePreview(OUString const & aUrl, OUString const & aName)
+{
+ if (SfxObjectShell* pObjectShell = SfxObjectShell::Current())
+ {
+ SfxMedium aMedium(aUrl, StreamMode::STD_READWRITE);
+ SfxObjectShellLock xTemplDoc = SfxObjectShell::CreateObjectByFactoryName(pObjectShell->GetFactory().GetFactoryName(), SfxObjectCreateMode::ORGANIZER);
+ xTemplDoc->DoInitNew();
+ if (xTemplDoc->LoadFrom(aMedium))
+ return GenerateStylePreview(*xTemplDoc, aName);
+ }
+ return BitmapEx();
+}
+
+}
+
+std::unique_ptr<PanelLayout> StylePresetsPanel::Create(weld::Widget* pParent)
+{
+ if (pParent == nullptr)
+ throw css::lang::IllegalArgumentException("no parent Window given to StylePresetsPanel::Create", nullptr, 0);
+
+ return std::make_unique<StylePresetsPanel>(pParent);
+}
+
+StylePresetsPanel::StylePresetsPanel(weld::Widget* pParent)
+ : PanelLayout(pParent, "StylePresetsPanel", "modules/swriter/ui/sidebarstylepresets.ui")
+ , mxValueSet(new ValueSet(nullptr))
+ , mxValueSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *mxValueSet))
+{
+ mxValueSet->SetColCount(2);
+
+ mxValueSet->SetColor(Application::GetSettings().GetStyleSettings().GetFaceColor());
+ mxValueSet->SetDoubleClickHdl(LINK(this, StylePresetsPanel, DoubleClickHdl));
+
+ RefreshList();
+}
+
+void StylePresetsPanel::RefreshList()
+{
+ SfxDocumentTemplates aTemplates;
+ sal_uInt16 nCount = aTemplates.GetRegionCount();
+ for (sal_uInt16 i = 0; i < nCount; ++i)
+ {
+ OUString aRegionName(aTemplates.GetFullRegionName(i));
+ if (aRegionName == "Styles")
+ {
+ for (sal_uInt16 j = 0; j < aTemplates.GetCount(i); ++j)
+ {
+ OUString aName = aTemplates.GetName(i,j);
+ OUString aURL = aTemplates.GetPath(i,j);
+ BitmapEx aPreview = CreatePreview(aURL, aName);
+ sal_uInt16 nId = j + 1;
+ mxValueSet->InsertItem(nId, Image(aPreview), aName);
+ maTemplateEntries.push_back(std::make_unique<TemplateEntry>(aURL));
+ mxValueSet->SetItemData(nId, maTemplateEntries.back().get());
+ }
+ mxValueSet->SetOptimalSize();
+ }
+ }
+}
+
+StylePresetsPanel::~StylePresetsPanel()
+{
+}
+
+IMPL_LINK_NOARG(StylePresetsPanel, DoubleClickHdl, ValueSet*, void)
+{
+ sal_Int32 nItemId = mxValueSet->GetSelectedItemId();
+ TemplateEntry* pEntry = static_cast<TemplateEntry*>(mxValueSet->GetItemData(nItemId));
+
+ if (SwDocShell* pDocSh = static_cast<SwDocShell*>(SfxObjectShell::Current()))
+ {
+ SwgReaderOption aOption;
+ aOption.SetTextFormats(true);
+ aOption.SetNumRules(true);
+ pDocSh->LoadStylesFromFile(pEntry->maURL, aOption, false);
+ }
+}
+
+void StylePresetsPanel::NotifyItemUpdate(const sal_uInt16 /*nSId*/,
+ const SfxItemState /*eState*/,
+ const SfxPoolItem* /*pState*/)
+{
+}
+
+} // end of namespace ::sw::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/StylePresetsPanel.hxx b/sw/source/uibase/sidebar/StylePresetsPanel.hxx
new file mode 100644
index 0000000000..f912688863
--- /dev/null
+++ b/sw/source/uibase/sidebar/StylePresetsPanel.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <memory>
+
+#include <sfx2/sidebar/PanelLayout.hxx>
+#include <sfx2/sidebar/ControllerItem.hxx>
+#include <svtools/valueset.hxx>
+#include <utility>
+
+namespace sw::sidebar {
+
+class StylePresetsPanel : public PanelLayout,
+ public sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface
+{
+public:
+ static std::unique_ptr<PanelLayout> Create(weld::Widget* pParent);
+
+ StylePresetsPanel(weld::Widget* pParent);
+
+ virtual ~StylePresetsPanel() override;
+
+ virtual void NotifyItemUpdate(const sal_uInt16 nSId,
+ const SfxItemState eState,
+ const SfxPoolItem* pState) override;
+
+ virtual void GetControlState(
+ const sal_uInt16 /*nSId*/,
+ boost::property_tree::ptree& /*rState*/) override {};
+
+private:
+ struct TemplateEntry
+ {
+ explicit TemplateEntry(OUString aURL)
+ : maURL(std::move(aURL))
+ {}
+
+ OUString maURL;
+ };
+
+ void RefreshList();
+
+ std::unique_ptr<ValueSet> mxValueSet;
+ std::unique_ptr<weld::CustomWeld> mxValueSetWin;
+
+ std::vector<std::unique_ptr<TemplateEntry>> maTemplateEntries;
+
+ DECL_LINK(DoubleClickHdl, ValueSet*, void);
+};
+
+} // end of namespace sw::sidebar
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/SwPanelFactory.cxx b/sw/source/uibase/sidebar/SwPanelFactory.cxx
new file mode 100644
index 0000000000..5ae3a781bc
--- /dev/null
+++ b/sw/source/uibase/sidebar/SwPanelFactory.cxx
@@ -0,0 +1,220 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/ui/XUIElementFactory.hpp>
+
+#include "A11yCheckIssuesPanel.hxx"
+#include "ThemePanel.hxx"
+#include "StylePresetsPanel.hxx"
+#include "PageStylesPanel.hxx"
+#include "PageFormatPanel.hxx"
+#include "PageHeaderPanel.hxx"
+#include "PageFooterPanel.hxx"
+#include "WrapPropertyPanel.hxx"
+#include "WriterInspectorTextPanel.hxx"
+#include "TableEditPanel.hxx"
+#include <navipi.hxx>
+#include <redlndlg.hxx>
+
+#include <sfx2/sidebar/SidebarPanelBase.hxx>
+#include <vcl/weldutils.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/compbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+
+using namespace css;
+using namespace css::uno;
+
+namespace {
+
+typedef comphelper::WeakComponentImplHelper <
+ css::ui::XUIElementFactory, css::lang::XServiceInfo
+ > PanelFactoryInterfaceBase;
+
+class SwPanelFactory final : public PanelFactoryInterfaceBase
+{
+private:
+ SwPanelFactory(SwPanelFactory const&) = delete;
+ SwPanelFactory& operator=(SwPanelFactory const&) = delete;
+
+public:
+ SwPanelFactory();
+
+ // XUIElementFactory
+ css::uno::Reference<css::ui::XUIElement> SAL_CALL createUIElement(
+ const OUString& rsResourceURL,
+ const css::uno::Sequence<css::beans::PropertyValue>& rArguments) override;
+
+ OUString SAL_CALL getImplementationName() override
+ { return "org.apache.openoffice.comp.sw.sidebar.SwPanelFactory"; }
+
+ sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
+ { return cppu::supportsService(this, ServiceName); }
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
+ { return {"com.sun.star.ui.UIElementFactory"}; }
+};
+
+SwPanelFactory::SwPanelFactory()
+{
+}
+
+Reference<ui::XUIElement> SAL_CALL SwPanelFactory::createUIElement (
+ const OUString& rsResourceURL,
+ const css::uno::Sequence<css::beans::PropertyValue>& rArguments)
+{
+ Reference<ui::XUIElement> xElement;
+
+ const ::comphelper::NamedValueCollection aArguments (rArguments);
+ Reference<frame::XFrame> xFrame (aArguments.getOrDefault("Frame", Reference<frame::XFrame>()));
+ Reference<awt::XWindow> xParentWindow (aArguments.getOrDefault("ParentWindow", Reference<awt::XWindow>()));
+ const sal_uInt64 nBindingsValue (aArguments.getOrDefault("SfxBindings", sal_uInt64(0)));
+ SfxBindings* pBindings = reinterpret_cast<SfxBindings*>(nBindingsValue);
+
+ weld::Widget* pParent(nullptr);
+ if (weld::TransportAsXWindow* pTunnel = dynamic_cast<weld::TransportAsXWindow*>(xParentWindow.get()))
+ pParent = pTunnel->getWidget();
+
+ if (!pParent)
+ throw RuntimeException(
+ "PanelFactory::createUIElement called without ParentWindow",
+ nullptr);
+ if ( ! xFrame.is())
+ throw RuntimeException(
+ "PanelFactory::createUIElement called without Frame",
+ nullptr);
+ if (pBindings == nullptr)
+ throw RuntimeException(
+ "PanelFactory::createUIElement called without SfxBindings",
+ nullptr);
+
+ if(rsResourceURL.endsWith("/PageStylesPanel"))
+ {
+ std::unique_ptr<PanelLayout> xPanel = sw::sidebar::PageStylesPanel::Create( pParent, pBindings );
+ xElement = sfx2::sidebar::SidebarPanelBase::Create(
+ rsResourceURL,
+ xFrame,
+ std::move(xPanel),
+ ui::LayoutSize(-1,-1,-1));
+ }
+ else if(rsResourceURL.endsWith("/PageFormatPanel"))
+ {
+ std::unique_ptr<PanelLayout> xPanel = sw::sidebar::PageFormatPanel::Create( pParent, pBindings );
+ xElement = sfx2::sidebar::SidebarPanelBase::Create(
+ rsResourceURL,
+ xFrame,
+ std::move(xPanel),
+ ui::LayoutSize(-1,-1,-1));
+ }
+ else if(rsResourceURL.endsWith("/PageHeaderPanel"))
+ {
+ std::unique_ptr<PanelLayout> xPanel = sw::sidebar::PageHeaderPanel::Create( pParent, pBindings );
+ xElement = sfx2::sidebar::SidebarPanelBase::Create(
+ rsResourceURL,
+ xFrame,
+ std::move(xPanel),
+ ui::LayoutSize(-1,-1,-1));
+ }
+ else if(rsResourceURL.endsWith("/PageFooterPanel"))
+ {
+ std::unique_ptr<PanelLayout> xPanel = sw::sidebar::PageFooterPanel::Create( pParent, pBindings );
+ xElement = sfx2::sidebar::SidebarPanelBase::Create(
+ rsResourceURL,
+ xFrame,
+ std::move(xPanel),
+ ui::LayoutSize(-1,-1,-1));
+ }
+ else if (rsResourceURL.endsWith("/WrapPropertyPanel"))
+ {
+ std::unique_ptr<PanelLayout> xPanel = sw::sidebar::WrapPropertyPanel::Create( pParent, xFrame, pBindings );
+ xElement = sfx2::sidebar::SidebarPanelBase::Create(
+ rsResourceURL,
+ xFrame,
+ std::move(xPanel),
+ ui::LayoutSize(-1,-1,-1));
+ }
+ else if (rsResourceURL.endsWith("/NavigatorPanel"))
+ {
+ std::unique_ptr<PanelLayout> xPanel = SwNavigationPI::Create( pParent, xFrame, pBindings );
+ xElement = sfx2::sidebar::SidebarPanelBase::Create(
+ rsResourceURL,
+ xFrame,
+ std::move(xPanel),
+ ui::LayoutSize(0,-1,-1));
+ }
+ else if (rsResourceURL.endsWith("/ManageChangesPanel"))
+ {
+ auto xPanel = std::make_unique<SwRedlineAcceptPanel>(pParent);
+ xElement = sfx2::sidebar::SidebarPanelBase::Create(
+ rsResourceURL,
+ xFrame,
+ std::move(xPanel),
+ ui::LayoutSize(0,-1,-1));
+ }
+ else if (rsResourceURL.endsWith("/WriterInspectorTextPanel"))
+ {
+ std::unique_ptr<PanelLayout> xPanel = sw::sidebar::WriterInspectorTextPanel::Create(pParent);
+ xElement = sfx2::sidebar::SidebarPanelBase::Create(
+ rsResourceURL,
+ xFrame,
+ std::move(xPanel),
+ ui::LayoutSize(0,-1,-1));
+ }
+ else if (rsResourceURL.endsWith("/StylePresetsPanel"))
+ {
+ std::unique_ptr<PanelLayout> xPanel = sw::sidebar::StylePresetsPanel::Create(pParent);
+ xElement = sfx2::sidebar::SidebarPanelBase::Create(
+ rsResourceURL, xFrame, std::move(xPanel), ui::LayoutSize(-1,-1,-1));
+ }
+ else if (rsResourceURL.endsWith("/ThemePanel"))
+ {
+ std::unique_ptr<PanelLayout> xPanel = sw::sidebar::ThemePanel::Create(pParent);
+ xElement = sfx2::sidebar::SidebarPanelBase::Create(
+ rsResourceURL, xFrame, std::move(xPanel), ui::LayoutSize(-1,-1,-1));
+ }
+ else if (rsResourceURL.endsWith("/TableEditPanel"))
+ {
+ std::unique_ptr<PanelLayout> xPanel = sw::sidebar::TableEditPanel::Create(pParent, xFrame, pBindings );
+ xElement = sfx2::sidebar::SidebarPanelBase::Create(
+ rsResourceURL, xFrame, std::move(xPanel), ui::LayoutSize(-1,-1,-1));
+ }
+ else if (rsResourceURL.endsWith("/A11yCheckIssuesPanel"))
+ {
+ std::unique_ptr<PanelLayout> xPanel = sw::sidebar::A11yCheckIssuesPanel::Create(pParent, pBindings);
+ xElement = sfx2::sidebar::SidebarPanelBase::Create(
+ rsResourceURL, xFrame, std::move(xPanel), ui::LayoutSize(-1,-1,-1));
+ }
+
+ return xElement;
+}
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+org_apache_openoffice_comp_sw_sidebar_SwPanelFactory_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new SwPanelFactory());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/TableEditPanel.cxx b/sw/source/uibase/sidebar/TableEditPanel.cxx
new file mode 100644
index 0000000000..61dcd2d4e5
--- /dev/null
+++ b/sw/source/uibase/sidebar/TableEditPanel.cxx
@@ -0,0 +1,233 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 "TableEditPanel.hxx"
+#include <sal/config.h>
+#include <swtypes.hxx>
+#include <cmdid.h>
+#include <svl/intitem.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <svx/dlgctrl.hxx>
+#include <swmodule.hxx>
+#include <usrpref.hxx>
+#include <comphelper/lok.hxx>
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+namespace sw::sidebar
+{
+std::unique_ptr<PanelLayout>
+TableEditPanel::Create(weld::Widget* pParent,
+ const css::uno::Reference<css::frame::XFrame>& rxFrame,
+ SfxBindings* pBindings)
+{
+ if (pParent == nullptr)
+ throw css::lang::IllegalArgumentException(
+ "no parent Window given to TableEditPanel::Create", nullptr, 0);
+ if (!rxFrame.is())
+ throw css::lang::IllegalArgumentException("no XFrame given to TableEditPanel::Create",
+ nullptr, 1);
+
+ return std::make_unique<TableEditPanel>(pParent, rxFrame, pBindings);
+}
+
+void TableEditPanel::NotifyItemUpdate(const sal_uInt16 nSID, const SfxItemState eState,
+ const SfxPoolItem* pState)
+{
+ switch (nSID)
+ {
+ case SID_ATTR_TABLE_ROW_HEIGHT:
+ {
+ bool bDisabled = eState == SfxItemState::DISABLED;
+ m_aRowHeightEdit.set_sensitive(!bDisabled);
+
+ if (pState && eState >= SfxItemState::DEFAULT)
+ {
+ const SfxUInt32Item* pItem = static_cast<const SfxUInt32Item*>(pState);
+ if (pItem)
+ {
+ tools::Long nNewHeight = pItem->GetValue();
+ nNewHeight = m_aRowHeightEdit.normalize(nNewHeight);
+ m_aRowHeightEdit.set_value(nNewHeight, FieldUnit::TWIP);
+ }
+ }
+ else if (eState != SfxItemState::DISABLED)
+ m_aRowHeightEdit.set_text("");
+
+ break;
+ }
+ case SID_ATTR_TABLE_COLUMN_WIDTH:
+ {
+ bool bDisabled = eState == SfxItemState::DISABLED;
+ m_aColumnWidthEdit.set_sensitive(!bDisabled);
+
+ if (pState && eState >= SfxItemState::DEFAULT)
+ {
+ const SfxUInt32Item* pItem = static_cast<const SfxUInt32Item*>(pState);
+ if (pItem)
+ {
+ tools::Long nNewWidth = pItem->GetValue();
+ nNewWidth = m_aColumnWidthEdit.normalize(nNewWidth);
+ m_aColumnWidthEdit.set_value(nNewWidth, FieldUnit::TWIP);
+ }
+ }
+ else if (eState != SfxItemState::DISABLED)
+ m_aColumnWidthEdit.set_text("");
+
+ break;
+ }
+ }
+}
+
+TableEditPanel::TableEditPanel(weld::Widget* pParent,
+ const css::uno::Reference<css::frame::XFrame>& rxFrame,
+ SfxBindings* pBindings)
+ : PanelLayout(pParent, "TableEditPanel", "modules/swriter/ui/sidebartableedit.ui")
+ , m_pBindings(pBindings)
+ , m_aRowHeightEdit(m_xBuilder->weld_metric_spin_button("rowheight", FieldUnit::CM))
+ , m_aColumnWidthEdit(m_xBuilder->weld_metric_spin_button("columnwidth", FieldUnit::CM))
+ , m_xInsert(m_xBuilder->weld_toolbar("insert"))
+ , m_xInsertDispatch(new ToolbarUnoDispatcher(*m_xInsert, *m_xBuilder, rxFrame))
+ , m_xSelect(m_xBuilder->weld_toolbar("select"))
+ , m_xSelectDispatch(new ToolbarUnoDispatcher(*m_xSelect, *m_xBuilder, rxFrame))
+ , m_xRowSizing(m_xBuilder->weld_toolbar("rowsizing"))
+ , m_xRowSizingDispatch(new ToolbarUnoDispatcher(*m_xRowSizing, *m_xBuilder, rxFrame))
+ , m_xColumnSizing(m_xBuilder->weld_toolbar("columnsizing"))
+ , m_xColumnSizingDispatch(new ToolbarUnoDispatcher(*m_xColumnSizing, *m_xBuilder, rxFrame))
+ , m_xDelete(m_xBuilder->weld_toolbar("delete"))
+ , m_xDeleteDispatch(new ToolbarUnoDispatcher(*m_xDelete, *m_xBuilder, rxFrame))
+ , m_xSplitMerge(m_xBuilder->weld_toolbar("split_merge"))
+ , m_xSplitMergeDispatch(new ToolbarUnoDispatcher(*m_xSplitMerge, *m_xBuilder, rxFrame))
+ , m_xMisc(m_xBuilder->weld_toolbar("misc"))
+ , m_xMiscDispatch(new ToolbarUnoDispatcher(*m_xMisc, *m_xBuilder, rxFrame))
+ , m_aRowHeightController(SID_ATTR_TABLE_ROW_HEIGHT, *pBindings, *this)
+ , m_aColumnWidthController(SID_ATTR_TABLE_COLUMN_WIDTH, *pBindings, *this)
+ , m_aInsertRowsBeforeController(FN_TABLE_INSERT_ROW_BEFORE, *pBindings, *this)
+ , m_aInsertRowsAfterController(FN_TABLE_INSERT_ROW_AFTER, *pBindings, *this)
+ , m_aInsertColumnsBeforeController(FN_TABLE_INSERT_COL_BEFORE, *pBindings, *this)
+ , m_aInsertColumnsAfterController(FN_TABLE_INSERT_COL_AFTER, *pBindings, *this)
+ , m_aDeleteRowsController(FN_TABLE_DELETE_ROW, *pBindings, *this)
+ , m_aDeleteColumnsController(FN_TABLE_DELETE_COL, *pBindings, *this)
+ , m_aDeleteTableController(FN_TABLE_DELETE_TABLE, *pBindings, *this)
+ , m_aSetMinimalRowHeightController(SID_TABLE_MINIMAL_ROW_HEIGHT, *pBindings, *this)
+ , m_aSetOptimalRowHeightController(FN_TABLE_OPTIMAL_HEIGHT, *pBindings, *this)
+ , m_aDistributeRowsController(FN_TABLE_BALANCE_ROWS, *pBindings, *this)
+ , m_aSetMinimalColumnWidthController(SID_TABLE_MINIMAL_COLUMN_WIDTH, *pBindings, *this)
+ , m_aSetOptimalColumnWidthController(FN_TABLE_ADJUST_CELLS, *pBindings, *this)
+ , m_aDistributeColumnsController(FN_TABLE_BALANCE_CELLS, *pBindings, *this)
+ , m_aMergeCellsController(FN_TABLE_MERGE_CELLS, *pBindings, *this)
+{
+ // tdf#130197 Give this toolbar a width as if it had 5 entries (the parent
+ // grid has homogeneous width set so both columns will have the same
+ // width). This will align this TableEditPanel's columns with
+ // ParaPropertyPanel's columns
+ padWidthForSidebar(*m_xSplitMerge, rxFrame);
+
+ InitRowHeightToolitem();
+ InitColumnWidthToolitem();
+
+ if (comphelper::LibreOfficeKit::isActive())
+ m_xMisc->set_item_visible(".uno:InsertFormula", false);
+}
+
+void TableEditPanel::InitRowHeightToolitem()
+{
+ Link<weld::MetricSpinButton&, void> aLink = LINK(this, TableEditPanel, RowHeightMofiyHdl);
+ m_aRowHeightEdit.connect_value_changed(aLink);
+
+ FieldUnit eFieldUnit = SW_MOD()->GetUsrPref(false)->GetMetric();
+ m_aRowHeightEdit.SetFieldUnit(eFieldUnit);
+
+ m_aRowHeightEdit.set_min(MINLAY, FieldUnit::TWIP);
+ m_aRowHeightEdit.set_max(SAL_MAX_INT32, FieldUnit::TWIP);
+
+ limitWidthForSidebar(m_aRowHeightEdit);
+}
+
+void TableEditPanel::InitColumnWidthToolitem()
+{
+ Link<weld::MetricSpinButton&, void> aLink = LINK(this, TableEditPanel, ColumnWidthMofiyHdl);
+ m_aColumnWidthEdit.connect_value_changed(aLink);
+
+ FieldUnit eFieldUnit = SW_MOD()->GetUsrPref(false)->GetMetric();
+ m_aColumnWidthEdit.SetFieldUnit(eFieldUnit);
+
+ m_aColumnWidthEdit.set_min(MINLAY, FieldUnit::TWIP);
+ m_aColumnWidthEdit.set_max(SAL_MAX_INT32, FieldUnit::TWIP);
+
+ limitWidthForSidebar(m_aColumnWidthEdit);
+}
+
+TableEditPanel::~TableEditPanel()
+{
+ m_xMiscDispatch.reset();
+ m_xMisc.reset();
+
+ m_xSplitMergeDispatch.reset();
+ m_xSplitMerge.reset();
+
+ m_xDeleteDispatch.reset();
+ m_xDelete.reset();
+
+ m_xColumnSizingDispatch.reset();
+ m_xColumnSizing.reset();
+
+ m_xRowSizingDispatch.reset();
+ m_xRowSizing.reset();
+
+ m_xSelectDispatch.reset();
+ m_xSelect.reset();
+
+ m_xInsertDispatch.reset();
+ m_xInsert.reset();
+
+ m_aRowHeightController.dispose();
+ m_aColumnWidthController.dispose();
+ m_aInsertRowsBeforeController.dispose();
+ m_aInsertRowsAfterController.dispose();
+ m_aInsertColumnsBeforeController.dispose();
+ m_aInsertColumnsAfterController.dispose();
+ m_aDeleteRowsController.dispose();
+ m_aDeleteColumnsController.dispose();
+ m_aDeleteTableController.dispose();
+ m_aSetMinimalRowHeightController.dispose();
+ m_aSetOptimalRowHeightController.dispose();
+ m_aDistributeRowsController.dispose();
+ m_aSetMinimalColumnWidthController.dispose();
+ m_aSetOptimalColumnWidthController.dispose();
+ m_aDistributeColumnsController.dispose();
+ m_aMergeCellsController.dispose();
+}
+
+IMPL_LINK_NOARG(TableEditPanel, RowHeightMofiyHdl, weld::MetricSpinButton&, void)
+{
+ SwTwips nNewHeight = static_cast<SwTwips>(
+ m_aRowHeightEdit.denormalize(m_aRowHeightEdit.get_value(FieldUnit::TWIP)));
+ SfxUInt32Item aRowHeight(SID_ATTR_TABLE_ROW_HEIGHT);
+ aRowHeight.SetValue(nNewHeight);
+
+ m_pBindings->GetDispatcher()->ExecuteList(SID_ATTR_TABLE_ROW_HEIGHT, SfxCallMode::RECORD,
+ { &aRowHeight });
+}
+
+IMPL_LINK_NOARG(TableEditPanel, ColumnWidthMofiyHdl, weld::MetricSpinButton&, void)
+{
+ SwTwips nNewWidth = static_cast<SwTwips>(
+ m_aColumnWidthEdit.denormalize(m_aColumnWidthEdit.get_value(FieldUnit::TWIP)));
+ SfxUInt32Item aColumnWidth(SID_ATTR_TABLE_COLUMN_WIDTH);
+ aColumnWidth.SetValue(nNewWidth);
+
+ m_pBindings->GetDispatcher()->ExecuteList(SID_ATTR_TABLE_COLUMN_WIDTH, SfxCallMode::RECORD,
+ { &aColumnWidth });
+}
+} // end of namespace ::sw::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/TableEditPanel.hxx b/sw/source/uibase/sidebar/TableEditPanel.hxx
new file mode 100644
index 0000000000..140de86538
--- /dev/null
+++ b/sw/source/uibase/sidebar/TableEditPanel.hxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <com/sun/star/frame/XFrame.hpp>
+#include <sfx2/sidebar/PanelLayout.hxx>
+#include <sfx2/sidebar/ControllerItem.hxx>
+#include <sfx2/weldutils.hxx>
+#include <svx/relfld.hxx>
+
+namespace sw::sidebar
+{
+class TableEditPanel : public PanelLayout,
+ public sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface
+{
+public:
+ static std::unique_ptr<PanelLayout>
+ Create(weld::Widget* pParent, const css::uno::Reference<css::frame::XFrame>& rxFrame,
+ SfxBindings* pBindings);
+
+ TableEditPanel(weld::Widget* pParent, const css::uno::Reference<css::frame::XFrame>& rxFrame,
+ SfxBindings* pBindings);
+ virtual ~TableEditPanel() override;
+
+ virtual void NotifyItemUpdate(const sal_uInt16 nSId, const SfxItemState eState,
+ const SfxPoolItem* pState) override;
+
+ virtual void GetControlState(const sal_uInt16 /*nSId*/,
+ boost::property_tree::ptree& /*rState*/) override{};
+
+private:
+ void InitRowHeightToolitem();
+ void InitColumnWidthToolitem();
+
+ SfxBindings* m_pBindings;
+
+ SvxRelativeField m_aRowHeightEdit;
+ SvxRelativeField m_aColumnWidthEdit;
+ std::unique_ptr<weld::Toolbar> m_xInsert;
+ std::unique_ptr<ToolbarUnoDispatcher> m_xInsertDispatch;
+ std::unique_ptr<weld::Toolbar> m_xSelect;
+ std::unique_ptr<ToolbarUnoDispatcher> m_xSelectDispatch;
+ std::unique_ptr<weld::Toolbar> m_xRowSizing;
+ std::unique_ptr<ToolbarUnoDispatcher> m_xRowSizingDispatch;
+ std::unique_ptr<weld::Toolbar> m_xColumnSizing;
+ std::unique_ptr<ToolbarUnoDispatcher> m_xColumnSizingDispatch;
+ std::unique_ptr<weld::Toolbar> m_xDelete;
+ std::unique_ptr<ToolbarUnoDispatcher> m_xDeleteDispatch;
+ std::unique_ptr<weld::Toolbar> m_xSplitMerge;
+ std::unique_ptr<ToolbarUnoDispatcher> m_xSplitMergeDispatch;
+ std::unique_ptr<weld::Toolbar> m_xMisc;
+ std::unique_ptr<ToolbarUnoDispatcher> m_xMiscDispatch;
+
+ ::sfx2::sidebar::ControllerItem m_aRowHeightController;
+ ::sfx2::sidebar::ControllerItem m_aColumnWidthController;
+ ::sfx2::sidebar::ControllerItem m_aInsertRowsBeforeController;
+ ::sfx2::sidebar::ControllerItem m_aInsertRowsAfterController;
+ ::sfx2::sidebar::ControllerItem m_aInsertColumnsBeforeController;
+ ::sfx2::sidebar::ControllerItem m_aInsertColumnsAfterController;
+ ::sfx2::sidebar::ControllerItem m_aDeleteRowsController;
+ ::sfx2::sidebar::ControllerItem m_aDeleteColumnsController;
+ ::sfx2::sidebar::ControllerItem m_aDeleteTableController;
+ ::sfx2::sidebar::ControllerItem m_aSetMinimalRowHeightController;
+ ::sfx2::sidebar::ControllerItem m_aSetOptimalRowHeightController;
+ ::sfx2::sidebar::ControllerItem m_aDistributeRowsController;
+ ::sfx2::sidebar::ControllerItem m_aSetMinimalColumnWidthController;
+ ::sfx2::sidebar::ControllerItem m_aSetOptimalColumnWidthController;
+ ::sfx2::sidebar::ControllerItem m_aDistributeColumnsController;
+ ::sfx2::sidebar::ControllerItem m_aMergeCellsController;
+
+ DECL_LINK(RowHeightMofiyHdl, weld::MetricSpinButton&, void);
+ DECL_LINK(ColumnWidthMofiyHdl, weld::MetricSpinButton&, void);
+};
+
+} // end of namespace sw::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/ThemePanel.cxx b/sw/source/uibase/sidebar/ThemePanel.cxx
new file mode 100644
index 0000000000..55853a544f
--- /dev/null
+++ b/sw/source/uibase/sidebar/ThemePanel.cxx
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 "ThemePanel.hxx"
+#include <sal/config.h>
+
+#include <doc.hxx>
+#include <docsh.hxx>
+#include <drawdoc.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <ThemeColorChanger.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <docmodel/theme/Theme.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/dialog/ThemeColorValueSet.hxx>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+namespace sw::sidebar
+{
+
+std::unique_ptr<PanelLayout> ThemePanel::Create(weld::Widget* pParent)
+{
+ if (pParent == nullptr)
+ throw css::lang::IllegalArgumentException("no parent Window given to PagePropertyPanel::Create", nullptr, 0);
+
+ return std::make_unique<ThemePanel>(pParent);
+}
+
+ThemePanel::ThemePanel(weld::Widget* pParent)
+ : PanelLayout(pParent, "ThemePanel", "modules/swriter/ui/sidebartheme.ui")
+ , mxValueSetColors(new svx::ThemeColorValueSet)
+ , mxValueSetColorsWin(new weld::CustomWeld(*m_xBuilder, "valueset_colors", *mxValueSetColors))
+ , mxApplyButton(m_xBuilder->weld_button("apply"))
+{
+ mxValueSetColors->SetColCount(2);
+ mxValueSetColors->SetLineCount(3);
+ mxValueSetColors->SetColor(Application::GetSettings().GetStyleSettings().GetFaceColor());
+
+ mxApplyButton->connect_clicked(LINK(this, ThemePanel, ClickHdl));
+ mxValueSetColors->SetDoubleClickHdl(LINK(this, ThemePanel, DoubleClickValueSetHdl));
+
+ auto const& rColorSets = svx::ColorSets::get();
+ for (model::ColorSet const& rColorSet : rColorSets.getColorSetVector())
+ {
+ mxValueSetColors->insert(rColorSet);
+ }
+
+ mxValueSetColors->SetOptimalSize();
+
+ if (!rColorSets.getColorSetVector().empty())
+ mxValueSetColors->SelectItem(1); // ItemId 1, position 0
+}
+
+ThemePanel::~ThemePanel()
+{
+ mxValueSetColorsWin.reset();
+ mxValueSetColors.reset();
+ mxApplyButton.reset();
+}
+
+IMPL_LINK_NOARG(ThemePanel, ClickHdl, weld::Button&, void)
+{
+ DoubleClickHdl();
+}
+
+IMPL_LINK_NOARG(ThemePanel, DoubleClickValueSetHdl, ValueSet*, void)
+{
+ DoubleClickHdl();
+}
+
+IMPL_LINK_NOARG(ThemePanel, DoubleClickHdl, weld::TreeView&, bool)
+{
+ DoubleClickHdl();
+ return true;
+}
+
+void ThemePanel::DoubleClickHdl()
+{
+ SwDocShell* pDocSh = static_cast<SwDocShell*>(SfxObjectShell::Current());
+ if (!pDocSh)
+ return;
+
+ sal_uInt32 nItemId = mxValueSetColors->GetSelectedItemId();
+ if (!nItemId)
+ return;
+ sal_uInt32 nIndex = nItemId - 1;
+
+ auto const& rColorSets = svx::ColorSets::get();
+ model::ColorSet const& rColorSet = rColorSets.getColorSet(nIndex);
+
+ ThemeColorChanger aChanger(pDocSh);
+ aChanger.apply(std::make_shared<model::ColorSet>(rColorSet));
+}
+
+void ThemePanel::NotifyItemUpdate(const sal_uInt16 /*nSId*/,
+ const SfxItemState /*eState*/,
+ const SfxPoolItem* /*pState*/)
+{
+}
+
+} // end of namespace ::sw::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/ThemePanel.hxx b/sw/source/uibase/sidebar/ThemePanel.hxx
new file mode 100644
index 0000000000..12285286f5
--- /dev/null
+++ b/sw/source/uibase/sidebar/ThemePanel.hxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/sidebar/PanelLayout.hxx>
+#include <sfx2/sidebar/ControllerItem.hxx>
+#include <svtools/valueset.hxx>
+#include <svx/ColorSets.hxx>
+
+namespace svx { class ThemeColorValueSet; }
+
+namespace sw::sidebar
+{
+
+class ThemePanel : public PanelLayout,
+ public sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface
+{
+public:
+ static std::unique_ptr<PanelLayout> Create(weld::Widget* pParent);
+
+ ThemePanel(weld::Widget* pParent);
+ virtual ~ThemePanel() override;
+
+ virtual void NotifyItemUpdate(const sal_uInt16 nSId,
+ const SfxItemState eState,
+ const SfxPoolItem* pState) override;
+
+ virtual void GetControlState(
+ const sal_uInt16 /*nSId*/,
+ boost::property_tree::ptree& /*rState*/) override {};
+
+private:
+ std::unique_ptr<weld::TreeView> mxListBoxFonts;
+ std::unique_ptr<svx::ThemeColorValueSet> mxValueSetColors;
+ std::unique_ptr<weld::CustomWeld> mxValueSetColorsWin;
+ std::unique_ptr<weld::Button> mxApplyButton;
+
+ DECL_LINK(ClickHdl, weld::Button&, void);
+ DECL_LINK(DoubleClickHdl, weld::TreeView&, bool);
+ DECL_LINK(DoubleClickValueSetHdl, ValueSet*, void);
+ void DoubleClickHdl();
+
+};
+
+} // end of namespace sw::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/WrapPropertyPanel.cxx b/sw/source/uibase/sidebar/WrapPropertyPanel.cxx
new file mode 100644
index 0000000000..8f38a161ff
--- /dev/null
+++ b/sw/source/uibase/sidebar/WrapPropertyPanel.cxx
@@ -0,0 +1,175 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WrapPropertyPanel.hxx"
+
+#include <editeng/editids.hrc>
+#include <svx/spacinglistbox.hxx>
+#include <svx/svdtrans.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <svl/itemset.hxx>
+#include <hintids.hxx>
+#include <strings.hrc>
+#include <uitool.hxx>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+namespace sw::sidebar {
+
+std::unique_ptr<PanelLayout> WrapPropertyPanel::Create (
+ weld::Widget* pParent,
+ const css::uno::Reference< css::frame::XFrame >& rxFrame,
+ SfxBindings* pBindings)
+{
+ if (pParent == nullptr)
+ throw css::lang::IllegalArgumentException("no parent Window given to WrapPropertyPanel::Create", nullptr, 0);
+ if ( ! rxFrame.is())
+ throw css::lang::IllegalArgumentException("no XFrame given to WrapPropertyPanel::Create", nullptr, 1);
+ if (pBindings == nullptr)
+ throw css::lang::IllegalArgumentException("no SfxBindings given to WrapPropertyPanel::Create", nullptr, 2);
+
+ return std::make_unique<WrapPropertyPanel>(pParent, rxFrame, pBindings);
+}
+
+WrapPropertyPanel::WrapPropertyPanel(
+ weld::Widget* pParent,
+ const css::uno::Reference< css::frame::XFrame >& rxFrame,
+ SfxBindings* pBindings )
+ : PanelLayout(pParent, "WrapPropertyPanel", "modules/swriter/ui/sidebarwrap.ui")
+ , mpBindings(pBindings)
+ // spacing
+ , m_nTop(0)
+ , m_nBottom(0)
+ , m_nLeft(0)
+ , m_nRight(0)
+ // resources
+ , m_aCustomEntry(SwResId(STR_WRAP_PANEL_CUSTOM_STR))
+ // controller items
+ , maSwLRSpacingControl(SID_ATTR_LRSPACE, *pBindings, *this)
+ , maSwULSpacingControl(SID_ATTR_ULSPACE, *pBindings, *this)
+ , mxWrapOptions(m_xBuilder->weld_toolbar("wrapoptions"))
+ , mxWrapOptionsDispatch(new ToolbarUnoDispatcher(*mxWrapOptions, *m_xBuilder, rxFrame))
+ , mxSpacingLB(m_xBuilder->weld_combo_box("spacingLB"))
+{
+ FieldUnit eMetric = ::GetDfltMetric(false);
+ SpacingListBox::Fill(IsInch(eMetric) ? SpacingType::SPACING_INCH : SpacingType::SPACING_CM, *mxSpacingLB);
+
+ Initialize();
+}
+
+WrapPropertyPanel::~WrapPropertyPanel()
+{
+
+ mxWrapOptionsDispatch.reset();
+ mxWrapOptions.reset();
+
+ maSwLRSpacingControl.dispose();
+ maSwULSpacingControl.dispose();
+}
+
+void WrapPropertyPanel::Initialize()
+{
+ mxSpacingLB->connect_changed(LINK(this, WrapPropertyPanel, SpacingLBHdl));
+
+ mpBindings->Update( SID_ATTR_LRSPACE );
+ mpBindings->Update( SID_ATTR_ULSPACE );
+}
+
+void WrapPropertyPanel::UpdateSpacingLB()
+{
+ if( (m_nLeft == m_nRight) && (m_nTop == m_nBottom) && (m_nLeft == m_nTop) )
+ {
+ sal_Int32 nCount = mxSpacingLB->get_count();
+ for (sal_Int32 i = 0; i < nCount; i++)
+ {
+ if (mxSpacingLB->get_id(i).toUInt32() == m_nLeft)
+ {
+ mxSpacingLB->set_active(i);
+ int nCustomEntry = mxSpacingLB->find_text(m_aCustomEntry);
+ if (nCustomEntry != -1)
+ mxSpacingLB->remove(nCustomEntry);
+ return;
+ }
+ }
+ }
+
+ if (mxSpacingLB->find_text(m_aCustomEntry) == -1)
+ mxSpacingLB->append_text(m_aCustomEntry);
+ mxSpacingLB->set_active_text(m_aCustomEntry);
+}
+
+IMPL_LINK(WrapPropertyPanel, SpacingLBHdl, weld::ComboBox&, rBox, void)
+{
+ sal_uInt16 nVal = rBox.get_active_id().toUInt32();
+
+ SvxLRSpaceItem aLRItem(nVal, nVal, 0, RES_LR_SPACE);
+ SvxULSpaceItem aULItem(nVal, nVal, RES_UL_SPACE);
+
+ m_nTop = m_nBottom = m_nLeft = m_nRight = nVal;
+ mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_LRSPACE,
+ SfxCallMode::RECORD, { &aLRItem });
+ mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_ULSPACE,
+ SfxCallMode::RECORD, { &aULItem });
+}
+
+void WrapPropertyPanel::NotifyItemUpdate(
+ const sal_uInt16 nSId,
+ const SfxItemState eState,
+ const SfxPoolItem* pState)
+{
+ switch(nSId)
+ {
+ case SID_ATTR_LRSPACE:
+ {
+ if(eState >= SfxItemState::DEFAULT)
+ {
+ const SvxLRSpaceItem* pItem = dynamic_cast< const SvxLRSpaceItem* >(pState);
+ if(pItem)
+ {
+ m_nLeft = pItem->GetLeft();
+ m_nRight = pItem->GetRight();
+
+ UpdateSpacingLB();
+ }
+ }
+ }
+ break;
+ case SID_ATTR_ULSPACE:
+ {
+ if(eState >= SfxItemState::DEFAULT)
+ {
+ const SvxULSpaceItem* pItem = dynamic_cast< const SvxULSpaceItem* >(pState);
+ if(pItem)
+ {
+ m_nTop = pItem->GetUpper();
+ m_nBottom = pItem->GetLower();
+
+ UpdateSpacingLB();
+ }
+ }
+ }
+ break;
+ }
+}
+
+} // end of namespace ::sw::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/WrapPropertyPanel.hxx b/sw/source/uibase/sidebar/WrapPropertyPanel.hxx
new file mode 100644
index 0000000000..d81cf71c97
--- /dev/null
+++ b/sw/source/uibase/sidebar/WrapPropertyPanel.hxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_WRAPPROPERTYPANEL_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_WRAPPROPERTYPANEL_HXX
+
+#include <sfx2/sidebar/PanelLayout.hxx>
+#include <sfx2/sidebar/ControllerItem.hxx>
+#include <sfx2/weldutils.hxx>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <vcl/weld.hxx>
+
+namespace sw::sidebar {
+
+ class WrapPropertyPanel
+ : public PanelLayout
+ , public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface
+ {
+ public:
+ static std::unique_ptr<PanelLayout> Create(
+ weld::Widget* pParent,
+ const css::uno::Reference< css::frame::XFrame>& rxFrame,
+ SfxBindings* pBindings );
+
+ // interface of ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface
+ virtual void NotifyItemUpdate(
+ const sal_uInt16 nSId,
+ const SfxItemState eState,
+ const SfxPoolItem* pState) override;
+
+ virtual void GetControlState(
+ const sal_uInt16 /*nSId*/,
+ boost::property_tree::ptree& /*rState*/) override {};
+
+ virtual ~WrapPropertyPanel() override;
+
+ WrapPropertyPanel(
+ weld::Widget* pParent,
+ const css::uno::Reference< css::frame::XFrame >& rxFrame,
+ SfxBindings* pBindings );
+ private:
+ SfxBindings* mpBindings;
+
+ //Spacing
+ sal_uInt16 m_nTop;
+ sal_uInt16 m_nBottom;
+ sal_uInt16 m_nLeft;
+ sal_uInt16 m_nRight;
+
+ //custom entry
+ OUString m_aCustomEntry;
+
+ // Controller Items
+ ::sfx2::sidebar::ControllerItem maSwLRSpacingControl;
+ ::sfx2::sidebar::ControllerItem maSwULSpacingControl;
+
+ std::unique_ptr<weld::Toolbar> mxWrapOptions;
+ std::unique_ptr<ToolbarUnoDispatcher> mxWrapOptionsDispatch;
+
+ std::unique_ptr<weld::ComboBox> mxSpacingLB;
+
+ void Initialize();
+ void UpdateSpacingLB();
+
+ DECL_LINK(SpacingLBHdl, weld::ComboBox&, void);
+ };
+
+} // end of namespace ::sw::sidebar
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx b/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx
new file mode 100644
index 0000000000..49086fa9a0
--- /dev/null
+++ b/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx
@@ -0,0 +1,773 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WriterInspectorTextPanel.hxx"
+
+#include <doc.hxx>
+#include <ndtxt.hxx>
+#include <docsh.hxx>
+#include <wrtsh.hxx>
+#include <unoprnms.hxx>
+#include <editeng/unoprnms.hxx>
+#include <com/sun/star/text/XBookmarksSupplier.hpp>
+#include <com/sun/star/text/XTextSectionsSupplier.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+#include <com/sun/star/text/XTextRangeCompare.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/table/BorderLine2.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/rdf/XMetadatable.hpp>
+#include <com/sun/star/rdf/XDocumentMetadataAccess.hpp>
+#include <com/sun/star/container/XChild.hpp>
+
+#include <unotextrange.hxx>
+#include <comphelper/string.hxx>
+#include <comphelper/processfactory.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <vcl/settings.hxx>
+#include <inspectorproperties.hrc>
+#include <strings.hrc>
+#include <rdfhelper.hxx>
+
+namespace sw::sidebar
+{
+static void UpdateTree(SwDocShell& rDocSh, SwEditShell& rEditSh,
+ std::vector<svx::sidebar::TreeNode>& aStore, sal_Int32& rParIdx);
+
+std::unique_ptr<PanelLayout> WriterInspectorTextPanel::Create(weld::Widget* pParent)
+{
+ if (pParent == nullptr)
+ throw lang::IllegalArgumentException(
+ "no parent Window given to WriterInspectorTextPanel::Create", nullptr, 0);
+ return std::make_unique<WriterInspectorTextPanel>(pParent);
+}
+
+WriterInspectorTextPanel::WriterInspectorTextPanel(weld::Widget* pParent)
+ : InspectorTextPanel(pParent)
+ , m_nParIdx(0)
+{
+ SwDocShell* pDocSh = dynamic_cast<SwDocShell*>(SfxObjectShell::Current());
+ m_pShell = pDocSh ? pDocSh->GetWrtShell() : nullptr;
+ if (m_pShell)
+ {
+ m_oldLink = m_pShell->GetChgLnk();
+ m_pShell->SetChgLnk(LINK(this, WriterInspectorTextPanel, AttrChangedNotify));
+
+ // tdf#154629 listen to know if the shell destructs before this panel does,
+ // which can happen on entering print preview
+ m_pShell->Add(this);
+ }
+
+ // Update panel on start
+ std::vector<svx::sidebar::TreeNode> aStore;
+ SwEditShell* pEditSh = pDocSh ? pDocSh->GetDoc()->GetEditShell() : nullptr;
+ if (pEditSh && pEditSh->GetCursor()->GetPointNode().GetTextNode())
+ UpdateTree(*pDocSh, *pEditSh, aStore, m_nParIdx);
+ updateEntries(aStore, m_nParIdx);
+}
+
+void WriterInspectorTextPanel::SwClientNotify(const SwModify& rModify, const SfxHint& rHint)
+{
+ if (rHint.GetId() == SfxHintId::SwLegacyModify)
+ {
+ const sw::LegacyModifyHint& rLegacy = static_cast<const sw::LegacyModifyHint&>(rHint);
+ if (rLegacy.GetWhich() == RES_OBJECTDYING)
+ m_pShell = nullptr;
+ }
+ SwClient::SwClientNotify(rModify, rHint);
+}
+
+WriterInspectorTextPanel::~WriterInspectorTextPanel()
+{
+ if (m_pShell)
+ {
+ m_pShell->SetChgLnk(m_oldLink);
+ m_pShell->Remove(this);
+ }
+}
+
+static OUString PropertyNametoRID(const OUString& rName)
+{
+ static const std::map<OUString, TranslateId> aNameToRID = {
+ { "BorderDistance", RID_BORDER_DISTANCE },
+ { "BottomBorder", RID_BOTTOM_BORDER },
+ { "BottomBorderDistance", RID_BOTTOM_BORDER_DISTANCE },
+ { "BreakType", RID_BREAK_TYPE },
+ { "Category", RID_CATEGORY },
+ { "Cell", RID_CELL },
+ { "CharAutoEscapement", RID_CHAR_AUTO_ESCAPEMENT },
+ { "CharAutoKerning", RID_CHAR_AUTO_KERNING },
+ { "CharAutoStyleName", RID_CHAR_AUTO_STYLE_NAME },
+ { "CharBackColor", RID_CHAR_BACK_COLOR },
+ { "CharBackTransparent", RID_CHAR_BACK_TRANSPARENT },
+ { "CharBorderDistance", RID_CHAR_BORDER_DISTANCE },
+ { "CharBottomBorder", RID_CHAR_BOTTOM_BORDER },
+ { "CharBottomBorderDistance", RID_CHAR_BOTTOM_BORDER_DISTANCE },
+ { "CharCaseMap", RID_CHAR_CASE_MAP },
+ { "CharColor", RID_CHAR_COLOR },
+ { "CharCombineIsOn", RID_CHAR_COMBINE_IS_ON },
+ { "CharCombinePrefix", RID_CHAR_COMBINE_PREFIX },
+ { "CharCombineSuffix", RID_CHAR_COMBINE_SUFFIX },
+ { "CharContoured", RID_CHAR_CONTOURED },
+ { "CharCrossedOut", RID_CHAR_CROSSED_OUT },
+ { "CharDiffHeight", RID_CHAR_DIFF_HEIGHT },
+ { "CharDiffHeightAsian", RID_CHAR_DIFF_HEIGHT_ASIAN },
+ { "CharDiffHeightComplex", RID_CHAR_DIFF_HEIGHT_COMPLEX },
+ { "CharEmphasis", RID_CHAR_EMPHASIS },
+ { "CharEscapement", RID_CHAR_ESCAPEMENT },
+ { "CharEscapementHeight", RID_CHAR_ESCAPEMENT_HEIGHT },
+ { "CharFlash", RID_CHAR_FLASH },
+ { "CharFontCharSet", RID_CHAR_FONT_CHAR_SET },
+ { "CharFontCharSetAsian", RID_CHAR_FONT_CHAR_SET_ASIAN },
+ { "CharFontCharSetComplex", RID_CHAR_FONT_CHAR_SET_COMPLEX },
+ { "CharFontFamily", RID_CHAR_FONT_FAMILY },
+ { "CharFontFamilyAsian", RID_CHAR_FONT_FAMILY_ASIAN },
+ { "CharFontFamilyComplex", RID_CHAR_FONT_FAMILY_COMPLEX },
+ { "CharFontName", RID_CHAR_FONT_NAME },
+ { "CharFontNameAsian", RID_CHAR_FONT_NAME_ASIAN },
+ { "CharFontNameComplex", RID_CHAR_FONT_NAME_COMPLEX },
+ { "CharFontPitch", RID_CHAR_FONT_PITCH },
+ { "CharFontPitchAsian", RID_CHAR_FONT_PITCH_ASIAN },
+ { "CharFontPitchComplex", RID_CHAR_FONT_PITCH_COMPLEX },
+ { "CharFontStyleName", RID_CHAR_FONT_STYLE_NAME },
+ { "CharFontStyleNameAsian", RID_CHAR_FONT_STYLE_NAME_ASIAN },
+ { "CharFontStyleNameComplex", RID_CHAR_FONT_STYLE_NAME_COMPLEX },
+ { "CharHeight", RID_CHAR_HEIGHT },
+ { "CharHeightAsian", RID_CHAR_HEIGHT_ASIAN },
+ { "CharHeightComplex", RID_CHAR_HEIGHT_COMPLEX },
+ { "CharHidden", RID_CHAR_HIDDEN },
+ { "CharHighlight", RID_CHAR_HIGHLIGHT },
+ { "CharInteropGrabBag", RID_CHAR_INTEROP_GRAB_BAG },
+ { "CharKerning", RID_CHAR_KERNING },
+ { "CharLeftBorder", RID_CHAR_LEFT_BORDER },
+ { "CharLeftBorderDistance", RID_CHAR_LEFT_BORDER_DISTANCE },
+ { "CharLocale", RID_CHAR_LOCALE },
+ { "CharLocaleAsian", RID_CHAR_LOCALE_ASIAN },
+ { "CharLocaleComplex", RID_CHAR_LOCALE_COMPLEX },
+ { "CharNoHyphenation", RID_CHAR_NO_HYPHENATION },
+ { "CharOverline", RID_CHAR_OVERLINE },
+ { "CharOverlineColor", RID_CHAR_OVERLINE_COLOR },
+ { "CharOverlineHasColor", RID_CHAR_OVERLINE_HAS_COLOR },
+ { "CharPosture", RID_CHAR_POSTURE },
+ { "CharPostureAsian", RID_CHAR_POSTURE_ASIAN },
+ { "CharPostureComplex", RID_CHAR_POSTURE_COMPLEX },
+ { "CharPropHeight", RID_CHAR_PROP_HEIGHT },
+ { "CharPropHeightAsian", RID_CHAR_PROP_HEIGHT_ASIAN },
+ { "CharPropHeightComplex", RID_CHAR_PROP_HEIGHT_COMPLEX },
+ { "CharRelief", RID_CHAR_RELIEF },
+ { "CharRightBorder", RID_CHAR_RIGHT_BORDER },
+ { "CharRightBorderDistance", RID_CHAR_RIGHT_BORDER_DISTANCE },
+ { "CharRotation", RID_CHAR_ROTATION },
+ { "CharRotationIsFitToLine", RID_CHAR_ROTATION_IS_FIT_TO_LINE },
+ { "CharScaleWidth", RID_CHAR_SCALE_WIDTH },
+ { "CharShadingValue", RID_CHAR_SHADING_VALUE },
+ { "CharShadowFormat", RID_CHAR_SHADOW_FORMAT },
+ { "CharShadowed", RID_CHAR_SHADOWED },
+ { "CharStrikeout", RID_CHAR_STRIKEOUT },
+ { "CharStyleName", RID_CHAR_STYLE_NAME },
+ { "CharStyleNames", RID_CHAR_STYLE_NAMES },
+ { "CharTopBorder", RID_CHAR_TOP_BORDER },
+ { "CharTopBorderDistance", RID_CHAR_TOP_BORDER_DISTANCE },
+ { "CharTransparence", RID_CHAR_TRANSPARENCE },
+ { "CharUnderline", RID_CHAR_UNDERLINE },
+ { "CharUnderlineColor", RID_CHAR_UNDERLINE_COLOR },
+ { "CharUnderlineHasColor", RID_CHAR_UNDERLINE_HAS_COLOR },
+ { "CharWeight", RID_CHAR_WEIGHT },
+ { "CharWeightAsian", RID_CHAR_WEIGHT_ASIAN },
+ { "CharWeightComplex", RID_CHAR_WEIGHT_COMPLEX },
+ { "CharWordMode", RID_CHAR_WORD_MODE },
+ { "ContinueingPreviousSubTree", RID_CONTINUING_PREVIOUS_SUB_TREE },
+ { "DisplayName", RID_DISPLAY_NAME },
+ { "DocumentIndex", RID_DOCUMENT_INDEX },
+ { "DocumentIndexMark", RID_DOCUMENT_INDEX_MARK },
+ { "DropCapCharStyleName", RID_DROP_CAP_CHAR_STYLE_NAME },
+ { "DropCapFormat", RID_DROP_CAP_FORMAT },
+ { "DropCapWholeWord", RID_DROP_CAP_WHOLE_WORD },
+ { "Endnote", RID_ENDNOTE },
+ { "FillBackground", RID_FILL_BACKGROUND },
+ { "FillBitmap", RID_FILL_BITMAP },
+ { "FillBitmapLogicalSize", RID_FILL_BITMAP_LOGICAL_SIZE },
+ { "FillBitmapMode", RID_FILL_BITMAP_MODE },
+ { "FillBitmapName", RID_FILL_BITMAP_NAME },
+ { "FillBitmapOffsetX", RID_FILL_BITMAP_OFFSET_X },
+ { "FillBitmapOffsetY", RID_FILL_BITMAP_OFFSET_Y },
+ { "FillBitmapPositionOffsetX", RID_FILL_BITMAP_POSITION_OFFSET_X },
+ { "FillBitmapPositionOffsetY", RID_FILL_BITMAP_POSITION_OFFSET_Y },
+ { "FillBitmapRectanglePoint", RID_FILL_BITMAP_RECTANGLE_POINT },
+ { "FillBitmapSizeX", RID_FILL_BITMAP_SIZE_X },
+ { "FillBitmapSizeY", RID_FILL_BITMAP_SIZE_Y },
+ { "FillBitmapStretch", RID_FILL_BITMAP_STRETCH },
+ { "FillBitmapTile", RID_FILL_BITMAP_TILE },
+ { "FillBitmapURL", RID_FILL_BITMAP_URL },
+ { "FillColor", RID_FILL_COLOR },
+ { "FillColor2", RID_FILL_COLOR2 },
+ { "FillGradient", RID_FILL_GRADIENT },
+ { "FillGradientName", RID_FILL_GRADIENT_NAME },
+ { "FillGradientStepCount", RID_FILL_GRADIENT_STEP_COUNT },
+ { "FillHatch", RID_FILL_HATCH },
+ { "FillHatchName", RID_FILL_HATCH_NAME },
+ { "FillStyle", RID_FILL_STYLE },
+ { "FillTransparence", RID_FILL_TRANSPARENCE },
+ { "FillTransparenceGradient", RID_FILL_TRANSPARENCE_GRADIENT },
+ { "FillTransparenceGradientName", RID_FILL_TRANSPARENCE_GRADIENT_NAME },
+ { "FollowStyle", RID_FOLLOW_STYLE },
+ { "Footnote", RID_FOOTNOTE },
+ { "Hidden", RID_HIDDEN },
+ { "HyperLinkEvents", RID_HYPERLINK_EVENTS },
+ { "HyperLinkName", RID_HYPERLINK_NAME },
+ { "HyperLinkTarget", RID_HYPERLINK_TARGET },
+ { "HyperLinkURL", RID_HYPERLINK_URL },
+ { "IsAutoUpdate", RID_IS_AUTO_UPDATE },
+ { "IsPhysical", RID_IS_PHYSICAL },
+ { "LeftBorder", RID_LEFT_BORDER },
+ { "LeftBorderDistance", RID_LEFT_BORDER_DISTANCE },
+ { "ListAutoFormat", RID_LIST_AUTO_FORMAT },
+ { "ListId", RID_LIST_ID },
+ { "ListLabelString", RID_LIST_LABEL_STRING },
+ { "MetadataReference", RID_METADATA_REFERENCE },
+ { "NestedTextContent", RID_NESTED_TEXT_CONTENT },
+ { "NumberingIsNumber", RID_NUMBERING_IS_NUMBER },
+ { "NumberingLevel", RID_NUMBERING_LEVEL },
+ { "NumberingRules", RID_NUMBERING_RULES },
+ { "NumberingStartValue", RID_NUMBERING_START_VALUE },
+ { "NumberingStyleName", RID_NUMBERING_STYLE_NAME },
+ { "OutlineContentVisible", RID_OUTLINE_CONTENT_VISIBLE },
+ { "OutlineLevel", RID_OUTLINE_LEVEL },
+ { "PageDescName", RID_PAGE_DESC_NAME },
+ { "PageNumberOffset", RID_PAGE_NUMBER_OFFSET },
+ { "PageStyleName", RID_PAGE_STYLE_NAME },
+ { "ParRsid", RID_PAR_RSID },
+ { "ParaAdjust", RID_PARA_ADJUST },
+ { "ParaAutoStyleName", RID_PARA_AUTO_STYLE_NAME },
+ { "ParaBackColor", RID_PARA_BACK_COLOR },
+ { "ParaBackGraphic", RID_PARA_BACK_GRAPHIC },
+ { "ParaBackGraphicFilter", RID_PARA_BACK_GRAPHIC_FILTER },
+ { "ParaBackGraphicLocation", RID_PARA_BACK_GRAPHIC_LOCATION },
+ { "ParaBackGraphicURL", RID_PARA_BACK_GRAPHIC_URL },
+ { "ParaBackTransparent", RID_PARA_BACK_TRANSPARENT },
+ { "ParaBottomMargin", RID_PARA_BOTTOM_MARGIN },
+ { "ParaBottomMarginRelative", RID_PARA_BOTTOM_MARGIN_RELATIVE },
+ { "ParaChapterNumberingLevel", RID_PARA_CHAPTER_NUMBERING_LEVEL },
+ { "ParaConditionalStyleName", RID_PARA_CONDITIONAL_STYLE_NAME },
+ { "ParaContextMargin", RID_PARA_CONTEXT_MARGIN },
+ { "ParaExpandSingleWord", RID_PARA_EXPAND_SINGLE_WORD },
+ { "ParaFirstLineIndent", RID_PARA_FIRST_LINE_INDENT },
+ { "ParaFirstLineIndentRelative", RID_PARA_FIRST_LINE_INDENT_RELATIVE },
+ { "ParaHyphenationMaxHyphens", RID_PARA_HYPHENATION_MAX_HYPHENS },
+ { "ParaHyphenationMaxLeadingChars", RID_PARA_HYPHENATION_MAX_LEADING_CHARS },
+ { "ParaHyphenationMaxTrailingChars", RID_PARA_HYPHENATION_MAX_TRAILING_CHARS },
+ { "ParaHyphenationNoCaps", RID_PARA_HYPHENATION_NO_CAPS },
+ { "ParaHyphenationNoLastWord", RID_PARA_HYPHENATION_NO_LAST_WORD },
+ { "ParaHyphenationMinWordLength", RID_PARA_HYPHENATION_MIN_WORD_LENGTH },
+ { "ParaHyphenationZone", RID_PARA_HYPHENATION_ZONE },
+ { "ParaInteropGrabBag", RID_PARA_INTEROP_GRAB_BAG },
+ { "ParaIsAutoFirstLineIndent", RID_PARA_IS_AUTO_FIRST_LINE_INDENT },
+ { "ParaIsCharacterDistance", RID_PARA_IS_CHARACTER_DISTANCE },
+ { "ParaIsConnectBorder", RID_PARA_IS_CONNECT_BORDER },
+ { "ParaIsForbiddenRules", RID_PARA_IS_FORBIDDEN_RULES },
+ { "ParaIsHangingPunctuation", RID_PARA_IS_HANGING_PUNCTUATION },
+ { "ParaIsHyphenation", RID_PARA_IS_HYPHENATION },
+ { "ParaIsNumberingRestart", RID_PARA_IS_NUMBERING_RESTART },
+ { "ParaKeepTogether", RID_PARA_KEEP_TOGETHER },
+ { "ParaLastLineAdjust", RID_PARA_LAST_LINE_ADJUST },
+ { "ParaLeftMargin", RID_PARA_LEFT_MARGIN },
+ { "ParaLeftMarginRelative", RID_PARA_LEFT_MARGIN_RELATIVE },
+ { "ParaLineNumberCount", RID_PARA_LINE_NUMBER_COUNT },
+ { "ParaLineNumberStartValue", RID_PARA_LINE_NUMBER_START_VALUE },
+ { "ParaLineSpacing", RID_PARA_LINE_SPACING },
+ { "ParaOrphans", RID_PARA_ORPHANS },
+ { "ParaRegisterModeActive", RID_PARA_REGISTER_MODE_ACTIVE },
+ { "ParaRightMargin", RID_PARA_RIGHT_MARGIN },
+ { "ParaRightMarginRelative", RID_PARA_RIGHT_MARGIN_RELATIVE },
+ { "ParaShadowFormat", RID_PARA_SHADOW_FORMAT },
+ { "ParaSplit", RID_PARA_SPLIT },
+ { "ParaStyleName", RID_PARA_STYLE_NAME },
+ { "ParaTabStops", RID_PARA_TAB_STOPS },
+ { "ParaTopMargin", RID_PARA_TOP_MARGIN },
+ { "ParaTopMarginRelative", RID_PARA_TOP_MARGIN_RELATIVE },
+ { "ParaUserDefinedAttributes", RID_PARA_USER_DEFINED_ATTRIBUTES },
+ { "ParaVertAlignment", RID_PARA_VERT_ALIGNMENT },
+ { "ParaWidows", RID_PARA_WIDOWS },
+ { "ReferenceMark", RID_REFERENCE_MARK },
+ { "RightBorder", RID_RIGHT_BORDER },
+ { "RightBorderDistance", RID_RIGHT_BORDER_DISTANCE },
+ { "Rsid", RID_RSID },
+ { "RubyAdjust", RID_RUBY_ADJUST },
+ { "RubyCharStyleName", RID_RUBY_CHAR_STYLE_NAME },
+ { "RubyIsAbove", RID_RUBY_IS_ABOVE },
+ { "RubyPosition", RID_RUBY_POSITION },
+ { "RubyText", RID_RUBY_TEXT },
+ { "SnapToGrid", RID_SNAP_TO_GRID },
+ { "StyleInteropGrabBag", RID_STYLE_INTEROP_GRAB_BAG },
+ { "TextField", RID_TEXT_FIELD },
+ { "TextFrame", RID_TEXT_FRAME },
+ { "TextParagraph", RID_TEXT_PARAGRAPH },
+ { "TextSection", RID_TEXT_SECTION },
+ { "TextTable", RID_TEXT_TABLE },
+ { "TextUserDefinedAttributes", RID_TEXT_USER_DEFINED_ATTRIBUTES },
+ { "TopBorder", RID_TOP_BORDER },
+ { "TopBorderDistance", RID_TOP_BORDER_DISTANCE },
+ { "UnvisitedCharStyleName", RID_UNVISITED_CHAR_STYLE_NAME },
+ { "VisitedCharStyleName", RID_VISITED_CHAR_STYLE_NAME },
+ { "WritingMode", RID_WRITING_MODE },
+ { "BorderColor", RID_BORDER_COLOR },
+ { "BorderInnerLineWidth", RID_BORDER_INNER_LINE_WIDTH },
+ { "BorderLineDistance", RID_BORDER_LINE_DISTANCE },
+ { "BorderLineStyle", RID_BORDER_LINE_STYLE },
+ { "BorderLineWidth", RID_BORDER_LINE_WIDTH },
+ { "BorderOuterLineWidth", RID_BORDER_OUTER_LINE_WIDTH },
+ };
+
+ auto itr = aNameToRID.find(rName);
+ if (itr != aNameToRID.end())
+ return SwResId(itr->second);
+ return rName;
+}
+
+static svx::sidebar::TreeNode SimplePropToTreeNode(const OUString& rName, const css::uno::Any& rVal)
+{
+ svx::sidebar::TreeNode aCurNode;
+ aCurNode.sNodeName = PropertyNametoRID(rName);
+ aCurNode.aValue = rVal;
+
+ return aCurNode;
+}
+
+static svx::sidebar::TreeNode BorderToTreeNode(const OUString& rName, const css::uno::Any& rVal)
+{
+ table::BorderLine2 aBorder;
+ rVal >>= aBorder;
+ svx::sidebar::TreeNode aCurNode;
+ aCurNode.sNodeName = PropertyNametoRID(rName);
+ aCurNode.NodeType = svx::sidebar::TreeNode::ComplexProperty;
+
+ aCurNode.children
+ = { SimplePropToTreeNode("BorderColor", css::uno::Any(aBorder.Color)),
+ SimplePropToTreeNode("BorderLineWidth", css::uno::Any(aBorder.LineWidth)),
+ SimplePropToTreeNode("BorderLineStyle", css::uno::Any(aBorder.LineStyle)),
+ SimplePropToTreeNode("BorderLineDistance", css::uno::Any(aBorder.LineDistance)),
+ SimplePropToTreeNode("BorderInnerLineWidth", css::uno::Any(aBorder.InnerLineWidth)),
+ SimplePropToTreeNode("BorderOuterLineWidth", css::uno::Any(aBorder.OuterLineWidth)) };
+ return aCurNode;
+}
+
+static svx::sidebar::TreeNode LocaleToTreeNode(const OUString& rName, const css::uno::Any& rVal)
+{
+ svx::sidebar::TreeNode aCurNode;
+ aCurNode.sNodeName = PropertyNametoRID(rName);
+ lang::Locale aLocale;
+ rVal >>= aLocale;
+ OUString aLocaleText(aLocale.Language + "-" + aLocale.Country);
+ if (!aLocale.Variant.isEmpty())
+ aLocaleText += " (" + aLocale.Variant + ")";
+ aCurNode.aValue <<= aLocaleText;
+
+ return aCurNode;
+}
+
+// Collect text of the current level of the annotated text
+// ranges (InContentMetadata) and metadata fields (MetadataField)
+static OUString NestedTextContentToText(const css::uno::Any& rVal)
+{
+ uno::Reference<container::XEnumerationAccess> xMeta;
+ if (rVal >>= xMeta)
+ {
+ uno::Reference<container::XEnumeration> xMetaPortions = xMeta->createEnumeration();
+
+ OUStringBuffer aBuf;
+ while (xMetaPortions->hasMoreElements())
+ {
+ uno::Reference<css::text::XTextRange> xRng(xMetaPortions->nextElement(),
+ uno::UNO_QUERY);
+ aBuf.append(xRng->getString());
+ }
+ return aBuf.makeStringAndClear();
+ }
+
+ return OUString();
+}
+
+// List metadata associated to the paragraph or character range
+static void MetadataToTreeNode(const css::uno::Reference<css::uno::XInterface>& rSource,
+ svx::sidebar::TreeNode& rNode)
+{
+ uno::Reference<rdf::XMetadatable> xMeta(rSource, uno::UNO_QUERY_THROW);
+ // don't add tree node "Metadata Reference", if there is no xml:id
+ if (!xMeta.is() || xMeta->getMetadataReference().Second.isEmpty())
+ return;
+
+ // add metadata of parents for nested annotated text ranges
+ uno::Reference<container::XChild> xChild(rSource, uno::UNO_QUERY);
+ if (xChild.is())
+ {
+ uno::Reference<container::XEnumerationAccess> xParentMeta(xChild->getParent(),
+ uno::UNO_QUERY);
+ if (xParentMeta.is())
+ MetadataToTreeNode(xParentMeta, rNode);
+ }
+
+ svx::sidebar::TreeNode aCurNode;
+ aCurNode.sNodeName = PropertyNametoRID("MetadataReference");
+ aCurNode.NodeType = svx::sidebar::TreeNode::ComplexProperty;
+
+ aCurNode.children.push_back(
+ SimplePropToTreeNode("xml:id", uno::Any(xMeta->getMetadataReference().Second)));
+
+ // list associated (predicate, object) pairs of the actual subject
+ // under the tree node "Metadata Reference"
+ if (SwDocShell* pDocSh = static_cast<SwDocShell*>(SfxObjectShell::Current()))
+ {
+ uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(pDocSh->GetBaseModel(),
+ uno::UNO_QUERY);
+ const uno::Reference<rdf::XRepository>& xRepo = xDocumentMetadataAccess->getRDFRepository();
+ const css::uno::Reference<css::rdf::XResource> xSubject(rSource, uno::UNO_QUERY);
+ std::map<OUString, OUString> xStatements
+ = SwRDFHelper::getStatements(pDocSh->GetBaseModel(), xRepo->getGraphNames(), xSubject);
+ for (const auto& pair : xStatements)
+ aCurNode.children.push_back(SimplePropToTreeNode(pair.first, uno::Any(pair.second)));
+ }
+
+ rNode.children.push_back(aCurNode);
+}
+
+static svx::sidebar::TreeNode
+PropertyToTreeNode(const css::beans::Property& rProperty,
+ const uno::Reference<beans::XPropertySet>& xPropertiesSet, const bool rIsGrey)
+{
+ const OUString& rPropName = rProperty.Name;
+ svx::sidebar::TreeNode aCurNode;
+ const uno::Any aAny = xPropertiesSet->getPropertyValue(rPropName);
+ aCurNode.sNodeName = PropertyNametoRID(rPropName);
+
+ // These properties are handled separately as they are stored in STRUCT and not in single data members
+ if (rPropName == "CharTopBorder" || rPropName == "CharBottomBorder"
+ || rPropName == "CharLeftBorder" || rPropName == "CharRightBorder"
+ || rPropName == "TopBorder" || rPropName == "BottomBorder" || rPropName == "LeftBorder"
+ || rPropName == "RightBorder")
+ {
+ aCurNode = BorderToTreeNode(rPropName, aAny);
+ }
+ else if (rPropName == "CharLocale")
+ {
+ aCurNode = LocaleToTreeNode(rPropName, aAny);
+ }
+ else
+ aCurNode = SimplePropToTreeNode(rPropName, aAny);
+
+ if (rIsGrey)
+ {
+ aCurNode.isGrey = true;
+ for (svx::sidebar::TreeNode& rChildNode : aCurNode.children)
+ rChildNode.isGrey = true; // grey out all the children nodes
+ }
+
+ return aCurNode;
+}
+
+static void InsertValues(const css::uno::Reference<css::uno::XInterface>& rSource,
+ std::unordered_map<OUString, bool>& rIsDefined,
+ svx::sidebar::TreeNode& rNode, const bool isRoot,
+ const std::vector<OUString>& rHiddenProperty,
+ svx::sidebar::TreeNode& rFieldsNode)
+{
+ uno::Reference<beans::XPropertySet> xPropertiesSet(rSource, uno::UNO_QUERY_THROW);
+ uno::Reference<beans::XPropertyState> xPropertiesState(rSource, uno::UNO_QUERY_THROW);
+ const uno::Sequence<beans::Property> aProperties
+ = xPropertiesSet->getPropertySetInfo()->getProperties();
+
+ for (const beans::Property& rProperty : aProperties)
+ {
+ const OUString& rPropName = rProperty.Name;
+ if (std::find(rHiddenProperty.begin(), rHiddenProperty.end(), rPropName)
+ != rHiddenProperty.end())
+ continue;
+
+ if (isRoot
+ || xPropertiesState->getPropertyState(rPropName) == beans::PropertyState_DIRECT_VALUE)
+ {
+ svx::sidebar::TreeNode aCurNode
+ = PropertyToTreeNode(rProperty, xPropertiesSet, rIsDefined[rPropName]);
+ rIsDefined[rPropName] = true;
+
+ // process NestedTextContent and show associated metadata
+ // under the tree node "Metadata Reference", if they exist
+ if (rPropName == "NestedTextContent")
+ {
+ uno::Reference<container::XEnumerationAccess> xMeta;
+ if (aCurNode.aValue >>= xMeta)
+ MetadataToTreeNode(xMeta, rFieldsNode);
+ aCurNode.aValue <<= NestedTextContentToText(aCurNode.aValue);
+ }
+
+ rNode.children.push_back(aCurNode);
+ }
+ }
+
+ const comphelper::string::NaturalStringSorter aSorter(
+ comphelper::getProcessComponentContext(),
+ Application::GetSettings().GetUILanguageTag().getLocale());
+
+ std::sort(
+ rNode.children.begin(), rNode.children.end(),
+ [&aSorter](svx::sidebar::TreeNode const& rEntry1, svx::sidebar::TreeNode const& rEntry2) {
+ return aSorter.compare(rEntry1.sNodeName, rEntry2.sNodeName) < 0;
+ });
+}
+
+static void UpdateTree(SwDocShell& rDocSh, SwEditShell& rEditSh,
+ std::vector<svx::sidebar::TreeNode>& aStore, sal_Int32& rParIdx)
+{
+ SwDoc* pDoc = rDocSh.GetDoc();
+ SwPaM* pCursor = rEditSh.GetCursor();
+ svx::sidebar::TreeNode aCharDFNode;
+ svx::sidebar::TreeNode aCharNode;
+ svx::sidebar::TreeNode aParaNode;
+ svx::sidebar::TreeNode aParaDFNode;
+ svx::sidebar::TreeNode aBookmarksNode;
+ svx::sidebar::TreeNode aFieldsNode;
+ svx::sidebar::TreeNode aTextSectionsNode;
+
+ aCharNode.sNodeName = SwResId(STR_CHARACTERSTYLEFAMILY);
+ aParaNode.sNodeName = SwResId(STR_PARAGRAPHSTYLEFAMILY);
+ aCharDFNode.sNodeName = SwResId(RID_CHAR_DIRECTFORMAT);
+ aParaDFNode.sNodeName = SwResId(RID_PARA_DIRECTFORMAT);
+ aBookmarksNode.sNodeName = SwResId(STR_CONTENT_TYPE_BOOKMARK);
+ aFieldsNode.sNodeName = SwResId(STR_CONTENT_TYPE_TEXTFIELD);
+ aTextSectionsNode.sNodeName = SwResId(STR_CONTENT_TYPE_REGION);
+ aCharDFNode.NodeType = svx::sidebar::TreeNode::Category;
+ aCharNode.NodeType = svx::sidebar::TreeNode::Category;
+ aParaNode.NodeType = svx::sidebar::TreeNode::Category;
+ aParaDFNode.NodeType = svx::sidebar::TreeNode::Category;
+ aBookmarksNode.NodeType = svx::sidebar::TreeNode::Category;
+ aFieldsNode.NodeType = svx::sidebar::TreeNode::Category;
+ aTextSectionsNode.NodeType = svx::sidebar::TreeNode::Category;
+
+ rtl::Reference<SwXTextRange> xRange(
+ SwXTextRange::CreateXTextRange(*pDoc, *pCursor->GetPoint(), nullptr));
+ if (!xRange)
+ throw uno::RuntimeException();
+ std::unordered_map<OUString, bool> aIsDefined;
+
+ const std::vector<OUString> aHiddenProperties{ UNO_NAME_RSID,
+ UNO_NAME_PARA_IS_NUMBERING_RESTART,
+ UNO_NAME_PARA_STYLE_NAME,
+ UNO_NAME_PARA_CONDITIONAL_STYLE_NAME,
+ UNO_NAME_PAGE_STYLE_NAME,
+ UNO_NAME_NUMBERING_START_VALUE,
+ UNO_NAME_NUMBERING_IS_NUMBER,
+ UNO_NAME_PARA_CONTINUEING_PREVIOUS_SUB_TREE,
+ UNO_NAME_CHAR_STYLE_NAME,
+ UNO_NAME_NUMBERING_LEVEL,
+ UNO_NAME_SORTED_TEXT_ID,
+ UNO_NAME_PARRSID,
+ UNO_NAME_CHAR_COLOR_THEME,
+ UNO_NAME_CHAR_COLOR_TINT_OR_SHADE };
+
+ const std::vector<OUString> aHiddenCharacterProperties{ UNO_NAME_CHAR_COLOR_THEME,
+ UNO_NAME_CHAR_COLOR_TINT_OR_SHADE };
+
+ InsertValues(static_cast<cppu::OWeakObject*>(xRange.get()), aIsDefined, aCharDFNode, false,
+ aHiddenProperties, aFieldsNode);
+
+ uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(rDocSh.GetBaseModel(),
+ uno::UNO_QUERY);
+ uno::Reference<container::XNameAccess> xStyleFamilies
+ = xStyleFamiliesSupplier->getStyleFamilies();
+ OUString sCurrentCharStyle, sCurrentParaStyle, sDisplayName;
+
+ uno::Reference<container::XNameAccess> xStyleFamily(
+ xStyleFamilies->getByName("CharacterStyles"), uno::UNO_QUERY_THROW);
+ xRange->getPropertyValue("CharStyleName") >>= sCurrentCharStyle;
+ xRange->getPropertyValue("ParaStyleName") >>= sCurrentParaStyle;
+
+ if (!sCurrentCharStyle.isEmpty())
+ {
+ uno::Reference<beans::XPropertySet> xPropertiesSet(
+ xStyleFamily->getByName(sCurrentCharStyle), css::uno::UNO_QUERY_THROW);
+ xPropertiesSet->getPropertyValue("DisplayName") >>= sDisplayName;
+ svx::sidebar::TreeNode aCurrentChild;
+ aCurrentChild.sNodeName = sDisplayName;
+ aCurrentChild.NodeType = svx::sidebar::TreeNode::ComplexProperty;
+
+ InsertValues(xPropertiesSet, aIsDefined, aCurrentChild, false, aHiddenCharacterProperties,
+ aFieldsNode);
+
+ aCharNode.children.push_back(aCurrentChild);
+ }
+
+ // Collect paragraph direct formatting
+ uno::Reference<container::XEnumeration> xParaEnum = xRange->createEnumeration();
+ uno::Reference<text::XTextRange> xThisParagraphRange(xParaEnum->nextElement(), uno::UNO_QUERY);
+ if (xThisParagraphRange.is())
+ {
+ // Collect metadata of the current paragraph
+ MetadataToTreeNode(xThisParagraphRange, aParaDFNode);
+ InsertValues(xThisParagraphRange, aIsDefined, aParaDFNode, false, aHiddenProperties,
+ aFieldsNode);
+ }
+
+ xStyleFamily.set(xStyleFamilies->getByName("ParagraphStyles"), uno::UNO_QUERY_THROW);
+
+ while (!sCurrentParaStyle.isEmpty())
+ {
+ uno::Reference<style::XStyle> xPropertiesStyle(xStyleFamily->getByName(sCurrentParaStyle),
+ uno::UNO_QUERY_THROW);
+ uno::Reference<beans::XPropertySet> xPropertiesSet(xPropertiesStyle,
+ css::uno::UNO_QUERY_THROW);
+ xPropertiesSet->getPropertyValue("DisplayName") >>= sDisplayName;
+ OUString aParentParaStyle = xPropertiesStyle->getParentStyle();
+ svx::sidebar::TreeNode aCurrentChild;
+ aCurrentChild.sNodeName = sDisplayName;
+ aCurrentChild.NodeType = svx::sidebar::TreeNode::ComplexProperty;
+
+ InsertValues(xPropertiesSet, aIsDefined, aCurrentChild, aParentParaStyle.isEmpty(),
+ aHiddenCharacterProperties, aFieldsNode);
+
+ aParaNode.children.push_back(aCurrentChild);
+ sCurrentParaStyle = aParentParaStyle;
+ }
+
+ std::reverse(aParaNode.children.begin(),
+ aParaNode.children.end()); // Parent style should be first then children
+
+ // Collect bookmarks at character position
+ uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(rDocSh.GetBaseModel(),
+ uno::UNO_QUERY);
+
+ uno::Reference<container::XIndexAccess> xBookmarks(xBookmarksSupplier->getBookmarks(),
+ uno::UNO_QUERY);
+ for (sal_Int32 i = 0; i < xBookmarks->getCount(); ++i)
+ {
+ svx::sidebar::TreeNode aCurNode;
+ uno::Reference<text::XTextContent> bookmark;
+ xBookmarks->getByIndex(i) >>= bookmark;
+ uno::Reference<container::XNamed> xBookmark(bookmark, uno::UNO_QUERY);
+
+ try
+ {
+ uno::Reference<text::XTextRange> bookmarkRange = bookmark->getAnchor();
+ uno::Reference<text::XTextRangeCompare> xTextRangeCompare(xRange->getText(),
+ uno::UNO_QUERY);
+ if (xTextRangeCompare.is()
+ && xTextRangeCompare->compareRegionStarts(bookmarkRange, xRange) != -1
+ && xTextRangeCompare->compareRegionEnds(xRange, bookmarkRange) != -1)
+ {
+ aCurNode.sNodeName = xBookmark->getName();
+ aCurNode.NodeType = svx::sidebar::TreeNode::ComplexProperty;
+
+ MetadataToTreeNode(xBookmark, aCurNode);
+ // show bookmark only if it has RDF metadata
+ if (aCurNode.children.size() > 0)
+ aBookmarksNode.children.push_back(aCurNode);
+ }
+ }
+ catch (const lang::IllegalArgumentException&)
+ {
+ }
+ }
+
+ // Collect sections at character position
+ uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(rDocSh.GetBaseModel(),
+ uno::UNO_QUERY);
+
+ uno::Reference<container::XIndexAccess> xTextSections(xTextSectionsSupplier->getTextSections(),
+ uno::UNO_QUERY);
+ for (sal_Int32 i = 0; i < xTextSections->getCount(); ++i)
+ {
+ svx::sidebar::TreeNode aCurNode;
+ uno::Reference<text::XTextContent> section;
+ xTextSections->getByIndex(i) >>= section;
+ uno::Reference<container::XNamed> xTextSection(section, uno::UNO_QUERY);
+
+ try
+ {
+ uno::Reference<text::XTextRange> sectionRange = section->getAnchor();
+ uno::Reference<text::XTextRangeCompare> xTextRangeCompare(xRange->getText(),
+ uno::UNO_QUERY);
+ if (xTextRangeCompare.is()
+ && xTextRangeCompare->compareRegionStarts(sectionRange, xRange) != -1
+ && xTextRangeCompare->compareRegionEnds(xRange, sectionRange) != -1)
+ {
+ aCurNode.sNodeName = xTextSection->getName();
+ aCurNode.NodeType = svx::sidebar::TreeNode::ComplexProperty;
+
+ MetadataToTreeNode(xTextSection, aCurNode);
+ // show section only if it has RDF metadata
+ if (aCurNode.children.size() > 0)
+ aTextSectionsNode.children.push_back(aCurNode);
+ }
+ }
+ catch (const lang::IllegalArgumentException&)
+ {
+ }
+ }
+
+ /*
+ Display Order :-
+ SECTIONS with RDF metadata (optional)
+ BOOKMARKS with RDF metadata (optional)
+ FIELDS with RDF metadata (optional)
+ PARAGRAPH STYLE
+ PARAGRAPH DIRECT FORMATTING
+ CHARACTER STYLE
+ DIRECT FORMATTING
+ */
+ rParIdx = 0;
+ // show sections, bookmarks and fields only if they have RDF metadata
+ if (aTextSectionsNode.children.size() > 0)
+ {
+ aStore.push_back(aTextSectionsNode);
+ rParIdx++;
+ }
+ if (aBookmarksNode.children.size() > 0)
+ {
+ aStore.push_back(aBookmarksNode);
+ rParIdx++;
+ }
+ if (aFieldsNode.children.size() > 0)
+ {
+ aStore.push_back(aFieldsNode);
+ rParIdx++;
+ }
+ aStore.push_back(aParaNode);
+ aStore.push_back(aParaDFNode);
+ aStore.push_back(aCharNode);
+ aStore.push_back(aCharDFNode);
+}
+
+IMPL_LINK(WriterInspectorTextPanel, AttrChangedNotify, LinkParamNone*, pLink, void)
+{
+ if (m_oldLink.IsSet())
+ m_oldLink.Call(pLink);
+
+ SwDocShell* pDocSh = m_pShell->GetDoc()->GetDocShell();
+ std::vector<svx::sidebar::TreeNode> aStore;
+
+ SwEditShell* pEditSh = pDocSh ? pDocSh->GetDoc()->GetEditShell() : nullptr;
+ if (pEditSh && pEditSh->GetCursor()->GetPointNode().GetTextNode())
+ UpdateTree(*pDocSh, *pEditSh, aStore, m_nParIdx);
+
+ updateEntries(aStore, m_nParIdx);
+}
+
+} // end of namespace svx::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/WriterInspectorTextPanel.hxx b/sw/source/uibase/sidebar/WriterInspectorTextPanel.hxx
new file mode 100644
index 0000000000..2c2df34a94
--- /dev/null
+++ b/sw/source/uibase/sidebar/WriterInspectorTextPanel.hxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <svx/sidebar/InspectorTextPanel.hxx>
+#include <calbck.hxx>
+
+class SwWrtShell;
+
+namespace sw::sidebar
+{
+class WriterInspectorTextPanel final : public svx::sidebar::InspectorTextPanel, public SwClient
+{
+public:
+ static std::unique_ptr<PanelLayout> Create(weld::Widget* pParent);
+
+ WriterInspectorTextPanel(weld::Widget* pParent);
+
+ virtual ~WriterInspectorTextPanel() override;
+
+private:
+ SwWrtShell* m_pShell;
+ Link<LinkParamNone*, void> m_oldLink;
+ sal_Int32 m_nParIdx; // count optional metadata tree items to collapse default paragraph styles
+
+ // attributes have changed
+ DECL_LINK(AttrChangedNotify, LinkParamNone*, void);
+
+ virtual void SwClientNotify(const SwModify&, const SfxHint& rHint) override;
+};
+
+} // end of namespace svx::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/table/chartins.cxx b/sw/source/uibase/table/chartins.cxx
new file mode 100644
index 0000000000..74bc534df9
--- /dev/null
+++ b/sw/source/uibase/table/chartins.cxx
@@ -0,0 +1,231 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/dispatch.hxx>
+#include <IDocumentChartDataProviderAccess.hxx>
+#include <osl/diagnose.h>
+
+#include <swmodule.hxx>
+#include <wrtsh.hxx>
+#include <docsh.hxx>
+#include <view.hxx>
+#include <chartins.hxx>
+#include <tablemgr.hxx>
+#include <frmfmt.hxx>
+#include <unochart.hxx>
+
+#include <edtwin.hxx>
+
+#include <cmdid.h>
+#include <anchoredobject.hxx>
+
+#include <cppuhelper/bootstrap.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <com/sun/star/awt/Point.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <svtools/dialogclosedlistener.hxx>
+#include <com/sun/star/chart2/data/XDataProvider.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XMultiComponentFactory.hpp>
+#include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+Point SwGetChartDialogPos( const vcl::Window *pParentWin, const Size& rDialogSize, const tools::Rectangle& rLogicChart )
+{
+ // positioning code according to spec; similar to Calc fuins2.cxx
+ Point aRet;
+
+ OSL_ENSURE( pParentWin, "Window not found" );
+ if (pParentWin)
+ {
+ tools::Rectangle aObjPixel = pParentWin->LogicToPixel( rLogicChart, pParentWin->GetMapMode() );
+ AbsoluteScreenPixelRectangle aObjAbs( pParentWin->OutputToAbsoluteScreenPixel( aObjPixel.TopLeft() ),
+ pParentWin->OutputToAbsoluteScreenPixel( aObjPixel.BottomRight() ) );
+
+ AbsoluteScreenPixelRectangle aDesktop = pParentWin->GetDesktopRectPixel();
+ Size aSpace = pParentWin->LogicToPixel(Size(8, 12), MapMode(MapUnit::MapAppFont));
+
+ bool bCenterHor = false;
+
+ if ( aDesktop.Bottom() - aObjAbs.Bottom() >= rDialogSize.Height() + aSpace.Height() )
+ {
+ // first preference: below the chart
+ aRet.setY( aObjAbs.Bottom() + aSpace.Height() );
+ bCenterHor = true;
+ }
+ else if ( aObjAbs.Top() - aDesktop.Top() >= rDialogSize.Height() + aSpace.Height() )
+ {
+ // second preference: above the chart
+ aRet.setY( aObjAbs.Top() - rDialogSize.Height() - aSpace.Height() );
+ bCenterHor = true;
+ }
+ else
+ {
+ bool bFitLeft = ( aObjAbs.Left() - aDesktop.Left() >= rDialogSize.Width() + aSpace.Width() );
+ bool bFitRight = ( aDesktop.Right() - aObjAbs.Right() >= rDialogSize.Width() + aSpace.Width() );
+
+ if ( bFitLeft || bFitRight )
+ {
+ if (SwView* pView = GetActiveView())
+ {
+ // if both fit, prefer right in RTL mode, left otherwise
+ bool bLayoutRTL = pView->GetWrtShell().IsTableRightToLeft();
+ bool bPutRight = bFitRight && ( bLayoutRTL || !bFitLeft );
+ if ( bPutRight )
+ aRet.setX( aObjAbs.Right() + aSpace.Width() );
+ else
+ aRet.setX( aObjAbs.Left() - rDialogSize.Width() - aSpace.Width() );
+ }
+
+ // center vertically
+ aRet.setY( aObjAbs.Top() + ( aObjAbs.GetHeight() - rDialogSize.Height() ) / 2 );
+ }
+ else
+ {
+ // doesn't fit on any edge - put at the bottom of the screen
+ aRet.setY( aDesktop.Bottom() - rDialogSize.Height() );
+ bCenterHor = true;
+ }
+ }
+ if ( bCenterHor )
+ aRet.setX( aObjAbs.Left() + ( aObjAbs.GetWidth() - rDialogSize.Width() ) / 2 );
+
+ // limit to screen (centering might lead to invalid positions)
+ if ( aRet.X() + rDialogSize.Width() - 1 > aDesktop.Right() )
+ aRet.setX( aDesktop.Right() - rDialogSize.Width() + 1 );
+ if ( aRet.X() < aDesktop.Left() )
+ aRet.setX( aDesktop.Left() );
+ if ( aRet.Y() + rDialogSize.Height() - 1 > aDesktop.Bottom() )
+ aRet.setY( aDesktop.Bottom() - rDialogSize.Height() + 1 );
+ if ( aRet.Y() < aDesktop.Top() )
+ aRet.setY( aDesktop.Top() );
+ }
+
+ return aRet;
+}
+
+SwInsertChart::SwInsertChart( const Link<css::ui::dialogs::DialogClosedEvent*, void>& rLink )
+{
+ SwView *pView = ::GetActiveView();
+ if (!pView)
+ return;
+
+ // get range string of marked data
+ SwWrtShell &rWrtShell = pView->GetWrtShell();
+ uno::Reference< chart2::data::XDataProvider > xDataProvider;
+ uno::Reference< frame::XModel > xChartModel;
+ OUString aRangeString;
+
+ if( rWrtShell.IsCursorInTable())
+ {
+ if (!rWrtShell.IsTableMode())
+ {
+ // select whole table
+ rWrtShell.GetView().GetViewFrame().GetDispatcher()->
+ Execute(FN_TABLE_SELECT_ALL, SfxCallMode::SYNCHRON);
+ }
+ if( ! rWrtShell.IsTableComplexForChart())
+ {
+ SwFrameFormat* pTableFormat = rWrtShell.GetTableFormat();
+ aRangeString = pTableFormat->GetName() + "." + rWrtShell.GetBoxNms();
+
+ // get table data provider
+ xDataProvider.set( pView->GetDocShell()->getIDocumentChartDataProviderAccess().GetChartDataProvider( true ) );
+ }
+ }
+
+ SwFlyFrameFormat *pFlyFrameFormat = nullptr;
+ xChartModel.set( SwTableFUNC( &rWrtShell ).InsertChart( xDataProvider, xDataProvider.is(), aRangeString, &pFlyFrameFormat ));
+
+ //open wizard
+ //@todo get context from writer if that has one
+ uno::Reference< uno::XComponentContext > xContext(
+ ::cppu::defaultBootstrap_InitialComponentContext() );
+ if( !(xContext.is() && xChartModel.is() && xDataProvider.is()))
+ return;
+
+ uno::Reference< lang::XMultiComponentFactory > xMCF( xContext->getServiceManager() );
+ if(!xMCF.is())
+ return;
+
+ uno::Reference< ui::dialogs::XAsynchronousExecutableDialog > xDialog(
+ xMCF->createInstanceWithContext(
+ "com.sun.star.comp.chart2.WizardDialog", xContext),
+ uno::UNO_QUERY);
+ uno::Reference< lang::XInitialization > xInit( xDialog, uno::UNO_QUERY );
+ if( xInit.is() )
+ {
+ // initialize dialog
+ uno::Sequence<uno::Any> aSeq(comphelper::InitAnyPropertySequence(
+ {
+ {"ParentWindow", uno::Any(uno::Reference< awt::XWindow >())},
+ {"ChartModel", uno::Any(xChartModel)}
+ }));
+ xInit->initialize( aSeq );
+
+ // try to set the dialog's position so it doesn't hide the chart
+ uno::Reference < beans::XPropertySet > xDialogProps( xDialog, uno::UNO_QUERY );
+ if ( xDialogProps.is() )
+ {
+ try
+ {
+ //get dialog size:
+ awt::Size aDialogAWTSize;
+ if( xDialogProps->getPropertyValue("Size")
+ >>= aDialogAWTSize )
+ {
+ Size aDialogSize( aDialogAWTSize.Width, aDialogAWTSize.Height );
+ if ( !aDialogSize.IsEmpty() )
+ {
+ //calculate and set new position
+ SwRect aSwRect;
+ if (pFlyFrameFormat)
+ aSwRect = pFlyFrameFormat->GetAnchoredObj()->GetObjRectWithSpaces();
+ tools::Rectangle aRect( aSwRect.SVRect() );
+ Point aDialogPos = SwGetChartDialogPos( &rWrtShell.GetView().GetEditWin(), aDialogSize, aRect );
+ xDialogProps->setPropertyValue("Position",
+ uno::Any( awt::Point(aDialogPos.getX(),aDialogPos.getY()) ) );
+ }
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ OSL_FAIL("Chart wizard couldn't be positioned automatically" );
+ }
+ }
+
+ rtl::Reference<::svt::DialogClosedListener> pListener = new ::svt::DialogClosedListener();
+ pListener->SetDialogClosedLink( rLink );
+
+ xDialog->startExecuteModal( pListener );
+ }
+ else
+ {
+ uno::Reference< lang::XComponent > xComponent( xDialog, uno::UNO_QUERY );
+ if( xComponent.is())
+ xComponent->dispose();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/table/swtablerep.cxx b/sw/source/uibase/table/swtablerep.cxx
new file mode 100644
index 0000000000..44a87df90b
--- /dev/null
+++ b/sw/source/uibase/table/swtablerep.cxx
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <tabcol.hxx>
+
+#include <swtablerep.hxx>
+#include <memory>
+
+SwTableRep::SwTableRep( const SwTabCols& rTabCol )
+ :
+ m_nTableWidth(0),
+ m_nSpace(0),
+ m_nLeftSpace(0),
+ m_nRightSpace(0),
+ m_nAlign(0),
+ m_nWidthPercent(0),
+ m_bLineSelected(false),
+ m_bWidthChanged(false),
+ m_bColsChanged(false)
+{
+ m_nAllCols = m_nColCount = rTabCol.Count();
+ m_aTColumns.resize(m_nColCount + 1);
+ SwTwips nStart = 0,
+ nEnd;
+ for( sal_uInt16 i = 0; i < m_nAllCols; ++i )
+ {
+ nEnd = rTabCol[ i ] - rTabCol.GetLeft();
+ m_aTColumns[ i ].nWidth = nEnd - nStart;
+ m_aTColumns[ i ].bVisible = !rTabCol.IsHidden(i);
+ if(!m_aTColumns[ i ].bVisible)
+ m_nColCount --;
+ nStart = nEnd;
+ }
+ m_aTColumns[ m_nAllCols ].nWidth = rTabCol.GetRight() - rTabCol.GetLeft() - nStart;
+ m_aTColumns[ m_nAllCols ].bVisible = true;
+ m_nColCount++;
+ m_nAllCols++;
+}
+
+SwTableRep::~SwTableRep()
+{
+}
+
+bool SwTableRep::FillTabCols( SwTabCols& rTabCols ) const
+{
+ tools::Long nOldLeft = rTabCols.GetLeft(),
+ nOldRight = rTabCols.GetRight();
+
+ bool bSingleLine = false;
+
+ for ( size_t i = 0; i < rTabCols.Count(); ++i )
+ if(!m_aTColumns[i].bVisible)
+ {
+ bSingleLine = true;
+ break;
+ }
+
+ SwTwips nPos = 0;
+ const SwTwips nLeft = GetLeftSpace();
+ rTabCols.SetLeft(nLeft);
+ if(bSingleLine)
+ {
+ // The invisible separators are taken from the old TabCols,
+ // the visible coming from pTColumns.
+ std::unique_ptr<TColumn[]> pOldTColumns(new TColumn[m_nAllCols + 1]);
+ SwTwips nStart = 0;
+ for ( sal_uInt16 i = 0; i < m_nAllCols - 1; ++i )
+ {
+ const SwTwips nEnd = rTabCols[i] - rTabCols.GetLeft();
+ pOldTColumns[i].nWidth = nEnd - nStart;
+ pOldTColumns[i].bVisible = !rTabCols.IsHidden(i);
+ nStart = nEnd;
+ }
+ pOldTColumns[m_nAllCols - 1].nWidth = rTabCols.GetRight() - rTabCols.GetLeft() - nStart;
+ pOldTColumns[m_nAllCols - 1].bVisible = true;
+
+ sal_uInt16 nOldPos = 0;
+ sal_uInt16 nNewPos = 0;
+ SwTwips nOld = 0;
+ SwTwips nNew = 0;
+ bool bOld = false;
+ bool bFirst = true;
+
+ for ( sal_uInt16 i = 0; i < m_nAllCols - 1; ++i )
+ {
+ while((bFirst || bOld ) && nOldPos < m_nAllCols )
+ {
+ nOld += pOldTColumns[nOldPos].nWidth;
+ nOldPos++;
+ if(!pOldTColumns[nOldPos - 1].bVisible)
+ break;
+ }
+ while((bFirst || !bOld ) && nNewPos < m_nAllCols )
+ {
+ nNew += m_aTColumns[nNewPos].nWidth;
+ nNewPos++;
+ if(pOldTColumns[nNewPos - 1].bVisible)
+ break;
+ }
+ bFirst = false;
+ // They have to be inserted sorted.
+ bOld = nOld < nNew;
+ nPos = bOld ? nOld : nNew;
+ rTabCols[i] = nPos + nLeft;
+ rTabCols.SetHidden( i, bOld );
+ }
+ rTabCols.SetRight(nLeft + m_nTableWidth);
+ }
+ else
+ {
+ for ( sal_uInt16 i = 0; i < m_nAllCols - 1; ++i )
+ {
+ nPos += m_aTColumns[i].nWidth;
+ rTabCols[i] = nPos + rTabCols.GetLeft();
+ rTabCols.SetHidden( i, !m_aTColumns[i].bVisible );
+ rTabCols.SetRight(nLeft + m_aTColumns[m_nAllCols - 1].nWidth + nPos);
+ }
+ }
+
+ // intercept rounding errors
+ if(std::abs(nOldLeft - rTabCols.GetLeft()) < 3)
+ rTabCols.SetLeft(nOldLeft);
+
+ if(std::abs(nOldRight - rTabCols.GetRight()) < 3)
+ rTabCols.SetRight(nOldRight);
+
+ if(GetRightSpace() >= 0 &&
+ rTabCols.GetRight() > rTabCols.GetRightMax())
+ rTabCols.SetRight(rTabCols.GetRightMax());
+ return bSingleLine;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/table/tablemgr.cxx b/sw/source/uibase/table/tablemgr.cxx
new file mode 100644
index 0000000000..8df92dae56
--- /dev/null
+++ b/sw/source/uibase/table/tablemgr.cxx
@@ -0,0 +1,352 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/chart/ChartDataRowSource.hpp>
+#include <com/sun/star/chart2/data/XDataProvider.hpp>
+#include <com/sun/star/chart2/data/XDataReceiver.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/beans/PropertyState.hpp>
+#include <com/sun/star/embed/EmbedVerbs.hpp>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
+
+#include <comphelper/classids.hxx>
+#include <svx/charthelper.hxx>
+#include <svtools/embedhlp.hxx>
+
+#include <edtwin.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <swundo.hxx>
+#include <tablemgr.hxx>
+#include <frmfmt.hxx>
+#include <swabstdlg.hxx>
+#include <swcli.hxx>
+#include <docsh.hxx>
+#include <unotbl.hxx>
+#include <unochart.hxx>
+
+#include <comphelper/lok.hxx>
+
+using namespace ::com::sun::star;
+
+// Adjust line height (dialogue)
+void SwTableFUNC::ColWidthDlg(weld::Window *pParent)
+{
+ InitTabCols();
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateSwTableWidthDlg(pParent, *this));
+ pDlg->Execute();
+}
+
+// Determine the width
+SwTwips SwTableFUNC::GetColWidth(sal_uInt16 nNum) const
+{
+ SwTwips nWidth = 0;
+
+ if( m_aCols.Count() > 0 )
+ {
+ if(m_aCols.Count() == GetColCount())
+ {
+ if(nNum == m_aCols.Count())
+ nWidth = m_aCols.GetRight() - m_aCols[nNum-1];
+ else
+ {
+ if(nNum == 0)
+ nWidth = m_aCols[nNum] - m_aCols.GetLeft();
+ else
+ nWidth = m_aCols[nNum] - m_aCols[nNum-1];
+ }
+ }
+ else
+ {
+ SwTwips nRValid = nNum < GetColCount() ?
+ m_aCols[GetRightSeparator(nNum)] :
+ m_aCols.GetRight();
+ SwTwips nLValid = nNum ?
+ m_aCols[GetRightSeparator(nNum - 1)] :
+ m_aCols.GetLeft();
+ nWidth = nRValid - nLValid;
+ }
+ }
+ else
+ nWidth = m_aCols.GetRight();
+ return nWidth;
+}
+
+SwTwips SwTableFUNC::GetMaxColWidth( sal_uInt16 nNum ) const
+{
+ OSL_ENSURE(nNum <= m_aCols.Count(), "Index out of Area");
+
+ if ( GetColCount() > 0 )
+ {
+ // The maximum width arises from the own width and
+ // the width each of the neighbor cells reduced by MINLAY.
+ SwTwips nMax;
+ if(nNum == 0)
+ nMax = GetColWidth(1) - MINLAY;
+ else
+ {
+ nMax = GetColWidth(nNum-1);
+ if(nNum == GetColCount())
+ nMax -= MINLAY;
+ else
+ nMax += GetColWidth(nNum+1) - 2 * MINLAY;
+ }
+ return nMax + GetColWidth(nNum);
+ }
+ else
+ return GetColWidth(nNum);
+}
+
+void SwTableFUNC::SetColWidth(sal_uInt16 nNum, SwTwips nNewWidth )
+{
+ // set current width
+ // move all of the following
+ bool bCurrentOnly = false;
+
+ if ( m_aCols.Count() > 0 )
+ {
+ if(m_aCols.Count() != GetColCount())
+ bCurrentOnly = true;
+ SwTwips nWidth = GetColWidth(nNum);
+
+ int nDiff = static_cast<int>(nNewWidth - nWidth);
+ if( !nNum )
+ m_aCols[ GetRightSeparator(0) ] += nDiff;
+ else if( nNum < GetColCount() )
+ {
+ if(nDiff < GetColWidth(nNum + 1) - MINLAY)
+ m_aCols[ GetRightSeparator(nNum) ] += nDiff;
+ else
+ {
+ int nDiffLeft = nDiff - static_cast<int>(GetColWidth(nNum + 1)) + int(MINLAY);
+ m_aCols[ GetRightSeparator(nNum) ] += (nDiff - nDiffLeft);
+ m_aCols[ GetRightSeparator(nNum - 1) ] -= nDiffLeft;
+ }
+ }
+ else
+ m_aCols[ GetRightSeparator(nNum-1) ] -= nDiff;
+ }
+ else
+ m_aCols.SetRight( std::min( nNewWidth, SwTwips(m_aCols.GetRightMax()) ) );
+
+ m_pSh->StartAllAction();
+ m_pSh->SetTabCols( m_aCols, bCurrentOnly );
+ m_pSh->EndAllAction();
+}
+
+void SwTableFUNC::InitTabCols()
+{
+ OSL_ENSURE(m_pSh, "no Shell");
+
+ if( m_pFormat && m_pSh)
+ m_pSh->GetTabCols( m_aCols );
+}
+
+SwTableFUNC::SwTableFUNC(SwWrtShell *pShell)
+ : m_pFormat(pShell->GetTableFormat()),
+ m_pSh(pShell)
+{
+}
+
+SwTableFUNC::~SwTableFUNC()
+{
+}
+
+void SwTableFUNC::UpdateChart()
+{
+ //Update of the fields triggered by the user, all Charts of
+ //the table will be brought up to date
+ SwFrameFormat *pFormat2 = m_pSh->GetTableFormat();
+ if ( pFormat2 && m_pSh->HasOLEObj( pFormat2->GetName() ) )
+ {
+ m_pSh->StartAllAction();
+ m_pSh->UpdateCharts( pFormat2->GetName() );
+ m_pSh->EndAllAction();
+ }
+}
+
+uno::Reference< frame::XModel > SwTableFUNC::InsertChart(
+ uno::Reference< chart2::data::XDataProvider > const &rxDataProvider,
+ bool bFillWithData,
+ const OUString &rCellRange,
+ SwFlyFrameFormat** ppFlyFrameFormat )
+{
+ uno::Reference< frame::XModel > xChartModel;
+ m_pSh->StartUndo( SwUndoId::UI_INSERT_CHART );
+ m_pSh->StartAllAction();
+
+ OUString aName;
+ if (m_pSh->IsCursorInTable())
+ {
+ aName = m_pSh->GetTableFormat()->GetName();
+ // insert node before table
+ m_pSh->MoveTable( GotoCurrTable, fnTableStart );
+ m_pSh->Up( false );
+ if ( m_pSh->IsCursorInTable() )
+ {
+ if ( aName != m_pSh->GetTableFormat()->GetName() )
+ m_pSh->Down( false ); // two adjacent tables
+ }
+ m_pSh->SplitNode();
+ }
+
+ // insert chart
+ OUString aObjName;
+ comphelper::EmbeddedObjectContainer aCnt;
+ uno::Reference < embed::XEmbeddedObject > xObj =
+ aCnt.CreateEmbeddedObject( SvGlobalName( SO3_SCH_CLASSID ).GetByteSequence(), aObjName );
+
+ ::svt::EmbeddedObjectRef aEmbObjRef( xObj, css::embed::Aspects::MSOLE_CONTENT );
+ if ( xObj.is() )
+ {
+
+ SwFlyFrameFormat* pTmp = nullptr;
+ m_pSh->InsertOleObject( aEmbObjRef, &pTmp );
+ if (ppFlyFrameFormat)
+ *ppFlyFrameFormat = pTmp;
+
+ xChartModel.set( xObj->getComponent(), uno::UNO_QUERY );
+ if( xChartModel.is() )
+ {
+ // Create a default chart type.
+ uno::Reference<chart2::XChartDocument> xChartDoc(xChartModel, uno::UNO_QUERY);
+ if (xChartDoc.is())
+ xChartDoc->createDefaultChart();
+
+ xChartModel->lockControllers(); //#i79578# don't request a new replacement image for charts to often - block change notifications
+ }
+
+ // set the table name at the OLE-node
+ if (!aName.isEmpty())
+ m_pSh->SetChartName( aName );
+ }
+ m_pSh->EndAllAction();
+
+ if (xObj.is() && !comphelper::LibreOfficeKit::isActive())
+ {
+ // Let the chart be activated after the inserting (unless
+ // via LibreOfficeKit)
+ SfxInPlaceClient* pClient = m_pSh->GetView().FindIPClient( xObj, &m_pSh->GetView().GetEditWin() );
+ if ( !pClient )
+ {
+ pClient = new SwOleClient( &m_pSh->GetView(), &m_pSh->GetView().GetEditWin(), aEmbObjRef );
+ m_pSh->SetCheckForOLEInCaption( true );
+ }
+ m_pSh->CalcAndSetScale( aEmbObjRef );
+ //#50270# We don't need to handle errors,
+ //this does the DoVerb in the SfxViewShell.
+ ErrCodeMsg nErr = pClient->DoVerb(embed::EmbedVerbs::MS_OLEVERB_SHOW);
+ (void) nErr;
+
+ // #i121334#
+ ChartHelper::AdaptDefaultsForChart( xObj );
+ }
+
+ uno::Reference< chart2::data::XDataReceiver > xDataReceiver( xChartModel, uno::UNO_QUERY );
+ if (bFillWithData && xDataReceiver.is() && rxDataProvider.is())
+ {
+ xDataReceiver->attachDataProvider( rxDataProvider );
+
+ uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( m_pSh->GetView().GetDocShell()->GetModel(), uno::UNO_QUERY );
+ xDataReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier );
+
+ // default values for ranges that do not consist of a single row or column
+ bool bHasCategories = true;
+ bool bFirstCellAsLabel = true;
+ chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
+
+ SwRangeDescriptor aDesc;
+ FillRangeDescriptor( aDesc, rCellRange );
+ bool bSingleRowCol = aDesc.nTop == aDesc.nBottom || aDesc.nLeft == aDesc.nRight;
+ if (bSingleRowCol)
+ {
+ aDesc.Normalize();
+ sal_Int32 nRowLen = aDesc.nRight - aDesc.nLeft + 1;
+ sal_Int32 nColLen = aDesc.nBottom - aDesc.nTop + 1;
+
+ bHasCategories = false;
+ if (nRowLen == 1 && nColLen == 1)
+ bFirstCellAsLabel = false;
+ else if (nRowLen > 1)
+ eDataRowSource = chart::ChartDataRowSource_ROWS;
+ else if (nColLen > 1)
+ eDataRowSource = chart::ChartDataRowSource_COLUMNS;
+ else {
+ OSL_FAIL("unexpected state" );
+ }
+ }
+
+ uno::Sequence< beans::PropertyValue > aArgs{
+ beans::PropertyValue(
+ "CellRangeRepresentation", -1,
+ uno::Any( rCellRange ), beans::PropertyState_DIRECT_VALUE ),
+ beans::PropertyValue(
+ "HasCategories", -1,
+ uno::Any( bHasCategories ), beans::PropertyState_DIRECT_VALUE ),
+ beans::PropertyValue(
+ "FirstCellAsLabel", -1,
+ uno::Any( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE ),
+ beans::PropertyValue(
+ "DataRowSource", -1,
+ uno::Any( eDataRowSource ), beans::PropertyState_DIRECT_VALUE )
+ };
+ xDataReceiver->setArguments( aArgs );
+ }
+
+ m_pSh->EndUndo( SwUndoId::UI_INSERT_CHART );
+
+ if( xChartModel.is() )
+ xChartModel->unlockControllers(); //#i79578# don't request a new replacement image for charts to often
+ return xChartModel;
+}
+
+sal_uInt16 SwTableFUNC::GetCurColNum() const
+{
+ const size_t nPos = m_pSh->GetCurTabColNum();
+ size_t nCount = 0;
+ for( size_t i = 0; i < nPos; i++ )
+ if(m_aCols.IsHidden(i))
+ nCount ++;
+ return nPos - nCount;
+}
+
+sal_uInt16 SwTableFUNC::GetColCount() const
+{
+ size_t nCount = 0;
+ for(size_t i = 0; i < m_aCols.Count(); i++ )
+ if(m_aCols.IsHidden(i))
+ nCount ++;
+ return m_aCols.Count() - nCount;
+}
+
+int SwTableFUNC::GetRightSeparator(int nNum) const
+{
+ OSL_ENSURE( nNum < static_cast<int>(GetColCount()) ,"Index out of range");
+ int i = 0;
+ while( nNum >= 0 )
+ {
+ if( !m_aCols.IsHidden(i) )
+ nNum--;
+ i++;
+ }
+ return i - 1;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/table/tablepg.hxx b/sw/source/uibase/table/tablepg.hxx
new file mode 100644
index 0000000000..b033cedc4d
--- /dev/null
+++ b/sw/source/uibase/table/tablepg.hxx
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+#include <prcntfld.hxx>
+#include <swtypes.hxx>
+#include <svx/frmdirlbox.hxx>
+
+class SwWrtShell;
+class SwTableRep;
+struct ImplSVEvent;
+
+class SwFormatTablePage : public SfxTabPage
+{
+ SwTableRep* m_pTableData;
+ std::unique_ptr<SwTableRep> m_xOrigTableData;
+ SwTwips m_nSaveWidth;
+ SwTwips m_nMinTableWidth;
+ bool m_bModified;
+ bool m_bFull:1;
+ bool m_bHtmlMode : 1;
+
+ std::unique_ptr<weld::Entry> m_xNameED;
+ std::unique_ptr<weld::Label> m_xWidthFT;
+ std::unique_ptr<SwPercentField> m_xWidthMF;
+ std::unique_ptr<weld::CheckButton> m_xRelWidthCB;
+
+ std::unique_ptr<weld::RadioButton> m_xFullBtn;
+ std::unique_ptr<weld::RadioButton> m_xLeftBtn;
+ std::unique_ptr<weld::RadioButton> m_xFromLeftBtn;
+ std::unique_ptr<weld::RadioButton> m_xRightBtn;
+ std::unique_ptr<weld::RadioButton> m_xCenterBtn;
+ std::unique_ptr<weld::RadioButton> m_xFreeBtn;
+
+ std::unique_ptr<weld::Label> m_xLeftFT;
+ std::unique_ptr<SwPercentField> m_xLeftMF;
+ std::unique_ptr<weld::Label> m_xRightFT;
+ std::unique_ptr<SwPercentField> m_xRightMF;
+ std::unique_ptr<weld::Label> m_xTopFT;
+ std::unique_ptr<weld::MetricSpinButton> m_xTopMF;
+ std::unique_ptr<weld::Label> m_xBottomFT;
+ std::unique_ptr<weld::MetricSpinButton> m_xBottomMF;
+
+ std::unique_ptr<svx::FrameDirectionListBox> m_xTextDirectionLB;
+ std::unique_ptr<weld::Widget> m_xProperties;
+
+ sal_Int64 m_nOrigWidthMin;
+ sal_Int64 m_nOrigWidthMax;
+ sal_Int64 m_nOrigLeftMin;
+ sal_Int64 m_nOrigLeftMax;
+ sal_Int64 m_nOrigRightMin;
+ sal_Int64 m_nOrigRightMax;
+
+ void Init();
+ void ModifyHdl(const weld::MetricSpinButton& rEdit, bool bAllowInconsistencies = false);
+
+ DECL_LINK(AutoClickHdl, weld::Toggleable&, void);
+ DECL_LINK(RelWidthClickHdl, weld::Toggleable&, void);
+ void RightModify();
+ DECL_LINK(ValueChangedHdl, weld::MetricSpinButton&, void);
+
+public:
+ SwFormatTablePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet );
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+ virtual ~SwFormatTablePage() override;
+
+ virtual bool FillItemSet( SfxItemSet* rSet ) override;
+ virtual void Reset( const SfxItemSet* rSet ) override;
+ virtual void ActivatePage( const SfxItemSet& rSet ) override;
+ virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override;
+};
+
+// TabPage Format/Table/Columns
+#define MET_FIELDS 5 //Number of the used MetricFields
+
+class SwTableColumnPage : public SfxTabPage
+{
+ SwTableRep* m_pTableData;
+ std::unique_ptr<SwTableRep> m_xOrigTableData;
+ ImplSVEvent* m_pSizeHdlEvent;
+ SwTwips m_nTableWidth;
+ SwTwips m_nMinWidth;
+ sal_uInt16 m_nMetFields;
+ sal_uInt16 m_nNoOfCols;
+ sal_uInt16 m_nNoOfVisibleCols;
+ // Remember the width, when switching to autoalign
+ sal_uInt16 m_aValueTable[MET_FIELDS];// primary assignment of the MetricFields
+ bool m_bModified:1;
+ bool m_bModifyTable:1;
+ bool m_bPercentMode:1;
+
+ SwPercentField m_aFieldArr[MET_FIELDS];
+ std::unique_ptr<weld::Label> m_aTextArr[MET_FIELDS];
+ std::unique_ptr<weld::CheckButton> m_xModifyTableCB;
+ std::unique_ptr<weld::CheckButton> m_xProportionalCB;
+ std::unique_ptr<weld::Label> m_xSpaceFT;
+ std::unique_ptr<weld::Label> m_xSpaceSFT;
+ std::unique_ptr<weld::MetricSpinButton> m_xSpaceED;
+ std::unique_ptr<weld::Button> m_xUpBtn;
+ std::unique_ptr<weld::Button> m_xDownBtn;
+
+ void Init(bool bWeb);
+ DECL_LINK(AutoClickHdl, weld::Button&, void);
+ void ModifyHdl(const weld::MetricSpinButton* pEdit);
+ DECL_LINK(ValueChangedHdl, weld::MetricSpinButton&, void);
+ DECL_LINK(ModeHdl, weld::Toggleable&, void);
+ void UpdateCols( sal_uInt16 nCurrentPos );
+ SwTwips GetVisibleWidth(sal_uInt16 nPos);
+ void SetVisibleWidth(sal_uInt16 nPos, SwTwips nNewWidth);
+ DECL_LINK(SizeHdl, void*, void);
+
+public:
+ SwTableColumnPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+ virtual ~SwTableColumnPage() override;
+
+ virtual bool FillItemSet( SfxItemSet* rSet ) override;
+ virtual void Reset( const SfxItemSet* rSet ) override;
+ virtual void ActivatePage( const SfxItemSet& rSet ) override;
+ virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override;
+
+};
+
+class SwTextFlowPage : public SfxTabPage
+{
+ SwWrtShell* m_pShell;
+ bool m_bPageBreak;
+ bool m_bHtmlMode;
+
+ std::unique_ptr<weld::CheckButton> m_xPgBrkCB;
+ std::unique_ptr<weld::RadioButton> m_xPgBrkRB;
+ std::unique_ptr<weld::RadioButton> m_xColBrkRB;
+ std::unique_ptr<weld::RadioButton> m_xPgBrkBeforeRB;
+ std::unique_ptr<weld::RadioButton> m_xPgBrkAfterRB;
+ std::unique_ptr<weld::CheckButton> m_xPageCollCB;
+ std::unique_ptr<weld::ComboBox> m_xPageCollLB;
+ std::unique_ptr<weld::CheckButton> m_xPageNoCB;
+ std::unique_ptr<weld::SpinButton> m_xPageNoNF;
+ std::unique_ptr<weld::CheckButton> m_xSplitCB;
+ std::unique_ptr<weld::CheckButton> m_xSplitRowCB;
+ std::unique_ptr<weld::CheckButton> m_xKeepCB;
+ std::unique_ptr<weld::CheckButton> m_xHeadLineCB;
+ std::unique_ptr<weld::Widget> m_xRepeatHeaderCombo;
+ std::unique_ptr<weld::SpinButton> m_xRepeatHeaderNF;
+ std::unique_ptr<weld::ComboBox> m_xTextDirectionLB;
+ std::unique_ptr<weld::ComboBox> m_xVertOrientLB;
+
+ DECL_LINK(PageBreakHdl_Impl, weld::Toggleable&, void);
+ DECL_LINK(ApplyCollClickHdl_Impl, weld::Toggleable&, void);
+ DECL_LINK(PageBreakPosHdl_Impl, weld::Toggleable&, void);
+ DECL_LINK(PageBreakTypeHdl_Impl, weld::Toggleable&, void);
+ DECL_LINK(PageNoClickHdl_Impl, weld::Toggleable&, void);
+ DECL_LINK(SplitHdl_Impl, weld::Toggleable&, void);
+ DECL_LINK(HeadLineCBClickHdl, weld::Toggleable&, void);
+
+public:
+ SwTextFlowPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+ virtual ~SwTextFlowPage() override;
+ virtual bool FillItemSet( SfxItemSet* rSet ) override;
+ virtual void Reset( const SfxItemSet* rSet ) override;
+
+ void SetShell(SwWrtShell* pSh);
+
+ void DisablePageBreak();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uitest/uiobject.cxx b/sw/source/uibase/uitest/uiobject.cxx
new file mode 100644
index 0000000000..097769e370
--- /dev/null
+++ b/sw/source/uibase/uitest/uiobject.cxx
@@ -0,0 +1,249 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <memory>
+#include <uiobject.hxx>
+#include <edtwin.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <ndtxt.hxx>
+#include <viewopt.hxx>
+#include <sfx2/sidebar/Sidebar.hxx>
+#include <sfx2/viewfrm.hxx>
+
+#include <AnnotationWin.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/editview.hxx>
+
+SwEditWinUIObject::SwEditWinUIObject(const VclPtr<SwEditWin>& xEditWin):
+ WindowUIObject(xEditWin),
+ mxEditWin(xEditWin)
+{
+}
+
+namespace {
+
+SwWrtShell& getWrtShell(VclPtr<SwEditWin> const & xEditWin)
+{
+ return xEditWin->GetView().GetWrtShell();
+}
+
+}
+
+StringMap SwEditWinUIObject::get_state()
+{
+ StringMap aMap = WindowUIObject::get_state();
+
+ aMap["SelectedText"] = mxEditWin->GetView().GetSelectionText();
+
+ sal_uInt16 nPageNum = 0;
+ sal_uInt16 nVirtPageNum = 0;
+ SwWrtShell& rWrtShell = getWrtShell(mxEditWin);
+ rWrtShell.GetPageNum(nPageNum, nVirtPageNum);
+ aMap["CurrentPage"] = OUString::number(nPageNum);
+ rWrtShell.GetPageNum(nPageNum, nVirtPageNum, false);
+ aMap["TopVisiblePage"] = OUString::number(nPageNum);
+ aMap["Zoom"] = OUString::number(rWrtShell.GetViewOptions()->GetZoom());
+
+ sal_uInt16 nPages = rWrtShell.GetPageCnt();
+ aMap["Pages"] = OUString::number(nPages);
+
+ aMap["StartWord"] = OUString::boolean(rWrtShell.IsStartWord());
+ aMap["EndWord"] = OUString::boolean(rWrtShell.IsEndWord());
+ aMap["StartSentence"] = OUString::boolean(rWrtShell.IsStartSentence());
+ aMap["EndSentence"] = OUString::boolean(rWrtShell.IsEndSentence());
+ aMap["StartPara"] = OUString::boolean(rWrtShell.IsSttPara());
+ aMap["EndPara"] = OUString::boolean(rWrtShell.IsEndPara());
+ aMap["StartDoc"] = OUString::boolean(rWrtShell.IsStartOfDoc());
+ aMap["EndDoc"] = OUString::boolean(rWrtShell.IsEndOfDoc());
+
+ return aMap;
+}
+
+void SwEditWinUIObject::execute(const OUString& rAction,
+ const StringMap& rParameters)
+{
+ if (rAction == "SET")
+ {
+ if (rParameters.find("ZOOM") != rParameters.end())
+ {
+ auto itr = rParameters.find("ZOOM");
+ OUString aVal = itr->second;
+ sal_Int32 nVal = aVal.toInt32();
+ mxEditWin->GetView().SetZoom(SvxZoomType::PERCENT, nVal);
+ }
+ }
+ else if (rAction == "GOTO")
+ {
+ if (rParameters.find("PAGE") != rParameters.end())
+ {
+ auto itr = rParameters.find("PAGE");
+ OUString aVal = itr->second;
+ sal_Int32 nVal = aVal.toInt32();
+ getWrtShell(mxEditWin).GotoPage(nVal, false);
+ }
+ }
+ else if (rAction == "SELECT")
+ {
+ if (rParameters.find("START_POS") != rParameters.end())
+ {
+ auto itr = rParameters.find("START_POS");
+ OUString aStartPos = itr->second;
+ TextFrameIndex const nStartPos(aStartPos.toInt32());
+
+ itr = rParameters.find("END_POS");
+ assert(itr != rParameters.end());
+ OUString aEndPos = itr->second;
+ TextFrameIndex const nEndPos(aEndPos.toInt32());
+
+ auto & shell = getWrtShell(mxEditWin);
+ if (shell.GetCursor_()->GetPoint()->GetNode().GetTextNode())
+ {
+ shell.Push();
+ shell.MovePara(GoCurrPara, fnParaEnd);
+ TextFrameIndex const len(shell.GetCursorPointAsViewIndex());
+ shell.Pop(SwCursorShell::PopMode::DeleteCurrent);
+ SAL_WARN_IF(
+ sal_Int32(nStartPos) < 0 || nStartPos > len || sal_Int32(nEndPos) < 0 || nEndPos > len, "sw.ui",
+ "SELECT START/END_POS " << sal_Int32(nStartPos) << ".." << sal_Int32(nEndPos) << " outside 0.." << sal_Int32(len));
+ shell.SelectTextView(
+ std::clamp(nStartPos, TextFrameIndex(0), len), std::clamp(nEndPos, TextFrameIndex(0), len));
+ }
+ else
+ {
+ SAL_WARN("sw.ui", "SELECT without SwTextNode");
+ }
+ }
+ }
+ else if (rAction == "SIDEBAR")
+ {
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ DBG_ASSERT(pViewFrm, "SwEditWinUIObject::execute: no viewframe");
+ pViewFrm->ShowChildWindow(SID_SIDEBAR);
+
+ if (rParameters.find("PANEL") != rParameters.end())
+ {
+ auto itr = rParameters.find("PANEL");
+ OUString aVal = itr->second;
+ ::sfx2::sidebar::Sidebar::ShowPanel(aVal, pViewFrm->GetFrame().GetFrameInterface());
+ }
+ }
+ else
+ WindowUIObject::execute(rAction, rParameters);
+}
+
+OUString SwEditWinUIObject::get_name() const
+{
+ return "SwEditWinUIObject";
+}
+
+std::unique_ptr<UIObject> SwEditWinUIObject::create(vcl::Window* pWindow)
+{
+ SwEditWin* pEditWin = dynamic_cast<SwEditWin*>(pWindow);
+ assert(pEditWin);
+ return std::unique_ptr<UIObject>(new SwEditWinUIObject(pEditWin));
+}
+
+CommentUIObject::CommentUIObject(const VclPtr<sw::annotation::SwAnnotationWin>& xCommentUIObject):
+ WindowUIObject(xCommentUIObject),
+ mxCommentUIObject(xCommentUIObject)
+{
+}
+
+StringMap CommentUIObject::get_state()
+{
+ StringMap aMap = WindowUIObject::get_state();
+ aMap["Author"] = mxCommentUIObject->GetAuthor();
+ aMap["ReadOnly"] = OUString::boolean(mxCommentUIObject->IsReadOnly());
+ aMap["Resolved"] = OUString::boolean(mxCommentUIObject->IsResolved());
+ aMap["Visible"] = OUString::boolean(mxCommentUIObject->IsVisible());
+
+ aMap["Text"] = mxCommentUIObject->GetOutliner()->GetEditEngine().GetText();
+ aMap["SelectedText"] = mxCommentUIObject->GetOutlinerView()->GetEditView().GetSelected();
+ return aMap;
+}
+
+void CommentUIObject::execute(const OUString& rAction,
+ const StringMap& rParameters)
+{
+ if (rAction == "SELECT")
+ {
+ if (rParameters.find("FROM") != rParameters.end() &&
+ rParameters.find("TO") != rParameters.end())
+ {
+ tools::Long nMin = rParameters.find("FROM")->second.toInt32();
+ tools::Long nMax = rParameters.find("TO")->second.toInt32();
+ ESelection aNewSelection( 0 , nMin, mxCommentUIObject->GetOutliner()->GetParagraphCount()-1, nMax );
+ mxCommentUIObject->GetOutlinerView()->SetSelection( aNewSelection );
+ }
+ }
+ else if (rAction == "LEAVE")
+ {
+ mxCommentUIObject->SwitchToFieldPos();
+ }
+ else if (rAction == "HIDE")
+ {
+ mxCommentUIObject->HideNote();
+ }
+ else if (rAction == "SHOW")
+ {
+ mxCommentUIObject->ShowNote();
+ }
+ else if (rAction == "DELETE")
+ {
+ mxCommentUIObject->Delete();
+ }
+ else if (rAction == "RESOLVE")
+ {
+ mxCommentUIObject->SetResolved(true);
+ }
+ else
+ WindowUIObject::execute(rAction, rParameters);
+}
+
+std::unique_ptr<UIObject> CommentUIObject::create(vcl::Window* pWindow)
+{
+ sw::annotation::SwAnnotationWin* pCommentUIObject = dynamic_cast<sw::annotation::SwAnnotationWin*>(pWindow);
+ assert(pCommentUIObject);
+ return std::unique_ptr<UIObject>(new CommentUIObject(pCommentUIObject));
+}
+
+OUString CommentUIObject::get_name() const
+{
+ return "CommentUIObject";
+}
+
+PageBreakUIObject::PageBreakUIObject(const VclPtr<SwBreakDashedLine>& xPageBreakUIObject):
+ WindowUIObject(xPageBreakUIObject),
+ mxPageBreakUIObject(xPageBreakUIObject)
+{
+}
+
+void PageBreakUIObject::execute(const OUString& rAction,
+ const StringMap& rParameters)
+{
+ if (rAction == "DELETE" || rAction == "EDIT")
+ mxPageBreakUIObject->execute(rAction.toAsciiLowerCase());
+ else
+ WindowUIObject::execute(rAction, rParameters);
+}
+
+std::unique_ptr<UIObject> PageBreakUIObject::create(vcl::Window* pWindow)
+{
+ SwBreakDashedLine* pPageBreakWin = dynamic_cast<SwBreakDashedLine*>(pWindow);
+ assert(pPageBreakWin);
+ return std::unique_ptr<UIObject>(new PageBreakUIObject(pPageBreakWin));
+}
+
+OUString PageBreakUIObject::get_name() const
+{
+ return "PageBreakUIObject";
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/formatclipboard.cxx b/sw/source/uibase/uiview/formatclipboard.cxx
new file mode 100644
index 0000000000..e722c04e90
--- /dev/null
+++ b/sw/source/uibase/uiview/formatclipboard.cxx
@@ -0,0 +1,590 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <utility>
+
+#include <formatclipboard.hxx>
+
+#include <cmdid.h>
+#include <charfmt.hxx>
+#include <frmfmt.hxx>
+#include <docstyle.hxx>
+#include <fchrfmt.hxx>
+#include <svx/svdview.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/formatbreakitem.hxx>
+#include <fmtlsplt.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtrowsplt.hxx>
+#include <frmatr.hxx>
+
+namespace
+{
+
+std::unique_ptr<SfxItemSet> lcl_CreateEmptyItemSet( SelectionType nSelectionType, SfxItemPool& rPool, bool bNoParagraphFormats = false )
+{
+ std::unique_ptr<SfxItemSet> pItemSet;
+ if( nSelectionType & (SelectionType::Frame | SelectionType::Ole | SelectionType::Graphic) )
+ {
+ pItemSet = std::make_unique<SfxItemSetFixed<
+ RES_FRMATR_BEGIN, RES_FILL_ORDER,
+ // no RES_FRM_SIZE
+ RES_PAPER_BIN, RES_SURROUND,
+ // no RES_VERT_ORIENT
+ // no RES_HORI_ORIENT
+ // no RES_ANCHOR
+ RES_BACKGROUND, RES_SHADOW,
+ // no RES_FRMMACRO
+ RES_COL, RES_KEEP,
+ // no RES_URL
+ RES_EDIT_IN_READONLY, RES_LAYOUT_SPLIT,
+ // no RES_CHAIN
+ RES_TEXTGRID, RES_FRMATR_END - 1>>(rPool);
+ }
+ else if( nSelectionType & SelectionType::DrawObject )
+ {
+ //is handled different
+ }
+ else if( nSelectionType & SelectionType::Text )
+ {
+ if( bNoParagraphFormats )
+ pItemSet = std::make_unique<SfxItemSetFixed
+ <RES_CHRATR_BEGIN, RES_CHRATR_END - 1>>(rPool);
+ else
+ pItemSet = std::make_unique<SfxItemSetFixed<
+ RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
+ RES_PARATR_BEGIN, RES_FILL_ORDER,
+ // no RES_FRM_SIZE
+ RES_PAPER_BIN, RES_SURROUND,
+ // no RES_VERT_ORIENT
+ // no RES_HORI_ORIENT
+ // no RES_ANCHOR
+ RES_BACKGROUND, RES_SHADOW,
+ // no RES_FRMMACRO
+ RES_COL, RES_KEEP,
+ // no RES_URL
+ RES_EDIT_IN_READONLY, RES_LAYOUT_SPLIT,
+ // no RES_CHAIN
+ RES_TEXTGRID, RES_FRMATR_END - 1>>(rPool);
+ }
+ return pItemSet;
+}
+
+void lcl_getTableAttributes( SfxItemSet& rSet, SwWrtShell &rSh )
+{
+ std::unique_ptr<SvxBrushItem> aBrush(std::make_unique<SvxBrushItem>(RES_BACKGROUND));
+ rSh.GetBoxBackground(aBrush);
+ rSet.Put( *aBrush );
+ if(rSh.GetRowBackground(aBrush))
+ {
+ aBrush->SetWhich(SID_ATTR_BRUSH_ROW);
+ rSet.Put( *aBrush );
+ }
+ else
+ rSet.InvalidateItem(SID_ATTR_BRUSH_ROW);
+ rSh.GetTabBackground(aBrush);
+ aBrush->SetWhich(SID_ATTR_BRUSH_TABLE);
+ rSet.Put( *aBrush );
+
+ SvxBoxInfoItem aBoxInfo( SID_ATTR_BORDER_INNER );
+ rSet.Put(aBoxInfo);
+ rSh.GetTabBorders( rSet );
+
+ std::unique_ptr<SvxFrameDirectionItem> aBoxDirection(std::make_unique<SvxFrameDirectionItem>(SvxFrameDirection::Environment, RES_FRAMEDIR));
+ if(rSh.GetBoxDirection( aBoxDirection ))
+ {
+ aBoxDirection->SetWhich(FN_TABLE_BOX_TEXTORIENTATION);
+ rSet.Put(std::move(aBoxDirection));
+ }
+
+ rSet.Put(SfxUInt16Item(FN_TABLE_SET_VERT_ALIGN, rSh.GetBoxAlign()));
+
+ rSet.Put( SfxUInt16Item( FN_PARAM_TABLE_HEADLINE, rSh.GetRowsToRepeat() ) );
+
+ SwFrameFormat *pFrameFormat = rSh.GetTableFormat();
+ if(pFrameFormat)
+ {
+ rSet.Put( pFrameFormat->GetShadow() );
+ rSet.Put( pFrameFormat->GetBreak() );
+ rSet.Put( pFrameFormat->GetPageDesc() );
+ rSet.Put( pFrameFormat->GetLayoutSplit() );
+ rSet.Put( pFrameFormat->GetKeep() );
+ rSet.Put( pFrameFormat->GetFrameDir() );
+ }
+
+ std::unique_ptr<SwFormatRowSplit> pSplit = rSh.GetRowSplit();
+ if(pSplit)
+ rSet.Put(std::move(pSplit));
+}
+
+void lcl_setTableAttributes( const SfxItemSet& rSet, SwWrtShell &rSh )
+{
+ bool bBorder = ( SfxItemState::SET == rSet.GetItemState( RES_BOX ) ||
+ SfxItemState::SET == rSet.GetItemState( SID_ATTR_BORDER_INNER ) );
+ const SvxBrushItem* pBackgroundItem = rSet.GetItemIfSet( RES_BACKGROUND, false );
+ const SvxBrushItem* pRowItem = rSet.GetItemIfSet( SID_ATTR_BRUSH_ROW, false );
+ const SvxBrushItem* pTableItem = rSet.GetItemIfSet( SID_ATTR_BRUSH_TABLE, false );
+ bool bBackground = pBackgroundItem || pRowItem || pTableItem;
+
+ if(bBackground)
+ {
+ if(pBackgroundItem)
+ rSh.SetBoxBackground( *pBackgroundItem );
+ if(pRowItem)
+ {
+ std::unique_ptr<SvxBrushItem> aBrush(pRowItem->Clone());
+ aBrush->SetWhich(RES_BACKGROUND);
+ rSh.SetRowBackground(*aBrush);
+ }
+ if(pTableItem)
+ {
+ std::unique_ptr<SvxBrushItem> aBrush(pTableItem->Clone());
+ aBrush->SetWhich(RES_BACKGROUND);
+ rSh.SetTabBackground(*aBrush);
+ }
+ }
+ if(bBorder)
+ rSh.SetTabBorders( rSet );
+
+ if( const SfxUInt16Item* pHeadlineItem = rSet.GetItemIfSet( FN_PARAM_TABLE_HEADLINE, false) )
+ rSh.SetRowsToRepeat( pHeadlineItem->GetValue() );
+
+ SwFrameFormat* pFrameFormat = rSh.GetTableFormat();
+ if(pFrameFormat)
+ {
+ //RES_SHADOW
+ const SfxPoolItem* pItem = rSet.GetItemIfSet(rSet.GetPool()->GetWhich(RES_SHADOW), false);
+ if(pItem)
+ pFrameFormat->SetFormatAttr( *pItem );
+
+ //RES_BREAK
+ pItem = rSet.GetItemIfSet(rSet.GetPool()->GetWhich(RES_BREAK), false);
+ if(pItem)
+ pFrameFormat->SetFormatAttr( *pItem );
+
+ //RES_PAGEDESC
+ pItem = rSet.GetItemIfSet(rSet.GetPool()->GetWhich(RES_PAGEDESC), false);
+ if(pItem)
+ pFrameFormat->SetFormatAttr( *pItem );
+
+ //RES_LAYOUT_SPLIT
+ pItem = rSet.GetItemIfSet(rSet.GetPool()->GetWhich(RES_LAYOUT_SPLIT), false);
+ if(pItem)
+ pFrameFormat->SetFormatAttr( *pItem );
+
+ //RES_KEEP
+ pItem = rSet.GetItemIfSet(rSet.GetPool()->GetWhich(RES_KEEP), false);
+ if(pItem)
+ pFrameFormat->SetFormatAttr( *pItem );
+
+ //RES_FRAMEDIR
+ pItem = rSet.GetItemIfSet(rSet.GetPool()->GetWhich(RES_FRAMEDIR), false);
+ if(pItem)
+ pFrameFormat->SetFormatAttr( *pItem );
+ }
+
+ if( const SvxFrameDirectionItem* pTextOriItem = rSet.GetItemIfSet( FN_TABLE_BOX_TEXTORIENTATION, false ) )
+ {
+ SvxFrameDirectionItem aDirection( SvxFrameDirection::Environment, RES_FRAMEDIR );
+ aDirection.SetValue(pTextOriItem->GetValue());
+ rSh.SetBoxDirection(aDirection);
+ }
+
+ if( const SfxUInt16Item* pVertAlignItem = rSet.GetItemIfSet( FN_TABLE_SET_VERT_ALIGN, false ))
+ rSh.SetBoxAlign(pVertAlignItem->GetValue());
+
+ if( const SwFormatRowSplit* pSplitItem = rSet.GetItemIfSet( RES_ROW_SPLIT, false ) )
+ rSh.SetRowSplit(*pSplitItem);
+}
+}//end anonymous namespace
+
+SwFormatClipboard::SwFormatClipboard()
+ : m_nSelectionType(SelectionType::NONE)
+ , m_bPersistentCopy(false)
+{
+}
+
+bool SwFormatClipboard::HasContent() const
+{
+ return m_pItemSet_TextAttr!=nullptr
+ || m_pItemSet_ParAttr!=nullptr
+ || m_pTableItemSet != nullptr
+ || !m_aCharStyle.isEmpty()
+ || !m_aParaStyle.isEmpty()
+ ;
+}
+bool SwFormatClipboard::HasContentForThisType( SelectionType nSelectionType ) const
+{
+ if( !HasContent() )
+ return false;
+
+ if( m_nSelectionType == nSelectionType )
+ return true;
+
+ if( ( nSelectionType & (SelectionType::Frame | SelectionType::Ole | SelectionType::Graphic) )
+ &&
+ ( m_nSelectionType & (SelectionType::Frame | SelectionType::Ole | SelectionType::Graphic) )
+ )
+ return true;
+
+ if( nSelectionType & SelectionType::Text && m_nSelectionType & SelectionType::Text )
+ return true;
+
+ return false;
+}
+
+bool SwFormatClipboard::CanCopyThisType( SelectionType nSelectionType )
+{
+ return bool(nSelectionType
+ & (SelectionType::Frame | SelectionType::Ole | SelectionType::Graphic
+ | SelectionType::Text | SelectionType::DrawObject | SelectionType::Table | SelectionType::TableCell ));
+}
+
+void SwFormatClipboard::Copy( SwWrtShell& rWrtShell, SfxItemPool& rPool, bool bPersistentCopy )
+{
+ // first clear the previously stored attributes
+ Erase();
+ m_bPersistentCopy = bPersistentCopy;
+
+ SelectionType nSelectionType = rWrtShell.GetSelectionType();
+ auto pItemSet_TextAttr = lcl_CreateEmptyItemSet( nSelectionType, rPool, true );
+ auto pItemSet_ParAttr = lcl_CreateEmptyItemSet( nSelectionType, rPool );
+
+ rWrtShell.StartAction();
+ rWrtShell.Push();
+
+ // modify the "Point and Mark" of the cursor
+ // in order to select only the last character of the
+ // selection(s) and then to get the attributes of this single character
+ if( nSelectionType == SelectionType::Text )
+ {
+ // get the current PaM, the cursor
+ // if there several selection it currently point
+ // on the last (sort by there creation time) selection
+ SwPaM* pCursor = rWrtShell.GetCursor();
+
+ bool bHasSelection = pCursor->HasMark();
+ bool bForwardSelection = false;
+
+ if(!bHasSelection && pCursor->IsMultiSelection())
+ {
+ // if cursor has multiple selections
+
+ // clear all the selections except the last
+ rWrtShell.KillPams();
+
+ // reset the cursor to the remaining selection
+ pCursor = rWrtShell.GetCursor();
+ bHasSelection = true;
+ }
+
+ bool dontMove = false;
+ if (bHasSelection)
+ {
+ bForwardSelection = (*pCursor->GetPoint()) > (*pCursor->GetMark());
+
+ // clear the selection leaving just the cursor
+ pCursor->DeleteMark();
+ pCursor->SetMark();
+ }
+ else
+ {
+ bool rightToLeft = rWrtShell.IsInRightToLeftText();
+ // if there were no selection (only a cursor) and the cursor was at
+ // the end of the paragraph then don't move
+ if ( rWrtShell.IsEndPara() && !rightToLeft )
+ dontMove = true;
+
+ // revert left and right
+ if ( rightToLeft )
+ {
+ if (pCursor->GetPoint()->GetContentIndex() == 0)
+ dontMove = true;
+ else
+ bForwardSelection = !bForwardSelection;
+ }
+ }
+
+ // move the cursor in order to select one character
+ if (!dontMove)
+ pCursor->Move( bForwardSelection ? fnMoveBackward : fnMoveForward );
+ }
+
+ if(pItemSet_TextAttr)
+ {
+ if( nSelectionType & (SelectionType::Frame | SelectionType::Ole | SelectionType::Graphic) )
+ rWrtShell.GetFlyFrameAttr(*pItemSet_TextAttr);
+ else
+ {
+ // get the text attributes from named and automatic formatting
+ rWrtShell.GetCurAttr(*pItemSet_TextAttr);
+
+ if( nSelectionType & SelectionType::Text )
+ {
+ // get the paragraph attributes (could be character properties)
+ // from named and automatic formatting
+ rWrtShell.GetCurParAttr(*pItemSet_ParAttr);
+ }
+ }
+ }
+ else if ( nSelectionType & SelectionType::DrawObject )
+ {
+ SdrView* pDrawView = rWrtShell.GetDrawView();
+ if(pDrawView)
+ {
+ if( pDrawView->AreObjectsMarked() )
+ {
+ pItemSet_TextAttr = std::make_unique<SfxItemSet>( pDrawView->GetAttrFromMarked(true/*bOnlyHardAttr*/) );
+ //remove attributes defining the type/data of custom shapes
+ pItemSet_TextAttr->ClearItem(SDRATTR_CUSTOMSHAPE_ENGINE);
+ pItemSet_TextAttr->ClearItem(SDRATTR_CUSTOMSHAPE_DATA);
+ pItemSet_TextAttr->ClearItem(SDRATTR_CUSTOMSHAPE_GEOMETRY);
+ }
+ }
+ }
+
+ if( nSelectionType & SelectionType::TableCell )//only copy table attributes if really cells are selected (not only text in tables)
+ {
+ m_pTableItemSet = std::make_unique<SfxItemSetFixed<
+ RES_PAGEDESC, RES_BREAK,
+ RES_BACKGROUND, RES_SHADOW, // RES_BOX is inbetween
+ RES_KEEP, RES_KEEP,
+ RES_LAYOUT_SPLIT, RES_LAYOUT_SPLIT,
+ RES_FRAMEDIR, RES_FRAMEDIR,
+ RES_ROW_SPLIT, RES_ROW_SPLIT,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_SHADOW,
+ // SID_ATTR_BORDER_OUTER is inbetween
+ SID_ATTR_BRUSH_ROW, SID_ATTR_BRUSH_TABLE,
+ FN_TABLE_SET_VERT_ALIGN, FN_TABLE_SET_VERT_ALIGN,
+ FN_TABLE_BOX_TEXTORIENTATION, FN_TABLE_BOX_TEXTORIENTATION,
+ FN_PARAM_TABLE_HEADLINE, FN_PARAM_TABLE_HEADLINE>>(rPool);
+ lcl_getTableAttributes( *m_pTableItemSet, rWrtShell );
+ }
+
+ m_nSelectionType = nSelectionType;
+ m_pItemSet_TextAttr = std::move(pItemSet_TextAttr);
+ m_pItemSet_ParAttr = std::move(pItemSet_ParAttr);
+
+ if( nSelectionType & SelectionType::Text )
+ {
+ // if text is selected save the named character format
+ SwFormat* pFormat = rWrtShell.GetCurCharFormat();
+ if( pFormat )
+ m_aCharStyle = pFormat->GetName();
+
+ // and the named paragraph format
+ pFormat = rWrtShell.GetCurTextFormatColl();
+ if( pFormat )
+ m_aParaStyle = pFormat->GetName();
+ }
+
+ rWrtShell.Pop(SwCursorShell::PopMode::DeleteCurrent);
+ rWrtShell.EndAction();
+}
+
+typedef std::vector< std::unique_ptr< SfxPoolItem > > ItemVector;
+// collect all PoolItems from the applied styles
+static void lcl_AppendSetItems( ItemVector& rItemVector, const SfxItemSet& rStyleAttrSet )
+{
+ const WhichRangesContainer& pRanges = rStyleAttrSet.GetRanges();
+ for(const auto & rPair : pRanges)
+ {
+ for ( sal_uInt16 nWhich = rPair.first; nWhich <= rPair.second; ++nWhich )
+ {
+ const SfxPoolItem* pItem;
+ if( SfxItemState::SET == rStyleAttrSet.GetItemState( nWhich, false, &pItem ) )
+ {
+ rItemVector.emplace_back( pItem->Clone() );
+ }
+ }
+ }
+}
+// remove all items that are inherited from the styles
+static void lcl_RemoveEqualItems( SfxItemSet& rTemplateItemSet, const ItemVector& rItemVector )
+{
+ for( const auto& rItem : rItemVector )
+ {
+ const SfxPoolItem* pItem;
+ if( SfxItemState::SET == rTemplateItemSet.GetItemState( rItem->Which(), true, &pItem ) &&
+ *pItem == *rItem )
+ {
+ rTemplateItemSet.ClearItem( rItem->Which() );
+ }
+ }
+}
+
+void SwFormatClipboard::Paste( SwWrtShell& rWrtShell, SfxStyleSheetBasePool* pPool
+ , bool bNoCharacterFormats, bool bNoParagraphFormats )
+{
+ SelectionType nSelectionType = rWrtShell.GetSelectionType();
+ if( !HasContentForThisType(nSelectionType) )
+ {
+ if(!m_bPersistentCopy)
+ Erase();
+ return;
+ }
+
+ rWrtShell.StartAction();
+ rWrtShell.StartUndo(SwUndoId::INSATTR);
+
+ ItemVector aItemVector;
+
+ if (m_pItemSet_TextAttr && !( nSelectionType & SelectionType::DrawObject))
+ {
+ // reset all direct formatting before applying anything
+ o3tl::sorted_vector<sal_uInt16> aAttrs;
+ for (sal_uInt16 nWhich = RES_CHRATR_BEGIN; nWhich < RES_CHRATR_END; nWhich++)
+ aAttrs.insert(nWhich);
+ rWrtShell.ResetAttr({ aAttrs });
+ }
+
+ if( nSelectionType & SelectionType::Text )
+ {
+ // apply the named text and paragraph formatting
+ if( pPool )
+ {
+ // if there is a named text format recorded and the user wants to apply it
+ if(!m_aCharStyle.isEmpty() && !bNoCharacterFormats )
+ {
+ // look for the named text format in the pool
+ SwDocStyleSheet* pStyle = static_cast<SwDocStyleSheet*>(pPool->Find(m_aCharStyle, SfxStyleFamily::Char));
+
+ // if the style is found
+ if( pStyle )
+ {
+ SwFormatCharFormat aFormat(pStyle->GetCharFormat());
+ // store the attributes from this style in aItemVector in order
+ // not to apply them as automatic formatting attributes later in the code
+ lcl_AppendSetItems( aItemVector, aFormat.GetCharFormat()->GetAttrSet());
+
+ // apply the named format
+ rWrtShell.SetAttrItem( aFormat );
+ }
+ }
+
+ // if there is a named paragraph format recorded and the user wants to apply it
+ if(!m_aParaStyle.isEmpty() && !bNoParagraphFormats )
+ {
+ // look for the named paragraph format in the pool
+ SwDocStyleSheet* pStyle = static_cast<SwDocStyleSheet*>(pPool->Find(m_aParaStyle, SfxStyleFamily::Para));
+ if( pStyle )
+ {
+ // store the attributes from this style in aItemVector in order
+ // not to apply them as automatic formatting attributes later in the code
+ lcl_AppendSetItems( aItemVector, pStyle->GetCollection()->GetAttrSet());
+
+ // apply the named format
+ rWrtShell.SetTextFormatColl( pStyle->GetCollection() );
+ }
+ }
+ }
+
+ // apply the paragraph automatic attributes
+ if ( m_pItemSet_ParAttr && m_pItemSet_ParAttr->Count() != 0 && !bNoParagraphFormats )
+ {
+ // temporary SfxItemSet
+ std::unique_ptr<SfxItemSet> pTemplateItemSet(lcl_CreateEmptyItemSet(
+ nSelectionType, *m_pItemSet_ParAttr->GetPool()));
+ // no need to verify the existence of pTemplateItemSet as we
+ // know that here the selection type is SEL_TXT
+
+ pTemplateItemSet->Put( *m_pItemSet_ParAttr );
+
+ // remove attribute that were applied by named text and paragraph formatting
+ lcl_RemoveEqualItems( *pTemplateItemSet, aItemVector );
+
+ // apply the paragraph automatic attributes to all the nodes in the selection
+ rWrtShell.SetAttrSet(*pTemplateItemSet);
+
+ // store the attributes in aItemVector in order not to apply them as
+ // text automatic formatting attributes later in the code
+ lcl_AppendSetItems( aItemVector, *pTemplateItemSet);
+ }
+ }
+
+ if(m_pItemSet_TextAttr)
+ {
+ if( nSelectionType & SelectionType::DrawObject )
+ {
+ SdrView* pDrawView = rWrtShell.GetDrawView();
+ if(pDrawView)
+ {
+ pDrawView->SetAttrToMarked(*m_pItemSet_TextAttr, true/*bReplaceAll*/);
+ }
+ }
+ else
+ {
+ // temporary SfxItemSet
+ std::unique_ptr<SfxItemSet> pTemplateItemSet(lcl_CreateEmptyItemSet(
+ nSelectionType, *m_pItemSet_TextAttr->GetPool(), true ));
+
+ if(pTemplateItemSet)
+ {
+ // copy the stored automatic text attributes in a temporary SfxItemSet
+ pTemplateItemSet->Put( *m_pItemSet_TextAttr );
+
+ // only attributes that were not apply by named style attributes and automatic
+ // paragraph attributes should be applied
+ lcl_RemoveEqualItems( *pTemplateItemSet, aItemVector );
+
+ // apply the character automatic attributes
+ if( nSelectionType & (SelectionType::Frame | SelectionType::Ole | SelectionType::Graphic) )
+ rWrtShell.SetFlyFrameAttr(*pTemplateItemSet);
+ else if ( !bNoCharacterFormats )
+ {
+ rWrtShell.SetAttrSet(*pTemplateItemSet);
+ }
+ }
+ }
+ }
+
+ if( m_pTableItemSet && nSelectionType & (SelectionType::Table | SelectionType::TableCell) )
+ lcl_setTableAttributes( *m_pTableItemSet, rWrtShell );
+
+ rWrtShell.EndUndo(SwUndoId::INSATTR);
+ rWrtShell.EndAction();
+
+ if(!m_bPersistentCopy)
+ Erase();
+}
+
+void SwFormatClipboard::Erase()
+{
+ m_nSelectionType = SelectionType::NONE;
+
+ m_pItemSet_TextAttr.reset();
+
+ m_pItemSet_ParAttr.reset();
+
+ m_pTableItemSet.reset();
+
+ if( !m_aCharStyle.isEmpty() )
+ m_aCharStyle.clear();
+ if( !m_aParaStyle.isEmpty() )
+ m_aParaStyle.clear();
+
+ m_bPersistentCopy = false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/pview.cxx b/sw/source/uibase/uiview/pview.cxx
new file mode 100644
index 0000000000..0b03a001d0
--- /dev/null
+++ b/sw/source/uibase/uiview/pview.cxx
@@ -0,0 +1,1905 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_wasm_strip.h>
+
+#include <sfx2/objface.hxx>
+#include <vcl/help.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/syswin.hxx>
+#include <vcl/weld.hxx>
+
+#include <svl/whiter.hxx>
+#include <svl/slstitm.hxx>
+#include <svl/eitem.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/dispatch.hxx>
+#include <editeng/paperinf.hxx>
+#include <svx/svdview.hxx>
+#include <svx/viewlayoutitem.hxx>
+#include <svx/zoomslideritem.hxx>
+#include <tools/svborder.hxx>
+#include <osl/diagnose.h>
+
+#include <globdoc.hxx>
+#include <wdocsh.hxx>
+#include <pvprtdat.hxx>
+#include <swmodule.hxx>
+#include <wrtsh.hxx>
+#include <docsh.hxx>
+#include <viewopt.hxx>
+#include <doc.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <pview.hxx>
+#include <view.hxx>
+#include <scroll.hxx>
+#include <prtopt.hxx>
+#include <usrpref.hxx>
+#include "viewfunc.hxx"
+
+#include <helpids.h>
+#include <cmdid.h>
+#include <strings.hrc>
+
+#define ShellClass_SwPagePreview
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+#include <pagepreviewlayout.hxx>
+
+#include <svx/svxdlg.hxx>
+
+#include <memory>
+#include <vcl/EnumContext.hxx>
+#include <vcl/notebookbar/notebookbar.hxx>
+
+using namespace ::com::sun::star;
+SFX_IMPL_NAMED_VIEWFACTORY(SwPagePreview, "PrintPreview")
+{
+ SFX_VIEW_REGISTRATION(SwDocShell);
+ SFX_VIEW_REGISTRATION(SwWebDocShell);
+ SFX_VIEW_REGISTRATION(SwGlobalDocShell);
+}
+
+SFX_IMPL_INTERFACE(SwPagePreview, SfxViewShell)
+
+void SwPagePreview::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("preview");
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT,
+ SfxVisibilityFlags::Standard|SfxVisibilityFlags::Client|SfxVisibilityFlags::FullScreen|SfxVisibilityFlags::ReadonlyDoc,
+ ToolbarId::PView_Toolbox);
+}
+
+
+#define SWVIEWFLAGS SfxViewShellFlags::HAS_PRINTOPTIONS
+
+#define MIN_PREVIEW_ZOOM 25
+#define MAX_PREVIEW_ZOOM 600
+
+static sal_uInt16 lcl_GetNextZoomStep(sal_uInt16 nCurrentZoom, bool bZoomIn)
+{
+ static const sal_uInt16 aZoomArr[] =
+ {
+ 25, 50, 75, 100, 150, 200, 400, 600
+ };
+ const int nZoomArrSize = static_cast<int>(SAL_N_ELEMENTS(aZoomArr));
+ if (bZoomIn)
+ {
+ for(sal_uInt16 i : aZoomArr)
+ {
+ if(nCurrentZoom < i)
+ return i;
+ }
+ }
+ else
+ {
+ for(int i = nZoomArrSize - 1; i >= 0; --i)
+ {
+ if(nCurrentZoom > aZoomArr[i] || !i)
+ return aZoomArr[i];
+ }
+ }
+ return bZoomIn ? MAX_PREVIEW_ZOOM : MIN_PREVIEW_ZOOM;
+};
+
+static void lcl_InvalidateZoomSlots(SfxBindings& rBindings)
+{
+ static sal_uInt16 const aInval[] =
+ {
+ SID_ATTR_ZOOM, SID_ZOOM_OUT, SID_ZOOM_IN, SID_ATTR_ZOOMSLIDER, FN_PREVIEW_ZOOM, FN_STAT_ZOOM,
+ 0
+ };
+ rBindings.Invalidate( aInval );
+}
+
+namespace {
+
+// At first the zoom dialog
+class SwPreviewZoomDlg : public weld::GenericDialogController
+{
+ SwPagePreviewWin& m_rParent;
+ std::unique_ptr<weld::SpinButton> m_xRowEdit;
+ std::unique_ptr<weld::SpinButton> m_xColEdit;
+
+public:
+ SwPreviewZoomDlg(SwPagePreviewWin& rParent)
+ : GenericDialogController(rParent.GetFrameWeld(), "modules/swriter/ui/previewzoomdialog.ui", "PreviewZoomDialog")
+ , m_rParent(rParent)
+ , m_xRowEdit(m_xBuilder->weld_spin_button("rows"))
+ , m_xColEdit(m_xBuilder->weld_spin_button("cols"))
+ {
+ m_xRowEdit->set_value(rParent.GetRow());
+ m_xColEdit->set_value(rParent.GetCol());
+ }
+
+ void execute()
+ {
+ if (run() == RET_OK)
+ {
+ m_rParent.CalcWish(m_xRowEdit->get_value(), m_xColEdit->get_value());
+ }
+ }
+};
+
+}
+
+// all for SwPagePreviewWin
+SwPagePreviewWin::SwPagePreviewWin( vcl::Window *pParent, SwPagePreview& rPView )
+ : Window(pParent, WinBits(WB_CLIPCHILDREN))
+ , mpViewShell(nullptr)
+ , mrView(rPView)
+ , mbCalcScaleForPreviewLayout(true)
+ , maPaintedPreviewDocRect(tools::Rectangle(0,0,0,0))
+ , mpPgPreviewLayout(nullptr)
+{
+ GetOutDev()->SetOutDevViewType( OutDevViewType::PrintPreview );
+ SetHelpId(HID_PAGEPREVIEW);
+ GetOutDev()->SetFillColor( GetBackground().GetColor() );
+ GetOutDev()->SetLineColor( GetBackground().GetColor());
+ SetMapMode( MapMode(MapUnit::MapTwip) );
+
+ const SwMasterUsrPref *pUsrPref = SW_MOD()->GetUsrPref(false);
+ mnRow = pUsrPref->GetPagePrevRow(); // 1 row
+ mnCol = pUsrPref->GetPagePrevCol(); // 1 column
+ mnSttPage = USHRT_MAX;
+}
+
+SwPagePreviewWin::~SwPagePreviewWin()
+{
+}
+
+void SwPagePreviewWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ if (!mpViewShell || !mpViewShell->GetLayout())
+ return;
+
+ if (USHRT_MAX == mnSttPage) // was never calculated ? (Init-Phase!)
+ {
+ // This is the size to which I always relate.
+ if (!maPxWinSize.Height() || !maPxWinSize.Width())
+ maPxWinSize = GetOutputSizePixel();
+
+ tools::Rectangle aRect(rRenderContext.LogicToPixel(rRect));
+ mpPgPreviewLayout->Prepare(1, Point(0,0), maPxWinSize,
+ mnSttPage, maPaintedPreviewDocRect);
+ SetSelectedPage(1);
+ mpPgPreviewLayout->Paint(rRenderContext, rRenderContext.PixelToLogic(aRect));
+ SetPagePreview(mnRow, mnCol);
+ }
+ else
+ {
+ MapMode aMM(rRenderContext.GetMapMode());
+ aMM.SetScaleX(maScale);
+ aMM.SetScaleY(maScale);
+ rRenderContext.SetMapMode(aMM);
+ mpPgPreviewLayout->GetParentViewShell().setOutputToWindow(true);
+ mpPgPreviewLayout->Paint(rRenderContext, rRect);
+ mpPgPreviewLayout->GetParentViewShell().setOutputToWindow(false);
+ }
+}
+
+void SwPagePreviewWin::CalcWish( sal_Int16 nNewRow, sal_Int16 nNewCol )
+{
+ if( !mpViewShell || !mpViewShell->GetLayout() )
+ return;
+
+ const sal_Int16 nOldCol = mnCol;
+ mnRow = nNewRow;
+ mnCol = nNewCol;
+ const sal_uInt16 nPages = mnRow * mnCol;
+ const sal_uInt16 nLastSttPg = mrView.GetPageCount()+1 > nPages
+ ? mrView.GetPageCount()+1 - nPages : 0;
+ if( mnSttPage > nLastSttPg )
+ mnSttPage = nLastSttPg;
+
+ mpPgPreviewLayout->Init( mnCol, mnRow, maPxWinSize );
+ mpPgPreviewLayout->Prepare( mnSttPage, Point(0,0), maPxWinSize,
+ mnSttPage, maPaintedPreviewDocRect );
+ SetSelectedPage( mnSttPage );
+ SetPagePreview(mnRow, mnCol);
+ maScale = GetMapMode().GetScaleX();
+
+ // If changes have taken place at the columns, the special case "single column"
+ // must be considered and corrected if necessary.
+ if( (1 == nOldCol) != (1 == mnCol) )
+ mrView.ScrollDocSzChg();
+
+ // Order must be maintained!
+ // additional invalidate page status.
+ static sal_uInt16 aInval[] =
+ {
+ SID_ATTR_ZOOM, SID_ZOOM_OUT, SID_ZOOM_IN,
+ FN_PREVIEW_ZOOM,
+ FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT, FN_PAGEUP, FN_PAGEDOWN,
+ FN_STAT_PAGE, FN_STAT_ZOOM,
+ FN_SHOW_TWO_PAGES, FN_SHOW_MULTIPLE_PAGES,
+ 0
+ };
+ SfxBindings& rBindings = mrView.GetViewFrame().GetBindings();
+ rBindings.Invalidate( aInval );
+ rBindings.Update( FN_SHOW_TWO_PAGES );
+ rBindings.Update( FN_SHOW_MULTIPLE_PAGES );
+ // adjust scrollbars
+ mrView.ScrollViewSzChg();
+}
+
+// mnSttPage is Absolute
+bool SwPagePreviewWin::MovePage( int eMoveMode )
+{
+ // number of pages up
+ const sal_uInt16 nPages = mnRow * mnCol;
+ sal_uInt16 nNewSttPage = mnSttPage;
+ const sal_uInt16 nPageCount = mrView.GetPageCount();
+ const sal_uInt16 nDefSttPg = GetDefSttPage();
+ bool bPaintPageAtFirstCol = true;
+
+ switch( eMoveMode )
+ {
+ case MV_PAGE_UP:
+ {
+ const sal_uInt16 nRelSttPage = mpPgPreviewLayout->ConvertAbsoluteToRelativePageNum( mnSttPage );
+ const sal_uInt16 nNewAbsSttPage = nRelSttPage - nPages > 0 ?
+ mpPgPreviewLayout->ConvertRelativeToAbsolutePageNum( nRelSttPage - nPages ) :
+ nDefSttPg;
+ nNewSttPage = nNewAbsSttPage;
+
+ const sal_uInt16 nRelSelPage = mpPgPreviewLayout->ConvertAbsoluteToRelativePageNum( SelectedPage() );
+ const sal_uInt16 nNewRelSelPage = nRelSelPage - nPages > 0 ?
+ nRelSelPage - nPages :
+ 1;
+ SetSelectedPage( mpPgPreviewLayout->ConvertRelativeToAbsolutePageNum( nNewRelSelPage ) );
+
+ break;
+ }
+ case MV_PAGE_DOWN:
+ {
+ const sal_uInt16 nRelSttPage = mpPgPreviewLayout->ConvertAbsoluteToRelativePageNum( mnSttPage );
+ const sal_uInt16 nNewAbsSttPage = mpPgPreviewLayout->ConvertRelativeToAbsolutePageNum( nRelSttPage + nPages );
+ nNewSttPage = std::min(nNewAbsSttPage, nPageCount);
+
+ const sal_uInt16 nRelSelPage = mpPgPreviewLayout->ConvertAbsoluteToRelativePageNum( SelectedPage() );
+ const sal_uInt16 nNewAbsSelPage = mpPgPreviewLayout->ConvertRelativeToAbsolutePageNum( nRelSelPage + nPages );
+ SetSelectedPage( std::min(nNewAbsSelPage, nPageCount) );
+
+ break;
+ }
+ case MV_DOC_STT:
+ nNewSttPage = nDefSttPg;
+ SetSelectedPage( mpPgPreviewLayout->ConvertRelativeToAbsolutePageNum( nNewSttPage ? nNewSttPage : 1 ) );
+ break;
+ case MV_DOC_END:
+ // correct calculation of new start page.
+ nNewSttPage = nPageCount;
+ SetSelectedPage( nPageCount );
+ break;
+
+ case MV_SELPAGE:
+ // <nNewSttPage> and <SelectedPage()> are already set.
+ // not start at first column, only if the
+ // complete preview layout columns doesn't fit into window.
+ if ( !mpPgPreviewLayout->DoesPreviewLayoutColsFitIntoWindow() )
+ bPaintPageAtFirstCol = false;
+ break;
+ case MV_SCROLL:
+ // check, if paint page at first column
+ // has to be avoided
+ if ( !mpPgPreviewLayout->DoesPreviewLayoutRowsFitIntoWindow() ||
+ !mpPgPreviewLayout->DoesPreviewLayoutColsFitIntoWindow() )
+ bPaintPageAtFirstCol = false;
+ break;
+ case MV_NEWWINSIZE:
+ // nothing special to do.
+ break;
+ case MV_CALC:
+ // re-init page preview layout.
+ mpPgPreviewLayout->ReInit();
+
+ // correct calculation of new start page.
+ if( nNewSttPage > nPageCount )
+ nNewSttPage = nPageCount;
+
+ // correct selected page number
+ if( SelectedPage() > nPageCount )
+ SetSelectedPage( nNewSttPage ? nNewSttPage : 1 );
+ }
+
+ mpPgPreviewLayout->Prepare( nNewSttPage, Point(0,0), maPxWinSize,
+ nNewSttPage,
+ maPaintedPreviewDocRect, bPaintPageAtFirstCol );
+ if( nNewSttPage == mnSttPage &&
+ eMoveMode != MV_SELPAGE )
+ return false;
+
+ SetPagePreview(mnRow, mnCol);
+ mnSttPage = nNewSttPage;
+
+ // additional invalidate page status.
+ static sal_uInt16 aInval[] =
+ {
+ FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT, FN_PAGEUP, FN_PAGEDOWN,
+ FN_STAT_PAGE, 0
+ };
+
+ SfxBindings& rBindings = mrView.GetViewFrame().GetBindings();
+ rBindings.Invalidate( aInval );
+
+ return true;
+}
+
+void SwPagePreviewWin::SetWinSize( const Size& rNewSize )
+{
+ // We always want the size as pixel units.
+ maPxWinSize = LogicToPixel( rNewSize );
+
+ if( USHRT_MAX == mnSttPage )
+ {
+ mnSttPage = GetDefSttPage();
+ SetSelectedPage( GetDefSttPage() );
+ }
+
+ if ( mbCalcScaleForPreviewLayout )
+ {
+ mpPgPreviewLayout->Init( mnCol, mnRow, maPxWinSize );
+ maScale = GetMapMode().GetScaleX();
+ }
+ mpPgPreviewLayout->Prepare( mnSttPage, Point(0,0), maPxWinSize,
+ mnSttPage, maPaintedPreviewDocRect );
+ if ( mbCalcScaleForPreviewLayout )
+ {
+ SetSelectedPage( mnSttPage );
+ mbCalcScaleForPreviewLayout = false;
+ }
+ SetPagePreview(mnRow, mnCol);
+ maScale = GetMapMode().GetScaleX();
+}
+
+OUString SwPagePreviewWin::GetStatusStr( sal_uInt16 nPageCnt ) const
+{
+ // show physical and virtual page number of
+ // selected page, if it's visible.
+ const sal_uInt16 nPageNum = mpPgPreviewLayout->IsPageVisible( mpPgPreviewLayout->SelectedPage() )
+ ? mpPgPreviewLayout->SelectedPage() : std::max<sal_uInt16>(mnSttPage, 1);
+
+ OUString aStatusStr;
+ const sal_uInt16 nVirtPageNum = mpPgPreviewLayout->GetVirtPageNumByPageNum( nPageNum );
+ if( nVirtPageNum && nVirtPageNum != nPageNum )
+ {
+ aStatusStr = OUString::number(nVirtPageNum) + " " ;
+ }
+ return aStatusStr + OUString::number(nPageNum) + " / " + OUString::number(nPageCnt);
+}
+
+void SwPagePreviewWin::KeyInput( const KeyEvent &rKEvt )
+{
+ const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
+ bool bHandled = false;
+ if(!rKeyCode.GetModifier())
+ {
+ sal_uInt16 nSlot = 0;
+ switch(rKeyCode.GetCode())
+ {
+ case KEY_ADD : nSlot = SID_ZOOM_IN; break;
+ case KEY_ESCAPE: nSlot = FN_CLOSE_PAGEPREVIEW; break;
+ case KEY_SUBTRACT : nSlot = SID_ZOOM_OUT; break;
+ }
+ if(nSlot)
+ {
+ bHandled = true;
+ mrView.GetViewFrame().GetDispatcher()->Execute(
+ nSlot, SfxCallMode::ASYNCHRON );
+ }
+ }
+ if( !bHandled && !mrView.KeyInput( rKEvt ) )
+ Window::KeyInput( rKEvt );
+}
+
+void SwPagePreviewWin::Command( const CommandEvent& rCEvt )
+{
+ bool bCallBase = true;
+ switch( rCEvt.GetCommand() )
+ {
+ case CommandEventId::ContextMenu:
+ SfxDispatcher::ExecutePopup();
+ bCallBase = false;
+ break;
+
+ case CommandEventId::Wheel:
+ case CommandEventId::StartAutoScroll:
+ case CommandEventId::AutoScroll:
+ {
+ const CommandWheelData* pData = rCEvt.GetWheelData();
+ if( pData )
+ {
+ const CommandWheelData aDataNew(pData->GetDelta(),pData->GetNotchDelta(),COMMAND_WHEEL_PAGESCROLL,
+ pData->GetMode(),pData->GetModifier(),pData->IsHorz(), pData->IsDeltaPixel());
+ const CommandEvent aEvent( rCEvt.GetMousePosPixel(),rCEvt.GetCommand(),rCEvt.IsMouseEvent(),&aDataNew);
+ bCallBase = !mrView.HandleWheelCommands( aEvent );
+ }
+ else
+ bCallBase = !mrView.HandleWheelCommands( rCEvt );
+ }
+ break;
+ default:
+ ;
+ }
+
+ if( bCallBase )
+ Window::Command( rCEvt );
+}
+
+void SwPagePreviewWin::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ // consider single-click to set selected page
+ if( MOUSE_LEFT != ( rMEvt.GetModifier() + rMEvt.GetButtons() ) )
+ return;
+
+ Point aPreviewPos( PixelToLogic( rMEvt.GetPosPixel() ) );
+ Point aDocPos;
+ bool bPosInEmptyPage;
+ sal_uInt16 nNewSelectedPage;
+ bool bIsDocPos =
+ mpPgPreviewLayout->IsPreviewPosInDocPreviewPage( aPreviewPos,
+ aDocPos, bPosInEmptyPage, nNewSelectedPage );
+ if ( bIsDocPos && rMEvt.GetClicks() == 2 )
+ {
+ // close page preview, set new cursor position and switch to
+ // normal view.
+ OUString sNewCursorPos = OUString::number( aDocPos.X() ) + ";" +
+ OUString::number( aDocPos.Y() ) + ";";
+ mrView.SetNewCursorPos( sNewCursorPos );
+
+ SfxViewFrame& rTmpFrame = mrView.GetViewFrame();
+ rTmpFrame.GetBindings().Execute( SID_VIEWSHELL0, nullptr,
+ SfxCallMode::ASYNCHRON );
+ }
+ else if ( bIsDocPos || bPosInEmptyPage )
+ {
+ // show clicked page as the selected one
+ mpPgPreviewLayout->MarkNewSelectedPage( nNewSelectedPage );
+ GetViewShell()->ShowPreviewSelection( nNewSelectedPage );
+ // adjust position at vertical scrollbar.
+ if ( mpPgPreviewLayout->DoesPreviewLayoutRowsFitIntoWindow() )
+ {
+ mrView.SetVScrollbarThumbPos( nNewSelectedPage );
+ }
+ // invalidate page status.
+ static sal_uInt16 aInval[] =
+ {
+ FN_STAT_PAGE, 0
+ };
+ SfxBindings& rBindings = mrView.GetViewFrame().GetBindings();
+ rBindings.Invalidate( aInval );
+ }
+}
+
+// Set user prefs or view options
+
+void SwPagePreviewWin::SetPagePreview( sal_Int16 nRow, sal_Int16 nCol )
+{
+ SwMasterUsrPref *pOpt = const_cast<SwMasterUsrPref *>(SW_MOD()->GetUsrPref(false));
+
+ if (nRow != pOpt->GetPagePrevRow() || nCol != pOpt->GetPagePrevCol())
+ {
+ pOpt->SetPagePrevRow( nRow );
+ pOpt->SetPagePrevCol( nCol );
+ pOpt->SetModified();
+
+ // Update scrollbar!
+ mrView.ScrollViewSzChg();
+ }
+}
+
+/** get selected page in document preview */
+sal_uInt16 SwPagePreviewWin::SelectedPage() const
+{
+ return mpPgPreviewLayout->SelectedPage();
+}
+
+/** set selected page number in document preview */
+void SwPagePreviewWin::SetSelectedPage( sal_uInt16 _nSelectedPageNum )
+{
+ mpPgPreviewLayout->SetSelectedPage( _nSelectedPageNum );
+}
+
+/** method to enable/disable book preview */
+bool SwPagePreviewWin::SetBookPreviewMode( const bool _bBookPreview )
+{
+ return mpPgPreviewLayout->SetBookPreviewMode( _bBookPreview,
+ mnSttPage,
+ maPaintedPreviewDocRect );
+}
+
+void SwPagePreviewWin::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ switch( rDCEvt.GetType() )
+ {
+ case DataChangedEventType::SETTINGS:
+ // Rearrange the scrollbars or trigger resize, because the
+ // size of the scrollbars may have be changed. Also the
+ // size of the scrollbars has to be retrieved from the settings
+ // out of the resize handler.
+ if( rDCEvt.GetFlags() & AllSettingsFlags::STYLE )
+ mrView.InvalidateBorder(); // Scrollbar widths
+ // zoom has to be disabled if Accessibility support is switched on
+ lcl_InvalidateZoomSlots(mrView.GetViewFrame().GetBindings());
+ break;
+
+ case DataChangedEventType::PRINTER:
+ case DataChangedEventType::DISPLAY:
+ case DataChangedEventType::FONTS:
+ case DataChangedEventType::FONTSUBSTITUTION:
+ mrView.GetDocShell()->UpdateFontList(); // Font change
+ mpViewShell->InvalidateLayout(true);
+ if ( mpViewShell->GetWin() )
+ mpViewShell->GetWin()->Invalidate();
+ break;
+ default: break;
+ }
+}
+
+/** help method to execute SfxRequest FN_PAGEUP and FN_PAGEDOWN */
+void SwPagePreview::ExecPgUpAndPgDown( const bool _bPgUp,
+ SfxRequest* _pReq )
+{
+ SwPagePreviewLayout* pPagePreviewLay = GetViewShell()->PagePreviewLayout();
+ // check, if top/bottom of preview is *not* already visible.
+ if( pPagePreviewLay->GetWinPagesScrollAmount( _bPgUp ? -1 : 1 ) != 0 )
+ {
+ if ( pPagePreviewLay->DoesPreviewLayoutRowsFitIntoWindow() &&
+ pPagePreviewLay->DoesPreviewLayoutColsFitIntoWindow() )
+ {
+ const int eMvMode = _bPgUp ?
+ SwPagePreviewWin::MV_PAGE_UP :
+ SwPagePreviewWin::MV_PAGE_DOWN;
+ if ( ChgPage( eMvMode ) )
+ m_pViewWin->Invalidate();
+ }
+ else
+ {
+ SwTwips nScrollAmount;
+ sal_uInt16 nNewSelectedPageNum = 0;
+ const sal_uInt16 nVisPages = m_pViewWin->GetRow() * m_pViewWin->GetCol();
+ if( _bPgUp )
+ {
+ if ( pPagePreviewLay->DoesPreviewLayoutRowsFitIntoWindow() )
+ {
+ nScrollAmount = pPagePreviewLay->GetWinPagesScrollAmount( -1 );
+ if ( (m_pViewWin->SelectedPage() - nVisPages) > 0 )
+ nNewSelectedPageNum = m_pViewWin->SelectedPage() - nVisPages;
+ else
+ nNewSelectedPageNum = 1;
+ }
+ else
+ nScrollAmount = - std::min( m_pViewWin->GetOutDev()->GetOutputSize().Height(),
+ m_pViewWin->GetPaintedPreviewDocRect().Top() );
+ }
+ else
+ {
+ if ( pPagePreviewLay->DoesPreviewLayoutRowsFitIntoWindow() )
+ {
+ nScrollAmount = pPagePreviewLay->GetWinPagesScrollAmount( 1 );
+ if ( (m_pViewWin->SelectedPage() + nVisPages) <= mnPageCount )
+ nNewSelectedPageNum = m_pViewWin->SelectedPage() + nVisPages;
+ else
+ nNewSelectedPageNum = mnPageCount;
+ }
+ else
+ nScrollAmount = std::min( m_pViewWin->GetOutDev()->GetOutputSize().Height(),
+ ( pPagePreviewLay->GetPreviewDocSize().Height() -
+ m_pViewWin->GetPaintedPreviewDocRect().Bottom() ) );
+ }
+ m_pViewWin->Scroll( 0, nScrollAmount );
+ if ( nNewSelectedPageNum != 0 )
+ {
+ m_pViewWin->SetSelectedPage( nNewSelectedPageNum );
+ }
+ ScrollViewSzChg();
+ // additional invalidate page status.
+ static sal_uInt16 aInval[] =
+ {
+ FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT, FN_PAGEUP, FN_PAGEDOWN,
+ FN_STAT_PAGE, 0
+ };
+ SfxBindings& rBindings = GetViewFrame().GetBindings();
+ rBindings.Invalidate( aInval );
+ m_pViewWin->Invalidate();
+ }
+ }
+
+ if ( _pReq )
+ _pReq->Done();
+}
+
+// Then all for the SwPagePreview
+void SwPagePreview::Execute( SfxRequest &rReq )
+{
+ int eMvMode = SwPagePreviewWin::MV_DOC_END;
+ sal_Int16 nRow = 1;
+ bool bRefresh = true;
+
+ switch(rReq.GetSlot())
+ {
+ case SID_REFRESH_VIEW:
+ case FN_STAT_PAGE:
+ case FN_STAT_ZOOM:
+ break;
+
+ case FN_SHOW_MULTIPLE_PAGES:
+ {
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ if( pArgs && pArgs->Count() >= 2 )
+ {
+ sal_Int16 nCols = pArgs->Get(SID_ATTR_TABLE_COLUMN).GetValue();
+ sal_Int16 nRows = pArgs->Get(SID_ATTR_TABLE_ROW).GetValue();
+ m_pViewWin->CalcWish( nRows, nCols );
+
+ }
+ else
+ {
+ SwPreviewZoomDlg aDlg(*m_pViewWin);
+ aDlg.execute();
+ }
+ }
+ break;
+ case FN_SHOW_BOOKVIEW:
+ {
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem;
+ bool bBookPreview = GetViewShell()->GetViewOptions()->IsPagePrevBookview();
+ if( pArgs && SfxItemState::SET == pArgs->GetItemState( FN_SHOW_BOOKVIEW, false, &pItem ) )
+ {
+ bBookPreview = static_cast< const SfxBoolItem* >( pItem )->GetValue();
+ const_cast<SwViewOption*>(GetViewShell()->GetViewOptions())->SetPagePrevBookview( bBookPreview );
+ // cast is not gentleman like, but it's common use in writer and in this case
+ }
+ if ( m_pViewWin->SetBookPreviewMode( bBookPreview ) )
+ {
+ // book preview mode changed. Thus, adjust scrollbars and
+ // invalidate corresponding states.
+ ScrollViewSzChg();
+ static sal_uInt16 aInval[] =
+ {
+ FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT, FN_PAGEUP, FN_PAGEDOWN,
+ FN_STAT_PAGE, FN_SHOW_BOOKVIEW, 0
+ };
+ SfxBindings& rBindings = GetViewFrame().GetBindings();
+ rBindings.Invalidate( aInval );
+ m_pViewWin->Invalidate();
+ }
+
+ }
+ break;
+ case FN_SHOW_TWO_PAGES:
+ m_pViewWin->CalcWish( nRow, 2 );
+ break;
+
+ case FN_SHOW_SINGLE_PAGE:
+ m_pViewWin->CalcWish( nRow, 1 );
+ break;
+
+ case FN_PREVIEW_ZOOM:
+ case SID_ATTR_ZOOM:
+ {
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ ScopedVclPtr<AbstractSvxZoomDialog> pDlg;
+ if(!pArgs)
+ {
+ SfxItemSetFixed<SID_ATTR_ZOOM, SID_ATTR_ZOOM> aCoreSet(GetPool());
+ const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
+ SvxZoomItem aZoom( pVOpt->GetZoomType(), pVOpt->GetZoom() );
+ aZoom.SetValueSet(
+ SvxZoomEnableFlags::N50|
+ SvxZoomEnableFlags::N75|
+ SvxZoomEnableFlags::N100|
+ SvxZoomEnableFlags::N150|
+ SvxZoomEnableFlags::N200|
+ SvxZoomEnableFlags::WHOLEPAGE);
+ aCoreSet.Put( aZoom );
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ pDlg.disposeAndReset(pFact->CreateSvxZoomDialog(GetViewFrame().GetFrameWeld(), aCoreSet));
+ pDlg->SetLimits( MINZOOM, MAXZOOM );
+
+ if( pDlg->Execute() != RET_CANCEL )
+ pArgs = pDlg->GetOutputItemSet();
+ }
+ if( pArgs )
+ {
+ SvxZoomType eType = SvxZoomType::PERCENT;
+ sal_uInt16 nZoomFactor = USHRT_MAX;
+ if(const SvxZoomItem* pZoomItem = pArgs->GetItemIfSet(SID_ATTR_ZOOM))
+ {
+ eType = pZoomItem->GetType();
+ nZoomFactor = pZoomItem->GetValue();
+ }
+ else if(const SfxUInt16Item* pPreviewItem = pArgs->GetItemIfSet(FN_PREVIEW_ZOOM))
+ nZoomFactor = pPreviewItem->GetValue();
+ if(USHRT_MAX != nZoomFactor)
+ SetZoom(eType, nZoomFactor);
+ }
+ }
+ break;
+ case SID_ATTR_ZOOMSLIDER :
+ {
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ const SvxZoomSliderItem* pItem;
+
+ if ( pArgs && (pItem = pArgs->GetItemIfSet(SID_ATTR_ZOOMSLIDER ) ) )
+ {
+ const sal_uInt16 nCurrentZoom = pItem->GetValue();
+ SetZoom( SvxZoomType::PERCENT, nCurrentZoom );
+ }
+ }
+ break;
+ case SID_ZOOM_IN:
+ case SID_ZOOM_OUT:
+ {
+ const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
+ SetZoom(SvxZoomType::PERCENT,
+ lcl_GetNextZoomStep(pVOpt->GetZoom(), SID_ZOOM_IN == rReq.GetSlot()));
+ }
+ break;
+ case FN_CHAR_LEFT:
+ case FN_CHAR_RIGHT:
+ case FN_LINE_UP:
+ case FN_LINE_DOWN:
+ {
+ SwPagePreviewLayout* pPagePreviewLay = GetViewShell()->PagePreviewLayout();
+ sal_uInt16 nNewSelectedPage;
+ sal_uInt16 nNewStartPage;
+ Point aNewStartPos;
+ sal_Int16 nHoriMove = 0;
+ sal_Int16 nVertMove = 0;
+ switch(rReq.GetSlot())
+ {
+ case FN_CHAR_LEFT: nHoriMove = -1; break;
+ case FN_CHAR_RIGHT: nHoriMove = 1; break;
+ case FN_LINE_UP: nVertMove = -1; break;
+ case FN_LINE_DOWN: nVertMove = 1; break;
+ }
+ pPagePreviewLay->CalcStartValuesForSelectedPageMove( nHoriMove, nVertMove,
+ nNewSelectedPage, nNewStartPage, aNewStartPos );
+ if ( m_pViewWin->SelectedPage() != nNewSelectedPage )
+ {
+ if ( pPagePreviewLay->IsPageVisible( nNewSelectedPage ) )
+ {
+ pPagePreviewLay->MarkNewSelectedPage( nNewSelectedPage );
+ // adjust position at vertical scrollbar.
+ SetVScrollbarThumbPos( nNewSelectedPage );
+ bRefresh = false;
+ }
+ else
+ {
+ m_pViewWin->SetSelectedPage( nNewSelectedPage );
+ m_pViewWin->SetSttPage( nNewStartPage );
+ bRefresh = ChgPage( SwPagePreviewWin::MV_SELPAGE );
+ }
+ GetViewShell()->ShowPreviewSelection( nNewSelectedPage );
+ // invalidate page status.
+ static sal_uInt16 aInval[] =
+ {
+ FN_STAT_PAGE, 0
+ };
+ SfxBindings& rBindings = GetViewFrame().GetBindings();
+ rBindings.Invalidate( aInval );
+ rReq.Done();
+ }
+ else
+ {
+ bRefresh = false;
+ }
+ break;
+ }
+ case FN_PAGEUP:
+ case FN_PAGEDOWN:
+ {
+ ExecPgUpAndPgDown( rReq.GetSlot() == FN_PAGEUP, &rReq );
+ break;
+ }
+ case SID_JUMP_TO_SPECIFIC_PAGE:
+ {
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ if( pArgs && pArgs->Count())
+ {
+ sal_uInt16 nPageNum = static_cast<const SfxUInt16Item &>(pArgs->Get(SID_JUMP_TO_SPECIFIC_PAGE)).GetValue();
+
+ if( nPageNum > 0 && nPageNum <= mnPageCount )
+ {
+ m_pViewWin->SetSttPage( nPageNum);
+ m_pViewWin->SetSelectedPage( nPageNum );
+ ChgPage( SwPagePreviewWin::MV_SPECIFIC_PAGE, false );
+ ScrollViewSzChg();
+ }
+ }
+ }
+ break;
+ case FN_START_OF_LINE:
+ case FN_START_OF_DOCUMENT:
+ eMvMode = SwPagePreviewWin::MV_DOC_STT;
+ [[fallthrough]];
+ case FN_END_OF_LINE:
+ case FN_END_OF_DOCUMENT:
+ m_pViewWin->SetSelectedPage(eMvMode == SwPagePreviewWin::MV_DOC_STT ? 1 : mnPageCount);
+ {
+ bool bRet = ChgPage( eMvMode );
+ // return value for Basic
+ rReq.SetReturnValue(SfxBoolItem(rReq.GetSlot(), !bRet));
+
+ bRefresh = bRet;
+ rReq.Done();
+ }
+ break;
+
+ case FN_PRINT_PAGEPREVIEW:
+ {
+ const SwPagePreviewPrtData* pPPVPD = m_pViewWin->GetViewShell()->GetDoc()->GetPreviewPrtData();
+ // The thing with the orientation
+ if(pPPVPD)
+ {
+ SfxPrinter* pPrinter = GetPrinter( true );
+ if((pPrinter->GetOrientation() == Orientation::Landscape)
+ != pPPVPD->GetLandscape())
+ pPrinter->SetOrientation(pPPVPD->GetLandscape() ? Orientation::Landscape : Orientation::Portrait);
+ }
+ ::SetAppPrintOptions( m_pViewWin->GetViewShell(), false );
+ m_bNormalPrint = false;
+ rReq.SetSlot( SID_PRINTDOC );
+ SfxViewShell::ExecuteSlot( rReq, SfxViewShell::GetInterface() );
+ rReq.SetSlot( FN_PRINT_PAGEPREVIEW );
+ return;
+ }
+ case SID_PRINTDOCDIRECT:
+ case SID_PRINTDOC:
+ ::SetAppPrintOptions( m_pViewWin->GetViewShell(), false );
+ m_bNormalPrint = true;
+ SfxViewShell::ExecuteSlot( rReq, SfxViewShell::GetInterface() );
+ return;
+ case FN_CLOSE_PAGEPREVIEW:
+ case SID_PRINTPREVIEW:
+ // print preview is now always in the same frame as the tab view
+ // -> always switch this frame back to normal view
+ // (ScTabViewShell ctor reads stored view data)
+ GetViewFrame().GetDispatcher()->Execute( SID_VIEWSHELL0, SfxCallMode::ASYNCHRON );
+ break;
+ case FN_INSERT_BREAK:
+ {
+ sal_uInt16 nSelPage = m_pViewWin->SelectedPage();
+ //if a dummy page is selected (e.g. a non-existing right/left page)
+ //the direct neighbor is used
+ if(GetViewShell()->IsDummyPage( nSelPage ) && GetViewShell()->IsDummyPage( --nSelPage ))
+ nSelPage +=2;
+ m_nNewPage = nSelPage;
+ SfxViewFrame& rTmpFrame = GetViewFrame();
+ rTmpFrame.GetBindings().Execute( SID_VIEWSHELL0, nullptr,
+ SfxCallMode::ASYNCHRON );
+ }
+ break;
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ return;
+ }
+
+ if( bRefresh )
+ m_pViewWin->Invalidate();
+}
+
+void SwPagePreview::GetState( SfxItemSet& rSet )
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ OSL_ENSURE(nWhich, "empty set");
+ SwPagePreviewLayout* pPagePreviewLay = GetViewShell()->PagePreviewLayout();
+
+ while(nWhich)
+ {
+ switch(nWhich)
+ {
+ case SID_BROWSER_MODE:
+ case FN_PRINT_LAYOUT:
+ rSet.DisableItem(nWhich);
+ break;
+ case FN_START_OF_DOCUMENT:
+ {
+ if ( pPagePreviewLay->IsPageVisible( 1 ) )
+ rSet.DisableItem(nWhich);
+ break;
+ }
+ case FN_END_OF_DOCUMENT:
+ {
+ if ( pPagePreviewLay->IsPageVisible( mnPageCount ) )
+ rSet.DisableItem(nWhich);
+ break;
+ }
+ case FN_PAGEUP:
+ {
+ if( pPagePreviewLay->GetWinPagesScrollAmount( -1 ) == 0 )
+ rSet.DisableItem(nWhich);
+ break;
+ }
+ case FN_PAGEDOWN:
+ {
+ if( pPagePreviewLay->GetWinPagesScrollAmount( 1 ) == 0 )
+ rSet.DisableItem(nWhich);
+ break;
+ }
+
+ case FN_STAT_PAGE:
+ {
+ std::vector<OUString> aStringList
+ {
+ m_sPageStr + m_pViewWin->GetStatusStr(mnPageCount),
+ OUString()
+ };
+ rSet.Put(SfxStringListItem(FN_STAT_PAGE, &aStringList));
+ }
+ break;
+
+ case SID_ATTR_ZOOM:
+ case FN_STAT_ZOOM:
+ {
+ const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
+ SvxZoomItem aZoom(pVOpt->GetZoomType(), pVOpt->GetZoom());
+ aZoom.SetValueSet(
+ SvxZoomEnableFlags::N50|
+ SvxZoomEnableFlags::N75|
+ SvxZoomEnableFlags::N100|
+ SvxZoomEnableFlags::N150|
+ SvxZoomEnableFlags::N200);
+ rSet.Put( aZoom );
+ }
+ break;
+ case SID_ATTR_ZOOMSLIDER :
+ {
+ const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
+ const sal_uInt16 nCurrentZoom = pVOpt->GetZoom();
+ SvxZoomSliderItem aZoomSliderItem( nCurrentZoom, MINZOOM, MAXZOOM );
+ aZoomSliderItem.AddSnappingPoint( 100 );
+ rSet.Put( aZoomSliderItem );
+ }
+ break;
+ case FN_PREVIEW_ZOOM:
+ {
+ const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
+ rSet.Put(SfxUInt16Item(nWhich, pVOpt->GetZoom()));
+ }
+ break;
+ case SID_ZOOM_IN:
+ case SID_ZOOM_OUT:
+ {
+ const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
+ if((SID_ZOOM_IN == nWhich && pVOpt->GetZoom() >= MAX_PREVIEW_ZOOM) ||
+ (SID_ZOOM_OUT == nWhich && pVOpt->GetZoom() <= MIN_PREVIEW_ZOOM))
+ {
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+ case SID_ATTR_VIEWLAYOUT:
+ {
+ rSet.DisableItem( SID_ATTR_VIEWLAYOUT );
+ }
+ break;
+ case FN_SHOW_MULTIPLE_PAGES:
+ // should never be disabled
+ break;
+ case FN_SHOW_BOOKVIEW:
+ {
+ bool b = GetViewShell()->GetViewOptions()->IsPagePrevBookview();
+ rSet.Put(SfxBoolItem(nWhich, b));
+ }
+ break;
+
+ case FN_SHOW_TWO_PAGES:
+ if( 2 == m_pViewWin->GetCol() && 1 == m_pViewWin->GetRow() )
+ rSet.DisableItem( nWhich );
+ break;
+
+ case FN_PRINT_PAGEPREVIEW:
+ // has the same status like the normal printing
+ {
+ const SfxPoolItem* pItem;
+ SfxItemSetFixed<SID_PRINTDOC, SID_PRINTDOC> aSet( *rSet.GetPool() );
+ GetSlotState( SID_PRINTDOC, SfxViewShell::GetInterface(), &aSet );
+ if( SfxItemState::DISABLED == aSet.GetItemState( SID_PRINTDOC, false ))
+ rSet.DisableItem( nWhich );
+ else if( SfxItemState::SET == aSet.GetItemState( SID_PRINTDOC,
+ false, &pItem ))
+ {
+ const_cast<SfxPoolItem*>(pItem)->SetWhich( FN_PRINT_PAGEPREVIEW );
+ rSet.Put( *pItem );
+ }
+ }
+ break;
+
+ case SID_PRINTPREVIEW:
+ rSet.Put( SfxBoolItem( nWhich, true ) );
+ break;
+
+ case SID_PRINTDOC:
+ case SID_PRINTDOCDIRECT:
+ GetSlotState( nWhich, SfxViewShell::GetInterface(), &rSet );
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwPagePreview::StateUndo(SfxItemSet& rSet)
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while (nWhich)
+ {
+ rSet.DisableItem(nWhich);
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwPagePreview::Init()
+{
+ if ( GetViewShell()->HasDrawView() )
+ GetViewShell()->GetDrawView()->SetAnimationEnabled( false );
+
+ m_bNormalPrint = true;
+
+ // Check and process the DocSize. The shell could not be found via
+ // the handler, because the shell is unknown to the SFX management
+ // within the CTOR phase.
+
+ const SwViewOption * pPrefs = SW_MOD()->GetUsrPref(false);
+
+ mbHScrollbarEnabled = pPrefs->IsViewHScrollBar();
+ mbVScrollbarEnabled = pPrefs->IsViewVScrollBar();
+
+ // Update the fields
+ // ATTENTION: Do cast the EditShell up, to use the SS.
+ // At the methods the current shell will be queried!
+ SwEditShell* pESh = dynamic_cast<SwEditShell*>(GetViewShell());
+ bool bIsModified = pESh != nullptr && pESh->IsModified();
+
+ SwViewOption aOpt( *pPrefs );
+ aOpt.SetPagePreview(true);
+ aOpt.SetTab( false );
+ aOpt.SetBlank( false );
+ aOpt.SetHardBlank( false );
+ aOpt.SetParagraph( false );
+ aOpt.SetLineBreak( false );
+ aOpt.SetPageBreak( false );
+ aOpt.SetColumnBreak( false );
+ aOpt.SetSoftHyph( false );
+ aOpt.SetFieldName( false );
+ aOpt.SetPostIts( false );
+ aOpt.SetShowBookmarks( false );
+ aOpt.SetShowHiddenChar( false );
+ aOpt.SetShowHiddenField( false );
+ aOpt.SetShowHiddenPara( false );
+ aOpt.SetViewHRuler( false );
+ aOpt.SetViewVRuler( false );
+ aOpt.SetGraphic( true );
+ aOpt.SetTable( true );
+ aOpt.SetSnap( false );
+ aOpt.SetGridVisible( false );
+ aOpt.SetOnlineSpell( false );
+ aOpt.SetHideWhitespaceMode( false );
+
+ GetViewShell()->ApplyViewOptions( aOpt );
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ GetViewShell()->ApplyAccessibilityOptions();
+#endif
+
+ // adjust view shell option to the same as for print
+ SwPrintData const aPrintOptions = *SW_MOD()->GetPrtOptions(false);
+ GetViewShell()->AdjustOptionsForPagePreview( aPrintOptions );
+
+ GetViewShell()->CalcLayout();
+ DocSzChgd( GetViewShell()->GetDocSize() );
+
+ if( !bIsModified && pESh != nullptr )
+ pESh->ResetModified();
+}
+
+SwPagePreview::SwPagePreview(SfxViewFrame& rViewFrame, SfxViewShell* pOldSh):
+ SfxViewShell(rViewFrame, SWVIEWFLAGS),
+ m_pViewWin( VclPtr<SwPagePreviewWin>::Create(&GetViewFrame().GetWindow(), *this ) ),
+ m_nNewPage(USHRT_MAX),
+ m_sPageStr(SwResId(STR_PAGE)),
+ m_pHScrollbar(nullptr),
+ m_pVScrollbar(nullptr),
+ mnPageCount( 0 ),
+ mbResetFormDesignMode( false ),
+ mbFormDesignModeToReset( false )
+{
+ SetName("PageView");
+ SetWindow( m_pViewWin );
+ CreateScrollbar( true );
+ CreateScrollbar( false );
+
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Printpreview));
+
+ SfxObjectShell* pObjShell = rViewFrame.GetObjectShell();
+ if ( !pOldSh )
+ {
+ // Exists already a view on the document?
+ SfxViewFrame *pF = SfxViewFrame::GetFirst( pObjShell );
+ if (pF == &rViewFrame)
+ pF = SfxViewFrame::GetNext( *pF, pObjShell );
+ if ( pF )
+ pOldSh = pF->GetViewShell();
+ }
+
+ SwViewShell *pVS, *pNew;
+
+ if (SwPagePreview* pPagePreview = dynamic_cast<SwPagePreview*>(pOldSh))
+ pVS = pPagePreview->GetViewShell();
+ else
+ {
+ if (SwView* pView = dynamic_cast<SwView *>(pOldSh))
+ {
+ pVS = pView->GetWrtShellPtr();
+ // save the current ViewData of the previous SwView
+ pOldSh->WriteUserData( m_sSwViewData );
+ }
+ else
+ pVS = GetDocShell()->GetWrtShell();
+ if( pVS )
+ {
+ // Set the current page as the first.
+ sal_uInt16 nPhysPg, nVirtPg;
+ static_cast<SwCursorShell*>(pVS)->GetPageNum( nPhysPg, nVirtPg, true, false );
+ if( 1 != m_pViewWin->GetCol() && 1 == nPhysPg )
+ --nPhysPg;
+ m_pViewWin->SetSttPage( nPhysPg );
+ }
+ }
+
+ // for form shell remember design mode of draw view
+ // of previous view shell
+ if ( pVS && pVS->HasDrawView() )
+ {
+ mbResetFormDesignMode = true;
+ mbFormDesignModeToReset = pVS->GetDrawView()->IsDesignMode();
+ }
+
+ if( pVS )
+ pNew = new SwViewShell( *pVS, m_pViewWin, nullptr, VSHELLFLAG_ISPREVIEW );
+ else
+ pNew = new SwViewShell(
+ *static_cast<SwDocShell*>(rViewFrame.GetObjectShell())->GetDoc(),
+ m_pViewWin, nullptr, nullptr, VSHELLFLAG_ISPREVIEW );
+
+ m_pViewWin->SetViewShell( pNew );
+ pNew->SetSfxViewShell( this );
+ Init();
+}
+
+SwPagePreview::~SwPagePreview()
+{
+ SetWindow( nullptr );
+ SwViewShell* pVShell = m_pViewWin->GetViewShell();
+ pVShell->SetWin(nullptr);
+ delete pVShell;
+
+ m_pViewWin.disposeAndClear();
+ m_pHScrollbar.disposeAndClear();
+ m_pVScrollbar.disposeAndClear();
+}
+
+void SwPagePreview::Activate(bool bMDI)
+{
+ SfxViewShell::Activate(bMDI);
+ SfxShell::Activate(bMDI);
+}
+
+SwDocShell* SwPagePreview::GetDocShell()
+{
+ return dynamic_cast<SwDocShell*>( GetViewFrame().GetObjectShell() );
+}
+
+void SwPagePreview::CreateScrollbar( bool bHori )
+{
+ vcl::Window *pMDI = &GetViewFrame().GetWindow();
+ VclPtr<SwScrollbar>& ppScrollbar = bHori ? m_pHScrollbar : m_pVScrollbar;
+
+ assert(!ppScrollbar); //check beforehand!
+ ppScrollbar = VclPtr<SwScrollbar>::Create( pMDI, bHori );
+
+ ScrollDocSzChg();
+
+ if (bHori)
+ ppScrollbar->SetScrollHdl( LINK( this, SwPagePreview, HoriScrollHdl ));
+ else
+ ppScrollbar->SetScrollHdl( LINK( this, SwPagePreview, VertScrollHdl ));
+
+ InvalidateBorder();
+ ppScrollbar->ExtendedShow();
+}
+
+bool SwPagePreview::ChgPage( int eMvMode, bool bUpdateScrollbar )
+{
+ tools::Rectangle aPixVisArea( m_pViewWin->LogicToPixel( m_aVisArea ) );
+ bool bChg = m_pViewWin->MovePage( eMvMode ) ||
+ eMvMode == SwPagePreviewWin::MV_CALC ||
+ eMvMode == SwPagePreviewWin::MV_NEWWINSIZE;
+ m_aVisArea = m_pViewWin->PixelToLogic( aPixVisArea );
+
+ if( bChg )
+ {
+ // Update statusbar
+ SfxBindings& rBindings = GetViewFrame().GetBindings();
+
+ if( bUpdateScrollbar )
+ {
+ ScrollViewSzChg();
+
+ static sal_uInt16 aInval[] =
+ {
+ FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT,
+ FN_PAGEUP, FN_PAGEDOWN, 0
+ };
+ rBindings.Invalidate( aInval );
+ }
+ std::vector<OUString> aStringList
+ {
+ m_sPageStr + m_pViewWin->GetStatusStr(mnPageCount),
+ OUString()
+ };
+ rBindings.SetState(SfxStringListItem(FN_STAT_PAGE, &aStringList));
+ }
+ return bChg;
+}
+
+// From here, everything was taken from the SwView.
+void SwPagePreview::CalcAndSetBorderPixel( SvBorder &rToFill )
+{
+ const StyleSettings &rSet = m_pViewWin->GetSettings().GetStyleSettings();
+ const tools::Long nTmp = rSet.GetScrollBarSize();
+ if (m_pVScrollbar->IsScrollbarVisible(true))
+ rToFill.Right() = nTmp;
+ if (m_pHScrollbar->IsScrollbarVisible(true))
+ rToFill.Bottom() = nTmp;
+ SetBorderPixel( rToFill );
+}
+
+void SwPagePreview::InnerResizePixel( const Point &rOfst, const Size &rSize, bool )
+{
+ SvBorder aBorder;
+ CalcAndSetBorderPixel( aBorder );
+ tools::Rectangle aRect( rOfst, rSize );
+ aRect += aBorder;
+ ViewResizePixel( *m_pViewWin->GetOutDev(), aRect.TopLeft(), aRect.GetSize(),
+ m_pViewWin->GetOutputSizePixel(),
+ *m_pVScrollbar, *m_pHScrollbar );
+
+ // Never set EditWin !
+ // Never set VisArea !
+}
+
+void SwPagePreview::OuterResizePixel( const Point &rOfst, const Size &rSize )
+{
+ SvBorder aBorder;
+ CalcAndSetBorderPixel( aBorder );
+
+ // Never set EditWin !
+
+ Size aTmpSize( m_pViewWin->GetOutputSizePixel() );
+ Point aBottomRight( m_pViewWin->PixelToLogic( Point( aTmpSize.Width(), aTmpSize.Height() ) ) );
+ SetVisArea( tools::Rectangle( Point(), aBottomRight ) );
+
+ // Call of the DocSzChgd-Method of the scrollbars is necessary,
+ // because from the maximum scroll range half the height of the
+ // VisArea is always deducted.
+ if ( m_pVScrollbar && !aTmpSize.IsEmpty() )
+ {
+ ScrollDocSzChg();
+ }
+
+ SvBorder aBorderNew;
+ CalcAndSetBorderPixel( aBorderNew );
+ ViewResizePixel( *m_pViewWin->GetOutDev(), rOfst, rSize, m_pViewWin->GetOutputSizePixel(),
+ *m_pVScrollbar, *m_pHScrollbar );
+}
+
+void SwPagePreview::SetVisArea( const tools::Rectangle &rRect )
+{
+ const Point aTopLeft(AlignToPixel(rRect.TopLeft()));
+ const Point aBottomRight(AlignToPixel(rRect.BottomRight()));
+ tools::Rectangle aLR(aTopLeft,aBottomRight);
+
+ if(aLR == m_aVisArea)
+ return;
+ // No negative position, no negative size
+
+ if(aLR.Top() < 0)
+ {
+ aLR.AdjustBottom(std::abs(aLR.Top()) );
+ aLR.SetTop( 0 );
+ }
+
+ if(aLR.Left() < 0)
+ {
+ aLR.AdjustRight(std::abs(aLR.Left()) );
+ aLR.SetLeft( 0 );
+ }
+ if(aLR.Right() < 0) aLR.SetRight( 0 );
+ if(aLR.Bottom() < 0) aLR.SetBottom( 0 );
+ if(aLR == m_aVisArea ||
+ // Ignore empty rectangle
+ ( 0 == aLR.Bottom() - aLR.Top() && 0 == aLR.Right() - aLR.Left() ) )
+ return;
+
+ if( aLR.Left() > aLR.Right() || aLR.Top() > aLR.Bottom() )
+ return;
+
+ // Before the data can be changed call an update if necessary.
+ // Thereby ensured, that adjacent paints are correctly converted into
+ // document coordinates.
+ // As a precaution, we do this only when at the shell runs an action,
+ // because then we do not really paint but the rectangles are just
+ // bookmarked (in document coordinates).
+ if( GetViewShell()->ActionPend() )
+ m_pViewWin->PaintImmediately();
+
+ // Set at View-Win the current size
+ m_aVisArea = aLR;
+ m_pViewWin->SetWinSize( aLR.GetSize() );
+ ChgPage( SwPagePreviewWin::MV_NEWWINSIZE );
+
+ m_pViewWin->Invalidate();
+}
+
+IMPL_LINK(SwPagePreview, HoriScrollHdl, weld::Scrollbar&, rScrollbar, void)
+{
+ ScrollHdl(rScrollbar, true);
+}
+
+IMPL_LINK(SwPagePreview, VertScrollHdl, weld::Scrollbar&, rScrollbar, void)
+{
+ ScrollHdl(rScrollbar, false);
+}
+
+void SwPagePreview::ScrollHdl(weld::Scrollbar& rScrollbar, bool bHori)
+{
+ if(!GetViewShell())
+ return;
+
+ EndScrollHdl(rScrollbar, bHori);
+
+ if( !bHori &&
+ rScrollbar.get_scroll_type() == ScrollType::Drag &&
+ Help::IsQuickHelpEnabled() &&
+ GetViewShell()->PagePreviewLayout()->DoesPreviewLayoutRowsFitIntoWindow())
+ {
+ // Scroll how many pages??
+ OUString sStateStr(m_sPageStr);
+ tools::Long nThmbPos = rScrollbar.adjustment_get_value();
+ if( 1 == m_pViewWin->GetCol() || !nThmbPos )
+ ++nThmbPos;
+ sStateStr += OUString::number( nThmbPos );
+ Point aPos = m_pVScrollbar->GetParent()->OutputToScreenPixel(
+ m_pVScrollbar->GetPosPixel());
+ aPos.setY( m_pVScrollbar->OutputToScreenPixel(m_pVScrollbar->GetPointerPosPixel()).Y() );
+ tools::Rectangle aRect;
+ aRect.SetLeft( aPos.X() -8 );
+ aRect.SetRight( aRect.Left() );
+ aRect.SetTop( aPos.Y() );
+ aRect.SetBottom( aRect.Top() );
+
+ Help::ShowQuickHelp(m_pVScrollbar, aRect, sStateStr,
+ QuickHelpFlags::Right|QuickHelpFlags::VCenter);
+
+ }
+}
+
+void SwPagePreview::EndScrollHdl(weld::Scrollbar& rScrollbar, bool bHori)
+{
+ if(!GetViewShell())
+ return;
+
+ // boolean to avoid unnecessary invalidation of the window.
+ bool bInvalidateWin = true;
+
+ if (!bHori) // scroll vertically
+ {
+ if ( Help::IsQuickHelpEnabled() )
+ Help::ShowQuickHelp(m_pVScrollbar, tools::Rectangle(), OUString());
+ if ( GetViewShell()->PagePreviewLayout()->DoesPreviewLayoutRowsFitIntoWindow() )
+ {
+ // Scroll how many pages ??
+ const sal_uInt16 nThmbPos = o3tl::narrowing<sal_uInt16>(rScrollbar.adjustment_get_value());
+ // adjust to new preview functionality
+ if( nThmbPos != m_pViewWin->SelectedPage() )
+ {
+ // consider case that page <nThmbPos>
+ // is already visible
+ SwPagePreviewLayout* pPagePreviewLay = GetViewShell()->PagePreviewLayout();
+ if ( pPagePreviewLay->IsPageVisible( nThmbPos ) )
+ {
+ pPagePreviewLay->MarkNewSelectedPage( nThmbPos );
+ // invalidation of window is unnecessary
+ bInvalidateWin = false;
+ }
+ else
+ {
+ // consider whether layout columns
+ // fit or not.
+ if ( !pPagePreviewLay->DoesPreviewLayoutColsFitIntoWindow() )
+ {
+ m_pViewWin->SetSttPage( nThmbPos );
+ m_pViewWin->SetSelectedPage( nThmbPos );
+ ChgPage( SwPagePreviewWin::MV_SCROLL, false );
+ // update scrollbars
+ ScrollViewSzChg();
+ }
+ else
+ {
+ // correct scroll amount
+ const sal_Int16 nPageDiff = nThmbPos - m_pViewWin->SelectedPage();
+ const sal_uInt16 nVisPages = m_pViewWin->GetRow() * m_pViewWin->GetCol();
+ sal_Int16 nWinPagesToScroll = nPageDiff / nVisPages;
+ if ( nPageDiff % nVisPages )
+ {
+ // decrease/increase number of preview pages to scroll
+ nPageDiff < 0 ? --nWinPagesToScroll : ++nWinPagesToScroll;
+ }
+ m_pViewWin->SetSelectedPage( nThmbPos );
+ m_pViewWin->Scroll( 0, pPagePreviewLay->GetWinPagesScrollAmount( nWinPagesToScroll ) );
+ }
+ }
+ // update accessibility
+ GetViewShell()->ShowPreviewSelection( nThmbPos );
+ }
+ else
+ {
+ // invalidation of window is unnecessary
+ bInvalidateWin = false;
+ }
+ }
+ else
+ {
+ tools::Long nThmbPos = rScrollbar.adjustment_get_value();
+ m_pViewWin->Scroll(0, nThmbPos - m_pViewWin->GetPaintedPreviewDocRect().Top());
+ }
+ }
+ else
+ {
+ tools::Long nThmbPos = rScrollbar.adjustment_get_value();
+ m_pViewWin->Scroll(nThmbPos - m_pViewWin->GetPaintedPreviewDocRect().Left(), 0);
+ }
+ // additional invalidate page status.
+ static sal_uInt16 aInval[] =
+ {
+ FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT, FN_PAGEUP, FN_PAGEDOWN,
+ FN_STAT_PAGE, 0
+ };
+ SfxBindings& rBindings = GetViewFrame().GetBindings();
+ rBindings.Invalidate( aInval );
+ // control invalidation of window
+ if ( bInvalidateWin )
+ {
+ m_pViewWin->Invalidate();
+ }
+}
+
+Point SwPagePreview::AlignToPixel(const Point &rPt) const
+{
+ return m_pViewWin->PixelToLogic( m_pViewWin->LogicToPixel( rPt ) );
+}
+
+void SwPagePreview::DocSzChgd( const Size &rSz )
+{
+ if( m_aDocSize == rSz )
+ return;
+
+ m_aDocSize = rSz;
+
+ // #i96726#
+ // Due to the multiple page layout it is needed to trigger recalculation
+ // of the page preview layout, even if the count of pages is not changing.
+ mnPageCount = GetViewShell()->GetNumPages();
+
+ if( m_aVisArea.GetWidth() )
+ {
+ ChgPage( SwPagePreviewWin::MV_CALC );
+ ScrollDocSzChg();
+
+ m_pViewWin->Invalidate();
+ }
+}
+
+void SwPagePreview::ScrollViewSzChg()
+{
+ if(!GetViewShell())
+ return ;
+
+ bool bShowVScrollbar = false, bShowHScrollbar = false;
+
+ if(m_pVScrollbar)
+ {
+ if(GetViewShell()->PagePreviewLayout()->DoesPreviewLayoutRowsFitIntoWindow())
+ {
+ //vertical scrolling by row
+ // adjust to new preview functionality
+ const sal_uInt16 nVisPages = m_pViewWin->GetRow() * m_pViewWin->GetCol();
+
+ m_pVScrollbar->SetVisibleSize( nVisPages );
+ // set selected page as scroll bar position,
+ // if it is visible.
+ SwPagePreviewLayout* pPagePreviewLay = GetViewShell()->PagePreviewLayout();
+ if ( pPagePreviewLay->IsPageVisible( m_pViewWin->SelectedPage() ) )
+ {
+ m_pVScrollbar->SetThumbPos( m_pViewWin->SelectedPage() );
+ }
+ else
+ {
+ m_pVScrollbar->SetThumbPos( m_pViewWin->GetSttPage() );
+ }
+ m_pVScrollbar->SetLineSize( m_pViewWin->GetCol() );
+ m_pVScrollbar->SetPageSize( nVisPages );
+ // calculate and set scrollbar range
+ Range aScrollbarRange( 1, mnPageCount );
+ // increase range by one, because left-top-corner is left blank.
+ ++aScrollbarRange.Max();
+ // increase range in order to access all pages
+ aScrollbarRange.Max() += ( nVisPages - 1 );
+ m_pVScrollbar->SetRange( aScrollbarRange );
+
+ bShowVScrollbar = nVisPages < mnPageCount;
+ }
+ else //vertical scrolling by pixel
+ {
+ const tools::Rectangle& rDocRect = m_pViewWin->GetPaintedPreviewDocRect();
+ const Size& rPreviewSize =
+ GetViewShell()->PagePreviewLayout()->GetPreviewDocSize();
+ m_pVScrollbar->SetRangeMax(rPreviewSize.Height()) ;
+ tools::Long nVisHeight = rDocRect.GetHeight();
+ m_pVScrollbar->SetVisibleSize( nVisHeight );
+ m_pVScrollbar->SetThumbPos( rDocRect.Top() );
+ m_pVScrollbar->SetLineSize( nVisHeight / 10 );
+ m_pVScrollbar->SetPageSize( nVisHeight / 2 );
+
+ bShowVScrollbar = true;
+ }
+
+ if (!mbVScrollbarEnabled)
+ bShowVScrollbar = false;
+
+ ShowVScrollbar(bShowVScrollbar);
+ }
+ if(m_pHScrollbar)
+ {
+ const tools::Rectangle& rDocRect = m_pViewWin->GetPaintedPreviewDocRect();
+ const Size& rPreviewSize =
+ GetViewShell()->PagePreviewLayout()->GetPreviewDocSize();
+ Range aRange(0,0);
+
+ if(rDocRect.GetWidth() < rPreviewSize.Width())
+ {
+ bShowHScrollbar = true;
+
+ tools::Long nVisWidth = rDocRect.GetWidth();
+ tools::Long nThumb = rDocRect.Left();
+ aRange = Range(0, rPreviewSize.Width());
+
+ m_pHScrollbar->SetRange( aRange );
+ m_pHScrollbar->SetVisibleSize( nVisWidth );
+ m_pHScrollbar->SetThumbPos( nThumb );
+ m_pHScrollbar->SetLineSize( nVisWidth / 10 );
+ m_pHScrollbar->SetPageSize( nVisWidth / 2 );
+ }
+
+ if (!mbHScrollbarEnabled)
+ bShowHScrollbar = false;
+
+ ShowHScrollbar(bShowHScrollbar);
+ }
+}
+
+void SwPagePreview::ScrollDocSzChg()
+{
+ ScrollViewSzChg();
+}
+
+// All about printing
+SfxPrinter* SwPagePreview::GetPrinter( bool bCreate )
+{
+ return m_pViewWin->GetViewShell()->getIDocumentDeviceAccess().getPrinter( bCreate );
+}
+
+sal_uInt16 SwPagePreview::SetPrinter( SfxPrinter *pNew, SfxPrinterChangeFlags nDiffFlags )
+{
+ SwViewShell &rSh = *GetViewShell();
+ SfxPrinter* pOld = rSh.getIDocumentDeviceAccess().getPrinter( false );
+ if ( pOld && pOld->IsPrinting() )
+ return SFX_PRINTERROR_BUSY;
+
+ SwEditShell &rESh = static_cast<SwEditShell&>(rSh); //Buh...
+ if( ( SfxPrinterChangeFlags::PRINTER | SfxPrinterChangeFlags::JOBSETUP ) & nDiffFlags )
+ {
+ rSh.getIDocumentDeviceAccess().setPrinter( pNew, true, true );
+ if( nDiffFlags & SfxPrinterChangeFlags::PRINTER )
+ rESh.SetModified();
+ }
+ if ( ( nDiffFlags & SfxPrinterChangeFlags::OPTIONS ) == SfxPrinterChangeFlags::OPTIONS )
+ ::SetPrinter( &rSh.getIDocumentDeviceAccess(), pNew, false );
+
+ const bool bChgOri = bool(nDiffFlags & SfxPrinterChangeFlags::CHG_ORIENTATION);
+ const bool bChgSize = bool(nDiffFlags & SfxPrinterChangeFlags::CHG_SIZE);
+ if ( bChgOri || bChgSize )
+ {
+ rESh.StartAllAction();
+ if ( bChgOri )
+ rSh.ChgAllPageOrientation( pNew->GetOrientation() );
+ if ( bChgSize )
+ {
+ Size aSz( SvxPaperInfo::GetPaperSize( pNew ) );
+ rSh.ChgAllPageSize( aSz );
+ }
+ if( !m_bNormalPrint )
+ m_pViewWin->CalcWish( m_pViewWin->GetRow(), m_pViewWin->GetCol() );
+ rESh.SetModified();
+ rESh.EndAllAction();
+
+ static sal_uInt16 aInval[] =
+ {
+ SID_ATTR_LONG_ULSPACE, SID_ATTR_LONG_LRSPACE,
+ SID_RULER_BORDERS, SID_RULER_PAGE_POS, 0
+ };
+#if OSL_DEBUG_LEVEL > 0
+ {
+ const sal_uInt16* pPtr = aInval + 1;
+ do {
+ OSL_ENSURE( *(pPtr - 1) < *pPtr, "wrong sorting!" );
+ } while( *++pPtr );
+ }
+#endif
+
+ GetViewFrame().GetBindings().Invalidate(aInval);
+ }
+
+ return 0;
+}
+
+bool SwPagePreview::HasPrintOptionsPage() const
+{
+ return true;
+}
+
+std::unique_ptr<SfxTabPage> SwPagePreview::CreatePrintOptionsPage(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet &rOptions)
+{
+ return ::CreatePrintOptionsPage(pPage, pController, rOptions, !m_bNormalPrint);
+}
+
+void SwPagePreviewWin::SetViewShell( SwViewShell* pShell )
+{
+ mpViewShell = pShell;
+ if ( mpViewShell && mpViewShell->IsPreview() )
+ {
+ mpPgPreviewLayout = mpViewShell->PagePreviewLayout();
+ }
+}
+
+void SwPagePreviewWin::RepaintCoreRect( const SwRect& rRect )
+{
+ // #i24183#
+ if ( mpPgPreviewLayout->PreviewLayoutValid() )
+ {
+ mpPgPreviewLayout->Repaint( tools::Rectangle( rRect.Pos(), rRect.SSize() ) );
+ }
+}
+
+/** method to adjust preview to a new zoom factor
+
+ #i19975# also consider zoom type - adding parameter <_eZoomType>
+*/
+void SwPagePreviewWin::AdjustPreviewToNewZoom( const sal_uInt16 _nZoomFactor,
+ const SvxZoomType _eZoomType )
+{
+ // #i19975# consider zoom type
+ if ( _eZoomType == SvxZoomType::WHOLEPAGE )
+ {
+ mnRow = 1;
+ mnCol = 1;
+ mpPgPreviewLayout->Init( mnCol, mnRow, maPxWinSize );
+ mpPgPreviewLayout->Prepare( mnSttPage, Point(0,0), maPxWinSize,
+ mnSttPage, maPaintedPreviewDocRect );
+ SetSelectedPage( mnSttPage );
+ SetPagePreview(mnRow, mnCol);
+ maScale = GetMapMode().GetScaleX();
+ }
+ else if ( _nZoomFactor != 0 )
+ {
+ // calculate new scaling and set mapping mode appropriately.
+ Fraction aNewScale( _nZoomFactor, 100 );
+ MapMode aNewMapMode = GetMapMode();
+ aNewMapMode.SetScaleX( aNewScale );
+ aNewMapMode.SetScaleY( aNewScale );
+ SetMapMode( aNewMapMode );
+
+ // calculate new start position for preview paint
+ Size aNewWinSize = PixelToLogic( maPxWinSize );
+ Point aNewPaintStartPos =
+ mpPgPreviewLayout->GetPreviewStartPosForNewScale( aNewScale, maScale, aNewWinSize );
+
+ // remember new scaling and prepare preview paint
+ // Note: paint of preview will be performed by a corresponding invalidate
+ // due to property changes.
+ maScale = aNewScale;
+ mpPgPreviewLayout->Prepare( 0, aNewPaintStartPos, maPxWinSize,
+ mnSttPage, maPaintedPreviewDocRect );
+ }
+
+}
+
+/**
+ * pixel scrolling - horizontally always or vertically
+ * when less than the desired number of rows fits into
+ * the view
+ */
+void SwPagePreviewWin::Scroll(tools::Long nXMove, tools::Long nYMove, ScrollFlags /*nFlags*/)
+{
+ maPaintedPreviewDocRect.Move(nXMove, nYMove);
+ mpPgPreviewLayout->Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
+ maPxWinSize, mnSttPage,
+ maPaintedPreviewDocRect );
+
+}
+
+bool SwPagePreview::HandleWheelCommands( const CommandEvent& rCEvt )
+{
+ bool bOk = false;
+ const CommandWheelData* pWData = rCEvt.GetWheelData();
+ if( pWData && CommandWheelMode::ZOOM == pWData->GetMode() )
+ {
+ //only the Preference shouldn't control the Zoom, it is better to detect AT tools running. So the bridge can be used here
+ if (!Application::GetSettings().GetMiscSettings().GetEnableATToolSupport())
+ {
+ sal_uInt16 nFactor = GetViewShell()->GetViewOptions()->GetZoom();
+ const sal_uInt16 nOffset = 10;
+ if( 0L > pWData->GetDelta() )
+ {
+ nFactor -= nOffset;
+ if(nFactor < MIN_PREVIEW_ZOOM)
+ nFactor = MIN_PREVIEW_ZOOM;
+ }
+ else
+ {
+ nFactor += nOffset;
+ if(nFactor > MAX_PREVIEW_ZOOM)
+ nFactor = MAX_PREVIEW_ZOOM;
+ }
+ SetZoom(SvxZoomType::PERCENT, nFactor);
+ }
+ bOk = true;
+ }
+ else
+ bOk = m_pViewWin->HandleScrollCommand( rCEvt, m_pHScrollbar, m_pVScrollbar );
+ return bOk;
+}
+
+uno::Reference< css::accessibility::XAccessible >
+ SwPagePreviewWin::CreateAccessible()
+{
+ SolarMutexGuard aGuard; // this should have happened already!!!
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ OSL_ENSURE( GetViewShell() != nullptr, "We need a view shell" );
+ css::uno::Reference< css::accessibility::XAccessible > xAcc = GetAccessible( false );
+ if (xAcc.is())
+ {
+ return xAcc;
+ }
+ if (mpViewShell)
+ {
+ css::uno::Reference< css::accessibility::XAccessible > xAccPreview = mpViewShell->CreateAccessiblePreview();
+ SetAccessible(xAccPreview);
+ }
+#endif
+ return GetAccessible( false );
+}
+
+void SwPagePreview::ApplyAccessibilityOptions()
+{
+ GetViewShell()->ApplyAccessibilityOptions();
+}
+
+void SwPagePreview::ShowHScrollbar(bool bShow)
+{
+ m_pHScrollbar->Show(bShow);
+ InvalidateBorder();
+}
+
+void SwPagePreview::ShowVScrollbar(bool bShow)
+{
+ m_pVScrollbar->Show(bShow);
+ InvalidateBorder();
+}
+
+void SwPagePreview::EnableHScrollbar(bool bEnable)
+{
+ if (mbHScrollbarEnabled != bEnable)
+ {
+ mbHScrollbarEnabled = bEnable;
+ ScrollViewSzChg();
+ }
+}
+
+void SwPagePreview::EnableVScrollbar(bool bEnable)
+{
+ if (mbVScrollbarEnabled != bEnable)
+ {
+ mbVScrollbarEnabled = bEnable;
+ ScrollViewSzChg();
+ }
+}
+
+void SwPagePreview::SetZoom(SvxZoomType eType, sal_uInt16 nFactor)
+{
+ SwViewShell& rSh = *GetViewShell();
+ SwViewOption aOpt(*rSh.GetViewOptions());
+ // perform action only on changes of zoom or zoom type.
+ if ( aOpt.GetZoom() != nFactor ||
+ aOpt.GetZoomType() != eType )
+ {
+ aOpt.SetZoom(nFactor);
+ aOpt.SetZoomType(eType);
+ rSh.ApplyViewOptions( aOpt );
+ lcl_InvalidateZoomSlots(GetViewFrame().GetBindings());
+ // #i19975# also consider zoom type
+ m_pViewWin->AdjustPreviewToNewZoom( nFactor, eType );
+ ScrollViewSzChg();
+ }
+}
+
+/** adjust position of vertical scrollbar */
+void SwPagePreview::SetVScrollbarThumbPos( const sal_uInt16 _nNewThumbPos )
+{
+ if ( m_pVScrollbar )
+ {
+ m_pVScrollbar->SetThumbPos( _nNewThumbPos );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/scroll.cxx b/sw/source/uibase/uiview/scroll.cxx
new file mode 100644
index 0000000000..7b1d7f915a
--- /dev/null
+++ b/sw/source/uibase/uiview/scroll.cxx
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <scroll.hxx>
+
+#define SCROLL_LINE_SIZE 250
+
+SwScrollbar::SwScrollbar(vcl::Window *pWin, bool bHoriz)
+ : ScrollAdaptor(pWin, bHoriz)
+ , m_bAuto(false)
+ , m_bVisible(false)
+ , m_bSizeSet(false)
+{
+ m_xScrollBar->show();
+
+ // No mirroring for horizontal scrollbars
+ if (bHoriz)
+ m_xScrollBar->set_direction(false);
+}
+
+// Will be called after a change of the document size
+// to refresh the range of the scrollbars.
+void SwScrollbar::DocSzChgd( const Size &rSize )
+{
+ m_aDocSz = rSize;
+ SetRange( Range( 0, m_bHori ? rSize.Width() : rSize.Height()) );
+ const tools::Long nVisSize = GetVisibleSize();
+ SetLineSize( SCROLL_LINE_SIZE );
+ SetPageSize( nVisSize * 77 / 100 );
+}
+
+// Will be called after a change of the visible view section.
+void SwScrollbar::ViewPortChgd( const tools::Rectangle &rRect )
+{
+ tools::Long nThumb, nVisible;
+ if( m_bHori )
+ {
+ nThumb = rRect.Left();
+ nVisible = rRect.GetWidth();
+ }
+ else
+ {
+ nThumb = rRect.Top();
+ nVisible = rRect.GetHeight();
+ }
+
+ SetVisibleSize( nVisible );
+ DocSzChgd(m_aDocSz);
+ SetThumbPos( nThumb );
+ if(m_bAuto)
+ AutoShow();
+}
+
+void SwScrollbar::ExtendedShow( bool bSet )
+{
+ m_bVisible = bSet;
+ if( (!bSet || !m_bAuto) && IsUpdateMode() && m_bSizeSet)
+ {
+ ScrollAdaptor::Show(bSet);
+ }
+}
+
+void SwScrollbar::SetPosSizePixel( const Point& rNewPos, const Size& rNewSize )
+{
+ ScrollAdaptor::SetPosSizePixel(rNewPos, rNewSize);
+ m_bSizeSet = true;
+ if(m_bVisible)
+ ExtendedShow();
+}
+
+void SwScrollbar::SetAuto(bool bSet)
+{
+ if(m_bAuto != bSet)
+ {
+ m_bAuto = bSet;
+
+ // hide automatically - then show
+ if(!m_bAuto && m_bVisible && !ScrollAdaptor::IsVisible())
+ ExtendedShow();
+ else if(m_bAuto)
+ AutoShow(); // or hide automatically
+ }
+}
+
+void SwScrollbar::AutoShow()
+{
+ tools::Long nVis = GetVisibleSize();
+ tools::Long nLen = GetRange().Len();
+ if (nVis >= nLen - 1)
+ {
+ if (ScrollAdaptor::IsVisible())
+ ScrollAdaptor::Show(false);
+ }
+ else if (!ScrollAdaptor::IsVisible())
+ {
+ ScrollAdaptor::Show();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/srcview.cxx b/sw/source/uibase/uiview/srcview.cxx
new file mode 100644
index 0000000000..563dd0b468
--- /dev/null
+++ b/sw/source/uibase/uiview/srcview.cxx
@@ -0,0 +1,839 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <rtl/tencinfo.h>
+#include <osl/diagnose.h>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <unotools/tempfile.hxx>
+#include <tools/urlobj.hxx>
+#include <vcl/errinf.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/textview.hxx>
+#include <vcl/svapp.hxx>
+#include <svl/intitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/undo.hxx>
+#include <svl/eitem.hxx>
+#include <svl/whiter.hxx>
+#include <vcl/transfer.hxx>
+#include <svtools/strings.hrc>
+#include <svtools/svtresid.hxx>
+#include <svtools/htmlcfg.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/docfile.hxx>
+#include <svx/srchdlg.hxx>
+#include <svx/statusitem.hxx>
+#include <svl/srchitem.hxx>
+#include <sfx2/sfxhtml.hxx>
+#include <swtypes.hxx>
+#include <docsh.hxx>
+#include <wdocsh.hxx>
+#include <srcview.hxx>
+#include "viewfunc.hxx"
+#include <doc.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentState.hxx>
+#include <sfx2/msg.hxx>
+#include <shellio.hxx>
+
+#include <cmdid.h>
+#include <strings.hrc>
+#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
+#include <sfx2/filedlghelper.hxx>
+#define ShellClass_SwSrcView
+#include <swslots.hxx>
+
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::sfx2;
+
+#define SWSRCVIEWFLAGS SfxViewShellFlags::NO_NEWWINDOW
+
+#define SRC_SEARCHOPTIONS (SearchOptionFlags::ALL & ~SearchOptionFlags(SearchOptionFlags::FORMAT|SearchOptionFlags::FAMILIES|SearchOptionFlags::SEARCHALL))
+
+// Printing margins -> like Basic - Ide
+#define LMARGPRN 1700
+#define RMARGPRN 900
+#define TMARGPRN 2000
+#define BMARGPRN 1000
+#define BORDERPRN 300
+
+SFX_IMPL_NAMED_VIEWFACTORY(SwSrcView, "SourceView")
+{
+ SFX_VIEW_REGISTRATION(SwWebDocShell);
+}
+
+SFX_IMPL_SUPERCLASS_INTERFACE(SwSrcView, SfxViewShell)
+
+void SwSrcView::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("source");
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_TOOLS,
+ SfxVisibilityFlags::Standard|SfxVisibilityFlags::Server,
+ ToolbarId::Webtools_Toolbox);
+
+ GetStaticInterface()->RegisterChildWindow(SvxSearchDialogWrapper::GetChildWindowId());
+}
+
+
+static void lcl_PrintHeader( vcl::RenderContext &rOutDev, sal_Int32 nPages, sal_Int32 nCurPage, const OUString& rTitle )
+{
+ short nLeftMargin = LMARGPRN;
+ Size aSz = rOutDev.GetOutputSize();
+ short nBorder = BORDERPRN;
+
+ Color aOldFillColor( rOutDev.GetFillColor() );
+ vcl::Font aOldFont( rOutDev.GetFont() );
+
+ rOutDev.SetFillColor( COL_TRANSPARENT );
+
+ vcl::Font aFont( aOldFont );
+ aFont.SetWeight( WEIGHT_BOLD );
+ aFont.SetAlignment( ALIGN_BOTTOM );
+ rOutDev.SetFont( aFont );
+
+ tools::Long nFontHeight = rOutDev.GetTextHeight();
+
+ // 1.Border => Line, 2+3 Border = Space.
+ tools::Long nYTop = TMARGPRN-3*nBorder-nFontHeight;
+
+ tools::Long nXLeft = nLeftMargin-nBorder;
+ tools::Long nXRight = aSz.Width()-RMARGPRN+nBorder;
+
+ rOutDev.DrawRect( tools::Rectangle(
+ Point( nXLeft, nYTop ),
+ Size( nXRight-nXLeft, aSz.Height() - nYTop - BMARGPRN + nBorder ) ) );
+
+ tools::Long nY = TMARGPRN-2*nBorder;
+ Point aPos( nLeftMargin, nY );
+ rOutDev.DrawText( aPos, rTitle );
+ if ( nPages != 1 )
+ {
+ aFont.SetWeight( WEIGHT_NORMAL );
+ rOutDev.SetFont( aFont );
+ OUString aPageStr = " [" + SwResId( STR_PAGE ) + " " + OUString::number( nCurPage ) + "]";
+ aPos.AdjustX(rOutDev.GetTextWidth( rTitle ) );
+ rOutDev.DrawText( aPos, aPageStr );
+ }
+
+ nY = TMARGPRN-nBorder;
+
+ rOutDev.DrawLine( Point( nXLeft, nY ), Point( nXRight, nY ) );
+
+ rOutDev.SetFont( aOldFont );
+ rOutDev.SetFillColor( aOldFillColor );
+}
+
+static rtl_TextEncoding lcl_GetStreamCharSet(rtl_TextEncoding eLoadEncoding)
+{
+ rtl_TextEncoding eRet = eLoadEncoding;
+ if(RTL_TEXTENCODING_DONTKNOW == eRet)
+ {
+ eRet = RTL_TEXTENCODING_UTF8;
+ }
+ return eRet;
+}
+
+static OUString lcl_ConvertTabsToSpaces( const OUString& sLine )
+{
+ if (sLine.isEmpty())
+ return sLine;
+
+ OUString aRet = sLine;
+ const sal_Unicode aPadSpaces[4] = {' ', ' ', ' ', ' '};
+ sal_Int32 nPos = 0;
+ for (;;)
+ {
+ nPos = aRet.indexOf('\t', nPos);
+ if (nPos<0)
+ {
+ break;
+ }
+ // Not 4 blanks, but on 4th TabPos:
+ const sal_Int32 nPadLen = 4 - (nPos % 4);
+ aRet = aRet.replaceAt(nPos, 1, std::u16string_view{aPadSpaces, static_cast<size_t>(nPadLen)});
+ nPos += nPadLen;
+ }
+ return aRet;
+}
+
+SwSrcView::SwSrcView(SfxViewFrame& rViewFrame, SfxViewShell*) :
+ SfxViewShell( rViewFrame, SWSRCVIEWFLAGS ),
+ m_aEditWin( VclPtr<SwSrcEditWindow>::Create( &rViewFrame.GetWindow(), this ) ),
+ m_bSourceSaved(false),
+ m_eLoadEncoding(RTL_TEXTENCODING_DONTKNOW)
+{
+ Init();
+}
+
+SwSrcView::~SwSrcView()
+{
+ SwDocShell* pDocShell = GetDocShell();
+ assert(dynamic_cast<SwWebDocShell*>( pDocShell) && "Why no WebDocShell?" );
+ const TextSelection& rSel = m_aEditWin->GetTextView()->GetSelection();
+ static_cast<SwWebDocShell*>(pDocShell)->SetSourcePara( static_cast< sal_uInt16 >( rSel.GetStart().GetPara() ) );
+
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ pDocShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps
+ = xDPS->getDocumentProperties();
+ OUString url = xDocProps->getAutoloadURL();
+ sal_Int32 delay = xDocProps->getAutoloadSecs();
+ pDocShell->SetAutoLoad(INetURLObject(url), delay,
+ (delay != 0) || !url.isEmpty());
+ EndListening(*pDocShell);
+ m_pSearchItem.reset();
+
+ m_aEditWin.disposeAndClear();
+}
+
+void SwSrcView::SaveContentTo(SfxMedium& rMed)
+{
+ SvStream* pOutStream = rMed.GetOutStream();
+ pOutStream->SetStreamCharSet(lcl_GetStreamCharSet(m_eLoadEncoding));
+ m_aEditWin->Write( *pOutStream );
+}
+
+void SwSrcView::Init()
+{
+ SetName("Source");
+ SetWindow( m_aEditWin.get() );
+ SwDocShell* pDocShell = GetDocShell();
+ // If the doc is still loading, then the DocShell must fire up
+ // the Load if the loading is completed.
+ if(!pDocShell->IsLoading())
+ Load(pDocShell);
+ else
+ {
+ m_aEditWin->SetReadonly(true);
+ }
+
+ SetNewWindowAllowed( false );
+ StartListening(*pDocShell, DuplicateHandling::Prevent);
+}
+
+SwDocShell* SwSrcView::GetDocShell()
+{
+ SfxObjectShell* pObjShell = GetViewFrame().GetObjectShell();
+ return dynamic_cast<SwDocShell*>( pObjShell );
+}
+
+void SwSrcView::SaveContent(const OUString& rTmpFile)
+{
+ SfxMedium aMedium( rTmpFile, StreamMode::WRITE);
+ SvStream* pOutStream = aMedium.GetOutStream();
+ pOutStream->SetStreamCharSet( lcl_GetStreamCharSet(m_eLoadEncoding) );
+ m_aEditWin->Write(*pOutStream);
+ aMedium.Commit();
+}
+
+void SwSrcView::Execute(SfxRequest& rReq)
+{
+ TextView* pTextView = m_aEditWin->GetTextView();
+ switch( rReq.GetSlot() )
+ {
+ case SID_SAVEACOPY:
+ case SID_SAVEASDOC:
+ {
+ // filesave dialog with autoextension
+ FileDialogHelper aDlgHelper(
+ TemplateDescription::FILESAVE_AUTOEXTENSION,
+ FileDialogFlags::NONE, m_aEditWin->GetFrameWeld());
+ uno::Reference < XFilePicker3 > xFP = aDlgHelper.GetFilePicker();
+
+ // search for an html filter for export
+ SfxFilterContainer* pFilterCont = GetObjectShell()->GetFactory().GetFilterContainer();
+ std::shared_ptr<const SfxFilter> pFilter =
+ pFilterCont->GetFilter4Extension( "html", SfxFilterFlags::EXPORT );
+ if ( pFilter )
+ {
+ // filter found -> use its uiname and wildcard
+ const OUString& rUIName = pFilter->GetUIName();
+ const WildCard& rCard = pFilter->GetWildcard();
+ xFP->appendFilter( rUIName, rCard.getGlob() );
+ xFP->setCurrentFilter( rUIName ) ;
+ }
+ else
+ {
+ // filter not found
+ OUString sHtml("HTML");
+ xFP->appendFilter( sHtml, "*.html;*.htm" );
+ xFP->setCurrentFilter( sHtml ) ;
+ }
+
+ if( aDlgHelper.Execute() == ERRCODE_NONE)
+ {
+ SfxMedium aMedium( xFP->getSelectedFiles().getConstArray()[0],
+ StreamMode::WRITE | StreamMode::SHARE_DENYNONE );
+ SvStream* pOutStream = aMedium.GetOutStream();
+ pOutStream->SetStreamCharSet(lcl_GetStreamCharSet(m_eLoadEncoding));
+ m_aEditWin->Write( *pOutStream );
+ aMedium.Commit();
+ }
+ }
+ break;
+ case SID_SAVEDOC:
+ {
+ SwDocShell* pDocShell = GetDocShell();
+ assert(pDocShell);
+ SfxMedium* pMed = nullptr;
+ if(pDocShell->HasName())
+ pMed = pDocShell->GetMedium();
+ else
+ {
+ const SfxPoolItemHolder& rResult(pDocShell->ExecuteSlot(rReq, pDocShell->GetInterface()));
+ const SfxBoolItem* pItem(static_cast<const SfxBoolItem*>(rResult.getItem()));
+ if(pItem && pItem->GetValue())
+ pMed = pDocShell->GetMedium();
+ }
+ if(pMed)
+ {
+ SvStream* pOutStream = pMed->GetOutStream();
+ pOutStream->Seek(0);
+ pOutStream->SetStreamSize(0);
+ pOutStream->SetStreamCharSet(lcl_GetStreamCharSet(m_eLoadEncoding));
+ m_aEditWin->Write( *pOutStream );
+ pMed->CloseOutStream();
+ pMed->Commit();
+ pDocShell->GetDoc()->getIDocumentState().ResetModified();
+ m_bSourceSaved = true;
+ m_aEditWin->ClearModifyFlag();
+ }
+ }
+ break;
+ case FID_SEARCH_NOW:
+ {
+ const SfxItemSet* pTmpArgs = rReq.GetArgs();
+
+ const sal_uInt16 nWhich = pTmpArgs->GetWhichByOffset( 0 );
+ OSL_ENSURE( nWhich, "Which for SearchItem ?" );
+ const SfxPoolItem& rItem = pTmpArgs->Get( nWhich );
+ SetSearchItem( static_cast<const SvxSearchItem&>(rItem));
+ StartSearchAndReplace( static_cast<const SvxSearchItem&>(rItem), rReq.IsAPI() );
+ if(m_aEditWin->IsModified())
+ {
+ SwDocShell* pDocShell = GetDocShell();
+ assert(pDocShell);
+ pDocShell->GetDoc()->getIDocumentState().SetModified();
+ }
+ }
+ break;
+ case FN_REPEAT_SEARCH:
+ {
+ SvxSearchItem* pSrchItem = GetSearchItem();
+ if(pSrchItem)
+ {
+ StartSearchAndReplace( *pSrchItem, rReq.IsAPI() );
+ if(m_aEditWin->IsModified())
+ GetDocShell()->GetDoc()->getIDocumentState().SetModified();
+ }
+ }
+ break;
+ case SID_PRINTDOC:
+ case SID_PRINTDOCDIRECT:
+ {
+ SfxViewShell::ExecuteSlot( rReq, SfxViewShell::GetInterface() );
+ }
+ break;
+ case SID_UNDO:
+ pTextView->Undo();
+ GetViewFrame().GetBindings().InvalidateAll(false);
+ break;
+ case SID_REDO:
+ pTextView->Redo();
+ GetViewFrame().GetBindings().InvalidateAll(false);
+ break;
+ case SID_REPEAT:
+ break;
+ case SID_CUT:
+ if(pTextView->HasSelection())
+ pTextView->Cut();
+ break;
+ case SID_COPY:
+ if(pTextView->HasSelection())
+ pTextView->Copy();
+ break;
+ case SID_PASTE:
+ pTextView->Paste();
+ break;
+ case SID_SELECTALL:
+ pTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
+ break;
+ }
+ m_aEditWin->Invalidate();
+}
+
+void SwSrcView::GetState(SfxItemSet& rSet)
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ TextView* pTextView = m_aEditWin->GetTextView();
+
+ while(nWhich)
+ {
+ switch(nWhich)
+ {
+ case SID_SAVEASDOC:
+ rSet.Put(SfxStringItem(nWhich, SwResId(STR_SAVEAS_SRC)));
+ break;
+ case SID_SAVEACOPY:
+ rSet.Put(SfxStringItem(nWhich, SwResId(STR_SAVEACOPY_SRC)));
+ break;
+ case SID_SAVEDOC:
+ {
+ SwDocShell* pDocShell = GetDocShell();
+ assert(pDocShell);
+ if(!pDocShell->IsModified())
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_PRINTDOC:
+ case SID_PRINTDOCDIRECT:
+ break;
+ case SID_TABLE_CELL:
+ {
+ TextSelection aSel = pTextView->GetSelection();
+ OUString aPos =
+ SwResId(STR_SRCVIEW_ROW)
+ + OUString::number( aSel.GetEnd().GetPara()+1 )
+ + " : "
+ + SwResId(STR_SRCVIEW_COL)
+ + OUString::number( aSel.GetEnd().GetIndex()+1 );
+ SvxStatusItem aItem( SID_TABLE_CELL, aPos, StatusCategory::RowColumn );
+ rSet.Put( aItem );
+ }
+ break;
+ case SID_SEARCH_OPTIONS:
+ {
+ SearchOptionFlags nOpt = SRC_SEARCHOPTIONS;
+ SwDocShell* pDocShell = GetDocShell();
+ assert(pDocShell);
+ if (pDocShell->IsReadOnly())
+ nOpt &= ~SearchOptionFlags(SearchOptionFlags::REPLACE|SearchOptionFlags::REPLACE_ALL);
+
+ rSet.Put( SfxUInt16Item( SID_SEARCH_OPTIONS, static_cast<sal_uInt16>(nOpt) ) );
+ }
+ break;
+ case SID_SEARCH_ITEM:
+ {
+ OUString sSelected;
+ if ( !pTextView->HasSelection() )
+ {
+ const TextSelection& rSel = pTextView->GetSelection();
+ sSelected = m_aEditWin->GetTextEngine()->GetWord( rSel.GetStart());
+ }
+ else
+ {
+ sSelected = pTextView->GetSelected();
+ }
+ SvxSearchItem * pSrchItem = GetSearchItem();
+ pSrchItem->SetSearchString( sSelected );
+ rSet.Put( *pSrchItem );
+ }
+ break;
+ case FN_REPEAT_SEARCH:
+ {
+ if(!GetSearchItem())
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_UNDO:
+ case SID_REDO:
+ {
+ SfxUndoManager& rMgr = pTextView->GetTextEngine()->GetUndoManager();
+ sal_uInt16 nCount = 0;
+ if(nWhich == SID_UNDO)
+ {
+ nCount = rMgr.GetUndoActionCount();
+ if(nCount)
+ {
+ OUString aStr = SvtResId( STR_UNDO) + rMgr.GetUndoActionComment(--nCount);
+ rSet.Put(SfxStringItem(nWhich, aStr));
+ }
+ else
+ rSet.DisableItem(nWhich);
+ }
+ else
+ {
+ nCount = rMgr.GetRedoActionCount();
+ if(nCount)
+ {
+ OUString aStr = SvtResId( STR_REDO) + rMgr.GetRedoActionComment(--nCount);
+ rSet.Put(SfxStringItem(nWhich,aStr));
+ }
+ else
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+ case SID_MAIL_SENDDOCASPDF:
+ case SID_MAIL_SENDDOC :
+ case SID_EXPORTDOCASPDF:
+ case SID_DIRECTEXPORTDOCASPDF:
+ case SID_EXPORTDOC:
+ case SID_REPEAT:
+ case SID_BROWSER_MODE:
+ case FN_PRINT_LAYOUT:
+ rSet.DisableItem(nWhich);
+ break;
+ case SID_CUT:
+ case SID_COPY:
+ if(!pTextView->HasSelection())
+ rSet.DisableItem(nWhich);
+ break;
+ case SID_PASTE:
+ {
+ TransferableDataHelper aDataHelper(
+ TransferableDataHelper::CreateFromSystemClipboard(
+ m_aEditWin.get()) );
+ bool bDisable = !aDataHelper.GetXTransferable().is() ||
+ 0 == aDataHelper.GetFormatCount();
+ if( bDisable )
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+SvxSearchItem* SwSrcView::GetSearchItem()
+{
+ if(!m_pSearchItem)
+ {
+ m_pSearchItem.reset(new SvxSearchItem(SID_SEARCH_ITEM));
+ }
+ return m_pSearchItem.get();
+}
+
+void SwSrcView::SetSearchItem( const SvxSearchItem& rItem )
+{
+ m_pSearchItem.reset(rItem.Clone());
+}
+
+void SwSrcView::StartSearchAndReplace(const SvxSearchItem& rSearchItem,
+ bool bApi,
+ bool bRecursive)
+{
+ TextView* pTextView = m_aEditWin->GetTextView();
+ TextPaM aPaM;
+
+ bool bForward = !rSearchItem.GetBackward();
+ bool bAtStart = pTextView->GetSelection() == TextSelection( aPaM, aPaM );
+
+ if( !bForward )
+ aPaM = TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL );
+
+ i18nutil::SearchOptions2 aSearchOpt( rSearchItem.GetSearchOptions() );
+ aSearchOpt.Locale = GetAppLanguageTag().getLocale();
+
+ sal_uInt16 nFound;
+ bool bAll = false;
+ switch( rSearchItem.GetCommand() )
+ {
+ case SvxSearchCmd::FIND:
+ case SvxSearchCmd::FIND_ALL:
+ nFound = pTextView->Search( aSearchOpt, bForward ) ? 1 : 0;
+ break;
+
+ case SvxSearchCmd::REPLACE_ALL: bAll = true;
+ [[fallthrough]];
+ case SvxSearchCmd::REPLACE:
+ nFound = pTextView->Replace( aSearchOpt, bAll, bForward );
+ break;
+
+ default:
+ nFound = 0;
+ }
+
+ if( nFound )
+ return;
+
+ bool bNotFoundMessage = false;
+ if(!bRecursive)
+ {
+ bNotFoundMessage = bAtStart;
+ }
+ else if(bAtStart)
+ {
+ bNotFoundMessage = true;
+ }
+
+ if(bApi)
+ return;
+
+ if(bNotFoundMessage)
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, "modules/swriter/ui/infonotfounddialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xInfoBox(xBuilder->weld_message_dialog("InfoNotFoundDialog"));
+ xInfoBox->run();
+ }
+ else if(!bRecursive)
+ {
+ int nRet;
+
+ if (!bForward)
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, "modules/swriter/ui/querycontinueenddialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xQueryBox(xBuilder->weld_message_dialog("QueryContinueEndDialog"));
+ nRet = xQueryBox->run();
+ }
+ else
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, "modules/swriter/ui/querycontinuebegindialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xQueryBox(xBuilder->weld_message_dialog("QueryContinueBeginDialog"));
+ nRet = xQueryBox->run();
+ }
+
+ if (nRet == RET_YES)
+ {
+ pTextView->SetSelection( TextSelection( aPaM, aPaM ) );
+ StartSearchAndReplace( rSearchItem, false, true );
+ }
+ }
+}
+
+sal_uInt16 SwSrcView::SetPrinter(SfxPrinter* pNew, SfxPrinterChangeFlags nDiffFlags )
+{
+ SwDocShell* pDocSh = GetDocShell();
+ assert(pDocSh);
+ if ( (SfxPrinterChangeFlags::JOBSETUP | SfxPrinterChangeFlags::PRINTER) & nDiffFlags )
+ {
+ pDocSh->GetDoc()->getIDocumentDeviceAccess().setPrinter( pNew, true, true );
+ if ( nDiffFlags & SfxPrinterChangeFlags::PRINTER )
+ pDocSh->SetModified();
+ }
+ if ( nDiffFlags & SfxPrinterChangeFlags::OPTIONS )
+ ::SetPrinter( &pDocSh->getIDocumentDeviceAccess(), pNew, true );
+
+ const bool bChgOri = bool(nDiffFlags & SfxPrinterChangeFlags::CHG_ORIENTATION);
+ const bool bChgSize = bool(nDiffFlags & SfxPrinterChangeFlags::CHG_SIZE);
+ if ( bChgOri || bChgSize )
+ {
+ pDocSh->SetModified();
+ }
+ return 0;
+}
+
+SfxPrinter* SwSrcView::GetPrinter( bool bCreate )
+{
+ SwDocShell* pDocSh = GetDocShell();
+ assert(pDocSh);
+ return pDocSh->GetDoc()->getIDocumentDeviceAccess().getPrinter(bCreate);
+}
+
+sal_Int32 SwSrcView::PrintSource(
+ OutputDevice *pOutDev,
+ sal_Int32 nPage,
+ bool bCalcNumPagesOnly )
+{
+ if (!pOutDev || nPage <= 0)
+ return 0;
+
+ //! This algorithm for printing the n-th page is very poor since it
+ //! needs to go over the text of all previous pages to get to the correct one.
+ //! But since HTML source code is expected to be just a small number of pages
+ //! even this poor algorithm should be enough...
+
+ pOutDev->Push();
+
+ TextEngine* pTextEngine = m_aEditWin->GetTextEngine();
+ pOutDev->SetMapMode(MapMode(MapUnit::Map100thMM));
+ vcl::Font aFont( m_aEditWin->GetOutWin()->GetFont() );
+ Size aSize( aFont.GetFontSize() );
+ aSize = m_aEditWin->GetOutWin()->PixelToLogic(aSize, MapMode(MapUnit::Map100thMM));
+ aFont.SetFontSize( aSize );
+ aFont.SetColor( COL_BLACK );
+ pOutDev->SetFont( aFont );
+
+ OUString aTitle( GetViewFrame().GetWindow().GetText() );
+
+ const tools::Long nLineHeight = pOutDev->GetTextHeight(); // slightly more
+ const tools::Long nParaSpace = 10;
+
+ Size aPaperSz = pOutDev->GetOutputSize();
+ aPaperSz.AdjustWidth( -(LMARGPRN + RMARGPRN) );
+ aPaperSz.AdjustHeight( -(TMARGPRN + BMARGPRN) );
+
+ // nLinepPage is not true, if lines have to be wrapped...
+ const tools::Long nLinespPage = nLineHeight ? aPaperSz.Height() / nLineHeight : 1;
+ const tools::Long nCharWidth = pOutDev->GetTextWidth("X");
+ const sal_Int32 nCharspLine = nCharWidth ? static_cast<sal_Int32>(aPaperSz.Width() / nCharWidth) : 1;
+ const sal_uInt32 nParas = pTextEngine->GetParagraphCount();
+
+ const sal_Int32 nPages = static_cast<sal_Int32>(nParas / nLinespPage + 1 );
+ sal_Int32 nCurPage = 1;
+
+ // Print header...
+ if (!bCalcNumPagesOnly && nPage == nCurPage)
+ lcl_PrintHeader( *pOutDev, nPages, nCurPage, aTitle );
+ const Point aStartPos( LMARGPRN, TMARGPRN );
+ Point aPos( aStartPos );
+ for ( sal_uInt32 nPara = 0; nPara < nParas; ++nPara )
+ {
+ const OUString aLine( lcl_ConvertTabsToSpaces(pTextEngine->GetText( nPara )) );
+ const sal_Int32 nLineLen = aLine.getLength();
+ const sal_Int32 nLines = (nLineLen+nCharspLine-1) / nCharspLine;
+ for ( sal_Int32 nLine = 0; nLine < nLines; ++nLine )
+ {
+ aPos.AdjustY(nLineHeight );
+ if ( aPos.Y() > ( aPaperSz.Height() + TMARGPRN - nLineHeight/2 ) )
+ {
+ ++nCurPage;
+ if (!bCalcNumPagesOnly && nPage == nCurPage)
+ lcl_PrintHeader( *pOutDev, nPages, nCurPage, aTitle );
+ aPos = aStartPos;
+ }
+ if (!bCalcNumPagesOnly && nPage == nCurPage)
+ {
+ const sal_Int32 nStart = nLine * nCharspLine;
+ const sal_Int32 nLen = std::min(nLineLen-nStart, nCharspLine);
+ pOutDev->DrawText( aPos, aLine.copy(nStart, nLen) );
+ }
+ }
+ aPos.AdjustY(nParaSpace );
+ }
+
+ pOutDev->Pop();
+
+ OSL_ENSURE( bCalcNumPagesOnly || nPage <= nCurPage, "page number out of range" );
+ return nCurPage;
+}
+
+void SwSrcView::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ if (rHint.GetId() == SfxHintId::ModeChanged || rHint.GetId() == SfxHintId::TitleChanged)
+ {
+ const SwDocShell* pDocSh = GetDocShell();
+ assert(pDocSh);
+ if (!(rHint.GetId() == SfxHintId::TitleChanged
+ && (pDocSh->IsReadOnly() || !m_aEditWin->IsReadonly())))
+ {
+ // Broadcast only comes once!
+ const bool bReadonly = pDocSh->IsReadOnly();
+ m_aEditWin->SetReadonly(bReadonly);
+ }
+ }
+ SfxViewShell::Notify(rBC, rHint);
+}
+
+void SwSrcView::Load(SwDocShell* pDocShell)
+{
+ rtl_TextEncoding eDestEnc = RTL_TEXTENCODING_UTF8;
+
+ m_aEditWin->SetReadonly(pDocShell->IsReadOnly());
+ m_aEditWin->SetTextEncoding(eDestEnc);
+ SfxMedium* pMedium = pDocShell->GetMedium();
+
+ std::shared_ptr<const SfxFilter> pFilter = pMedium->GetFilter();
+ bool bHtml = pFilter && pFilter->GetUserData() == "HTML";
+ bool bDocModified = pDocShell->IsModified();
+ if(bHtml && !bDocModified && pDocShell->HasName())
+ {
+ SvStream* pStream = pMedium->GetInStream();
+ if(pStream && ERRCODE_NONE == pStream->GetError() )
+ {
+ rtl_TextEncoding eHeaderEnc =
+ SfxHTMLParser::GetEncodingByHttpHeader(
+ pDocShell->GetHeaderAttributes() );
+ if( RTL_TEXTENCODING_DONTKNOW == eHeaderEnc )
+ {
+ const char *pTmpCharSet =
+ rtl_getBestMimeCharsetFromTextEncoding( RTL_TEXTENCODING_ISO_8859_1 );
+ eHeaderEnc = rtl_getTextEncodingFromMimeCharset( pTmpCharSet );
+ }
+ if( RTL_TEXTENCODING_DONTKNOW != eHeaderEnc &&
+ eDestEnc != eHeaderEnc )
+ {
+ eDestEnc = eHeaderEnc;
+ m_aEditWin->SetTextEncoding(eDestEnc);
+ }
+ pStream->SetStreamCharSet( eDestEnc );
+ pStream->Seek(0);
+ TextEngine* pTextEngine = m_aEditWin->GetTextEngine();
+ pTextEngine->EnableUndo(false);
+ m_aEditWin->Read(*pStream);
+ pTextEngine->EnableUndo(true);
+ }
+ else
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetViewFrame().GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_ERR_SRCSTREAM)));
+ xBox->run();
+ }
+ }
+ else
+ {
+ utl::TempFileNamed aTempFile;
+ aTempFile.EnableKillingFile();
+ const OUString sFileURL( aTempFile.GetURL() );
+
+ {
+ SfxMedium aMedium( sFileURL,StreamMode::READWRITE );
+ SwWriter aWriter( aMedium, *pDocShell->GetDoc() );
+ WriterRef xWriter;
+ ::GetHTMLWriter(std::u16string_view(), aMedium.GetBaseURL( true ), xWriter);
+ const OUString sWriteName = pDocShell->HasName()
+ ? pMedium->GetName()
+ : sFileURL;
+ ErrCodeMsg nRes = aWriter.Write(xWriter, &sWriteName);
+ if(nRes)
+ {
+ ErrorHandler::HandleError(nRes);
+ m_aEditWin->SetReadonly(true);
+ }
+ aMedium.Commit();
+ SvStream* pInStream = aMedium.GetInStream();
+ pInStream->Seek(0);
+ pInStream->SetStreamCharSet( eDestEnc );
+
+ m_aEditWin->Read(*pInStream);
+ }
+ }
+ m_aEditWin->ClearModifyFlag();
+
+ m_eLoadEncoding = eDestEnc;
+
+ if(bDocModified)
+ pDocShell->SetModified();// The flag will be reset in between times.
+ // Disable AutoLoad
+ pDocShell->SetAutoLoad(INetURLObject(), 0, false);
+ assert(dynamic_cast<SwWebDocShell*>( pDocShell) && "Why no WebDocShell?" );
+ sal_uInt16 nLine = static_cast<SwWebDocShell*>(pDocShell)->GetSourcePara();
+ m_aEditWin->SetStartLine(nLine);
+ m_aEditWin->GetTextEngine()->ResetUndo();
+ m_aEditWin->GetOutWin()->GrabFocus();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/swcli.cxx b/sw/source/uibase/uiview/swcli.cxx
new file mode 100644
index 0000000000..ea7093516e
--- /dev/null
+++ b/sw/source/uibase/uiview/swcli.cxx
@@ -0,0 +1,193 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
+#include <wrtsh.hxx>
+#include <doc.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <view.hxx>
+#include <edtwin.hxx>
+#include <swcli.hxx>
+#include <svtools/embedhlp.hxx>
+#include <osl/diagnose.h>
+
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <ndole.hxx>
+
+using namespace com::sun::star;
+
+SwOleClient::SwOleClient(SwView *pView, SwEditWin *pWin, const svt::EmbeddedObjectRef& xObj)
+ : SfxInPlaceClient( pView, pWin, xObj.GetViewAspect() )
+ , m_IsInDoVerb(false)
+ , m_IsOldCheckForOLEInCaption(pView->GetWrtShell().IsCheckForOLEInCaption())
+{
+ SetObject( xObj.GetObject() );
+}
+
+void SwOleClient::RequestNewObjectArea( tools::Rectangle& aLogRect )
+{
+ // The server wants to change the client size.
+ // We put the desired size in the core. The attributes of the frame
+ // are set to the desired value. This value will be passed on to the
+ // InPlaceClient.
+ // The core accepts or formats the adjusted values not necessarily.
+ // If the Ole-Frame is formatted, then the CalcAndSetScale() of the WrtShell
+ // will be called. There the scaling of the SwOleClient is set if necessary.
+
+ SwWrtShell &rSh = static_cast<SwView*>(GetViewShell())->GetWrtShell();
+
+ rSh.StartAllAction();
+
+ // the aLogRect will get the preliminary size now
+ aLogRect.SetSize( rSh.RequestObjectResize( SwRect( aLogRect ), GetObject() ) );
+
+ // the EndAllAction() call will trigger CalcAndSetScale() call,
+ // so the embedded object must get the correct size before
+ if ( aLogRect.GetSize() != GetScaledObjArea().GetSize() )
+ {
+ // size has changed, so first change visual area of the object before we resize its view
+ // without this the object always would be scaled - now it has the choice
+
+ // TODO/LEAN: getMapUnit can switch object to running state
+ MapMode aObjectMap( VCLUnoHelper::UnoEmbed2VCLMapUnit( GetObject()->getMapUnit( GetAspect() ) ) );
+ MapMode aClientMap( GetEditWin()->GetMapMode().GetMapUnit() );
+
+ Size aNewObjSize( tools::Long( aLogRect.GetWidth() / GetScaleWidth() ),
+ tools::Long( aLogRect.GetHeight() / GetScaleHeight() ) );
+
+ // convert to logical coordinates of the embedded object
+ Size aNewSize = GetEditWin()->LogicToLogic( aNewObjSize, &aClientMap, &aObjectMap );
+ GetObject()->setVisualAreaSize( GetAspect(), awt::Size( aNewSize.Width(), aNewSize.Height() ) );
+ }
+
+ rSh.EndAllAction();
+
+ SwRect aFrame( rSh.GetAnyCurRect( CurRectType::FlyEmbedded, nullptr, GetObject() )),
+ aPrt( rSh.GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, GetObject() ));
+ aLogRect.SetPos( aPrt.Pos() + aFrame.Pos() );
+ aLogRect.SetSize( aPrt.SSize() );
+}
+
+void SwOleClient::ObjectAreaChanged()
+{
+ SwWrtShell &rSh = static_cast<SwView*>(GetViewShell())->GetWrtShell();
+ SwRect aFrame( rSh.GetAnyCurRect( CurRectType::FlyEmbedded, nullptr, GetObject() ));
+ if ( !aFrame.Overlaps( rSh.VisArea() ) )
+ rSh.MakeVisible( aFrame );
+}
+
+void SwOleClient::ViewChanged()
+{
+ if (m_IsInDoVerb)
+ return;
+
+ if ( GetAspect() == embed::Aspects::MSOLE_ICON )
+ {
+ // the iconified object seems not to need such a scaling handling
+ // since the replacement image and the size a completely controlled by the container
+ // TODO/LATER: when the icon exchange is implemented the scaling handling
+ // might be required again here
+ return;
+ }
+
+ SwWrtShell &rSh = static_cast<SwView*>(GetViewShell())->GetWrtShell();
+
+ // Adjust the size of the object in the core. The Scaling must
+ // be considered. Repercussions on the object are considered by
+ // CalcAndSetScale() of the WrtShell if the size / position of
+ // the frame in the core changes.
+
+ // TODO/LEAN: getMapUnit can switch object to running state
+ awt::Size aSz;
+ try
+ {
+ aSz = GetObject()->getVisualAreaSize( GetAspect() );
+ }
+ catch (const embed::NoVisualAreaSizeException&)
+ {
+ // Nothing will be done
+ }
+ catch (const uno::Exception&)
+ {
+ OSL_FAIL( "Something goes wrong on requesting object size!" );
+ }
+
+ Size aVisSize( aSz.Width, aSz.Height );
+
+ // As long as from the object comes no reasonable size
+ // nothing can be scaled.
+ if( !aVisSize.Width() || !aVisSize.Height() )
+ return;
+
+ // first convert to TWIPS before scaling, because scaling factors are calculated for
+ // the TWIPS mapping and so they will produce the best results if applied to TWIPS based
+ // coordinates
+ const MapMode aMyMap ( MapUnit::MapTwip );
+ const MapMode aObjMap( VCLUnoHelper::UnoEmbed2VCLMapUnit( GetObject()->getMapUnit( GetAspect() ) ) );
+ aVisSize = OutputDevice::LogicToLogic( aVisSize, aObjMap, aMyMap );
+
+ aVisSize.setWidth( tools::Long(aVisSize.Width() * GetScaleWidth()) );
+ aVisSize.setHeight( tools::Long(aVisSize.Height() * GetScaleHeight()) );
+
+ SwRect aRect( Point( LONG_MIN, LONG_MIN ), aVisSize );
+ rSh.LockView( true ); // Prevent scrolling in the EndAction
+ rSh.StartAllAction();
+ rSh.RequestObjectResize( aRect, GetObject() );
+ rSh.EndAllAction();
+ rSh.LockView( false );
+}
+
+void SwOleClient::FormatChanged()
+{
+ const uno::Reference < embed::XEmbeddedObject >& xObj( GetObject() );
+ SwView * pView = dynamic_cast< SwView * >( GetViewShell() );
+ if ( pView && xObj.is() && SotExchange::IsMath( xObj->getClassID() ) )
+ {
+ SwWrtShell & rWrtSh = pView->GetWrtShell();
+ if (rWrtSh.GetDoc()->getIDocumentSettingAccess().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT ))
+ rWrtSh.AlignFormulaToBaseline( xObj );
+ }
+}
+
+bool SwOleClient::IsProtected() const
+{
+ auto pView = dynamic_cast<SwView*>(GetViewShell());
+ if (!pView)
+ {
+ return false;
+ }
+
+ SwWrtShell& rWrtSh = pView->GetWrtShell();
+ if (rWrtSh.IsTableMode())
+ {
+ return false;
+ }
+
+ SwOLENode* pOLENode = rWrtSh.GetCursor()->GetPointNode().GetOLENode();
+ if (!pOLENode)
+ {
+ return false;
+ }
+
+ return pOLENode->GetOLEObj().IsProtected();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/uivwimp.cxx b/sw/source/uibase/uiview/uivwimp.cxx
new file mode 100644
index 0000000000..ed0c3c68fc
--- /dev/null
+++ b/sw/source/uibase/uiview/uivwimp.cxx
@@ -0,0 +1,333 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+#include <config_fuzzers.h>
+
+#include <cmdid.h>
+
+#include <com/sun/star/scanner/XScannerManager2.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/svapp.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/docfile.hxx>
+
+#include <sfx2/docinsert.hxx>
+#include <sfx2/request.hxx>
+#include <uivwimp.hxx>
+#include <unotxvw.hxx>
+#include <unodispatch.hxx>
+#include <swmodule.hxx>
+#include <swdtflvr.hxx>
+
+#include <strings.hrc>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::scanner;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::datatransfer::clipboard;
+
+SwView_Impl::SwView_Impl(SwView* pShell)
+ : m_pView(pShell)
+ , m_eShellMode(ShellMode::Text)
+ , m_nParam(0)
+ , m_bSelectObject(false)
+ , m_bEditingPositionSet(false)
+{
+ mxXTextView = new SwXTextView(m_pView);
+ m_xDispatchProviderInterceptor = new SwXDispatchProviderInterceptor(*m_pView);
+}
+
+SwView_Impl::~SwView_Impl()
+{
+ if(m_xDispatchProviderInterceptor)
+ m_xDispatchProviderInterceptor->Invalidate();
+ mxXTextView->Invalidate();
+ mxXTextView.clear();
+
+ if( mxScanEvtLstnr.is() )
+ mxScanEvtLstnr->ViewDestroyed();
+ if( mxClipEvtLstnr.is() )
+ {
+ mxClipEvtLstnr->AddRemoveListener( false );
+ mxClipEvtLstnr->ViewDestroyed();
+ }
+ DisconnectTransferableDDE();
+
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+ m_xConfigItem.reset();
+#endif
+ m_pDocInserter.reset();
+ m_pRequest.reset();
+}
+
+void SwView_Impl::SetShellMode(ShellMode eSet)
+{
+ m_eShellMode = eSet;
+}
+
+view::XSelectionSupplier* SwView_Impl::GetUNOObject()
+{
+ return mxXTextView.get();
+}
+
+SwXTextView* SwView_Impl::GetUNOObject_Impl()
+{
+ return mxXTextView.get();
+}
+
+void SwView_Impl::ExecuteScan( SfxRequest& rReq )
+{
+ switch(rReq.GetSlot())
+ {
+ case SID_TWAIN_SELECT:
+ {
+ bool bDone = false;
+ Reference< XScannerManager2 > xScanMgr = SW_MOD()->GetScannerManager();
+
+ if( xScanMgr.is() )
+ {
+ try
+ {
+ SwScannerEventListener& rListener = GetScannerEventListener();
+ const Sequence< ScannerContext >
+ aContexts( xScanMgr->getAvailableScanners() );
+
+ if( aContexts.hasElements() )
+ {
+ Reference< XEventListener > xLstner = &rListener;
+ ScannerContext aContext( aContexts.getConstArray()[ 0 ] );
+
+ Reference<lang::XInitialization> xInit(xScanMgr, UNO_QUERY);
+ if (xInit.is())
+ {
+ // initialize dialog
+ weld::Window* pWindow = rReq.GetFrameWeld();
+ uno::Sequence<uno::Any> aSeq(comphelper::InitAnyPropertySequence(
+ {
+ {"ParentWindow", pWindow ? uno::Any(pWindow->GetXWindow()) : uno::Any(Reference<awt::XWindow>())}
+ }));
+ xInit->initialize( aSeq );
+ }
+
+ bDone = xScanMgr->configureScannerAndScan( aContext, xLstner );
+ }
+ }
+ catch(...)
+ {
+ }
+
+ }
+ if( bDone )
+ rReq.Done();
+ else
+ {
+ rReq.Ignore();
+ }
+ }
+ break;
+
+ case SID_TWAIN_TRANSFER:
+ {
+ bool bDone = false;
+
+ Reference< XScannerManager2 > xScanMgr = SW_MOD()->GetScannerManager();
+ if( xScanMgr.is() )
+ {
+ SwScannerEventListener& rListener = GetScannerEventListener();
+ try
+ {
+ const Sequence< scanner::ScannerContext >aContexts( xScanMgr->getAvailableScanners() );
+ if( aContexts.hasElements() )
+ {
+ Reference< XEventListener > xLstner = &rListener;
+ xScanMgr->startScan( aContexts.getConstArray()[ 0 ], xLstner );
+ bDone = true;
+ }
+ }
+ catch(...)
+ {
+ }
+ }
+
+ if( !bDone )
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(rReq.GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_SCAN_NOSOURCE)));
+ xBox->run();
+ rReq.Ignore();
+ }
+ else
+ {
+ rReq.Done();
+ SfxBindings& rBind = m_pView->GetViewFrame().GetBindings();
+ rBind.Invalidate( SID_TWAIN_SELECT );
+ rBind.Invalidate( SID_TWAIN_TRANSFER );
+ }
+ }
+ break;
+ }
+}
+
+SwScannerEventListener& SwView_Impl::GetScannerEventListener()
+{
+ if(!mxScanEvtLstnr.is())
+ mxScanEvtLstnr = new SwScannerEventListener(*m_pView);
+ return *mxScanEvtLstnr;
+}
+
+void SwView_Impl::AddClipboardListener()
+{
+ if(!mxClipEvtLstnr.is())
+ {
+ mxClipEvtLstnr = new SwClipboardChangeListener( *m_pView );
+ mxClipEvtLstnr->AddRemoveListener( true );
+ }
+}
+
+void SwView_Impl::Invalidate()
+{
+ GetUNOObject_Impl()->Invalidate();
+ for (const auto& xTransferable: mxTransferables)
+ {
+ rtl::Reference<SwTransferable> pTransferable = xTransferable.get();
+ if(pTransferable)
+ pTransferable->Invalidate();
+ }
+}
+
+void SwView_Impl::DisconnectTransferableDDE()
+{
+ for (const auto& xTransferable: mxTransferables)
+ {
+ rtl::Reference<SwTransferable> pTransferable = xTransferable.get();
+ if(pTransferable)
+ pTransferable->DisconnectDDE();
+ }
+}
+
+void SwView_Impl::AddTransferable(SwTransferable& rTransferable)
+{
+ //prevent removing of the non-referenced SwTransferable
+ osl_atomic_increment(&rTransferable.m_refCount);
+ {
+ // Remove previously added, but no longer existing weak references.
+ std::erase_if(mxTransferables,
+ [](const unotools::WeakReference<SwTransferable>& rTunnel) {
+ return !rTunnel.get();
+ });
+
+ mxTransferables.emplace_back(&rTransferable);
+ }
+ osl_atomic_decrement(&rTransferable.m_refCount);
+}
+
+void SwView_Impl::StartDocumentInserter(
+ const OUString& rFactory,
+ const Link<sfx2::FileDialogHelper*,void>& rEndDialogHdl,
+ const sal_uInt16 nSlotId
+)
+{
+ sfx2::DocumentInserter::Mode mode {sfx2::DocumentInserter::Mode::Insert};
+ switch( nSlotId )
+ {
+ case SID_DOCUMENT_MERGE:
+ mode = sfx2::DocumentInserter::Mode::Merge;
+ break;
+ case SID_DOCUMENT_COMPARE:
+ mode = sfx2::DocumentInserter::Mode::Compare;
+ break;
+ default:
+ break;
+ }
+
+ m_pDocInserter.reset(new ::sfx2::DocumentInserter(m_pView->GetFrameWeld(), rFactory, mode));
+ m_pDocInserter->StartExecuteModal( rEndDialogHdl );
+}
+
+std::unique_ptr<SfxMedium> SwView_Impl::CreateMedium()
+{
+ return m_pDocInserter->CreateMedium();
+}
+
+void SwView_Impl::InitRequest( const SfxRequest& rRequest )
+{
+ m_pRequest.reset(new SfxRequest( rRequest ));
+}
+
+SwScannerEventListener::~SwScannerEventListener()
+{
+}
+
+void SAL_CALL SwScannerEventListener::disposing( const EventObject& /*rEventObject*/)
+{
+#if defined(_WIN32) || defined UNX
+ SolarMutexGuard aGuard;
+ if( m_pView )
+ m_pView->ScannerEventHdl();
+#endif
+}
+
+SwClipboardChangeListener::~SwClipboardChangeListener()
+{
+}
+
+void SAL_CALL SwClipboardChangeListener::disposing( const EventObject& /*rEventObject*/ )
+{
+ SolarMutexGuard aGuard;
+ m_pView = nullptr; // so we don't touch the view if changedContents somehow fires afterwards
+}
+
+void SAL_CALL SwClipboardChangeListener::changedContents( const css::datatransfer::clipboard::ClipboardEvent& rEventObject )
+
+{
+ const SolarMutexGuard aGuard;
+ if( !m_pView )
+ return;
+
+ {
+ TransferableDataHelper aDataHelper( rEventObject.Contents );
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+
+ m_pView->m_nLastPasteDestination = SwTransferable::GetSotDestination( rSh );
+ m_pView->m_bPasteState = aDataHelper.GetXTransferable().is() &&
+ SwTransferable::IsPaste( rSh, aDataHelper );
+
+ m_pView->m_bPasteSpecialState = aDataHelper.GetXTransferable().is() &&
+ SwTransferable::IsPasteSpecial( rSh, aDataHelper );
+ }
+
+ SfxBindings& rBind = m_pView->GetViewFrame().GetBindings();
+ rBind.Invalidate( SID_PASTE );
+ rBind.Invalidate( SID_PASTE_SPECIAL );
+ rBind.Invalidate( SID_CLIPBOARD_FORMAT_ITEMS );
+}
+
+void SwClipboardChangeListener::AddRemoveListener( bool bAdd )
+{
+ m_pView->AddRemoveClipboardListener( Reference< XClipboardListener >( this ), bAdd );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/view.cxx b/sw/source/uibase/uiview/view.cxx
new file mode 100644
index 0000000000..2d46cd04f2
--- /dev/null
+++ b/sw/source/uibase/uiview/view.cxx
@@ -0,0 +1,2120 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <config_features.h>
+#include <config_wasm_strip.h>
+
+#include <stdlib.h>
+#include <hintids.hxx>
+#include <comphelper/string.hxx>
+#include <comphelper/lok.hxx>
+#include <o3tl/any.hxx>
+#include <o3tl/string_view.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/inputctx.hxx>
+#include <svl/eitem.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/lingucfg.hxx>
+#include <unotools/useroptions.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/request.hxx>
+#include <svx/ruler.hxx>
+#include <svx/srchdlg.hxx>
+#include <svx/fmshell.hxx>
+#include <svx/extrusionbar.hxx>
+#include <svx/fontworkbar.hxx>
+#include <svx/fmview.hxx>
+#include <unotxvw.hxx>
+#include <cmdid.h>
+#include <svl/hint.hxx>
+#include <swmodule.hxx>
+#include <inputwin.hxx>
+#include <uivwimp.hxx>
+#include <edtwin.hxx>
+#include <textsh.hxx>
+#include <listsh.hxx>
+#include <tabsh.hxx>
+#include <grfsh.hxx>
+#include <mediash.hxx>
+#include <docsh.hxx>
+#include <frmsh.hxx>
+#include <olesh.hxx>
+#include <drawsh.hxx>
+#include <drawbase.hxx>
+#include <drformsh.hxx>
+#include <drwtxtsh.hxx>
+#include <beziersh.hxx>
+#include <navsh.hxx>
+#include <globdoc.hxx>
+#include <scroll.hxx>
+#include <gloshdl.hxx>
+#include <usrpref.hxx>
+#include <srcview.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <DocumentFieldsManager.hxx>
+#include <IDocumentState.hxx>
+#include <IDocumentLayoutAccess.hxx>
+#include <drawdoc.hxx>
+#include <wdocsh.hxx>
+#include <wrtsh.hxx>
+#include <barcfg.hxx>
+#include <pview.hxx>
+#include <swdtflvr.hxx>
+#include <prtopt.hxx>
+#include <unotxdoc.hxx>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/frame/XLayoutManager.hpp>
+#include <com/sun/star/scanner/ScannerContext.hpp>
+#include <com/sun/star/scanner/XScannerManager2.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/sdb/XDatabaseContext.hpp>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <sal/log.hxx>
+
+#include <formatclipboard.hxx>
+#include <PostItMgr.hxx>
+#include <annotsh.hxx>
+#include <swruler.hxx>
+#include <svx/theme/ThemeColorPaletteManager.hxx>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <sfx2/lokhelper.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <svtools/embedhlp.hxx>
+#include <tools/UnitConversion.hxx>
+
+#include <svx/sdr/overlay/overlayselection.hxx>
+#include <svx/sdr/overlay/overlayobject.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <svx/sdrpaintwindow.hxx>
+#include <svx/svdview.hxx>
+#include <node2lay.hxx>
+#include <cntfrm.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::scanner;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+
+#define SWVIEWFLAGS SfxViewShellFlags::HAS_PRINTOPTIONS
+
+// Statics. OMG.
+
+bool bDocSzUpdated = true;
+
+SvxSearchItem* SwView::s_pSrchItem = nullptr;
+
+bool SwView::s_bExtra = false;
+bool SwView::s_bFound = false;
+bool SwView::s_bJustOpened = false;
+
+std::unique_ptr<SearchAttrItemList> SwView::s_xSearchList;
+std::unique_ptr<SearchAttrItemList> SwView::s_xReplaceList;
+
+SfxDispatcher &SwView::GetDispatcher()
+{
+ return *GetViewFrame().GetDispatcher();
+}
+
+void SwView::ImpSetVerb( SelectionType nSelType )
+{
+ bool bResetVerbs = m_bVerbsActive;
+ if ( !GetViewFrame().GetFrame().IsInPlace() &&
+ (SelectionType::Ole|SelectionType::Graphic) & nSelType )
+ {
+ FlyProtectFlags eProtectFlags = m_pWrtShell->IsSelObjProtected(FlyProtectFlags::Content);
+ if (eProtectFlags == FlyProtectFlags::NONE || nSelType & SelectionType::Ole)
+ {
+ if ( nSelType & SelectionType::Ole )
+ {
+ SetVerbs( GetWrtShell().GetOLEObject()->getSupportedVerbs() );
+ m_bVerbsActive = true;
+ bResetVerbs = false;
+ }
+ }
+ }
+ if ( bResetVerbs )
+ {
+ SetVerbs( Sequence< embed::VerbDescriptor >() );
+ m_bVerbsActive = false;
+ }
+}
+
+// Called by the SwEditWin when it gets the focus.
+
+void SwView::GotFocus() const
+{
+ // if we got the focus, and the form shell *is* on the top of the dispatcher
+ // stack, then we need to rebuild the stack (the form shell doesn't belong to
+ // the top then)
+ const SfxDispatcher& rDispatcher = const_cast< SwView* >( this )->GetDispatcher();
+ SfxShell* pTopShell = rDispatcher.GetShell( 0 );
+ FmFormShell* pAsFormShell = dynamic_cast<FmFormShell*>( pTopShell );
+ if ( pAsFormShell )
+ {
+ pAsFormShell->ForgetActiveControl();
+ const_cast< SwView* >( this )->AttrChangedNotify(nullptr);
+ }
+ else if ( m_pPostItMgr )
+ {
+ SwAnnotationShell* pAsAnnotationShell = dynamic_cast<SwAnnotationShell*>( pTopShell );
+ if ( pAsAnnotationShell )
+ {
+ m_pPostItMgr->SetActiveSidebarWin(nullptr);
+ const_cast< SwView* >( this )->AttrChangedNotify(nullptr);
+ }
+ }
+ if (SwWrtShell* pWrtShell = GetWrtShellPtr())
+ {
+ SwWrtShell& rWrtShell = GetWrtShell();
+ rWrtShell.GetDoc()->getIDocumentLayoutAccess().SetCurrentViewShell( pWrtShell );
+ rWrtShell.GetDoc()->getIDocumentSettingAccess().set( DocumentSettingId::BROWSE_MODE,
+ rWrtShell.GetViewOptions()->getBrowseMode() );
+ }
+}
+
+// called by the FormShell when a form control is focused. This is
+// a request to put the form shell on the top of the dispatcher stack
+
+IMPL_LINK_NOARG(SwView, FormControlActivated, LinkParamNone*, void)
+{
+ // if a form control has been activated, and the form shell is not on the top
+ // of the dispatcher stack, then we need to activate it
+ const SfxDispatcher& rDispatcher = GetDispatcher();
+ const SfxShell* pTopShell = rDispatcher.GetShell( 0 );
+ const FmFormShell* pAsFormShell = dynamic_cast<const FmFormShell*>( pTopShell );
+ if ( !pAsFormShell )
+ {
+ // if we're editing text currently, cancel this
+ SdrView *pSdrView = m_pWrtShell ? m_pWrtShell->GetDrawView() : nullptr;
+ if ( pSdrView && pSdrView->IsTextEdit() )
+ pSdrView->SdrEndTextEdit( true );
+
+ AttrChangedNotify(nullptr);
+ }
+}
+
+namespace
+{
+uno::Reference<frame::XLayoutManager> getLayoutManager(const SfxViewFrame& rViewFrame)
+{
+ uno::Reference<frame::XLayoutManager> xLayoutManager;
+ uno::Reference<beans::XPropertySet> xPropSet(rViewFrame.GetFrame().GetFrameInterface(),
+ uno::UNO_QUERY);
+ if (xPropSet.is())
+ {
+ try
+ {
+ xLayoutManager.set(xPropSet->getPropertyValue("LayoutManager"), uno::UNO_QUERY);
+ }
+ catch (const Exception& e)
+ {
+ SAL_WARN("sw.ui", "Failure getting layout manager: " + e.Message);
+ }
+ }
+ return xLayoutManager;
+}
+}
+
+void SwView::ShowUIElement(const OUString& sElementURL) const
+{
+ if (auto xLayoutManager = getLayoutManager(GetViewFrame()))
+ {
+ if (!xLayoutManager->getElement(sElementURL).is())
+ {
+ xLayoutManager->createElement(sElementURL);
+ xLayoutManager->showElement(sElementURL);
+ }
+ }
+}
+
+void SwView::SelectShell()
+{
+ // Attention: Maintain the SelectShell for the WebView additionally
+
+ // In case of m_bDying, our SfxShells are already gone, don't try to select a shell at all.
+ if(m_bInDtor || m_bDying)
+ return;
+
+ // Decision if the UpdateTable has to be called
+ bool bUpdateTable = false;
+ const SwFrameFormat* pCurTableFormat = m_pWrtShell->GetTableFormat();
+ if(pCurTableFormat && pCurTableFormat != m_pLastTableFormat)
+ {
+ bUpdateTable = true; // can only be executed later
+ }
+ m_pLastTableFormat = pCurTableFormat;
+
+ //SEL_TBL and SEL_TBL_CELLS can be ORed!
+ SelectionType nNewSelectionType = m_pWrtShell->GetSelectionType()
+ & ~SelectionType::TableCell;
+
+ // Determine if a different fly frame was selected.
+ bool bUpdateFly = false;
+ const SwFrameFormat* pCurFlyFormat = nullptr;
+ if (m_pWrtShell->IsSelFrameMode())
+ {
+ pCurFlyFormat = m_pWrtShell->GetFlyFrameFormat();
+ }
+ if (pCurFlyFormat && m_pLastFlyFormat && pCurFlyFormat != m_pLastFlyFormat)
+ {
+ // Only do an explicit update when switching between flys.
+ bUpdateFly = true;
+ }
+ m_pLastFlyFormat = pCurFlyFormat;
+
+ if ( m_pFormShell && m_pFormShell->IsActiveControl() )
+ nNewSelectionType |= SelectionType::FormControl;
+
+ if ( nNewSelectionType == m_nSelectionType )
+ {
+ GetViewFrame().GetBindings().InvalidateAll( false );
+ if ( m_nSelectionType & SelectionType::Ole ||
+ m_nSelectionType & SelectionType::Graphic )
+ // For graphs and OLE the verb can be modified of course!
+ ImpSetVerb( nNewSelectionType );
+
+ if (bUpdateFly)
+ {
+ SfxViewFrame& rViewFrame = GetViewFrame();
+ uno::Reference<frame::XFrame> xFrame = rViewFrame.GetFrame().GetFrameInterface();
+ if (xFrame.is())
+ {
+ // Invalidate cached dispatch objects.
+ xFrame->contextChanged();
+ }
+ }
+ }
+ else
+ {
+
+ SfxDispatcher &rDispatcher = GetDispatcher();
+ SwToolbarConfigItem *pBarCfg = SW_MOD()->GetToolbarConfig();
+
+ if ( m_pShell )
+ {
+ rDispatcher.Flush(); // Really erase all cached shells
+ //Remember to the old selection which toolbar was visible
+ ToolbarId eId = rDispatcher.GetObjectBarId(SFX_OBJECTBAR_OBJECT);
+ if (eId != ToolbarId::None)
+ pBarCfg->SetTopToolbar(m_nSelectionType, eId);
+
+ for ( sal_uInt16 i = 0; true; ++i )
+ {
+ SfxShell *pSfxShell = rDispatcher.GetShell( i );
+ if ( dynamic_cast< const SwBaseShell *>( pSfxShell ) != nullptr
+ || dynamic_cast< const SwDrawTextShell *>( pSfxShell ) != nullptr
+ || dynamic_cast< const svx::ExtrusionBar*>( pSfxShell ) != nullptr
+ || dynamic_cast< const svx::FontworkBar*>( pSfxShell ) != nullptr
+ || dynamic_cast< const SwAnnotationShell *>( pSfxShell ) != nullptr
+ )
+ {
+ rDispatcher.Pop( *pSfxShell, SfxDispatcherPopFlags::POP_DELETE );
+ }
+ else if ( dynamic_cast< const FmFormShell *>( pSfxShell ) != nullptr )
+ {
+ rDispatcher.Pop( *pSfxShell );
+ }
+ else
+ break;
+ }
+ }
+
+ bool bInitFormShell = false;
+ if (!m_pFormShell)
+ {
+ bInitFormShell = true;
+ m_pFormShell = new FmFormShell( this );
+ m_pFormShell->SetControlActivationHandler( LINK( this, SwView, FormControlActivated ) );
+ StartListening(*m_pFormShell);
+ }
+
+ bool bSetExtInpCntxt = false;
+ m_nSelectionType = nNewSelectionType;
+ ShellMode eShellMode;
+
+ if ( !( m_nSelectionType & SelectionType::FormControl ) )
+ rDispatcher.Push( *m_pFormShell );
+
+ m_pShell = new SwNavigationShell( *this );
+ rDispatcher.Push( *m_pShell );
+
+ if ( m_nSelectionType & SelectionType::Ole )
+ {
+ eShellMode = ShellMode::Object;
+ m_pShell = new SwOleShell( *this );
+ rDispatcher.Push( *m_pShell );
+ }
+ else if ( m_nSelectionType & SelectionType::Frame
+ || m_nSelectionType & SelectionType::Graphic)
+ {
+ eShellMode = ShellMode::Frame;
+ m_pShell = new SwFrameShell( *this );
+ rDispatcher.Push( *m_pShell );
+ if(m_nSelectionType & SelectionType::Graphic )
+ {
+ eShellMode = ShellMode::Graphic;
+ m_pShell = new SwGrfShell( *this );
+ rDispatcher.Push( *m_pShell );
+ }
+ }
+ else if ( m_nSelectionType & SelectionType::DrawObject )
+ {
+ eShellMode = ShellMode::Draw;
+ m_pShell = new SwDrawShell( *this );
+ rDispatcher.Push( *m_pShell );
+
+ if ( m_nSelectionType & SelectionType::Ornament )
+ {
+ eShellMode = ShellMode::Bezier;
+ m_pShell = new SwBezierShell( *this );
+ rDispatcher.Push( *m_pShell );
+ }
+#if HAVE_FEATURE_AVMEDIA
+ else if( m_nSelectionType & SelectionType::Media )
+ {
+ eShellMode = ShellMode::Media;
+ m_pShell = new SwMediaShell( *this );
+ rDispatcher.Push( *m_pShell );
+ }
+#endif
+ if (m_nSelectionType & SelectionType::ExtrudedCustomShape)
+ {
+ eShellMode = ShellMode::ExtrudedCustomShape;
+ m_pShell = new svx::ExtrusionBar(this);
+ rDispatcher.Push( *m_pShell );
+ }
+ if (m_nSelectionType & SelectionType::FontWork)
+ {
+ eShellMode = ShellMode::FontWork;
+ m_pShell = new svx::FontworkBar(this);
+ rDispatcher.Push( *m_pShell );
+ }
+ }
+ else if ( m_nSelectionType & SelectionType::DbForm )
+ {
+ eShellMode = ShellMode::DrawForm;
+ m_pShell = new SwDrawFormShell( *this );
+
+ rDispatcher.Push( *m_pShell );
+ }
+ else if ( m_nSelectionType & SelectionType::DrawObjectEditMode )
+ {
+ bSetExtInpCntxt = true;
+ eShellMode = ShellMode::DrawText;
+ rDispatcher.Push( *(new SwBaseShell( *this )) );
+ m_pShell = new SwDrawTextShell( *this );
+ rDispatcher.Push( *m_pShell );
+ }
+ else if ( m_nSelectionType & SelectionType::PostIt )
+ {
+ eShellMode = ShellMode::PostIt;
+ m_pShell = new SwAnnotationShell( *this );
+ rDispatcher.Push( *m_pShell );
+ }
+ else
+ {
+ bSetExtInpCntxt = true;
+ eShellMode = ShellMode::Text;
+ if ( m_nSelectionType & SelectionType::NumberList )
+ {
+ eShellMode = ShellMode::ListText;
+ m_pShell = new SwListShell( *this );
+ rDispatcher.Push( *m_pShell );
+ }
+ m_pShell = new SwTextShell(*this);
+ rDispatcher.Push( *m_pShell );
+ if ( m_nSelectionType & SelectionType::Table )
+ {
+ eShellMode = eShellMode == ShellMode::ListText ? ShellMode::TableListText
+ : ShellMode::TableText;
+ m_pShell = new SwTableShell( *this );
+ rDispatcher.Push( *m_pShell );
+ }
+ }
+
+ if ( m_nSelectionType & SelectionType::FormControl )
+ rDispatcher.Push( *m_pFormShell );
+
+ m_pViewImpl->SetShellMode(eShellMode);
+ ImpSetVerb( m_nSelectionType );
+
+ if( !GetDocShell()->IsReadOnly() )
+ {
+ if( bSetExtInpCntxt && GetWrtShell().HasReadonlySel() )
+ bSetExtInpCntxt = false;
+
+ InputContext aCntxt( GetEditWin().GetInputContext() );
+ aCntxt.SetOptions( bSetExtInpCntxt
+ ? (aCntxt.GetOptions() |
+ ( InputContextFlags::Text |
+ InputContextFlags::ExtText ))
+ : (aCntxt.GetOptions() & ~
+ InputContextFlags( InputContextFlags::Text |
+ InputContextFlags::ExtText )) );
+ GetEditWin().SetInputContext( aCntxt );
+ }
+
+ // Show Mail Merge toolbar initially for documents with Database fields
+ if (!m_bInitOnceCompleted && GetWrtShell().IsAnyDatabaseFieldInDoc() && !utl::ConfigManager::IsFuzzing())
+ ShowUIElement("private:resource/toolbar/mailmerge");
+
+ // Activate the toolbar to the new selection which also was active last time.
+ // Before a flush () must be, but does not affect the UI according to MBA and
+ // is not a performance problem.
+ // TODO/LATER: maybe now the Flush() command is superfluous?!
+ rDispatcher.Flush();
+
+ Point aPnt = GetEditWin().OutputToScreenPixel(GetEditWin().GetPointerPosPixel());
+ aPnt = GetEditWin().PixelToLogic(aPnt);
+ GetEditWin().UpdatePointer(aPnt);
+
+ SdrView* pDView = GetWrtShell().GetDrawView();
+ if ( bInitFormShell && pDView )
+ m_pFormShell->SetView(dynamic_cast<FmFormView*>( pDView) );
+
+ }
+ // Opportune time for the communication with OLE objects?
+ if ( GetDocShell()->GetDoc()->IsOLEPrtNotifyPending() )
+ GetDocShell()->GetDoc()->PrtOLENotify( false );
+
+ // now the table-update
+ if(bUpdateTable)
+ m_pWrtShell->UpdateTable();
+
+ GetViewImpl()->GetUNOObject_Impl()->NotifySelChanged();
+
+ m_bInitOnceCompleted = true;
+}
+
+// Interaction: AttrChangedNotify() and TimeoutHdl.
+// No Update if actions are still open, since the cursor on the core side
+// can be somewhere in no man's land.
+// But since we can no longer supply status and we want instead lock
+// the dispatcher.
+
+extern "C"
+{
+ static int lcl_CmpIds( const void *pFirst, const void *pSecond)
+ {
+ return *static_cast<sal_uInt16 const *>(pFirst) - *static_cast<sal_uInt16 const *>(pSecond);
+ }
+}
+
+IMPL_LINK_NOARG(SwView, AttrChangedNotify, LinkParamNone*, void)
+{
+ if ( GetEditWin().IsChainMode() )
+ GetEditWin().SetChainMode( false );
+
+ if (!m_pWrtShell || !GetDocShell())
+ {
+ return;
+ }
+
+ //Opt: Not if PaintLocked. During unlock a notify will be once more triggered.
+ if( !m_pWrtShell->IsPaintLocked() && !g_bNoInterrupt &&
+ GetDocShell()->IsReadOnly() )
+ CheckReadonlyState();
+
+ if( !m_pWrtShell->IsPaintLocked() && !g_bNoInterrupt )
+ CheckReadonlySelection();
+
+ if( !m_bAttrChgNotified )
+ {
+ if (m_pWrtShell->ActionPend() || g_bNoInterrupt ||
+ GetDispatcher().IsLocked() || //do not confuse the SFX
+ GetViewFrame().GetBindings().IsInUpdate() )//do not confuse the SFX
+ {
+ m_bAttrChgNotified = true;
+ m_aTimer.Start();
+
+ const SfxBoolItem *pItem =
+ GetObjectShell()->GetMedium()->GetItemSet().
+ GetItemIfSet( SID_HIDDEN, false );
+ if ( !pItem || !pItem->GetValue() )
+ {
+ GetViewFrame().GetBindings().ENTERREGISTRATIONS();
+ m_bAttrChgNotifiedWithRegistrations = true;
+ }
+
+ }
+ else
+ SelectShell();
+
+ }
+
+ // change ui if cursor is at a SwPostItField
+ if (m_pPostItMgr)
+ {
+ // only perform the code that is needed to determine, if at the
+ // actual cursor position is a post-it field
+ m_pPostItMgr->SetShadowState( m_pWrtShell->GetPostItFieldAtCursor() );
+ }
+}
+
+IMPL_LINK_NOARG(SwView, TimeoutHdl, Timer *, void)
+{
+ if (m_pWrtShell->ActionPend() || g_bNoInterrupt)
+ {
+ m_aTimer.Start();
+ return;
+ }
+
+ if ( m_bAttrChgNotifiedWithRegistrations )
+ {
+ GetViewFrame().GetBindings().LEAVEREGISTRATIONS();
+ m_bAttrChgNotifiedWithRegistrations = false;
+ }
+
+ CheckReadonlyState();
+ CheckReadonlySelection();
+
+ bool bOldUndo = m_pWrtShell->DoesUndo();
+ m_pWrtShell->DoUndo( false );
+ SelectShell();
+ m_pWrtShell->DoUndo( bOldUndo );
+ m_bAttrChgNotified = false;
+ GetViewImpl()->GetUNOObject_Impl()->NotifySelChanged();
+}
+
+void SwView::CheckReadonlyState()
+{
+ SfxDispatcher &rDis = GetDispatcher();
+ // To be able to recognize if it is already disabled!
+ SfxItemState eStateRO, eStateProtAll;
+ SfxPoolItemHolder aResult;
+ // Query the status from a slot which is only known to us.
+ // Otherwise the slot is known from other; like the BasicIde
+ eStateRO = rDis.QueryState(FN_INSERT_BOOKMARK, aResult);
+ eStateProtAll = rDis.QueryState(FN_EDIT_REGION, aResult);
+ bool bChgd = false;
+
+ if ( !m_pWrtShell->IsCursorReadonly() )
+ {
+ static sal_uInt16 aROIds[] =
+ {
+ SID_DELETE, FN_BACKSPACE, FN_SHIFT_BACKSPACE,
+ SID_UNDO,
+ SID_REDO, SID_REPEAT, SID_PASTE,
+ SID_PASTE_UNFORMATTED, FN_PASTE_NESTED_TABLE, FN_TABLE_PASTE_ROW_BEFORE,
+ FN_TABLE_PASTE_COL_BEFORE, SID_PASTE_SPECIAL, SID_SBA_BRW_INSERT,
+ SID_BACKGROUND_COLOR, FN_INSERT_BOOKMARK, SID_CHARMAP_CONTROL,
+ SID_CHARMAP, FN_INSERT_SOFT_HYPHEN,
+ FN_INSERT_HARDHYPHEN, FN_INSERT_HARD_SPACE, FN_INSERT_NNBSP,
+ FN_INSERT_BREAK, FN_INSERT_LINEBREAK, FN_INSERT_COLUMN_BREAK,
+ FN_INSERT_BREAK_DLG, FN_INSERT_CONTENT_CONTROL, FN_INSERT_CHECKBOX_CONTENT_CONTROL,
+ FN_INSERT_DROPDOWN_CONTENT_CONTROL, FN_INSERT_PICTURE_CONTENT_CONTROL,
+ FN_INSERT_DATE_CONTENT_CONTROL, FN_INSERT_PLAIN_TEXT_CONTENT_CONTROL,
+ FN_INSERT_COMBO_BOX_CONTENT_CONTROL,
+ FN_DELETE_SENT, FN_DELETE_BACK_SENT, FN_DELETE_WORD,
+ FN_DELETE_BACK_WORD, FN_DELETE_LINE, FN_DELETE_BACK_LINE,
+ FN_DELETE_PARA, FN_DELETE_BACK_PARA, FN_DELETE_WHOLE_LINE,
+ FN_CALCULATE, FN_FORMAT_RESET,
+ FN_POSTIT, FN_JAVAEDIT, SID_ATTR_PARA_ADJUST_LEFT,
+ SID_ATTR_PARA_ADJUST_RIGHT, SID_ATTR_PARA_ADJUST_CENTER,SID_ATTR_PARA_ADJUST_BLOCK,
+ SID_ATTR_PARA_LINESPACE_10, SID_ATTR_PARA_LINESPACE_15, SID_ATTR_PARA_LINESPACE_20,
+ SID_ATTR_CHAR_FONT, SID_ATTR_CHAR_FONTHEIGHT, SID_ATTR_CHAR_COLOR_BACKGROUND,
+ SID_ATTR_CHAR_BACK_COLOR,
+ SID_ATTR_CHAR_COLOR_BACKGROUND_EXT, SID_ATTR_CHAR_COLOR_EXT,
+ SID_ATTR_CHAR_COLOR, SID_ATTR_CHAR_WEIGHT, SID_ATTR_CHAR_POSTURE,
+ SID_ATTR_CHAR_OVERLINE,
+ SID_ATTR_CHAR_UNDERLINE, SID_ATTR_FLASH, SID_ATTR_CHAR_STRIKEOUT,
+ SID_ULINE_VAL_SINGLE, SID_ULINE_VAL_DOUBLE, SID_ULINE_VAL_DOTTED,
+ SID_ATTR_CHAR_CONTOUR, SID_ATTR_CHAR_SHADOWED,
+ SID_ATTR_CHAR_AUTOKERN, SID_ATTR_CHAR_ESCAPEMENT, FN_SET_SUPER_SCRIPT,
+ FN_SET_SUB_SCRIPT, SID_ATTR_CHAR_CASEMAP, SID_ATTR_CHAR_LANGUAGE,
+ SID_ATTR_CHAR_KERNING, SID_CHAR_DLG, SID_ATTR_CHAR_WORDLINEMODE,
+ FN_GROW_FONT_SIZE, FN_SHRINK_FONT_SIZE, FN_TXTATR_INET,
+ FN_FORMAT_DROPCAPS, SID_ATTR_PARA_ADJUST, SID_ATTR_PARA_LINESPACE,
+ SID_ATTR_PARA_SPLIT, SID_ATTR_PARA_KEEP, SID_ATTR_PARA_WIDOWS,
+ SID_ATTR_PARA_ORPHANS,
+ SID_ATTR_PARA_MODEL, SID_PARA_DLG,
+ FN_SELECT_PARA, SID_DEC_INDENT,
+ SID_INC_INDENT
+ };
+ static bool bFirst = true;
+ if ( bFirst )
+ {
+ qsort( static_cast<void*>(aROIds), SAL_N_ELEMENTS(aROIds), sizeof(sal_uInt16), lcl_CmpIds );
+ bFirst = false;
+ }
+ if ( SfxItemState::DISABLED == eStateRO )
+ {
+ rDis.SetSlotFilter( SfxSlotFilterState::ENABLED_READONLY, aROIds );
+ bChgd = true;
+ }
+ }
+ else if( m_pWrtShell->IsAllProtect() )
+ {
+ if ( SfxItemState::DISABLED == eStateProtAll )
+ {
+ static sal_uInt16 aAllProtIds[] = { SID_SAVEDOC, FN_EDIT_REGION };
+ static bool bAllProtFirst = true;
+ if ( bAllProtFirst )
+ {
+ qsort( static_cast<void*>(aAllProtIds), SAL_N_ELEMENTS(aAllProtIds), sizeof(sal_uInt16), lcl_CmpIds );
+ bAllProtFirst = false;
+ }
+ rDis.SetSlotFilter( SfxSlotFilterState::ENABLED_READONLY, aAllProtIds );
+ bChgd = true;
+ }
+ }
+ else if ( SfxItemState::DISABLED != eStateRO ||
+ SfxItemState::DISABLED != eStateProtAll )
+ {
+ bChgd = true;
+ rDis.SetSlotFilter();
+ }
+ if ( bChgd )
+ GetViewFrame().GetBindings().InvalidateAll(true);
+}
+
+void SwView::CheckReadonlySelection()
+{
+ SfxDisableFlags nDisableFlags = SfxDisableFlags::NONE;
+ SfxDispatcher &rDis = GetDispatcher();
+
+ if( m_pWrtShell->HasReadonlySel() &&
+ ( !m_pWrtShell->GetDrawView() ||
+ !m_pWrtShell->GetDrawView()->GetMarkedObjectList().GetMarkCount() ))
+ nDisableFlags |= SfxDisableFlags::SwOnProtectedCursor;
+
+ if( (SfxDisableFlags::SwOnProtectedCursor & nDisableFlags ) !=
+ (SfxDisableFlags::SwOnProtectedCursor & rDis.GetDisableFlags() ) )
+ {
+ // Additionally move at the Window the InputContext, so that
+ // in japanese / chinese versions the external input will be
+ // turned on or off. This but only if the correct shell is on
+ // the stack.
+ switch( m_pViewImpl->GetShellMode() )
+ {
+ case ShellMode::Text:
+ case ShellMode::ListText:
+ case ShellMode::TableText:
+ case ShellMode::TableListText:
+ {
+// Temporary solution!!! Should set the font of the current insertion point
+// at each cursor movement, so outside of this "if". But TH does not
+// evaluates the font at this time and the "purchase" appears to me
+// as too expensive.
+// Moreover, we don't have a font, but only attributes from which the
+// text formatting and the correct font will be build together.
+
+ InputContext aCntxt( GetEditWin().GetInputContext() );
+ aCntxt.SetOptions( SfxDisableFlags::SwOnProtectedCursor & nDisableFlags
+ ? (aCntxt.GetOptions() & ~
+ InputContextFlags( InputContextFlags::Text |
+ InputContextFlags::ExtText ))
+ : (aCntxt.GetOptions() |
+ ( InputContextFlags::Text |
+ InputContextFlags::ExtText )) );
+ GetEditWin().SetInputContext( aCntxt );
+ }
+ break;
+ default:
+ ;
+ }
+
+ }
+
+ if( nDisableFlags != rDis.GetDisableFlags() )
+ {
+ rDis.SetDisableFlags( nDisableFlags );
+ GetViewFrame().GetBindings().InvalidateAll( true );
+ }
+}
+
+SwView::SwView(SfxViewFrame& _rFrame, SfxViewShell* pOldSh)
+ : SfxViewShell(_rFrame, SWVIEWFLAGS),
+ m_aTimer( "sw::SwView m_aTimer" ),
+ m_nNewPage(USHRT_MAX),
+ m_nOldPageNum(0),
+ m_pNumRuleNodeFromDoc(nullptr),
+ m_pEditWin( VclPtr<SwEditWin>::Create( &_rFrame.GetWindow(), *this ) ),
+ m_pShell(nullptr),
+ m_pFormShell(nullptr),
+ m_pHScrollbar(nullptr),
+ m_pVScrollbar(nullptr),
+ m_pVRuler(VclPtr<SvxRuler>::Create(&GetViewFrame().GetWindow(), m_pEditWin,
+ SvxRulerSupportFlags::TABS | SvxRulerSupportFlags::PARAGRAPH_MARGINS_VERTICAL|
+ SvxRulerSupportFlags::BORDERS | SvxRulerSupportFlags::REDUCED_METRIC,
+ GetViewFrame().GetBindings(),
+ WB_VSCROLL | WB_EXTRAFIELD | WB_BORDER )),
+ m_pLastTableFormat(nullptr),
+ m_pLastFlyFormat(nullptr),
+ m_pFormatClipboard(new SwFormatClipboard()),
+ m_nSelectionType( SelectionType::All ),
+ m_nPageCnt(0),
+ m_nDrawSfxId( USHRT_MAX ),
+ m_nFormSfxId( USHRT_MAX ),
+ m_eFormObjKind(SdrObjKind::NONE),
+ m_nLastPasteDestination( static_cast<SotExchangeDest>(0xFFFF) ),
+ m_nLeftBorderDistance( 0 ),
+ m_nRightBorderDistance( 0 ),
+ m_eLastSearchCommand( static_cast<SvxSearchCmd>(0xFFFF) ),
+ m_bWheelScrollInProgress(false),
+ m_bCenterCursor(false),
+ m_bTopCursor(false),
+ m_bTabColFromDoc(false),
+ m_bTabRowFromDoc(false),
+ m_bSetTabColFromDoc(false),
+ m_bSetTabRowFromDoc(false),
+ m_bAttrChgNotified(false),
+ m_bAttrChgNotifiedWithRegistrations(false),
+ m_bVerbsActive(false),
+ m_bDrawRotate(false),
+ m_bDrawSelMode(true),
+ m_bShowAtResize(true),
+ m_bInOuterResizePixel(false),
+ m_bInInnerResizePixel(false),
+ m_bPasteState(false),
+ m_bPasteSpecialState(false),
+ m_bInMailMerge(false),
+ m_bInDtor(false),
+ m_bOldShellWasPagePreview(false),
+ m_bIsPreviewDoubleClick(false),
+ m_bMakeSelectionVisible(false),
+ m_bForceChangesToolbar(true),
+ m_nLOKPageUpDownOffset(0),
+ m_aBringToAttentionBlinkTimer("SwView m_aBringToAttentionBlinkTimer"),
+ m_nBringToAttentionBlinkTimeOutsRemaining(0)
+{
+ static bool bRequestDoubleBuffering = getenv("VCL_DOUBLEBUFFERING_ENABLE");
+ if (bRequestDoubleBuffering)
+ m_pEditWin->RequestDoubleBuffering(true);
+
+ // According to discussion with MBA and further
+ // investigations, no old SfxViewShell will be set as parameter <pOldSh>,
+ // if function "New Window" is performed to open an additional view beside
+ // an already existing one.
+ // If the view is switch from one to another, the 'old' view is given by
+ // parameter <pOldSh>.
+
+ bDocSzUpdated = true;
+
+ static bool bFuzzing = utl::ConfigManager::IsFuzzing();
+
+ if (!bFuzzing)
+ {
+ CreateScrollbar( true );
+ CreateScrollbar( false );
+ }
+
+ m_pViewImpl.reset(new SwView_Impl(this));
+ SetName("View");
+ SetWindow( m_pEditWin );
+
+ m_aTimer.SetTimeout( 120 );
+
+ SwDocShell& rDocSh = dynamic_cast<SwDocShell&>(*_rFrame.GetObjectShell());
+ bool bOldModifyFlag = rDocSh.IsEnableSetModified();
+ if (bOldModifyFlag)
+ rDocSh.EnableSetModified( false );
+ // HACK: SwDocShell has some cached font info, VCL informs about font updates,
+ // but loading of docs with embedded fonts happens after SwDocShell is created
+ // but before SwEditWin (which handles the VCL event) is created. So update
+ // manually.
+ if (rDocSh.GetDoc()->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_FONTS ))
+ rDocSh.UpdateFontList();
+ bool bWebDShell = dynamic_cast<const SwWebDocShell*>(&rDocSh) != nullptr;
+
+ const SwMasterUsrPref *pUsrPref = SW_MOD()->GetUsrPref(bWebDShell);
+ SwViewOption aUsrPref( *pUsrPref);
+
+ //! get lingu options without loading lingu DLL
+ SvtLinguOptions aLinguOpt;
+ SvtLinguConfig().GetOptions( aLinguOpt );
+ aUsrPref.SetOnlineSpell( aLinguOpt.bIsSpellAuto );
+
+ bool bOldShellWasSrcView = false;
+
+ // determine if there is an existing view for
+ // document
+ SfxViewShell* pExistingSh = nullptr;
+ if ( pOldSh )
+ {
+ pExistingSh = pOldSh;
+ // determine type of existing view
+ if (SwPagePreview* pPagePreview = dynamic_cast<SwPagePreview *>(pExistingSh))
+ {
+ m_sSwViewData = pPagePreview->GetPrevSwViewData();
+ m_sNewCursorPos = pPagePreview->GetNewCursorPos();
+ m_nNewPage = pPagePreview->GetNewPage();
+ m_bOldShellWasPagePreview = true;
+ m_bIsPreviewDoubleClick = !m_sNewCursorPos.isEmpty() || m_nNewPage != USHRT_MAX;
+ }
+ else if (dynamic_cast<const SwSrcView *>(pExistingSh) != nullptr)
+ bOldShellWasSrcView = true;
+ }
+
+ SAL_INFO( "sw.ui", "before create WrtShell" );
+ if (SwView *pView = dynamic_cast<SwView*>(pExistingSh))
+ {
+ m_pWrtShell.reset(new SwWrtShell(*pView->m_pWrtShell, m_pEditWin, *this));
+ }
+ else if (SwWrtShell *pWrtShell = dynamic_cast<SwWrtShell*>(rDocSh.GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell()))
+ {
+ m_pWrtShell.reset(new SwWrtShell(*pWrtShell, m_pEditWin, *this));
+ }
+ else
+ {
+ SwDoc& rDoc = *rDocSh.GetDoc();
+
+ if( !bOldShellWasSrcView && bWebDShell && !m_bOldShellWasPagePreview )
+ aUsrPref.setBrowseMode( true );
+ else
+ aUsrPref.setBrowseMode( rDoc.getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE) );
+
+ //For the BrowseMode we do not assume a factor.
+ if( aUsrPref.getBrowseMode() && aUsrPref.GetZoomType() != SvxZoomType::PERCENT )
+ {
+ aUsrPref.SetZoomType( SvxZoomType::PERCENT );
+ aUsrPref.SetZoom( 100 );
+ }
+ if (rDocSh.IsPreview())
+ {
+ aUsrPref.SetZoomType( SvxZoomType::WHOLEPAGE );
+ aUsrPref.SetViewLayoutBookMode( false );
+ aUsrPref.SetViewLayoutColumns( 1 );
+ }
+ m_pWrtShell.reset(new SwWrtShell(rDoc, m_pEditWin, *this, &aUsrPref));
+ // creating an SwView from a SwPagePreview needs to
+ // add the SwViewShell to the ring of the other SwViewShell(s)
+ if(m_bOldShellWasPagePreview)
+ {
+ SwViewShell& rPreviewViewShell = *static_cast<SwPagePreview*>(pExistingSh)->GetViewShell();
+ m_pWrtShell->MoveTo(&rPreviewViewShell);
+ // to update the field command et.al. if necessary
+ const SwViewOption* pPreviewOpt = rPreviewViewShell.GetViewOptions();
+ if( pPreviewOpt->IsFieldName() != aUsrPref.IsFieldName() ||
+ pPreviewOpt->IsShowHiddenField() != aUsrPref.IsShowHiddenField() ||
+ pPreviewOpt->IsShowHiddenPara() != aUsrPref.IsShowHiddenPara() ||
+ pPreviewOpt->IsShowHiddenChar() != aUsrPref.IsShowHiddenChar() )
+ rPreviewViewShell.ApplyViewOptions(aUsrPref);
+ // reset design mode at draw view for form
+ // shell, if needed.
+ if ( static_cast<SwPagePreview*>(pExistingSh)->ResetFormDesignMode() &&
+ m_pWrtShell->HasDrawView() )
+ {
+ SdrView* pDrawView = m_pWrtShell->GetDrawView();
+ pDrawView->SetDesignMode( static_cast<SwPagePreview*>(pExistingSh)->FormDesignModeToReset() );
+ }
+ }
+ }
+ SAL_INFO( "sw.ui", "after create WrtShell" );
+ m_pHRuler = VclPtr<SwCommentRuler>::Create(m_pWrtShell.get(), &GetViewFrame().GetWindow(), m_pEditWin,
+ SvxRulerSupportFlags::TABS |
+ SvxRulerSupportFlags::PARAGRAPH_MARGINS |
+ SvxRulerSupportFlags::BORDERS |
+ SvxRulerSupportFlags::NEGATIVE_MARGINS|
+ SvxRulerSupportFlags::REDUCED_METRIC,
+ GetViewFrame().GetBindings(),
+ WB_STDRULER | WB_EXTRAFIELD | WB_BORDER);
+
+ // assure that modified state of document
+ // isn't reset, if document is already modified.
+ const bool bIsDocModified = m_pWrtShell->GetDoc()->getIDocumentState().IsModified();
+
+ // Thus among other things, the HRuler is not displayed in the read-only case.
+ aUsrPref.SetReadonly( m_pWrtShell->GetViewOptions()->IsReadonly() );
+
+ // no margin for OLE!
+ Size aBrwsBorder;
+ if( SfxObjectCreateMode::EMBEDDED != rDocSh.GetCreateMode() )
+ aBrwsBorder = GetMargin();
+
+ m_pWrtShell->SetBrowseBorder( aBrwsBorder );
+
+ // In CTOR no shell changes may take place, which must be temporarily stored
+ // with the timer. Otherwise, the SFX removes them from the stack!
+ bool bOld = g_bNoInterrupt;
+ g_bNoInterrupt = true;
+
+ m_pHRuler->SetActive();
+ m_pVRuler->SetActive();
+
+ SfxViewFrame& rViewFrame = GetViewFrame();
+
+ StartListening(rViewFrame, DuplicateHandling::Prevent);
+ StartListening(rDocSh, DuplicateHandling::Prevent);
+
+ // Set Zoom-factor from HRuler
+ Fraction aZoomFract( aUsrPref.GetZoom(), 100 );
+ m_pHRuler->SetZoom( aZoomFract );
+ m_pVRuler->SetZoom( aZoomFract );
+ m_pHRuler->SetDoubleClickHdl(LINK( this, SwView, ExecRulerClick ));
+ FieldUnit eMetric = pUsrPref->GetHScrollMetric();
+ m_pHRuler->SetUnit( eMetric );
+
+ eMetric = pUsrPref->GetVScrollMetric();
+ m_pVRuler->SetUnit( eMetric );
+
+ m_pHRuler->SetCharWidth( 371 ); // default character width
+ m_pVRuler->SetLineHeight( 551 ); // default line height
+
+ // Set DocShell
+ m_xGlueDocShell.reset(new SwViewGlueDocShell(*this, rDocSh));
+ m_pPostItMgr.reset(new SwPostItMgr(this));
+
+ // Check and process the DocSize. Via the handler, the shell could not
+ // be found, because the shell is not known in the SFX management
+ // within the CTOR phase.
+ DocSzChgd( m_pWrtShell->GetDocSize() );
+
+ // Set AttrChangedNotify link
+ m_pWrtShell->SetChgLnk(LINK(this, SwView, AttrChangedNotify));
+
+ if (rDocSh.GetCreateMode() == SfxObjectCreateMode::EMBEDDED &&
+ !rDocSh.GetVisArea(ASPECT_CONTENT).IsEmpty())
+ SetVisArea(rDocSh.GetVisArea(ASPECT_CONTENT),false);
+
+ SAL_WARN_IF(
+ officecfg::Office::Common::Undo::Steps::get() <= 0,
+ "sw.ui", "/org.openoffice.Office.Common/Undo/Steps <= 0");
+ if (!bFuzzing && 0 < officecfg::Office::Common::Undo::Steps::get())
+ {
+ m_pWrtShell->DoUndo();
+ }
+
+ const bool bBrowse = m_pWrtShell->GetViewOptions()->getBrowseMode();
+ // Disable "multiple window"
+ SetNewWindowAllowed(!bBrowse);
+ // End of disabled multiple window
+
+ m_bVScrollbarEnabled = aUsrPref.IsViewVScrollBar();
+ m_bHScrollbarEnabled = aUsrPref.IsViewHScrollBar();
+ if (m_pHScrollbar)
+ m_pHScrollbar->SetAuto(bBrowse);
+ if( aUsrPref.IsViewHRuler() )
+ CreateTab();
+ if( aUsrPref.IsViewVRuler() )
+ CreateVRuler();
+
+ m_pWrtShell->SetUIOptions( aUsrPref );
+ m_pWrtShell->SetReadOnlyAvailable( aUsrPref.IsCursorInProtectedArea() );
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ m_pWrtShell->ApplyAccessibilityOptions();
+#endif
+
+ if( m_pWrtShell->GetDoc()->getIDocumentState().IsUpdateExpField() )
+ {
+ if (m_pWrtShell->GetDoc()->GetDocumentFieldsManager().containsUpdatableFields())
+ {
+ CurrShell aCurr(m_pWrtShell.get());
+ m_pWrtShell->StartAction();
+ m_pWrtShell->CalcLayout();
+ m_pWrtShell->GetDoc()->getIDocumentFieldsAccess().UpdateFields(false);
+ m_pWrtShell->EndAction();
+ }
+ m_pWrtShell->GetDoc()->getIDocumentState().SetUpdateExpFieldStat( false );
+ }
+
+ // Update all tables if necessary:
+ if( m_pWrtShell->GetDoc()->IsUpdateTOX() )
+ {
+ SfxRequest aSfxRequest( FN_UPDATE_TOX, SfxCallMode::SLOT, GetPool() );
+ Execute( aSfxRequest );
+ m_pWrtShell->GetDoc()->SetUpdateTOX( false ); // reset again
+ m_pWrtShell->SttEndDoc(true);
+ }
+
+ // No ResetModified, if there is already a view to this doc.
+ SfxViewFrame& rVFrame = GetViewFrame();
+ SfxViewFrame* pFirst = SfxViewFrame::GetFirst(&rDocSh);
+ // Currently(360) the view is registered firstly after the CTOR,
+ // the following expression is also working if this changes.
+ // If the modification cannot be canceled by undo, then do NOT set
+ // the modify back.
+ // no reset of modified state, if document
+ // was already modified.
+ if (!m_pWrtShell->GetDoc()->GetIDocumentUndoRedo().IsUndoNoResetModified() &&
+ ( !pFirst || pFirst == &rVFrame ) &&
+ !bIsDocModified )
+ {
+ m_pWrtShell->ResetModified();
+ }
+
+ g_bNoInterrupt = bOld;
+
+ // If a new GlobalDoc will be created, the navigator will also be generated.
+ if( dynamic_cast<const SwGlobalDocShell*>(&rDocSh) != nullptr &&
+ !rVFrame.GetChildWindow( SID_NAVIGATOR ))
+ {
+ SfxBoolItem aNavi(SID_NAVIGATOR, true);
+ GetDispatcher().ExecuteList(SID_NAVIGATOR, SfxCallMode::ASYNCHRON, { &aNavi });
+ }
+
+ uno::Reference< frame::XFrame > xFrame = rVFrame.GetFrame().GetFrameInterface();
+
+ uno::Reference< frame::XFrame > xBeamerFrame = xFrame->findFrame(
+ "_beamer", frame::FrameSearchFlag::CHILDREN);
+ if(xBeamerFrame.is())
+ {
+ SwDBData aData = m_pWrtShell->GetDBData();
+ SwModule::ShowDBObj( *this, aData );
+ }
+
+ // has anybody calls the attrchanged handler in the constructor?
+ if( m_bAttrChgNotifiedWithRegistrations )
+ {
+ GetViewFrame().GetBindings().LEAVEREGISTRATIONS();
+ if( m_aTimer.IsActive() )
+ m_aTimer.Stop();
+ }
+
+ m_aTimer.SetInvokeHandler(LINK(this, SwView, TimeoutHdl));
+ m_bAttrChgNotified = m_bAttrChgNotifiedWithRegistrations = false;
+ if (bOldModifyFlag)
+ rDocSh.EnableSetModified();
+ InvalidateBorder();
+
+ if (!bFuzzing)
+ {
+ if (!m_pHScrollbar->IsScrollbarVisible(true))
+ ShowHScrollbar( false );
+ if (!m_pVScrollbar->IsScrollbarVisible(true))
+ ShowVScrollbar( false );
+ }
+
+ if (m_pWrtShell->GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ m_pWrtShell->InvalidateOutlineContentVisibility();
+
+ if (!bFuzzing)
+ GetViewFrame().GetWindow().AddChildEventListener(LINK(this, SwView, WindowChildEventListener));
+
+ m_aBringToAttentionBlinkTimer.SetInvokeHandler(
+ LINK(this, SwView, BringToAttentionBlinkTimerHdl));
+ m_aBringToAttentionBlinkTimer.SetTimeout(350);
+
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ SwXTextDocument* pModel = comphelper::getFromUnoTunnel<SwXTextDocument>(GetCurrentDocument());
+ SfxLokHelper::notifyViewRenderState(this, pModel);
+ }
+}
+
+SwViewGlueDocShell::SwViewGlueDocShell(SwView& rView, SwDocShell& rDocSh)
+ : m_rView(rView)
+{
+ // Set DocShell
+ rDocSh.SetView(&m_rView);
+ SW_MOD()->SetView(&m_rView);
+}
+
+SwViewGlueDocShell::~SwViewGlueDocShell()
+{
+ SwDocShell* pDocSh = m_rView.GetDocShell();
+ if (pDocSh && pDocSh->GetView() == &m_rView)
+ pDocSh->SetView(nullptr);
+ if (SW_MOD()->GetView() == &m_rView)
+ SW_MOD()->SetView(nullptr);
+}
+
+SwView::~SwView()
+{
+ // Notify other LOK views that we are going away.
+ SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", "false"_ostr);
+ SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", ""_ostr);
+ SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", "EMPTY"_ostr);
+
+ // Need to remove activated field's button before disposing EditWin.
+ GetWrtShell().getIDocumentMarkAccess()->ClearFieldActivation();
+
+ GetViewFrame().GetWindow().RemoveChildEventListener( LINK( this, SwView, WindowChildEventListener ) );
+ m_pPostItMgr.reset();
+
+ m_bInDtor = true;
+ m_pEditWin->Hide(); // prevent problems with painting
+
+ // Set pointer in SwDocShell to the view again
+ m_xGlueDocShell.reset();
+
+ if( m_aTimer.IsActive() && m_bAttrChgNotifiedWithRegistrations )
+ GetViewFrame().GetBindings().LEAVEREGISTRATIONS();
+
+ // the last view must end the text edit
+ SdrView *pSdrView = m_pWrtShell->GetDrawView();
+ if( pSdrView && pSdrView->IsTextEdit() )
+ pSdrView->SdrEndTextEdit( true );
+ else if (pSdrView)
+ {
+ pSdrView->DisposeUndoManager();
+ }
+
+ SetWindow( nullptr );
+
+ m_pViewImpl->Invalidate();
+ EndListening(GetViewFrame());
+ EndListening(*GetDocShell());
+
+ // tdf#155410 speedup shutdown, prevent unnecessary broadcasting during teardown of draw model
+ auto pDrawModel = GetWrtShell().getIDocumentDrawModelAccess().GetDrawModel();
+ const bool bWasLocked = pDrawModel->isLocked();
+ pDrawModel->setLock(true);
+ m_pWrtShell.reset(); // reset here so that it is not accessible by the following dtors.
+ pDrawModel->setLock(bWasLocked);
+
+ m_pHScrollbar.disposeAndClear();
+ m_pVScrollbar.disposeAndClear();
+ m_pHRuler.disposeAndClear();
+ m_pVRuler.disposeAndClear();
+ m_pGlosHdl.reset();
+ m_pViewImpl.reset();
+
+ // If this was enabled in the ctor for the frame, then disable it here.
+ static bool bRequestDoubleBuffering = getenv("VCL_DOUBLEBUFFERING_ENABLE");
+ if (bRequestDoubleBuffering)
+ m_pEditWin->RequestDoubleBuffering(false);
+ m_pEditWin.disposeAndClear();
+
+ m_pFormatClipboard.reset();
+}
+
+void SwView::SetDying()
+{
+ m_bDying = true;
+}
+
+void SwView::afterCallbackRegistered()
+{
+ if (!comphelper::LibreOfficeKit::isActive())
+ return;
+
+ // common tasks
+ SfxViewShell::afterCallbackRegistered();
+
+ auto* pDocShell = GetDocShell();
+ if (pDocShell)
+ {
+ svx::ThemeColorPaletteManager aManager(pDocShell->GetThemeColors());
+ libreOfficeKitViewCallback(LOK_CALLBACK_COLOR_PALETTES, aManager.generateJSON());
+ }
+}
+
+SwDocShell* SwView::GetDocShell()
+{
+ SfxObjectShell* pDocShell = GetViewFrame().GetObjectShell();
+ return dynamic_cast<SwDocShell*>( pDocShell );
+}
+
+// Remember CursorPos
+
+void SwView::WriteUserData( OUString &rUserData, bool bBrowse )
+{
+ // The browse flag will be passed from Sfx when documents are browsed
+ // (not to be confused with the BrowseMode).
+ // Then that stored data are not persistent!
+
+ const SwRect& rRect = m_pWrtShell->GetCharRect();
+ const tools::Rectangle& rVis = GetVisArea();
+
+ rUserData = OUString::number( rRect.Left() );
+ rUserData += ";";
+ rUserData += OUString::number( rRect.Top() );
+ rUserData += ";";
+ rUserData += OUString::number( m_pWrtShell->GetViewOptions()->GetZoom() );
+ rUserData += ";";
+ rUserData += OUString::number( rVis.Left() );
+ rUserData += ";";
+ rUserData += OUString::number( rVis.Top() );
+ rUserData += ";";
+ rUserData += OUString::number( bBrowse ? SAL_MIN_INT32 : rVis.Right());
+ rUserData += ";";
+ rUserData += OUString::number( bBrowse ? SAL_MIN_INT32 : rVis.Bottom());
+ rUserData += ";";
+ rUserData += OUString::number(
+ static_cast<sal_uInt16>(m_pWrtShell->GetViewOptions()->GetZoomType()));//eZoom;
+ rUserData += ";";
+ rUserData += FrameTypeFlags::NONE == m_pWrtShell->GetSelFrameType() ? std::u16string_view(u"0") : std::u16string_view(u"1");
+}
+
+// Set CursorPos
+
+static bool lcl_IsOwnDocument( SwView& rView )
+{
+ if (::officecfg::Office::Common::Load::ViewPositionForAnyUser::get())
+ {
+ return true;
+ }
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ rView.GetDocShell()->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps
+ = xDPS->getDocumentProperties();
+ OUString Created = xDocProps->getAuthor();
+ OUString Changed = xDocProps->getModifiedBy();
+ OUString FullName = SW_MOD()->GetUserOptions().GetFullName();
+ return !FullName.isEmpty()
+ && (Changed == FullName || (Changed.isEmpty() && Created == FullName));
+}
+
+void SwView::ReadUserData( const OUString &rUserData, bool bBrowse )
+{
+ if ( !(rUserData.indexOf(';')>=0 && // more than one token
+ // For document without layout only in the onlinelayout or
+ // while forward/backward
+ (!m_pWrtShell->IsNewLayout() || m_pWrtShell->GetViewOptions()->getBrowseMode() || bBrowse)) )
+ return;
+
+ bool bIsOwnDocument = lcl_IsOwnDocument( *this );
+
+ CurrShell aCurr(m_pWrtShell.get());
+
+ sal_Int32 nPos = 0;
+
+ // No it is *not* a good idea to call GetToken within Point constr. immediately,
+ // because which parameter is evaluated first?
+ tools::Long nX = o3tl::toInt32(o3tl::getToken(rUserData, 0, ';', nPos )),
+ nY = o3tl::toInt32(o3tl::getToken(rUserData, 0, ';', nPos ));
+ Point aCursorPos( nX, nY );
+
+ sal_uInt16 nZoomFactor =
+ static_cast< sal_uInt16 >( o3tl::toInt32(o3tl::getToken(rUserData, 0, ';', nPos )) );
+
+ tools::Long nLeft = o3tl::toInt32(o3tl::getToken(rUserData, 0, ';', nPos )),
+ nTop = o3tl::toInt32(o3tl::getToken(rUserData, 0, ';', nPos )),
+ nRight = o3tl::toInt32(o3tl::getToken(rUserData, 0, ';', nPos )),
+ nBottom= o3tl::toInt32(o3tl::getToken(rUserData, 0, ';', nPos ));
+
+ const tools::Long nAdd = m_pWrtShell->GetViewOptions()->getBrowseMode() ? DOCUMENTBORDER : DOCUMENTBORDER*2;
+ if ( nBottom > (m_pWrtShell->GetDocSize().Height()+nAdd) )
+ return;
+
+ m_pWrtShell->EnableSmooth( false );
+
+ const tools::Rectangle aVis( nLeft, nTop, nRight, nBottom );
+
+ sal_Int32 nOff = 0;
+ SvxZoomType eZoom;
+ if( !m_pWrtShell->GetViewOptions()->getBrowseMode() )
+ eZoom = static_cast<SvxZoomType>(o3tl::narrowing<sal_uInt16>(o3tl::toInt32(o3tl::getToken(rUserData, nOff, ';', nPos ))));
+ else
+ {
+ eZoom = SvxZoomType::PERCENT;
+ ++nOff;
+ }
+
+ bool bSelectObj = (0 != o3tl::toInt32(o3tl::getToken(rUserData, nOff, ';', nPos )))
+ && m_pWrtShell->IsObjSelectable( aCursorPos );
+
+ // restore editing position
+ m_pViewImpl->SetRestorePosition(aCursorPos, bSelectObj);
+ // set flag value to avoid macro execution.
+ bool bSavedFlagValue = m_pWrtShell->IsMacroExecAllowed();
+ m_pWrtShell->SetMacroExecAllowed( false );
+// os: changed: The user data has to be read if the view is switched back from page preview
+// go to the last editing position when opening own files
+ if(m_bOldShellWasPagePreview || bIsOwnDocument)
+ {
+ m_pWrtShell->SwCursorShell::SetCursor( aCursorPos, !bSelectObj );
+ if( bSelectObj )
+ {
+ m_pWrtShell->SelectObj( aCursorPos );
+ m_pWrtShell->EnterSelFrameMode( &aCursorPos );
+ }
+ }
+
+ // reset flag value
+ m_pWrtShell->SetMacroExecAllowed( bSavedFlagValue );
+
+ // set visible area before applying
+ // information from print preview. Otherwise, the applied information
+ // is lost.
+// os: changed: The user data has to be read if the view is switched back from page preview
+// go to the last editing position when opening own files
+ if(m_bOldShellWasPagePreview || bIsOwnDocument )
+ {
+ if ( bBrowse )
+ SetVisArea( aVis.TopLeft() );
+ else
+ SetVisArea( aVis );
+ }
+
+ //apply information from print preview - if available
+ if( !m_sNewCursorPos.isEmpty() )
+ {
+ sal_Int32 nIdx{ 0 };
+ const tools::Long nXTmp = o3tl::toInt32(o3tl::getToken(m_sNewCursorPos, 0, ';', nIdx ));
+ const tools::Long nYTmp = o3tl::toInt32(o3tl::getToken(m_sNewCursorPos, 0, ';', nIdx ));
+ Point aCursorPos2( nXTmp, nYTmp );
+ bSelectObj = m_pWrtShell->IsObjSelectable( aCursorPos2 );
+
+ m_pWrtShell->SwCursorShell::SetCursor( aCursorPos2 );
+ if( bSelectObj )
+ {
+ m_pWrtShell->SelectObj( aCursorPos2 );
+ m_pWrtShell->EnterSelFrameMode( &aCursorPos2 );
+ }
+ m_pWrtShell->MakeSelVisible();
+ m_sNewCursorPos.clear();
+ }
+ else if(USHRT_MAX != m_nNewPage)
+ {
+ m_pWrtShell->GotoPage(m_nNewPage, true);
+ m_nNewPage = USHRT_MAX;
+ }
+
+ SelectShell();
+
+ m_pWrtShell->StartAction();
+ const SwViewOption* pVOpt = m_pWrtShell->GetViewOptions();
+ if( pVOpt->GetZoom() != nZoomFactor || pVOpt->GetZoomType() != eZoom )
+ SetZoom( eZoom, nZoomFactor);
+
+ m_pWrtShell->LockView( true );
+ m_pWrtShell->EndAction();
+ m_pWrtShell->LockView( false );
+ m_pWrtShell->EnableSmooth( true );
+}
+
+void SwView::ReadUserDataSequence ( const uno::Sequence < beans::PropertyValue >& rSequence )
+{
+ if(GetDocShell()->IsPreview()||m_bIsPreviewDoubleClick)
+ return;
+ bool bIsOwnDocument = lcl_IsOwnDocument( *this );
+
+ CurrShell aCurr(m_pWrtShell.get());
+ const SwRect& rRect = m_pWrtShell->GetCharRect();
+ const tools::Rectangle &rVis = GetVisArea();
+ const SwViewOption* pVOpt = m_pWrtShell->GetViewOptions();
+
+ sal_Int64 nX = rRect.Left(), nY = rRect.Top(), nLeft = rVis.Left(), nTop = rVis.Top();
+ sal_Int16 nZoomType = static_cast< sal_Int16 >(pVOpt->GetZoomType());
+ sal_Int16 nZoomFactor = static_cast < sal_Int16 > (pVOpt->GetZoom());
+ bool bViewLayoutBookMode = pVOpt->IsViewLayoutBookMode();
+ sal_Int16 nViewLayoutColumns = pVOpt->GetViewLayoutColumns();
+
+ bool bSelectedFrame = ( m_pWrtShell->GetSelFrameType() != FrameTypeFlags::NONE ),
+ bGotVisibleLeft = false,
+ bGotVisibleTop = false,
+ bGotZoomType = false,
+ bGotZoomFactor = false, bGotIsSelectedFrame = false,
+ bGotViewLayoutColumns = false, bGotViewLayoutBookMode = false,
+ bBrowseMode = false, bGotBrowseMode = false;
+ bool bKeepRatio = pVOpt->IsKeepRatio();
+ bool bGotKeepRatio = false;
+
+ for (const beans::PropertyValue& rValue : rSequence)
+ {
+ if ( rValue.Name == "ViewLeft" )
+ {
+ rValue.Value >>= nX;
+ nX = o3tl::toTwips(nX, o3tl::Length::mm100);
+ }
+ else if ( rValue.Name == "ViewTop" )
+ {
+ rValue.Value >>= nY;
+ nY = o3tl::toTwips(nY, o3tl::Length::mm100);
+ }
+ else if ( rValue.Name == "VisibleLeft" )
+ {
+ rValue.Value >>= nLeft;
+ nLeft = o3tl::toTwips(nLeft, o3tl::Length::mm100);
+ bGotVisibleLeft = true;
+ }
+ else if ( rValue.Name == "VisibleTop" )
+ {
+ rValue.Value >>= nTop;
+ nTop = o3tl::toTwips(nTop, o3tl::Length::mm100);
+ bGotVisibleTop = true;
+ }
+ else if ( rValue.Name == "ZoomType" )
+ {
+ rValue.Value >>= nZoomType;
+ bGotZoomType = true;
+ }
+ else if ( rValue.Name == "ZoomFactor" )
+ {
+ rValue.Value >>= nZoomFactor;
+ bGotZoomFactor = true;
+ }
+ else if ( rValue.Name == "ViewLayoutColumns" )
+ {
+ rValue.Value >>= nViewLayoutColumns;
+ bGotViewLayoutColumns = true;
+ }
+ else if ( rValue.Name == "ViewLayoutBookMode" )
+ {
+ bViewLayoutBookMode = *o3tl::doAccess<bool>(rValue.Value);
+ bGotViewLayoutBookMode = true;
+ }
+ else if ( rValue.Name == "IsSelectedFrame" )
+ {
+ rValue.Value >>= bSelectedFrame;
+ bGotIsSelectedFrame = true;
+ }
+ else if (rValue.Name == "ShowOnlineLayout")
+ {
+ rValue.Value >>= bBrowseMode;
+ bGotBrowseMode = true;
+ }
+ else if (rValue.Name == "KeepRatio")
+ {
+ rValue.Value >>= bKeepRatio;
+ bGotKeepRatio = true;
+ }
+ // Fallback to common SdrModel processing
+ else
+ GetDocShell()->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->ReadUserDataSequenceValue(&rValue);
+ }
+ if (bGotBrowseMode)
+ {
+ // delegate further
+ GetViewImpl()->GetUNOObject_Impl()->getViewSettings()->setPropertyValue("ShowOnlineLayout", uno::Any(bBrowseMode));
+ }
+
+ SelectShell();
+
+ Point aCursorPos( nX, nY );
+
+ m_pWrtShell->EnableSmooth( false );
+
+ SvxZoomType eZoom;
+ if ( !m_pWrtShell->GetViewOptions()->getBrowseMode() )
+ eZoom = static_cast < SvxZoomType > ( nZoomType );
+ else
+ {
+ eZoom = SvxZoomType::PERCENT;
+ }
+ if (bGotIsSelectedFrame)
+ {
+ bool bSelectObj = bSelectedFrame && m_pWrtShell->IsObjSelectable( aCursorPos );
+
+ // set flag value to avoid macro execution.
+ bool bSavedFlagValue = m_pWrtShell->IsMacroExecAllowed();
+ m_pWrtShell->SetMacroExecAllowed( false );
+// os: changed: The user data has to be read if the view is switched back from page preview
+// go to the last editing position when opening own files
+ m_pViewImpl->SetRestorePosition(aCursorPos, bSelectObj);
+ if(m_bOldShellWasPagePreview|| bIsOwnDocument)
+ {
+ m_pWrtShell->SwCursorShell::SetCursor( aCursorPos, !bSelectObj );
+
+ // Update the shell to toggle Header/Footer edit if needed
+ bool bInHeader = true;
+ if ( m_pWrtShell->IsInHeaderFooter( &bInHeader ) )
+ {
+ if ( !bInHeader )
+ {
+ m_pWrtShell->SetShowHeaderFooterSeparator( FrameControlType::Footer, true );
+ m_pWrtShell->SetShowHeaderFooterSeparator( FrameControlType::Header, false );
+ }
+ else
+ {
+ m_pWrtShell->SetShowHeaderFooterSeparator( FrameControlType::Header, true );
+ m_pWrtShell->SetShowHeaderFooterSeparator( FrameControlType::Footer, false );
+ }
+
+ // Force repaint
+ m_pWrtShell->GetWin()->Invalidate();
+ }
+ if ( m_pWrtShell->IsInHeaderFooter() != m_pWrtShell->IsHeaderFooterEdit() )
+ m_pWrtShell->ToggleHeaderFooterEdit();
+
+ if( bSelectObj )
+ {
+ m_pWrtShell->SelectObj( aCursorPos );
+ m_pWrtShell->EnterSelFrameMode( &aCursorPos );
+ }
+ }
+
+ // reset flag value
+ m_pWrtShell->SetMacroExecAllowed( bSavedFlagValue );
+ }
+
+ if (bGotKeepRatio && bKeepRatio != pVOpt->IsKeepRatio())
+ {
+ // Got a custom value, then it makes sense to trigger notifications.
+ SwViewOption aUsrPref(*pVOpt);
+ aUsrPref.SetKeepRatio(bKeepRatio);
+ SW_MOD()->ApplyUsrPref(aUsrPref, this);
+ }
+
+ // Set ViewLayoutSettings
+ const bool bSetViewLayoutSettings = bGotViewLayoutColumns && bGotViewLayoutBookMode &&
+ ( pVOpt->GetViewLayoutColumns() != nViewLayoutColumns || pVOpt->IsViewLayoutBookMode() != bViewLayoutBookMode );
+
+ const bool bSetViewSettings = bGotZoomType && bGotZoomFactor &&
+ ( pVOpt->GetZoom() != nZoomFactor || pVOpt->GetZoomType() != eZoom );
+
+ // In case we have a 'fixed' view layout of 2 or more columns,
+ // we have to apply the view options *before* starting the action.
+ // Otherwise the SetZoom function cannot work correctly, because
+ // the view layout hasn't been calculated.
+ const bool bZoomNeedsViewLayout = bSetViewLayoutSettings &&
+ 1 < nViewLayoutColumns &&
+ bSetViewSettings &&
+ eZoom != SvxZoomType::PERCENT;
+
+ if ( !bZoomNeedsViewLayout )
+ m_pWrtShell->StartAction();
+
+ if ( bSetViewLayoutSettings )
+ SetViewLayout( nViewLayoutColumns, bViewLayoutBookMode, true );
+
+ if ( bZoomNeedsViewLayout )
+ m_pWrtShell->StartAction();
+
+ if ( bSetViewSettings )
+ SetZoom( eZoom, nZoomFactor, true );
+
+// os: changed: The user data has to be read if the view is switched back from page preview
+// go to the last editing position when opening own files
+ if(m_bOldShellWasPagePreview||bIsOwnDocument)
+ {
+ if ( bGotVisibleLeft && bGotVisibleTop )
+ {
+ Point aTopLeft(nLeft, nTop);
+ // make sure the document is still centered
+ const SwTwips lBorder = IsDocumentBorder() ? DOCUMENTBORDER : 2 * DOCUMENTBORDER;
+ SwTwips nEditWidth = GetEditWin().GetOutDev()->GetOutputSize().Width();
+ if(nEditWidth > (m_aDocSz.Width() + lBorder ))
+ aTopLeft.setX( ( m_aDocSz.Width() + lBorder - nEditWidth ) / 2 );
+ else
+ {
+ //check if the values are possible
+ tools::Long nXMax = m_pHScrollbar->GetRangeMax() - m_pHScrollbar->GetVisibleSize();
+ if( aTopLeft.X() > nXMax )
+ aTopLeft.setX( nXMax < 0 ? 0 : nXMax );
+ }
+ SetVisArea( aTopLeft );
+ }
+ }
+
+ m_pWrtShell->LockView( true );
+ m_pWrtShell->EndAction();
+ m_pWrtShell->LockView( false );
+ m_pWrtShell->EnableSmooth( true );
+
+}
+
+void SwView::WriteUserDataSequence ( uno::Sequence < beans::PropertyValue >& rSequence )
+{
+ const SwRect& rRect = m_pWrtShell->GetCharRect();
+ const tools::Rectangle& rVis = GetVisArea();
+
+ std::vector<beans::PropertyValue> aVector;
+
+ sal_uInt16 nViewID( GetViewFrame().GetCurViewId());
+ aVector.push_back(comphelper::makePropertyValue("ViewId", "view" + OUString::number(nViewID)));
+
+ aVector.push_back(comphelper::makePropertyValue("ViewLeft", convertTwipToMm100 ( rRect.Left() )));
+
+ aVector.push_back(comphelper::makePropertyValue("ViewTop", convertTwipToMm100 ( rRect.Top() )));
+
+ auto visibleLeft = convertTwipToMm100 ( rVis.Left() );
+ aVector.push_back(comphelper::makePropertyValue("VisibleLeft", visibleLeft));
+
+ auto visibleTop = convertTwipToMm100 ( rVis.Top() );
+ aVector.push_back(comphelper::makePropertyValue("VisibleTop", visibleTop));
+
+ // We don't read VisibleRight and VisibleBottom anymore, but write them,
+ // because older versions rely on their presence to restore position
+
+ auto visibleRight = rVis.IsWidthEmpty() ? visibleLeft : convertTwipToMm100 ( rVis.Right() );
+ aVector.push_back(comphelper::makePropertyValue("VisibleRight", visibleRight));
+
+ auto visibleBottom = rVis.IsHeightEmpty() ? visibleTop : convertTwipToMm100 ( rVis.Bottom() );
+ aVector.push_back(comphelper::makePropertyValue("VisibleBottom", visibleBottom));
+
+ const sal_Int16 nZoomType = static_cast< sal_Int16 >(m_pWrtShell->GetViewOptions()->GetZoomType());
+ aVector.push_back(comphelper::makePropertyValue("ZoomType", nZoomType));
+
+ const sal_Int16 nViewLayoutColumns = static_cast< sal_Int16 >(m_pWrtShell->GetViewOptions()->GetViewLayoutColumns());
+ aVector.push_back(comphelper::makePropertyValue("ViewLayoutColumns", nViewLayoutColumns));
+
+ aVector.push_back(comphelper::makePropertyValue("ViewLayoutBookMode", m_pWrtShell->GetViewOptions()->IsViewLayoutBookMode()));
+
+ aVector.push_back(comphelper::makePropertyValue("ZoomFactor", static_cast < sal_Int16 > (m_pWrtShell->GetViewOptions()->GetZoom())));
+
+ aVector.push_back(comphelper::makePropertyValue("IsSelectedFrame", FrameTypeFlags::NONE != m_pWrtShell->GetSelFrameType()));
+
+ aVector.push_back(
+ comphelper::makePropertyValue("KeepRatio", m_pWrtShell->GetViewOptions()->IsKeepRatio()));
+
+ rSequence = comphelper::containerToSequence(aVector);
+
+ // Common SdrModel processing
+ GetDocShell()->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->WriteUserDataSequence(rSequence);
+}
+
+void SwView::ShowCursor( bool bOn )
+{
+ //don't scroll the cursor into the visible area
+ bool bUnlockView = !m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView( true ); //lock visible section
+
+ if( !bOn )
+ m_pWrtShell->HideCursor();
+ else if( !m_pWrtShell->IsFrameSelected() && !m_pWrtShell->IsObjSelected() )
+ m_pWrtShell->ShowCursor();
+
+ if( bUnlockView )
+ m_pWrtShell->LockView( false );
+}
+
+ErrCode SwView::DoVerb(sal_Int32 nVerb)
+{
+ if ( !GetViewFrame().GetFrame().IsInPlace() )
+ {
+ SwWrtShell &rSh = GetWrtShell();
+ const SelectionType nSel = rSh.GetSelectionType();
+ if ( nSel & SelectionType::Ole )
+ rSh.LaunchOLEObj( nVerb );
+ }
+ return ERRCODE_NONE;
+}
+
+// only return true for a text selection
+
+bool SwView::HasSelection( bool bText ) const
+{
+ return bText ? GetWrtShell().SwCursorShell::HasSelection()
+ : GetWrtShell().HasSelection();
+}
+
+OUString SwView::GetSelectionText( bool bCompleteWrds, bool /*bOnlyASample*/ )
+{
+ return GetSelectionTextParam( bCompleteWrds, true );
+}
+
+OUString SwView::GetSelectionTextParam( bool bCompleteWrds, bool bEraseTrail )
+{
+ OUString sReturn;
+ if( bCompleteWrds && !GetWrtShell().HasSelection() )
+ GetWrtShell().SelWrd();
+
+ GetWrtShell().GetSelectedText( sReturn );
+ if( bEraseTrail )
+ sReturn = comphelper::string::stripEnd(sReturn, ' ');
+ return sReturn;
+}
+
+SwGlossaryHdl* SwView::GetGlosHdl()
+{
+ if(!m_pGlosHdl)
+ m_pGlosHdl.reset(new SwGlossaryHdl(GetViewFrame(), m_pWrtShell.get()));
+ return m_pGlosHdl.get();
+}
+
+void SwView::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ bool bCallBase = true;
+ if(auto pChangedHint = dynamic_cast<const FmDesignModeChangedHint*>(&rHint))
+ {
+ bool bDesignMode = pChangedHint->GetDesignMode();
+ if (!bDesignMode && GetDrawFuncPtr())
+ {
+ GetDrawFuncPtr()->Deactivate();
+ SetDrawFuncPtr(nullptr);
+ LeaveDrawCreate();
+ AttrChangedNotify(nullptr);
+ }
+ }
+ else
+ {
+ SfxHintId nId = rHint.GetId();
+
+ switch ( nId )
+ {
+ // sub shells will be destroyed by the
+ // dispatcher, if the view frame is dying. Thus, reset member <pShell>.
+ case SfxHintId::Dying:
+ {
+ if ( &rBC == &GetViewFrame() )
+ {
+ ResetSubShell();
+ }
+ }
+ break;
+ case SfxHintId::ModeChanged:
+ {
+ // Modal mode change-over?
+ bool bModal = GetDocShell()->IsInModalMode();
+ m_pHRuler->SetActive( !bModal );
+ m_pVRuler->SetActive( !bModal );
+ }
+
+ [[fallthrough]];
+
+ case SfxHintId::TitleChanged:
+ if ( GetDocShell()->IsReadOnly() != GetWrtShell().GetViewOptions()->IsReadonly() )
+ {
+ SwWrtShell &rSh = GetWrtShell();
+ rSh.SetReadonlyOption( GetDocShell()->IsReadOnly() );
+
+ if ( rSh.GetViewOptions()->IsViewVRuler() )
+ CreateVRuler();
+ else
+ KillVRuler();
+ if ( rSh.GetViewOptions()->IsViewHRuler() )
+ CreateTab();
+ else
+ KillTab();
+ bool bReadonly = GetDocShell()->IsReadOnly();
+ // if document is to be opened in alive-mode then this has to be
+ // regarded while switching from readonly-mode to edit-mode
+ if( !bReadonly )
+ {
+ SwDrawModel * pDrawDoc = GetDocShell()->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
+ if (pDrawDoc)
+ {
+ if( !pDrawDoc->GetOpenInDesignMode() )
+ break;// don't touch the design mode
+ }
+ }
+ SfxBoolItem aItem( SID_FM_DESIGN_MODE, !bReadonly);
+ GetDispatcher().ExecuteList(SID_FM_DESIGN_MODE,
+ SfxCallMode::ASYNCHRON, { &aItem });
+ }
+ break;
+
+ case SfxHintId::SwDrawViewsCreated:
+ {
+ bCallBase = false;
+ if ( GetFormShell() )
+ {
+ GetFormShell()->SetView(dynamic_cast<FmFormView*>(GetWrtShell().GetDrawView()));
+ SfxBoolItem aItem( SID_FM_DESIGN_MODE, !GetDocShell()->IsReadOnly());
+ GetDispatcher().ExecuteList(SID_FM_DESIGN_MODE,
+ SfxCallMode::SYNCHRON, { &aItem });
+ }
+ }
+ break;
+ case SfxHintId::RedlineChanged:
+ {
+ static sal_uInt16 const aSlotRedLine[] = {
+ FN_REDLINE_ACCEPT_DIRECT,
+ FN_REDLINE_REJECT_DIRECT,
+ FN_REDLINE_NEXT_CHANGE,
+ FN_REDLINE_PREV_CHANGE,
+ FN_REDLINE_ACCEPT_ALL,
+ FN_REDLINE_REJECT_ALL,
+ 0
+ };
+ GetViewFrame().GetBindings().Invalidate(aSlotRedLine);
+ }
+ break;
+ default: break;
+ }
+ }
+
+ if ( bCallBase )
+ SfxViewShell::Notify(rBC, rHint);
+}
+
+#if defined(_WIN32) || defined UNX
+
+void SwView::ScannerEventHdl()
+{
+ uno::Reference< XScannerManager2 > xScanMgr = SW_MOD()->GetScannerManager();
+ if( xScanMgr.is() )
+ {
+ const ScannerContext aContext( xScanMgr->getAvailableScanners().getConstArray()[ 0 ] );
+ const ScanError eError = xScanMgr->getError( aContext );
+
+ if( ScanError_ScanErrorNone == eError )
+ {
+ const uno::Reference< awt::XBitmap > xBitmap( xScanMgr->getBitmap( aContext ) );
+
+ if( xBitmap.is() )
+ {
+ const BitmapEx aScanBmp( VCLUnoHelper::GetBitmap( xBitmap ) );
+
+ if( !aScanBmp.IsEmpty() )
+ {
+ Graphic aGrf(aScanBmp);
+ m_pWrtShell->InsertGraphic( OUString(), OUString(), aGrf );
+ }
+ }
+ }
+ }
+ SfxBindings& rBind = GetViewFrame().GetBindings();
+ rBind.Invalidate( SID_TWAIN_SELECT );
+ rBind.Invalidate( SID_TWAIN_TRANSFER );
+}
+#endif
+
+void SwView::StopShellTimer()
+{
+ if(m_aTimer.IsActive())
+ {
+ m_aTimer.Stop();
+ if ( m_bAttrChgNotifiedWithRegistrations )
+ {
+ GetViewFrame().GetBindings().LEAVEREGISTRATIONS();
+ m_bAttrChgNotifiedWithRegistrations = false;
+ }
+ SelectShell();
+ m_bAttrChgNotified = false;
+ }
+}
+
+bool SwView::PrepareClose( bool bUI )
+{
+ SfxViewFrame& rVFrame = GetViewFrame();
+ rVFrame.SetChildWindow( SwInputChild::GetChildWindowId(), false );
+ if( rVFrame.GetDispatcher()->IsLocked() )
+ rVFrame.GetDispatcher()->Lock(false);
+
+ if ( m_pFormShell && !m_pFormShell->PrepareClose( bUI ) )
+ {
+ return false;
+ }
+ return SfxViewShell::PrepareClose( bUI );
+}
+
+// status methods for clipboard.
+// Status changes now notified from the clipboard.
+bool SwView::IsPasteAllowed()
+{
+ SotExchangeDest nPasteDestination = SwTransferable::GetSotDestination( *m_pWrtShell );
+ if( m_nLastPasteDestination != nPasteDestination )
+ {
+ TransferableDataHelper aDataHelper(
+ TransferableDataHelper::CreateFromSystemClipboard(
+ &GetEditWin()) );
+ if( aDataHelper.GetXTransferable().is() )
+ {
+ m_bPasteState = SwTransferable::IsPaste( *m_pWrtShell, aDataHelper );
+ m_bPasteSpecialState = SwTransferable::IsPasteSpecial(
+ *m_pWrtShell, aDataHelper );
+ }
+ else
+ m_bPasteState = m_bPasteSpecialState = false;
+
+ if( static_cast<SotExchangeDest>(0xFFFF) == m_nLastPasteDestination ) // the init value
+ m_pViewImpl->AddClipboardListener();
+ m_nLastPasteDestination = nPasteDestination;
+ }
+ return m_bPasteState;
+}
+
+bool SwView::IsPasteSpecialAllowed()
+{
+ if ( m_pFormShell && m_pFormShell->IsActiveControl() )
+ return false;
+
+ SotExchangeDest nPasteDestination = SwTransferable::GetSotDestination( *m_pWrtShell );
+ if( m_nLastPasteDestination != nPasteDestination )
+ {
+ TransferableDataHelper aDataHelper(
+ TransferableDataHelper::CreateFromSystemClipboard(
+ &GetEditWin()) );
+ if( aDataHelper.GetXTransferable().is() )
+ {
+ m_bPasteState = SwTransferable::IsPaste( *m_pWrtShell, aDataHelper );
+ m_bPasteSpecialState = SwTransferable::IsPasteSpecial(
+ *m_pWrtShell, aDataHelper );
+ }
+ else
+ m_bPasteState = m_bPasteSpecialState = false;
+
+ if( static_cast<SotExchangeDest>(0xFFFF) == m_nLastPasteDestination ) // the init value
+ m_pViewImpl->AddClipboardListener();
+ }
+ return m_bPasteSpecialState;
+}
+
+bool SwView::IsPasteSpreadsheet(bool bHasOwnTableCopied)
+{
+ TransferableDataHelper aDataHelper(
+ TransferableDataHelper::CreateFromSystemClipboard(
+ &GetEditWin()) );
+ if( aDataHelper.GetXTransferable().is() )
+ {
+ if (bHasOwnTableCopied && SwTransferable::IsPasteOwnFormat( aDataHelper ))
+ return true;
+ return aDataHelper.HasFormat( SotClipboardFormatId::SYLK ) || aDataHelper.HasFormat( SotClipboardFormatId::SYLK_BIGCAPS );
+ }
+ return false;
+}
+
+void SwView::NotifyDBChanged()
+{
+ GetViewImpl()->GetUNOObject_Impl()->NotifyDBChanged();
+}
+
+// Printing
+
+SfxObjectShellLock SwView::CreateTmpSelectionDoc()
+{
+ SwXTextView *const pTempImpl = GetViewImpl()->GetUNOObject_Impl();
+ return pTempImpl->BuildTmpSelectionDoc();
+}
+
+void SwView::AddTransferable(SwTransferable& rTransferable)
+{
+ GetViewImpl()->AddTransferable(rTransferable);
+}
+
+tools::Rectangle SwView::getLOKVisibleArea() const
+{
+ if (SwViewShell* pVwSh = GetWrtShellPtr())
+ return pVwSh->getLOKVisibleArea();
+ else
+ return tools::Rectangle();
+}
+
+void SwView::flushPendingLOKInvalidateTiles()
+{
+ if (SwWrtShell* pSh = GetWrtShellPtr())
+ pSh->FlushPendingLOKInvalidateTiles();
+}
+
+std::optional<OString> SwView::getLOKPayload(int nType, int nViewId) const
+{
+ if (SwWrtShell* pSh = GetWrtShellPtr())
+ return pSh->getLOKPayload(nType, nViewId);
+ else
+ return std::nullopt;
+}
+
+OUString SwView::GetDataSourceName() const
+{
+ uno::Reference<lang::XMultiServiceFactory> xFactory(GetDocShell()->GetModel(), uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xSettings(
+ xFactory->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY);
+ OUString sDataSourceName = "";
+ xSettings->getPropertyValue("CurrentDatabaseDataSource") >>= sDataSourceName;
+
+ return sDataSourceName;
+}
+
+bool SwView::IsDataSourceAvailable(const OUString sDataSourceName)
+{
+ uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
+ Reference< XDatabaseContext> xDatabaseContext = DatabaseContext::create(xContext);
+
+ return xDatabaseContext->hasByName(sDataSourceName);
+}
+
+void SwView::BringToAttention(std::vector<basegfx::B2DRange>&& aRanges)
+{
+ m_nBringToAttentionBlinkTimeOutsRemaining = 0;
+ m_aBringToAttentionBlinkTimer.Stop();
+ if (aRanges.empty())
+ m_xBringToAttentionOverlayObject.reset();
+ else
+ {
+ m_xBringToAttentionOverlayObject.reset(
+ new sdr::overlay::OverlaySelection(sdr::overlay::OverlayType::Invert,
+ Color(), std::move(aRanges),
+ true /*unused for Invert type*/));
+ m_nBringToAttentionBlinkTimeOutsRemaining = 4;
+ m_aBringToAttentionBlinkTimer.Start();
+ }
+}
+
+void SwView::BringToAttention(const tools::Rectangle& rRect)
+{
+ std::vector<basegfx::B2DRange> aRanges{ basegfx::B2DRange(rRect.Left(), rRect.Top(),
+ rRect.Right(), rRect.Bottom()) };
+ BringToAttention(std::move(aRanges));
+}
+
+void SwView::BringToAttention(const SwNode* pNode)
+{
+ if (!pNode)
+ return;
+
+ std::vector<basegfx::B2DRange> aRanges;
+ const SwFrame* pFrame;
+ if (pNode->IsContentNode())
+ {
+ pFrame = pNode->GetContentNode()->getLayoutFrame(GetWrtShell().GetLayout());
+ }
+ else
+ {
+ // section and table nodes
+ SwNode2Layout aTmp(*pNode, pNode->GetIndex() - 1);
+ pFrame = aTmp.NextFrame();
+ }
+ while (pFrame)
+ {
+ const SwRect& rFrameRect = pFrame->getFrameArea();
+ if (!rFrameRect.IsEmpty())
+ aRanges.emplace_back(rFrameRect.Left(), rFrameRect.Top() + pFrame->GetTopMargin(),
+ rFrameRect.Right(), rFrameRect.Bottom());
+ if (!pFrame->IsFlowFrame())
+ break;
+ const SwFlowFrame* pFollow = SwFlowFrame::CastFlowFrame(pFrame)->GetFollow();
+ if (!pFollow)
+ break;
+ pFrame = &pFollow->GetFrame();
+ }
+ BringToAttention(std::move(aRanges));
+}
+
+IMPL_LINK_NOARG(SwView, BringToAttentionBlinkTimerHdl, Timer*, void)
+{
+ if (GetDrawView() && m_xBringToAttentionOverlayObject)
+ {
+ if (SdrView* pView = GetDrawView())
+ {
+ if (SdrPaintWindow* pPaintWindow = pView->GetPaintWindow(0))
+ {
+ const rtl::Reference<sdr::overlay::OverlayManager>& xOverlayManager
+ = pPaintWindow->GetOverlayManager();
+ if (m_nBringToAttentionBlinkTimeOutsRemaining % 2 == 0)
+ xOverlayManager->add(*m_xBringToAttentionOverlayObject);
+ else
+ xOverlayManager->remove(*m_xBringToAttentionOverlayObject);
+ --m_nBringToAttentionBlinkTimeOutsRemaining;
+ }
+ else
+ m_nBringToAttentionBlinkTimeOutsRemaining = 0;
+ }
+ else
+ m_nBringToAttentionBlinkTimeOutsRemaining = 0;
+ }
+ else
+ m_nBringToAttentionBlinkTimeOutsRemaining = 0;
+ if (m_nBringToAttentionBlinkTimeOutsRemaining == 0)
+ {
+ m_xBringToAttentionOverlayObject.reset();
+ m_aBringToAttentionBlinkTimer.Stop();
+ }
+}
+
+namespace sw {
+
+void InitPrintOptionsFromApplication(SwPrintData & o_rData, bool const bWeb)
+{
+ o_rData = *SW_MOD()->GetPrtOptions(bWeb);
+}
+
+} // namespace sw
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/view0.cxx b/sw/source/uibase/uiview/view0.cxx
new file mode 100644
index 0000000000..66d8c66597
--- /dev/null
+++ b/sw/source/uibase/uiview/view0.cxx
@@ -0,0 +1,770 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+#include <config_wasm_strip.h>
+
+#include <SwSpellDialogChildWindow.hxx>
+#include <svl/eitem.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/linguprops.hxx>
+#include <unotools/lingucfg.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <viewopt.hxx>
+#include <globals.h>
+#include <sfx2/infobar.hxx>
+#include <sfx2/request.hxx>
+#include <svl/whiter.hxx>
+#include <svx/srchdlg.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/sidebar/SidebarChildWindow.hxx>
+#include <uivwimp.hxx>
+#include <avmedia/mediaplayer.hxx>
+#include <swmodule.hxx>
+#include <com/sun/star/linguistic2/XLinguProperties.hpp>
+#include <osl/diagnose.h>
+
+#include <sfx2/objface.hxx>
+#include <wrtsh.hxx>
+#include <edtwin.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <doc.hxx>
+#include <globals.hrc>
+#include <cmdid.h>
+#include <globdoc.hxx>
+#include <wview.hxx>
+#include <OnlineAccessibilityCheck.hxx>
+
+#define ShellClass_SwView
+#define ShellClass_Text
+#define ShellClass_TextDrawText
+
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+#include <PostItMgr.hxx>
+
+#include <unotools/moduleoptions.hxx>
+#include <sfx2/viewfac.hxx>
+
+#include <memory>
+#include <swabstdlg.hxx>
+
+using namespace ::com::sun::star;
+
+SFX_IMPL_NAMED_VIEWFACTORY(SwView, "Default")
+{
+ if (utl::ConfigManager::IsFuzzing() || SvtModuleOptions().IsWriter())
+ {
+ SFX_VIEW_REGISTRATION(SwDocShell);
+ SFX_VIEW_REGISTRATION(SwGlobalDocShell);
+ }
+}
+
+SFX_IMPL_INTERFACE(SwView, SfxViewShell)
+
+void SwView::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterChildWindow(SID_NAVIGATOR, true);
+
+ GetStaticInterface()->RegisterChildWindow(::sfx2::sidebar::SidebarChildWindow::GetChildWindowId());
+
+ GetStaticInterface()->RegisterChildWindow(SfxInfoBarContainerChild::GetChildWindowId());
+ GetStaticInterface()->RegisterChildWindow(SvxSearchDialogWrapper::GetChildWindowId());
+ GetStaticInterface()->RegisterChildWindow(SwSpellDialogChildWindow::GetChildWindowId());
+ GetStaticInterface()->RegisterChildWindow(FN_REDLINE_ACCEPT);
+ GetStaticInterface()->RegisterChildWindow(SID_HYPERLINK_DIALOG);
+ GetStaticInterface()->RegisterChildWindow(FN_WORDCOUNT_DIALOG);
+#if HAVE_FEATURE_AVMEDIA
+ GetStaticInterface()->RegisterChildWindow(::avmedia::MediaPlayer::GetChildWindowId());
+#endif
+ GetStaticInterface()->RegisterChildWindow(FN_INSERT_FIELD_DATA_ONLY);
+
+ GetStaticInterface()->RegisterChildWindow(FN_SYNC_LABELS, false, SfxShellFeature::SwChildWindowLabel);
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_TOOLS, SfxVisibilityFlags::Standard|SfxVisibilityFlags::Server,
+ ToolbarId::Tools_Toolbox);
+}
+
+
+ShellMode SwView::GetShellMode() const
+{
+ return m_pViewImpl->GetShellMode();
+}
+
+view::XSelectionSupplier* SwView::GetUNOObject()
+{
+ return m_pViewImpl->GetUNOObject();
+}
+
+void SwView::ApplyAccessibilityOptions()
+{
+#if ENABLE_WASM_STRIP_ACCESSIBILITY
+#else
+ m_pWrtShell->ApplyAccessibilityOptions();
+ //to enable the right state of the selection cursor in readonly documents
+ if(GetDocShell()->IsReadOnly())
+ m_pWrtShell->ShowCursor();
+#endif
+}
+
+void SwView::SetMailMergeConfigItem(std::shared_ptr<SwMailMergeConfigItem> const & rConfigItem)
+{
+ m_pViewImpl->SetMailMergeConfigItem(rConfigItem);
+ UIFeatureChanged();
+}
+
+std::shared_ptr<SwMailMergeConfigItem> const & SwView::GetMailMergeConfigItem() const
+{
+ return m_pViewImpl->GetMailMergeConfigItem();
+}
+
+static bool lcl_IsViewMarks( const SwViewOption& rVOpt )
+{
+ return rVOpt.IsHardBlank() &&
+ rVOpt.IsSoftHyph() &&
+ rVOpt.IsFieldShadings();
+}
+static void lcl_SetViewMarks(SwViewOption& rVOpt, bool bOn )
+{
+ rVOpt.SetHardBlank(bOn);
+ rVOpt.SetSoftHyph(bOn);
+ rVOpt.SetAppearanceFlag(
+ ViewOptFlags::FieldShadings, bOn, true);
+}
+
+static void lcl_SetViewMetaChars( SwViewOption& rVOpt, bool bOn)
+{
+ rVOpt.SetViewMetaChars( bOn );
+ if(bOn && !(rVOpt.IsParagraph() ||
+ rVOpt.IsTab() ||
+ rVOpt.IsLineBreak() ||
+ rVOpt.IsShowHiddenChar() ||
+ rVOpt.IsShowBookmarks() ||
+ rVOpt.IsBlank()))
+ {
+ rVOpt.SetParagraph(bOn);
+ rVOpt.SetTab(bOn);
+ rVOpt.SetLineBreak(bOn);
+ rVOpt.SetBlank(bOn);
+ rVOpt.SetShowHiddenChar(bOn);
+ rVOpt.SetShowBookmarks(bOn);
+ }
+}
+
+void SwView::RecheckBrowseMode()
+{
+ // OS: pay attention to numerical order!
+ static sal_uInt16 const aInva[] =
+ {
+ //SID_NEWWINDOW,/*5620*/
+ SID_BROWSER_MODE, /*6313*/
+ SID_RULER_BORDERS, SID_RULER_PAGE_POS,
+ //SID_ATTR_LONG_LRSPACE,
+ SID_HTML_MODE,
+ SID_RULER_PROTECT, /* 10915 */
+ //SID_AUTOSPELL_CHECK,
+ //SID_AUTOSPELL_MARKOFF,
+ SID_TOGGLE_RESOLVED_NOTES, /* 11672*/
+ FN_RULER, /*20211*/
+ FN_VIEW_GRAPHIC, /*20213*/
+ FN_VIEW_BOUNDS, /**/
+ FN_VIEW_FIELDS, /*20215*/
+ FN_VLINEAL, /*20216*/
+ FN_VSCROLLBAR, /*20217*/
+ FN_HSCROLLBAR, /*20218*/
+ FN_VIEW_SECTION_BOUNDARIES, /*20219*/
+ FN_VIEW_META_CHARS, /**/
+ FN_VIEW_MARKS, /**/
+ //FN_VIEW_FIELDNAME, /**/
+ FN_VIEW_TABLEGRID, /*20227*/
+ FN_PRINT_LAYOUT, /*20237*/
+ FN_QRY_MERGE, /*20364*/
+ FN_SHADOWCURSOR, /**/
+ 0
+ };
+ // the view must not exist!
+ GetViewFrame().GetBindings().Invalidate(aInva);
+ CheckVisArea();
+
+ SvxZoomType eType;
+ if( GetWrtShell().GetViewOptions()->getBrowseMode() && SvxZoomType::PERCENT != (eType =
+ GetWrtShell().GetViewOptions()->GetZoomType()) )
+ SetZoom( eType );
+ InvalidateBorder();
+}
+
+// State of view options
+
+void SwView::StateViewOptions(SfxItemSet &rSet)
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ SfxBoolItem aBool;
+ const SwViewOption* pOpt = GetWrtShell().GetViewOptions();
+
+ while(nWhich)
+ {
+ bool bReadonly = GetDocShell()->IsReadOnly();
+ if (bReadonly && nWhich != FN_VIEW_GRAPHIC && nWhich != FN_HIGHLIGHT_CHAR_DF)
+ {
+ rSet.DisableItem(nWhich);
+ nWhich = 0;
+ }
+ switch(nWhich)
+ {
+ case FN_RULER:
+ {
+ if(!pOpt->IsViewHRuler(true) && !pOpt->IsViewVRuler(true))
+ {
+ rSet.DisableItem(nWhich);
+ nWhich = 0;
+ }
+ else
+ aBool.SetValue( pOpt->IsViewAnyRuler());
+ }
+ break;
+ case SID_BROWSER_MODE:
+ case FN_PRINT_LAYOUT:
+ {
+ bool bState = pOpt->getBrowseMode();
+ if(FN_PRINT_LAYOUT == nWhich)
+ bState = !bState;
+ aBool.SetValue( bState );
+ }
+ break;
+ case FN_VIEW_BOUNDS:
+ aBool.SetValue( pOpt->IsDocBoundaries()); break;
+ case FN_VIEW_SECTION_BOUNDARIES:
+ aBool.SetValue(pOpt->IsSectionBoundaries()); break;
+ case FN_VIEW_GRAPHIC:
+ aBool.SetValue( pOpt->IsGraphic() ); break;
+ case FN_VIEW_FIELDS:
+ aBool.SetValue( pOpt->IsFieldShadings() ); break;
+ case FN_VIEW_FIELDNAME:
+ aBool.SetValue( pOpt->IsFieldName() ); break;
+ case FN_VIEW_MARKS:
+ aBool.SetValue( lcl_IsViewMarks(*pOpt) ); break;
+ case FN_VIEW_META_CHARS:
+ aBool.SetValue( pOpt->IsViewMetaChars() ); break;
+ case FN_VIEW_TABLEGRID:
+ aBool.SetValue( pOpt->IsTableBoundaries() ); break;
+ case SID_TOGGLE_NOTES:
+ {
+ if (!GetPostItMgr()->HasNotes())
+ {
+ rSet.DisableItem(nWhich);
+ nWhich = 0;
+ }
+ else
+ aBool.SetValue( pOpt->IsPostIts());
+ break;
+ }
+ case SID_TOGGLE_RESOLVED_NOTES:
+ {
+ if (!GetPostItMgr()->HasNotes())
+ {
+ rSet.DisableItem(nWhich);
+ nWhich = 0;
+ }
+ else
+ aBool.SetValue( pOpt->IsResolvedPostIts());
+ break;
+ }
+ case FN_VIEW_HIDDEN_PARA:
+ aBool.SetValue( pOpt->IsShowHiddenPara()); break;
+ case FN_VIEW_HIDE_WHITESPACE:
+ {
+ if (pOpt->getBrowseMode() || !pOpt->CanHideWhitespace())
+ {
+ rSet.DisableItem(nWhich);
+ nWhich = 0;
+ }
+ else
+ aBool.SetValue(pOpt->IsHideWhitespaceMode());
+ break;
+ }
+ case FN_VIEW_SHOW_WHITESPACE:
+ {
+ aBool.SetValue(!pOpt->IsHideWhitespaceMode());
+ break;
+ }
+ case SID_GRID_VISIBLE:
+ aBool.SetValue( pOpt->IsGridVisible() ); break;
+ case SID_GRID_USE:
+ aBool.SetValue( pOpt->IsSnap() ); break;
+ case SID_HELPLINES_MOVE:
+ aBool.SetValue( pOpt->IsCrossHair() ); break;
+ case FN_VIEW_SMOOTH_SCROLL:
+ aBool.SetValue( pOpt->IsSmoothScroll()); break;
+ case FN_VLINEAL:
+ aBool.SetValue( StatVRuler() ); break;
+ case FN_HSCROLLBAR:
+ if( pOpt->getBrowseMode() )
+ {
+ rSet.DisableItem(nWhich);
+ nWhich = 0;
+ }
+ else
+ aBool.SetValue( IsHScrollbarVisible() );
+ break;
+ case FN_VSCROLLBAR:
+ aBool.SetValue( IsVScrollbarVisible() ); break;
+ case SID_AUTOSPELL_CHECK:
+ aBool.SetValue( pOpt->IsOnlineSpell() );
+ break;
+ case SID_ACCESSIBILITY_CHECK_ONLINE:
+ {
+ bool bOnlineAccessibilityCheck = officecfg::Office::Common::Accessibility::OnlineAccessibilityCheck::get();
+ aBool.SetValue(bOnlineAccessibilityCheck);
+ }
+ break;
+ case FN_SHADOWCURSOR:
+ if ( pOpt->getBrowseMode() )
+ {
+ rSet.DisableItem( nWhich );
+ nWhich = 0;
+ }
+ else
+ aBool.SetValue( pOpt->IsShadowCursor() );
+ break;
+ case FN_SHOW_INLINETOOLTIPS:
+ aBool.SetValue( pOpt->IsShowInlineTooltips() );
+ break;
+ case FN_USE_HEADERFOOTERMENU:
+ aBool.SetValue( pOpt->IsUseHeaderFooterMenu() );
+ break;
+ case FN_SHOW_OUTLINECONTENTVISIBILITYBUTTON:
+ aBool.SetValue( pOpt->IsShowOutlineContentVisibilityButton() );
+ break;
+ case FN_SHOW_CHANGES_IN_MARGIN:
+ aBool.SetValue( pOpt->IsShowChangesInMargin() );
+ break;
+ case FN_HIGHLIGHT_CHAR_DF:
+ aBool.SetValue(m_bIsHighlightCharDF);
+ break;
+ case SID_SPOTLIGHT_PARASTYLES:
+ aBool.SetValue(m_bIsSpotlightParaStyles);
+ break;
+ case SID_SPOTLIGHT_CHARSTYLES:
+ aBool.SetValue(m_bIsSpotlightCharStyles);
+ break;
+ }
+
+ if( nWhich )
+ {
+ aBool.SetWhich( nWhich );
+ rSet.Put( aBool );
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+// execute view options
+
+void SwView::ExecViewOptions(SfxRequest &rReq)
+{
+ std::optional<SwViewOption> pOpt( *GetWrtShell().GetViewOptions() );
+ bool bModified = GetWrtShell().IsModified();
+
+ int eState = STATE_TOGGLE;
+ bool bSet = false;
+ bool bBrowseModeChanged = false;
+
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ sal_uInt16 nSlot = rReq.GetSlot();
+ const SfxPoolItem* pAttr=nullptr;
+
+ if( pArgs && SfxItemState::SET == pArgs->GetItemState( nSlot , false, &pAttr ))
+ {
+ bSet = static_cast<const SfxBoolItem*>(pAttr)->GetValue();
+ eState = bSet ? STATE_ON : STATE_OFF;
+ }
+
+ bool bFlag = STATE_ON == eState;
+ uno::Reference< linguistic2::XLinguProperties > xLngProp( ::GetLinguPropertySet() );
+
+ switch ( nSlot )
+ {
+ case FN_VIEW_GRAPHIC:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsGraphic();
+ pOpt->SetGraphic( bFlag );
+ break;
+
+ case FN_VIEW_FIELDS:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsFieldShadings() ;
+ pOpt->SetAppearanceFlag(ViewOptFlags::FieldShadings, bFlag, true );
+ break;
+
+ case FN_VIEW_BOUNDS:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsDocBoundaries();
+ pOpt->SetAppearanceFlag(ViewOptFlags::DocBoundaries, bFlag, true );
+ break;
+
+ case FN_VIEW_SECTION_BOUNDARIES:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsSectionBoundaries();
+ pOpt->SetAppearanceFlag(ViewOptFlags::SectionBoundaries, bFlag, true );
+ break;
+
+ case SID_GRID_VISIBLE:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsGridVisible();
+
+ pOpt->SetGridVisible( bFlag );
+ break;
+
+ case SID_GRID_USE:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsSnap();
+
+ pOpt->SetSnap( bFlag );
+ break;
+
+ case SID_HELPLINES_MOVE:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsCrossHair();
+
+ pOpt->SetCrossHair( bFlag );
+ break;
+
+ case SID_BROWSER_MODE:
+ bBrowseModeChanged = !pOpt->getBrowseMode();
+ pOpt->setBrowseMode(true );
+ break;
+
+ case FN_PRINT_LAYOUT:
+ bBrowseModeChanged = pOpt->getBrowseMode();
+ pOpt->setBrowseMode( false );
+ break;
+
+ case SID_TOGGLE_NOTES:
+ if ( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsPostIts();
+
+ GetPostItMgr()->SetLayout();
+ pOpt->SetPostIts( bFlag );
+ if (pOpt->IsPostIts())
+ GetPostItMgr()->CheckMetaText();
+ break;
+
+ case SID_TOGGLE_RESOLVED_NOTES:
+ if ( STATE_TOGGLE == eState )
+ bFlag = pOpt->IsResolvedPostIts();
+
+ GetPostItMgr()->ShowHideResolvedNotes(!bFlag);
+
+ GetPostItMgr()->SetLayout();
+ pOpt->SetResolvedPostIts( !bFlag );
+
+ break;
+
+ case FN_VIEW_HIDDEN_PARA:
+ if ( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsShowHiddenPara();
+
+ pOpt->SetShowHiddenPara( bFlag );
+ break;
+
+ case FN_VIEW_HIDE_WHITESPACE:
+ if ( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsHideWhitespaceMode();
+
+ pOpt->SetHideWhitespaceMode(bFlag);
+ break;
+
+ case FN_VIEW_SHOW_WHITESPACE:
+ if ( STATE_TOGGLE == eState )
+ bFlag = pOpt->IsHideWhitespaceMode();
+
+ pOpt->SetHideWhitespaceMode(!bFlag);
+ break;
+
+ case FN_VIEW_SMOOTH_SCROLL:
+
+ if ( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsSmoothScroll();
+
+ pOpt->SetSmoothScroll( bFlag );
+ break;
+
+ case FN_VLINEAL:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsViewVRuler();
+
+ pOpt->SetViewVRuler( bFlag );
+ break;
+
+ case FN_VSCROLLBAR:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsViewVScrollBar();
+
+ pOpt->SetViewVScrollBar( bFlag );
+ break;
+
+ case FN_HSCROLLBAR:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsViewHScrollBar();
+
+ pOpt->SetViewHScrollBar( bFlag );
+ break;
+
+ case FN_RULER:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsViewAnyRuler();
+
+ pOpt->SetViewAnyRuler( bFlag );
+ break;
+
+ case FN_VIEW_TABLEGRID:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsTableBoundaries();
+ pOpt->SetAppearanceFlag(ViewOptFlags::TableBoundaries, bFlag, true );
+ break;
+
+ case FN_VIEW_FIELDNAME:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsFieldName() ;
+
+ pOpt->SetFieldName( bFlag );
+ break;
+
+ case FN_VIEW_MARKS:
+ if( STATE_TOGGLE == eState )
+ bFlag = !lcl_IsViewMarks(*pOpt) ;
+
+ lcl_SetViewMarks( *pOpt, bFlag );
+ break;
+
+ case FN_HIGHLIGHT_CHAR_DF:
+ if (STATE_TOGGLE == eState)
+ bFlag = !m_bIsHighlightCharDF;
+ m_bIsHighlightCharDF = bFlag;
+ break;
+
+ case SID_SPOTLIGHT_PARASTYLES:
+ if (!pArgs || (pArgs && !pArgs->HasItem(FN_PARAM_1)))
+ {
+ const SfxStringItem sDeckName(SID_SIDEBAR_DECK, "StyleListDeck");
+ GetDispatcher().ExecuteList(SID_SIDEBAR_DECK, SfxCallMode::SYNCHRON, { &sDeckName });
+ }
+ if (STATE_TOGGLE == eState)
+ bFlag = !m_bIsSpotlightParaStyles;
+ m_bIsSpotlightParaStyles = bFlag;
+ break;
+
+ case SID_SPOTLIGHT_CHARSTYLES:
+ if (!pArgs || (pArgs && !pArgs->HasItem(FN_PARAM_1)))
+ {
+ const SfxStringItem sDeckName(SID_SIDEBAR_DECK, "StyleListDeck");
+ GetDispatcher().ExecuteList(SID_SIDEBAR_DECK, SfxCallMode::SYNCHRON, { &sDeckName });
+ }
+ if (STATE_TOGGLE == eState)
+ bFlag = !m_bIsSpotlightCharStyles;
+ m_bIsSpotlightCharStyles = bFlag;
+ break;
+
+ case FN_VIEW_META_CHARS:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsViewMetaChars();
+
+ lcl_SetViewMetaChars( *pOpt, bFlag );
+ break;
+
+ case SID_AUTOSPELL_CHECK:
+ const SfxPoolItem* pItem;
+
+ if (pArgs && pArgs->HasItem(FN_PARAM_1, &pItem))
+ bSet = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ else if( STATE_TOGGLE == eState )
+ {
+ bFlag = !pOpt->IsOnlineSpell();
+ bSet = bFlag;
+ }
+
+ pOpt->SetOnlineSpell(bSet);
+ {
+ SvtLinguConfig aCfg;
+ aCfg.SetProperty( UPN_IS_SPELL_AUTO, uno::Any( bSet ) );
+
+ if (xLngProp.is())
+ xLngProp->setIsSpellAuto( bSet );
+
+ // for the time being we do not have a specific option for grammarchecking.
+ // thus we'll use the one for spell checking...
+ if (bSet)
+ {
+ SwDocShell *pDocSh = GetDocShell();
+ SwDoc *pDoc = pDocSh? pDocSh->GetDoc() : nullptr;
+
+ // right now we don't have view options for automatic grammar checking. Thus...
+ bool bIsAutoGrammar = false;
+ aCfg.GetProperty( UPN_IS_GRAMMAR_AUTO ) >>= bIsAutoGrammar;
+
+ if (pDoc && bIsAutoGrammar)
+ pDoc->StartGrammarChecking();
+ }
+ }
+ break;
+
+ case SID_ACCESSIBILITY_CHECK_ONLINE:
+ {
+ if (pArgs && pArgs->HasItem(FN_PARAM_1, &pItem))
+ {
+ bSet = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ }
+ else if (STATE_TOGGLE == eState)
+ {
+ bool bOnlineCheck = officecfg::Office::Common::Accessibility::OnlineAccessibilityCheck::get();
+ bSet = !bOnlineCheck;
+ }
+ std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Accessibility::OnlineAccessibilityCheck::set(bSet, batch);
+ batch->commit();
+
+ SwDocShell *pDocSh = GetDocShell();
+ SwDoc* pDocument = pDocSh? pDocSh->GetDoc() : nullptr;
+ if (pDocument)
+ pDocument->getOnlineAccessibilityCheck()->updateCheckerActivity();
+ }
+ break;
+
+ case FN_SHADOWCURSOR:
+ if( STATE_TOGGLE == eState )
+ {
+ bFlag = !pOpt->IsShadowCursor();
+ bSet = bFlag;
+ }
+
+ pOpt->SetShadowCursor(bSet);
+ break;
+
+ case FN_SHOW_INLINETOOLTIPS:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsShowInlineTooltips();
+
+ pOpt->SetShowInlineTooltips( bFlag );
+ break;
+
+ case FN_USE_HEADERFOOTERMENU:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsUseHeaderFooterMenu();
+
+ pOpt->SetUseHeaderFooterMenu( bFlag );
+ break;
+
+ case FN_SHOW_OUTLINECONTENTVISIBILITYBUTTON:
+ {
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsShowOutlineContentVisibilityButton();
+
+ SwWrtShell &rSh = GetWrtShell();
+
+ if (!bFlag) // Outline folding is being turned ON!
+ rSh.MakeAllFoldedOutlineContentVisible();
+
+ pOpt->SetShowOutlineContentVisibilityButton(bFlag);
+
+ // Apply option change here so if toggling the outline folding feature ON
+ // the invalidate function will see this.
+ rSh.StartAction();
+ rSh.ApplyViewOptions(*pOpt);
+ rSh.EndAction();
+
+ if (bFlag) // Outline folding is being turned OFF!
+ rSh.MakeAllFoldedOutlineContentVisible(false);
+
+ break;
+ }
+
+ case FN_SHOW_CHANGES_IN_MARGIN:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsShowChangesInMargin();
+
+ pOpt->SetShowChangesInMargin( bFlag );
+ break;
+
+ default:
+ OSL_FAIL("wrong request method");
+ return;
+ }
+
+ // Set UserPrefs, mark request as modified
+ bool bWebView = dynamic_cast<const SwWebView*>(this) != nullptr;
+ SwWrtShell &rSh = GetWrtShell();
+ rSh.StartAction();
+ SwModule* pModule = SW_MOD();
+ if( *rSh.GetViewOptions() != *pOpt )
+ {
+ rSh.ApplyViewOptions( *pOpt );
+ if( bBrowseModeChanged )
+ {
+ GetDocShell()->ToggleLayoutMode(this);
+ }
+
+ // The UsrPref must be marked as modified.
+ // call for initialization
+ pModule->GetUsrPref(bWebView);
+ SwModule::CheckSpellChanges( pOpt->IsOnlineSpell(), false, false, false );
+ }
+ //OS: Set back modified again, because view/fields sets the Doc modified.
+ if( !bModified )
+ rSh.ResetModified();
+
+ pModule->ApplyUsrPref( *pOpt, this, bWebView ? SvViewOpt::DestWeb : SvViewOpt::DestText );
+
+ // #i6193# let postits know about new spellcheck setting
+ if ( nSlot == SID_AUTOSPELL_CHECK )
+ GetPostItMgr()->SetSpellChecking();
+
+ const bool bLockedView = rSh.IsViewLocked();
+ rSh.LockView( true ); //lock visible section
+ GetWrtShell().EndAction();
+ if( bBrowseModeChanged && !bFlag )
+ CalcVisArea( GetEditWin().GetOutputSizePixel() );
+ rSh.LockView( bLockedView );
+
+ pOpt.reset();
+ Invalidate(rReq.GetSlot());
+ if(!pArgs)
+ rReq.AppendItem(SfxBoolItem(nSlot, bFlag));
+ rReq.Done();
+}
+
+void SwView::ExecFormatFootnote()
+{
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateSwFootNoteOptionDlg(GetFrameWeld(), GetWrtShell()));
+ pDlg->Execute();
+}
+
+void SwView::ExecNumberingOutline(SfxItemPool & rPool)
+{
+ SfxItemSetFixed<FN_PARAM_1, FN_PARAM_1> aTmp(rPool);
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateOutlineTabDialog(GetFrameWeld(), &aTmp, GetWrtShell()));
+ pDlg->Execute();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/view1.cxx b/sw/source/uibase/uiview/view1.cxx
new file mode 100644
index 0000000000..ca51ceba98
--- /dev/null
+++ b/sw/source/uibase/uiview/view1.cxx
@@ -0,0 +1,213 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/eitem.hxx>
+#include <svx/ruler.hxx>
+#include <idxmrk.hxx>
+#include <view.hxx>
+#include <basesh.hxx>
+#include <wrtsh.hxx>
+#include <swmodule.hxx>
+#include <docsh.hxx>
+#include <fldwrap.hxx>
+#include <redlndlg.hxx>
+#include <edtwin.hxx>
+#include <formatclipboard.hxx>
+#include <cmdid.h>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <wordcountdialog.hxx>
+
+void SwView::Activate(bool bMDIActivate)
+{
+ // fdo#40438 Update the layout to make sure everything is correct before showing the content
+ m_pWrtShell->StartAction();
+ m_pWrtShell->EndAction( true );
+
+ // Register the current View at the DocShell.
+ // The view remains active at the DocShell until it will
+ // be destroyed or by Activate a new one will be set.
+ SwDocShell* pDocSh = GetDocShell();
+ if(pDocSh)
+ pDocSh->SetView(this);
+ SwModule* pSwMod = SW_MOD();
+ pSwMod->SetView(this);
+
+ // Document size has changed.
+ if(!bDocSzUpdated)
+ DocSzChgd(m_aDocSz);
+
+ // make selection visible
+ if(m_bMakeSelectionVisible)
+ {
+ m_pWrtShell->MakeSelVisible();
+ m_bMakeSelectionVisible = false;
+ }
+ m_pHRuler->SetActive();
+ m_pVRuler->SetActive();
+
+ if ( bMDIActivate )
+ {
+ if ( m_pShell )
+ {
+ SfxDispatcher &rDispatcher = GetDispatcher();
+ SfxShell *pTopShell = rDispatcher.GetShell( 0 );
+
+ // this SwView is the top-most shell on the stack
+ if ( pTopShell == this )
+ {
+ for ( sal_uInt16 i = 1; true; ++i )
+ {
+ SfxShell *pSfxShell = rDispatcher.GetShell( i );
+ // does the stack contain any shells spawned by this SwView already?
+ if ( ( dynamic_cast< const SwBaseShell *>( pSfxShell ) != nullptr
+ || dynamic_cast< const FmFormShell *>( pSfxShell ) != nullptr )
+ && ( pSfxShell->GetViewShell() == this ) )
+ {
+ // it shouldn't b/c we haven't been activated yet
+ // so assert that 'cause it'll crash during dispose at the latest
+ assert( pSfxShell && "Corrupted shell stack: dependent shell positioned below its view");
+ }
+ else
+ break;
+ }
+ }
+ }
+
+ m_pWrtShell->ShellGetFocus(); // Selections visible
+
+ if( !m_sSwViewData.isEmpty() )
+ {
+ ReadUserData(m_sSwViewData);
+ m_sSwViewData.clear();
+ }
+
+ AttrChangedNotify(nullptr);
+
+ // Initialize Fielddlg newly if necessary (e.g. for TYP_SETVAR)
+ sal_uInt16 nId = SwFieldDlgWrapper::GetChildWindowId();
+ SfxViewFrame& rVFrame = GetViewFrame();
+ SwFieldDlgWrapper *pWrp = static_cast<SwFieldDlgWrapper*>(rVFrame.GetChildWindow(nId));
+ if (pWrp)
+ pWrp->ReInitDlg(GetDocShell());
+
+ // Initialize RedlineDlg newly if necessary
+ nId = SwRedlineAcceptChild::GetChildWindowId();
+ SwRedlineAcceptChild *pRed = static_cast<SwRedlineAcceptChild*>(rVFrame.GetChildWindow(nId));
+ if (pRed)
+ pRed->ReInitDlg(GetDocShell());
+
+ // reinit IdxMarkDlg
+ nId = SwInsertIdxMarkWrapper::GetChildWindowId();
+ SwInsertIdxMarkWrapper *pIdxMrk = static_cast<SwInsertIdxMarkWrapper*>(rVFrame.GetChildWindow(nId));
+ if (pIdxMrk)
+ pIdxMrk->ReInitDlg(*m_pWrtShell);
+
+ // reinit AuthMarkDlg
+ nId = SwInsertAuthMarkWrapper::GetChildWindowId();
+ SwInsertAuthMarkWrapper *pAuthMrk = static_cast<SwInsertAuthMarkWrapper*>(rVFrame.
+ GetChildWindow(nId));
+ if (pAuthMrk)
+ pAuthMrk->ReInitDlg(*m_pWrtShell);
+ }
+ else
+ // At least call the Notify (as a precaution because of the SlotFilter).
+ AttrChangedNotify(nullptr);
+
+ SfxViewShell::Activate(bMDIActivate);
+}
+
+void SwView::Deactivate(bool bMDIActivate)
+{
+ GetEditWin().FlushInBuffer(); // Flush characters still in the input buffer.
+
+ if( bMDIActivate )
+ {
+ m_pWrtShell->ShellLoseFocus(); // Selections invisible
+
+ m_pHRuler->SetActive( false );
+ m_pVRuler->SetActive( false );
+ }
+ SfxViewShell::Deactivate(bMDIActivate);
+}
+
+void SwView::MarginChanged()
+{
+ GetWrtShell().SetBrowseBorder( GetMargin() );
+}
+
+void SwView::ExecFormatPaintbrush(SfxRequest const & rReq)
+{
+ if(!m_pFormatClipboard)
+ return;
+
+ if( m_pFormatClipboard->HasContent() )
+ {
+ m_pFormatClipboard->Erase();
+
+ SwApplyTemplate aTemplate;
+ GetEditWin().SetApplyTemplate(aTemplate);
+ }
+ else
+ {
+ bool bPersistentCopy = false;
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ if( pArgs && pArgs->Count() >= 1 )
+ {
+ bPersistentCopy = pArgs->Get(SID_FORMATPAINTBRUSH).GetValue();
+ }
+
+ m_pFormatClipboard->Copy( GetWrtShell(), GetPool(), bPersistentCopy );
+
+ SwApplyTemplate aTemplate;
+ aTemplate.m_pFormatClipboard = m_pFormatClipboard.get();
+ GetEditWin().SetApplyTemplate(aTemplate);
+ }
+ GetViewFrame().GetBindings().Invalidate(SID_FORMATPAINTBRUSH);
+}
+
+void SwView::StateFormatPaintbrush(SfxItemSet &rSet)
+{
+ if(!m_pFormatClipboard)
+ return;
+
+ const bool bHasContent = m_pFormatClipboard->HasContent();
+ if( !bHasContent &&
+ !SwFormatClipboard::CanCopyThisType( GetWrtShell().GetSelectionType())
+ )
+ {
+ rSet.DisableItem( SID_FORMATPAINTBRUSH );
+ }
+ else
+ rSet.Put(SfxBoolItem(SID_FORMATPAINTBRUSH, bHasContent));
+}
+
+void SwView::UpdateWordCount(SfxShell* pShell, sal_uInt16 nSlot)
+{
+ SfxViewFrame& rVFrame = GetViewFrame();
+ rVFrame.ToggleChildWindow(FN_WORDCOUNT_DIALOG);
+ pShell->Invalidate(nSlot);
+
+ SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(rVFrame.GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
+ if (pWrdCnt)
+ pWrdCnt->UpdateCounts();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/view2.cxx b/sw/source/uibase/uiview/view2.cxx
new file mode 100644
index 0000000000..cc6faf78a3
--- /dev/null
+++ b/sw/source/uibase/uiview/view2.cxx
@@ -0,0 +1,3197 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+#include <config_fuzzers.h>
+
+#include <com/sun/star/util/SearchAlgorithms2.hpp>
+#include <o3tl/any.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
+#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
+#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
+#include <com/sun/star/ui/dialogs/ListboxControlActions.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <com/sun/star/linguistic2/XProofreadingIterator.hpp>
+#include <com/sun/star/linguistic2/XDictionary.hpp>
+#include <comphelper/propertyvalue.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <SwCapObjType.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <docary.hxx>
+#include <hintids.hxx>
+#include <SwRewriter.hxx>
+#include <numrule.hxx>
+#include <swundo.hxx>
+#include <svl/PasswordHelper.hxx>
+#include <svl/urihelper.hxx>
+#include <sfx2/passwd.hxx>
+#include <sfx2/sfxdlg.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <editeng/langitem.hxx>
+#include <svx/linkwarn.hxx>
+#include <svx/statusitem.hxx>
+#include <svx/viewlayoutitem.hxx>
+#include <svx/zoomslideritem.hxx>
+#include <sfx2/htmlmode.hxx>
+#include <vcl/svapp.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/bindings.hxx>
+#include <editeng/lrspitem.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <unotools/syslocale.hxx>
+#include <editeng/unolingu.hxx>
+#include <vcl/weld.hxx>
+#include <editeng/tstpitem.hxx>
+#include <sfx2/event.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <editeng/sizeitem.hxx>
+#include <sfx2/dispatch.hxx>
+#include <svl/whiter.hxx>
+#include <svl/ptitem.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <vcl/errinf.hxx>
+#include <tools/urlobj.hxx>
+#include <svx/svdview.hxx>
+#include <swtypes.hxx>
+#include <swwait.hxx>
+#include <redlndlg.hxx>
+#include <gotodlg.hxx>
+#include <view.hxx>
+#include <uivwimp.hxx>
+#include <docsh.hxx>
+#include <doc.hxx>
+#include <printdata.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <DocumentRedlineManager.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentStatistics.hxx>
+#include <IDocumentOutlineNodes.hxx>
+#include <wrtsh.hxx>
+#include <viewopt.hxx>
+#include <basesh.hxx>
+#include <swmodule.hxx>
+#include <uitool.hxx>
+#include <shellio.hxx>
+#include <fmtinfmt.hxx>
+#include <mdiexp.hxx>
+#include <drawbase.hxx>
+#include <frmatr.hxx>
+#include <frmmgr.hxx>
+#include <pagedesc.hxx>
+#include <section.hxx>
+#include <tox.hxx>
+#include <edtwin.hxx>
+#include <wview.hxx>
+#include <cmdid.h>
+#include <sfx2/strings.hrc>
+#include <sfx2/sfxresid.hxx>
+#include <strings.hrc>
+#include <swerror.h>
+#include <globals.hrc>
+#include <fmtclds.hxx>
+#include <sfx2/templatedlg.hxx>
+#include <dbconfig.hxx>
+#include <dbmgr.hxx>
+#include <reffld.hxx>
+#include <comphelper/lok.hxx>
+#include <comphelper/string.hxx>
+#include <comphelper/docpasswordhelper.hxx>
+#include <svtools/strings.hrc>
+#include <svtools/svtresid.hxx>
+
+#include <PostItMgr.hxx>
+
+#include <comphelper/processfactory.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+#include <svx/svxdlg.hxx>
+#include <swabstdlg.hxx>
+#include <fmthdft.hxx>
+#include <unotextrange.hxx>
+#include <docstat.hxx>
+#include <wordcountdialog.hxx>
+#include <OnlineAccessibilityCheck.hxx>
+#include <sfx2/sidebar/Sidebar.hxx>
+
+#include <vcl/GraphicNativeTransform.hxx>
+#include <vcl/GraphicNativeMetadata.hxx>
+#include <vcl/settings.hxx>
+#include <i18nutil/searchopt.hxx>
+#include <osl/diagnose.h>
+#include <paratr.hxx>
+#include <rootfrm.hxx>
+#include <frameformats.hxx>
+
+#include <viewimp.hxx>
+#include <pagefrm.hxx>
+
+#include <memory>
+#include <string_view>
+#include <svl/slstitm.hxx>
+
+#include <basegfx/utils/zoomtools.hxx>
+
+#include <ndtxt.hxx>
+
+#include <svx/srchdlg.hxx>
+#include <o3tl/string_view.hxx>
+
+const char sStatusDelim[] = " : ";
+
+using namespace sfx2;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::scanner;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::ui::dialogs;
+
+namespace {
+
+class SwNumberInputDlg : public SfxDialogController
+{
+private:
+ std::unique_ptr<weld::Label> m_xLabel1;
+ std::unique_ptr<weld::SpinButton> m_xSpinButton;
+ std::unique_ptr<weld::Label> m_xLabel2;
+ std::unique_ptr<weld::Button> m_xOKButton;
+
+ DECL_LINK(InputModifiedHdl, weld::Entry&, void);
+public:
+ SwNumberInputDlg(weld::Window* pParent, const OUString& rTitle,
+ const OUString& rLabel1, const sal_Int64 nValue, const sal_Int64 min, const sal_Int64 max,
+ OUString rLabel2 = OUString())
+ : SfxDialogController(pParent, "modules/swriter/ui/numberinput.ui", "NumberInputDialog")
+ , m_xLabel1(m_xBuilder->weld_label("label1"))
+ , m_xSpinButton(m_xBuilder->weld_spin_button("spinbutton"))
+ , m_xLabel2(m_xBuilder->weld_label("label2"))
+ , m_xOKButton(m_xBuilder->weld_button("ok"))
+ {
+ m_xDialog->set_title(rTitle);
+ m_xLabel1->set_label(rLabel1);
+ m_xSpinButton->set_value(nValue);
+ m_xSpinButton->set_range(min, max);
+ m_xSpinButton->set_position(-1);
+ m_xSpinButton->select_region(0, -1);
+ m_xSpinButton->connect_changed(LINK(this, SwNumberInputDlg, InputModifiedHdl));
+ if (!rLabel2.isEmpty())
+ {
+ m_xLabel2->set_label(rLabel2);
+ m_xLabel2->show();
+ }
+ }
+
+ auto GetNumber()
+ {
+ return m_xSpinButton->get_text().toInt32();
+ }
+};
+
+IMPL_LINK_NOARG(SwNumberInputDlg, InputModifiedHdl, weld::Entry&, void)
+{
+ m_xOKButton->set_sensitive(!m_xSpinButton->get_text().isEmpty());
+ if (!m_xOKButton->get_sensitive())
+ return;
+
+ auto nValue = m_xSpinButton->get_text().toInt32();
+ if (nValue <= m_xSpinButton->get_min())
+ m_xSpinButton->set_value(m_xSpinButton->get_min());
+ else if (nValue > m_xSpinButton->get_max())
+ m_xSpinButton->set_value(m_xSpinButton->get_max());
+ else
+ m_xSpinButton->set_value(nValue);
+
+ m_xSpinButton->set_position(-1);
+}
+
+}
+
+static void lcl_SetAllTextToDefaultLanguage( SwWrtShell &rWrtSh, TypedWhichId<SvxLanguageItem> nWhichId )
+{
+ if (!(nWhichId == RES_CHRATR_LANGUAGE ||
+ nWhichId == RES_CHRATR_CJK_LANGUAGE ||
+ nWhichId == RES_CHRATR_CTL_LANGUAGE))
+ return;
+
+ rWrtSh.StartAction();
+ rWrtSh.LockView( true );
+ rWrtSh.Push();
+
+ // prepare to apply new language to all text in document
+ rWrtSh.SelAll();
+ rWrtSh.ExtendedSelectAll();
+
+ // set language attribute to default for all text
+ rWrtSh.ResetAttr({ nWhichId });
+
+ rWrtSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+ rWrtSh.LockView( false );
+ rWrtSh.EndAction();
+
+}
+
+/**
+ * Create string for showing the page number in the statusbar
+ *
+ * @param nPhyNum The physical page number
+ * @param nVirtNum The logical page number (user-assigned)
+ * @param rPgStr User-defined page name (will be shown if different from logical page number)
+ *
+ * @return OUString Formatted string: Page 1 of 10 (Page 1 of 8 to print OR Page nVirtNumv/rPgStr)
+ **/
+OUString SwView::GetPageStr(sal_uInt16 nPhyNum, sal_uInt16 nVirtNum, const OUString& rPgStr)
+{
+ // Show user-defined page number in brackets if any.
+ OUString extra;
+ if (!rPgStr.isEmpty() && std::u16string_view(OUString::number(nPhyNum)) != rPgStr)
+ extra = rPgStr;
+ else if (nPhyNum != nVirtNum)
+ extra = OUString::number(nVirtNum);
+
+ sal_uInt16 nPageCount = GetWrtShell().GetPageCnt();
+ sal_uInt16 nPrintedPhyNum = nPhyNum;
+ sal_uInt16 nPrintedPageCount = nPageCount;
+ if (!GetWrtShell().getIDocumentDeviceAccess().getPrintData().IsPrintEmptyPages())
+ SwDoc::CalculateNonBlankPages(*m_pWrtShell->GetLayout(), nPrintedPageCount, nPrintedPhyNum);
+ // Show printed page numbers only, when they are different
+ OUString aStr( nPageCount != nPrintedPageCount
+ ? SwResId(STR_PAGE_COUNT_PRINTED)
+ : (extra.isEmpty() ? SwResId(STR_PAGE_COUNT) : SwResId(STR_PAGE_COUNT_CUSTOM)));
+ aStr = aStr.replaceFirst("%1", OUString::number(nPhyNum));
+ aStr = aStr.replaceFirst("%2", OUString::number(nPageCount));
+ if (nPageCount != nPrintedPageCount)
+ {
+ aStr = aStr.replaceFirst("%3", OUString::number(nPrintedPhyNum));
+ aStr = aStr.replaceFirst("%4", OUString::number(nPrintedPageCount));
+ }
+ else
+ aStr = aStr.replaceFirst("%3", extra);
+
+ return aStr;
+}
+
+ErrCode SwView::InsertGraphic( const OUString &rPath, const OUString &rFilter,
+ bool bLink, GraphicFilter *pFilter )
+{
+ SwWait aWait( *GetDocShell(), true );
+
+ Graphic aGraphic;
+ ErrCode aResult = ERRCODE_NONE;
+ if( !pFilter )
+ {
+ pFilter = &GraphicFilter::GetGraphicFilter();
+ }
+ aResult = GraphicFilter::LoadGraphic( rPath, rFilter, aGraphic, pFilter );
+
+ if( ERRCODE_NONE == aResult )
+ {
+ GraphicNativeMetadata aMetadata;
+ if ( aMetadata.read(aGraphic) )
+ {
+ const Degree10 aRotation = aMetadata.getRotation();
+ if (aRotation)
+ {
+ GraphicNativeTransform aTransform( aGraphic );
+ aTransform.rotate( aRotation );
+ }
+ }
+
+ SwFlyFrameAttrMgr aFrameManager( true, GetWrtShellPtr(), Frmmgr_Type::GRF, nullptr );
+ SwWrtShell& rShell = GetWrtShell();
+
+ // #i123922# determine if we really want to insert or replace the graphic at a selected object
+ const bool bReplaceMode(rShell.HasSelection() && SelectionType::Frame == rShell.GetSelectionType());
+
+ if(bReplaceMode)
+ {
+ // #i123922# Do same as in D&D, ReRead graphic and all is done
+ rShell.ReRead(
+ bLink ? rPath : OUString(),
+ bLink ? rFilter : OUString(),
+ &aGraphic);
+ }
+ else
+ {
+ rShell.StartAction();
+ if( bLink )
+ {
+ SwDocShell* pDocSh = GetDocShell();
+ INetURLObject aTemp(
+ pDocSh->HasName() ?
+ pDocSh->GetMedium()->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ) :
+ OUString());
+
+ OUString sURL = URIHelper::SmartRel2Abs(
+ aTemp, rPath, URIHelper::GetMaybeFileHdl() );
+ aGraphic.setOriginURL(sURL);
+ rShell.InsertGraphic( sURL, rFilter, aGraphic, &aFrameManager );
+ }
+ else
+ {
+ rShell.InsertGraphic( OUString(), OUString(), aGraphic, &aFrameManager );
+ }
+
+ // it is too late after "EndAction" because the Shell can already be destroyed.
+ rShell.EndAction();
+ }
+ }
+ return aResult;
+}
+
+bool SwView::InsertGraphicDlg( SfxRequest& rReq )
+{
+ bool bReturn = false;
+ SwDocShell* pDocShell = GetDocShell();
+ SwDoc* pDoc = pDocShell->GetDoc();
+
+ OUString sGraphicFormat = SwResId(STR_POOLFRM_GRAPHIC);
+
+// No file pickers in a non-desktop (mobile app) build.
+
+#if HAVE_FEATURE_DESKTOP
+ // when in HTML mode insert only as a link
+ const sal_uInt16 nHtmlMode = ::GetHtmlMode(pDocShell);
+ std::unique_ptr<FileDialogHelper> pFileDlg(new FileDialogHelper(
+ ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE,
+ FileDialogFlags::Graphic, GetFrameWeld()));
+ pFileDlg->SetTitle(SwResId(STR_INSERT_GRAPHIC ));
+ pFileDlg->SetContext( FileDialogHelper::WriterInsertImage );
+
+ uno::Reference < XFilePicker3 > xFP = pFileDlg->GetFilePicker();
+ uno::Reference < XFilePickerControlAccess > xCtrlAcc(xFP, UNO_QUERY);
+ if(nHtmlMode & HTMLMODE_ON)
+ {
+ xCtrlAcc->setValue( ExtendedFilePickerElementIds::CHECKBOX_LINK, 0, Any(true));
+ xCtrlAcc->enableControl( ExtendedFilePickerElementIds::CHECKBOX_LINK, false);
+ }
+
+ std::vector<OUString> aFormats;
+ const size_t nArrLen = pDoc->GetFrameFormats()->size();
+ for( size_t i = 0; i < nArrLen; ++i )
+ {
+ const SwFrameFormat* pFormat = (*pDoc->GetFrameFormats())[ i ];
+ if(pFormat->IsDefault() || pFormat->IsAuto())
+ continue;
+ aFormats.push_back(pFormat->GetName());
+ }
+
+ // pool formats
+
+ const std::vector<OUString>& rFramePoolArr(
+ SwStyleNameMapper::GetFrameFormatUINameArray());
+ for(const auto & i : rFramePoolArr)
+ {
+ aFormats.push_back(i);
+ }
+
+ std::sort(aFormats.begin(), aFormats.end());
+ aFormats.erase(std::unique(aFormats.begin(), aFormats.end()), aFormats.end());
+
+ Sequence<OUString> aListBoxEntries(aFormats.size());
+ OUString* pEntries = aListBoxEntries.getArray();
+ sal_Int16 nSelect = 0;
+ for( size_t i = 0; i < aFormats.size(); ++i )
+ {
+ pEntries[i] = aFormats[i];
+ if(pEntries[i] == sGraphicFormat)
+ nSelect = i;
+ }
+ try
+ {
+ Any aTemplates(&aListBoxEntries, cppu::UnoType<decltype(aListBoxEntries)>::get());
+
+ xCtrlAcc->setValue( ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE,
+ ListboxControlActions::ADD_ITEMS , aTemplates );
+
+ Any aSelectPos(&nSelect, cppu::UnoType<decltype(nSelect)>::get());
+ xCtrlAcc->setValue( ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE,
+ ListboxControlActions::SET_SELECT_ITEM, aSelectPos );
+ }
+ catch (const Exception&)
+ {
+ OSL_FAIL("control access failed");
+ }
+#endif
+
+ const SfxStringItem* pName = rReq.GetArg<SfxStringItem>(SID_INSERT_GRAPHIC);
+ bool bShowError = !pName;
+
+ bool bHaveName = pName != nullptr;
+#if HAVE_FEATURE_DESKTOP
+ if (!bHaveName && !Application::IsHeadlessModeEnabled())
+ {
+ // execute file dialog, without capturing mouse (tdf#156033)
+ vcl::Window* pWin = GetWindow();
+ const bool bMouseCaptured = pWin && pWin->IsMouseCaptured();
+ if (bMouseCaptured)
+ pWin->ReleaseMouse();
+ bHaveName = ERRCODE_NONE == pFileDlg->Execute();
+ if (bMouseCaptured)
+ pWin->CaptureMouse();
+ }
+#endif
+ if (bHaveName)
+ {
+
+ OUString aFileName, aFilterName;
+ if ( pName )
+ {
+ aFileName = pName->GetValue();
+ const SfxStringItem* pFilter = rReq.GetArg<SfxStringItem>(FN_PARAM_FILTER);
+ if ( pFilter )
+ aFilterName = pFilter->GetValue();
+ }
+#if HAVE_FEATURE_DESKTOP
+ else
+ {
+ aFileName = pFileDlg->GetPath();
+ aFilterName = pFileDlg->GetCurrentFilter();
+ rReq.AppendItem( SfxStringItem( SID_INSERT_GRAPHIC, aFileName ) );
+ rReq.AppendItem( SfxStringItem( FN_PARAM_FILTER, aFilterName ) );
+
+ bool bAsLink = false;
+ if(nHtmlMode & HTMLMODE_ON)
+ bAsLink = true;
+ else
+ {
+ try
+ {
+ Any aVal = xCtrlAcc->getValue( ExtendedFilePickerElementIds::CHECKBOX_LINK, 0);
+ OSL_ENSURE(aVal.hasValue(), "Value CBX_INSERT_AS_LINK not found");
+ bAsLink = !aVal.hasValue() || *o3tl::doAccess<bool>(aVal);
+ Any aTemplateValue = xCtrlAcc->getValue(
+ ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE,
+ ListboxControlActions::GET_SELECTED_ITEM );
+ OUString sTmpl;
+ aTemplateValue >>= sTmpl;
+ rReq.AppendItem( SfxStringItem( FN_PARAM_2, sTmpl) );
+ }
+ catch (const Exception&)
+ {
+ OSL_FAIL("control access failed");
+ }
+ }
+ rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bAsLink ) );
+ }
+ const SfxBoolItem* pAsLink = rReq.GetArg<SfxBoolItem>(FN_PARAM_1);
+ const SfxStringItem* pStyle = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
+#endif
+
+ bool bAsLink = false;
+
+#if HAVE_FEATURE_DESKTOP
+ if( nHtmlMode & HTMLMODE_ON )
+ bAsLink = true;
+ else
+ {
+ if ( rReq.GetArgs() )
+ {
+ if ( pAsLink )
+ bAsLink = pAsLink->GetValue();
+ if ( pStyle && !pStyle->GetValue().isEmpty() )
+ sGraphicFormat = pStyle->GetValue();
+ }
+ else
+ {
+ Any aVal = xCtrlAcc->getValue( ExtendedFilePickerElementIds::CHECKBOX_LINK, 0);
+ OSL_ENSURE(aVal.hasValue(), "Value CBX_INSERT_AS_LINK not found");
+ bAsLink = !aVal.hasValue() || *o3tl::doAccess<bool>(aVal);
+ Any aTemplateValue = xCtrlAcc->getValue(
+ ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE,
+ ListboxControlActions::GET_SELECTED_ITEM );
+ OUString sTmpl;
+ aTemplateValue >>= sTmpl;
+ if( !sTmpl.isEmpty() )
+ sGraphicFormat = sTmpl;
+ rReq.AppendItem( SfxStringItem( FN_PARAM_2, sGraphicFormat ) );
+ rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bAsLink ) );
+ }
+
+ // really store as link only?
+ if( bAsLink && officecfg::Office::Common::Misc::ShowLinkWarningDialog::get() )
+ {
+ SvxLinkWarningDialog aWarnDlg(GetFrameWeld(), pFileDlg->GetPath());
+ if (aWarnDlg.run() != RET_OK)
+ bAsLink=false; // don't store as link
+ }
+ }
+#endif
+
+ SwWrtShell& rSh = GetWrtShell();
+ rSh.LockPaint(LockPaintReason::InsertGraphic);
+ rSh.StartAction();
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, SwResId(STR_GRAPHIC_DEFNAME));
+
+ // #i123922# determine if we really want to insert or replace the graphic at a selected object
+ const bool bReplaceMode(rSh.HasSelection() && SelectionType::Frame == rSh.GetSelectionType());
+
+ rSh.StartUndo(SwUndoId::INSERT, &aRewriter);
+
+ ErrCode nError = InsertGraphic( aFileName, aFilterName, bAsLink, &GraphicFilter::GetGraphicFilter() );
+
+ // format not equal to current filter (with autodetection)
+ if( nError == ERRCODE_GRFILTER_FORMATERROR )
+ nError = InsertGraphic( aFileName, OUString(), bAsLink, &GraphicFilter::GetGraphicFilter() );
+
+ // #i123922# no new FrameFormat for replace mode, only when new object was created,
+ // else this would reset the current setting for the frame holding the graphic
+ if ( !bReplaceMode && rSh.IsFrameSelected() )
+ {
+ SwFrameFormat* pFormat = pDoc->FindFrameFormatByName( sGraphicFormat );
+ if(!pFormat)
+ pFormat = pDoc->MakeFrameFormat(sGraphicFormat,
+ pDocShell->GetDoc()->GetDfltFrameFormat(),
+ true, false);
+ rSh.SetFrameFormat( pFormat );
+ }
+
+ TranslateId pResId;
+ if( nError == ERRCODE_GRFILTER_OPENERROR )
+ pResId = STR_GRFILTER_OPENERROR;
+ else if( nError == ERRCODE_GRFILTER_IOERROR )
+ pResId = STR_GRFILTER_IOERROR;
+ else if( nError ==ERRCODE_GRFILTER_FORMATERROR )
+ pResId = STR_GRFILTER_FORMATERROR;
+ else if( nError ==ERRCODE_GRFILTER_VERSIONERROR )
+ pResId = STR_GRFILTER_VERSIONERROR;
+ else if( nError ==ERRCODE_GRFILTER_FILTERERROR )
+ pResId = STR_GRFILTER_FILTERERROR;
+ else if( nError ==ERRCODE_GRFILTER_TOOBIG )
+ pResId = STR_GRFILTER_TOOBIG;
+
+ rSh.EndAction();
+ rSh.UnlockPaint();
+ if (pResId)
+ {
+ if( bShowError )
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(pResId)));
+ xInfoBox->run();
+ }
+ rReq.Ignore();
+ }
+ else
+ {
+ // set the specific graphic attributes to the graphic
+ bReturn = true;
+ AutoCaption( GRAPHIC_CAP );
+ rReq.Done();
+ }
+
+ rSh.EndUndo(); // due to possible change of Shell
+ }
+
+ return bReturn;
+}
+
+void SwView::Execute(SfxRequest &rReq)
+{
+ const sal_uInt16 nSlot = rReq.GetSlot();
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem;
+ bool bIgnore = false;
+ switch( nSlot )
+ {
+ case SID_CREATE_SW_DRAWVIEW:
+ m_pWrtShell->getIDocumentDrawModelAccess().GetOrCreateDrawModel();
+ break;
+
+ case FN_LINE_NUMBERING_DLG:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateVclSwViewDialog(*this));
+ VclAbstractDialog::AsyncContext aContext;
+ aContext.maEndDialogFn = [](sal_Int32){};
+ pDlg->StartExecuteAsync(aContext);
+ break;
+ }
+ case FN_EDIT_LINK_DLG:
+ EditLinkDlg();
+ break;
+ case SID_REFRESH_VIEW:
+ GetEditWin().Invalidate();
+ m_pWrtShell->Reformat();
+ break;
+ case FN_PAGEUP:
+ case FN_PAGEUP_SEL:
+ case FN_PAGEDOWN:
+ case FN_PAGEDOWN_SEL:
+ {
+ tools::Rectangle aVis( GetVisArea() );
+ SwEditWin& rTmpWin = GetEditWin();
+ if ( FN_PAGEUP == nSlot || FN_PAGEUP_SEL == nSlot )
+ PageUpCursor(FN_PAGEUP_SEL == nSlot);
+ else
+ PageDownCursor(FN_PAGEDOWN_SEL == nSlot);
+
+ rReq.SetReturnValue(SfxBoolItem(nSlot,
+ aVis != GetVisArea()));
+ //#i42732# - notify the edit window that from now on we do not use the input language
+ rTmpWin.SetUseInputLanguage( false );
+ }
+ break;
+ case SID_ZOOM_IN:
+ case SID_ZOOM_OUT:
+ {
+ sal_uInt16 nFact = m_pWrtShell->GetViewOptions()->GetZoom();
+ if (SID_ZOOM_IN == nSlot)
+ nFact = basegfx::zoomtools::zoomIn(nFact);
+ else
+ nFact = basegfx::zoomtools::zoomOut(nFact);
+ SetZoom(SvxZoomType::PERCENT, nFact);
+ }
+ break;
+ case FN_TO_PREV_PAGE:
+ case FN_TO_NEXT_PAGE:
+ {
+ sal_uInt16 nPage = 0;
+ if (m_pWrtShell->IsCursorVisible())
+ nPage = m_pWrtShell->GetCursor()->GetPageNum();
+ else
+ {
+ SwFrame* pPageFrame = m_pWrtShell->Imp()->GetFirstVisPage(m_pWrtShell->GetOut());
+ if (pPageFrame)
+ nPage = pPageFrame->GetPhyPageNum();
+ }
+ if (nPage != 0)
+ {
+ sal_uInt16 nOldPage(nPage);
+ if (FN_TO_PREV_PAGE == nSlot && nPage > 1)
+ nPage--;
+ else if (FN_TO_NEXT_PAGE == nSlot && nPage < m_pWrtShell->GetPageCount())
+ nPage++;
+ if (nPage != nOldPage)
+ {
+ m_pWrtShell->LockPaint(LockPaintReason::GotoPage);
+ if (IsDrawMode())
+ LeaveDrawCreate();
+ m_pWrtShell->EnterStdMode();
+ m_pWrtShell->GotoPage(nPage, true);
+ // set visible area (borrowed from SwView::PhyPageUp/Down)
+ const Point aPt(m_aVisArea.Left(), m_pWrtShell->GetPagePos(nPage).Y());
+ Point aAlPt(AlignToPixel(aPt));
+ if(aPt.Y() != aAlPt.Y())
+ aAlPt.AdjustY(3 * GetEditWin().PixelToLogic(Size(0, 1)).Height());
+ SetVisArea(aAlPt);
+ m_pWrtShell->UnlockPaint();
+ }
+ }
+ }
+ break;
+ case FN_SELECTION_CYCLE:
+ {
+ if (m_pWrtShell->IsSelFrameMode())
+ break;
+ if (!m_pWrtShell->IsStdMode())
+ m_pWrtShell->EnterStdMode();
+ SwShellCursor *pCursor = m_pWrtShell->SwCursorShell::GetCursor_();
+ Point CurrMarkPt = pCursor->GetMkPos();
+ Point CurrPointPt = pCursor->GetPtPos();
+ sal_uInt16 nStep = m_aSelectCycle.nStep;
+ if (nStep && (CurrMarkPt != m_aSelectCycle.m_MarkPt || CurrPointPt != m_aSelectCycle.m_PointPt))
+ nStep = 0;
+ switch(nStep)
+ {
+ case 0:
+ m_aSelectCycle.m_pInitialCursor = CurrPointPt;
+ m_pWrtShell->SwCursorShell::ClearMark();
+ m_pWrtShell->SelWrd(&CurrPointPt);
+ break;
+ case 1:
+ m_pWrtShell->SelSentence(&CurrPointPt);
+ break;
+ case 2:
+ m_pWrtShell->SelPara(&CurrPointPt);
+ break;
+ case 3:
+ m_pWrtShell->SwCursorShell::ClearMark();
+ m_pWrtShell->SwCursorShell::SetCursor(m_aSelectCycle.m_pInitialCursor);
+ break;
+ }
+ nStep++;
+ nStep %= 4;
+ pCursor = m_pWrtShell->SwCursorShell::GetCursor_();
+ m_aSelectCycle.m_MarkPt = pCursor->GetMkPos();
+ m_aSelectCycle.m_PointPt = pCursor->GetPtPos();
+ m_aSelectCycle.nStep = nStep;
+ }
+ break;
+ case FN_REDLINE_ON:
+ {
+ if( pArgs &&
+ SfxItemState::SET == pArgs->GetItemState(nSlot, false, &pItem ))
+ {
+ IDocumentRedlineAccess& rIDRA = m_pWrtShell->getIDocumentRedlineAccess();
+ Sequence <sal_Int8> aPasswd = rIDRA.GetRedlinePassword();
+ if( aPasswd.hasElements() )
+ {
+ OSL_ENSURE( !static_cast<const SfxBoolItem*>(pItem)->GetValue(), "SwView::Execute(): password set and redlining off doesn't match!" );
+
+ // xmlsec05: new password dialog
+ SfxPasswordDialog aPasswdDlg(GetFrameWeld());
+ aPasswdDlg.SetMinLen(1);
+ //#i69751# the result of Execute() can be ignored
+ (void)aPasswdDlg.run();
+ OUString sNewPasswd(aPasswdDlg.GetPassword());
+
+ // password verification
+ bool bPasswordOk = false;
+ if (aPasswd.getLength() == 1 && aPasswd[0] == 1)
+ {
+ // dummy RedlinePassword from OOXML import: get real password info
+ // from the grab-bag to verify the password
+ const css::uno::Sequence< css::beans::PropertyValue > aDocumentProtection =
+ static_cast<SfxObjectShell*>(GetDocShell())->
+ GetDocumentProtectionFromGrabBag();
+
+ bPasswordOk =
+ // password is ok, if there is no DocumentProtection in the GrabBag,
+ // i.e. the dummy RedlinePassword imported from an OpenDocument file
+ !aDocumentProtection.hasElements() ||
+ // verify password with the password info imported from OOXML
+ ::comphelper::DocPasswordHelper::IsModifyPasswordCorrect(sNewPasswd,
+ ::comphelper::DocPasswordHelper::ConvertPasswordInfo ( aDocumentProtection ) );
+ }
+ else
+ {
+ // the simplified RedlinePassword
+ Sequence <sal_Int8> aNewPasswd = rIDRA.GetRedlinePassword();
+ SvPasswordHelper::GetHashPassword( aNewPasswd, sNewPasswd );
+ bPasswordOk = SvPasswordHelper::CompareHashPassword(aPasswd, sNewPasswd);
+ }
+
+ if (bPasswordOk)
+ rIDRA.SetRedlinePassword(Sequence <sal_Int8> ());
+ else
+ { // xmlsec05: message box for wrong password
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Info, VclButtonsType::Ok,
+ SfxResId(RID_SVXSTR_INCORRECT_PASSWORD)));
+ xInfoBox->run();
+ break;
+ }
+ }
+
+ SwDocShell* pDocShell = GetDocShell();
+ pDocShell->SetChangeRecording( static_cast<const SfxBoolItem*>(pItem)->GetValue(), /*bLockAllViews=*/true );
+
+ // Notify all view shells of this document, as the track changes mode is document-global.
+ for (SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst(pDocShell); pViewFrame; pViewFrame = SfxViewFrame::GetNext(*pViewFrame, pDocShell))
+ {
+ pViewFrame->GetBindings().Invalidate(FN_REDLINE_ON);
+ pViewFrame->GetBindings().Update(FN_REDLINE_ON);
+ }
+ }
+ }
+ break;
+ case FN_REDLINE_PROTECT :
+ {
+ IDocumentRedlineAccess& rIDRA = m_pWrtShell->getIDocumentRedlineAccess();
+ Sequence <sal_Int8> aPasswd = rIDRA.GetRedlinePassword();
+ if( pArgs && SfxItemState::SET == pArgs->GetItemState(nSlot, false, &pItem )
+ && static_cast<const SfxBoolItem*>(pItem)->GetValue() == aPasswd.hasElements() )
+ break;
+
+ // xmlsec05: new password dialog
+ // message box for wrong password
+ SfxPasswordDialog aPasswdDlg(GetFrameWeld());
+ aPasswdDlg.SetMinLen(1);
+ if (!aPasswd.hasElements())
+ aPasswdDlg.ShowExtras(SfxShowExtras::CONFIRM);
+ if (aPasswdDlg.run())
+ {
+ RedlineFlags nOn = RedlineFlags::On;
+ OUString sNewPasswd(aPasswdDlg.GetPassword());
+ Sequence <sal_Int8> aNewPasswd =
+ rIDRA.GetRedlinePassword();
+ SvPasswordHelper::GetHashPassword( aNewPasswd, sNewPasswd );
+ if(!aPasswd.hasElements())
+ {
+ rIDRA.SetRedlinePassword(aNewPasswd);
+ }
+ else if(SvPasswordHelper::CompareHashPassword(aPasswd, sNewPasswd))
+ {
+ rIDRA.SetRedlinePassword(Sequence <sal_Int8> ());
+ nOn = RedlineFlags::NONE;
+ }
+ const RedlineFlags nMode = rIDRA.GetRedlineFlags();
+ m_pWrtShell->SetRedlineFlagsAndCheckInsMode( (nMode & ~RedlineFlags::On) | nOn);
+ rReq.AppendItem( SfxBoolItem( FN_REDLINE_PROTECT, !(nMode&RedlineFlags::On) ) );
+ }
+ else
+ bIgnore = true;
+ }
+ break;
+ case FN_REDLINE_SHOW:
+
+ if( pArgs &&
+ SfxItemState::SET == pArgs->GetItemState(nSlot, false, &pItem))
+ {
+ // tdf#125754 avoid recursive layout
+ // because all views share the layout, have to use AllAction
+ const bool bShow = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ m_pWrtShell->StartAllAction();
+ // always show redline insertions in Hide Changes mode
+ if ( m_pWrtShell->GetViewOptions()->IsShowChangesInMargin() &&
+ m_pWrtShell->GetViewOptions()->IsShowChangesInMargin2() )
+ {
+ GetDocShell()->GetDoc()->GetDocumentRedlineManager().HideAll(/*bDeletion=*/!bShow);
+ }
+ m_pWrtShell->GetLayout()->SetHideRedlines( !bShow );
+ m_pWrtShell->EndAllAction();
+ if (m_pWrtShell->IsRedlineOn())
+ m_pWrtShell->SetInsMode();
+ }
+ break;
+ case FN_MAILMERGE_SENDMAIL_CHILDWINDOW:
+ case FN_REDLINE_ACCEPT:
+ GetViewFrame().ToggleChildWindow(nSlot);
+ break;
+ case FN_REDLINE_ACCEPT_DIRECT:
+ case FN_REDLINE_REJECT_DIRECT:
+ case FN_REDLINE_ACCEPT_TONEXT:
+ case FN_REDLINE_REJECT_TONEXT:
+ {
+ SwDoc *pDoc = m_pWrtShell->GetDoc();
+ SwPaM *pCursor = m_pWrtShell->GetCursor();
+ const SwRedlineTable& rRedlineTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
+ SwRedlineTable::size_type nRedline = SwRedlineTable::npos;
+ if (pArgs && pArgs->GetItemState(nSlot, false, &pItem) == SfxItemState::SET)
+ {
+ const sal_Int64 nChangeId = static_cast<const SfxUInt32Item*>(pItem)->GetValue();
+ for (SwRedlineTable::size_type i = 0; i < rRedlineTable.size(); ++i)
+ {
+ if (nChangeId == rRedlineTable[i]->GetId())
+ nRedline = i;
+ }
+ }
+
+ if( pCursor->HasMark() && nRedline == SwRedlineTable::npos)
+ {
+ bool bAccept = FN_REDLINE_ACCEPT_DIRECT == nSlot || FN_REDLINE_ACCEPT_TONEXT == nSlot;
+ SwUndoId eUndoId = bAccept ? SwUndoId::ACCEPT_REDLINE : SwUndoId::REJECT_REDLINE;
+ SwWrtShell& rSh = GetWrtShell();
+ SwRewriter aRewriter;
+ bool bTableSelection = rSh.IsTableMode();
+ if ( bTableSelection )
+ {
+ aRewriter.AddRule(UndoArg1, SwResId( STR_REDLINE_TABLECHG ));
+ rSh.StartUndo( eUndoId, &aRewriter);
+ }
+ if ( bAccept )
+ m_pWrtShell->AcceptRedlinesInSelection();
+ else
+ m_pWrtShell->RejectRedlinesInSelection();
+ if ( bTableSelection )
+ rSh.EndUndo( eUndoId, &aRewriter);
+ }
+ else
+ {
+ // We check for a redline at the start of the selection/cursor, not the point.
+ // This ensures we work properly with FN_REDLINE_NEXT_CHANGE, which leaves the
+ // point at the *end* of the redline and the mark at the start (so GetRedline
+ // would return NULL if called on the point)
+ const SwRangeRedline* pRedline = nullptr;
+ if (nRedline != SwRedlineTable::npos)
+ {
+ // A redline was explicitly requested by specifying an
+ // index, don't guess based on the cursor position.
+
+ if (nRedline < rRedlineTable.size())
+ pRedline = rRedlineTable[nRedline];
+ }
+ else
+ pRedline = pDoc->getIDocumentRedlineAccess().GetRedline(*pCursor->Start(), &nRedline);
+
+ // accept or reject table row deletion or insertion
+ bool bTableChange = false;
+ if ( !pRedline && m_pWrtShell->IsCursorInTable() )
+ {
+ nRedline = 0;
+ auto pTabBox = pCursor->Start()->GetNode().GetTableBox();
+ auto pTabLine = pTabBox->GetUpper();
+ const SwTableNode* pTableNd = pCursor->Start()->GetNode().FindTableNode();
+
+ if ( RedlineType::None != pTabLine->GetRedlineType() )
+ {
+ nRedline = pTabLine->UpdateTextChangesOnly(nRedline);
+
+ if ( nRedline != SwRedlineTable::npos )
+ {
+ bTableChange = true;
+
+ SwWrtShell& rSh = GetWrtShell();
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UndoArg1, SwResId(
+ rRedlineTable[nRedline]->GetType() == RedlineType::Delete
+ ? STR_REDLINE_TABLE_ROW_DELETE
+ : STR_REDLINE_TABLE_ROW_INSERT ));
+
+ SwUndoId eUndoId =
+ (FN_REDLINE_ACCEPT_DIRECT == nSlot || FN_REDLINE_ACCEPT_TONEXT == nSlot)
+ ? SwUndoId::ACCEPT_REDLINE
+ : SwUndoId::REJECT_REDLINE;
+
+ rSh.StartUndo( eUndoId, &aRewriter);
+ while ( nRedline != SwRedlineTable::npos && nRedline < rRedlineTable.size() )
+ {
+ pRedline = rRedlineTable[nRedline];
+
+ // until next redline is not in the same row
+ SwTableBox* pTableBox = pRedline->Start()->GetNode().GetTableBox();
+ if ( !pTableBox || pTableBox->GetUpper() != pTabLine )
+ break;
+
+ if (FN_REDLINE_ACCEPT_DIRECT == nSlot || FN_REDLINE_ACCEPT_TONEXT == nSlot)
+ m_pWrtShell->AcceptRedline(nRedline);
+ else
+ m_pWrtShell->RejectRedline(nRedline);
+ }
+ rSh.EndUndo( eUndoId, &aRewriter);
+ }
+ }
+ else if ( RedlineType::None != pTabBox->GetRedlineType() )
+ {
+ nRedline = pTabBox->GetRedline();
+
+ if ( nRedline != SwRedlineTable::npos )
+ {
+ bTableChange = true;
+
+ SwWrtShell& rSh = GetWrtShell();
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UndoArg1, SwResId(
+ rRedlineTable[nRedline]->GetType() == RedlineType::Delete
+ ? STR_REDLINE_TABLE_COLUMN_DELETE
+ : STR_REDLINE_TABLE_COLUMN_INSERT ));
+
+ SwUndoId eUndoId =
+ (FN_REDLINE_ACCEPT_DIRECT == nSlot || FN_REDLINE_ACCEPT_TONEXT == nSlot)
+ ? SwUndoId::ACCEPT_REDLINE
+ : SwUndoId::REJECT_REDLINE;
+
+ // change only the cells with the same data
+ SwRedlineData aData(rRedlineTable[nRedline]->GetRedlineData(0));
+
+ // start from the first redline of the table to handle all the
+ // cells of the changed column(s)
+ while ( nRedline )
+ {
+ pRedline = rRedlineTable[nRedline-1];
+ SwTableBox* pTableBox = pRedline->Start()->GetNode().GetTableBox();
+ SwTableNode* pTableNode = pRedline->Start()->GetNode().FindTableNode();
+
+ // previous redline is not in the same table
+ if ( !pTableBox || pTableNode != pTableNd )
+ break;
+
+ --nRedline;
+ }
+
+ rSh.StartUndo( eUndoId, &aRewriter);
+ while ( nRedline != SwRedlineTable::npos && nRedline < rRedlineTable.size() )
+ {
+ pRedline = rRedlineTable[nRedline];
+
+ // until next redline is not in the same table
+ SwTableBox* pTableBox = pRedline->Start()->GetNode().GetTableBox();
+ SwTableNode* pTableNode = pRedline->Start()->GetNode().FindTableNode();
+ if ( !pTableBox || pTableNode != pTableNd )
+ break;
+
+ // skip cells which are not from the same author, same type change
+ // or timestamp, i.e. keep only the cells of the same tracked
+ // column insertion or deletion
+ if ( !pRedline->GetRedlineData(0).CanCombine(aData) ||
+ // not a tracked cell change
+ RedlineType::None == pTableBox->GetRedlineType() )
+ {
+ ++nRedline;
+ continue;
+ }
+
+ if (FN_REDLINE_ACCEPT_DIRECT == nSlot || FN_REDLINE_ACCEPT_TONEXT == nSlot)
+ m_pWrtShell->AcceptRedline(nRedline);
+ else
+ m_pWrtShell->RejectRedline(nRedline);
+ }
+ rSh.EndUndo( eUndoId, &aRewriter);
+ }
+ }
+ }
+ else
+ {
+ assert(pRedline != nullptr);
+ }
+
+ if (pRedline && !bTableChange)
+ {
+ if (FN_REDLINE_ACCEPT_DIRECT == nSlot || FN_REDLINE_ACCEPT_TONEXT == nSlot)
+ m_pWrtShell->AcceptRedline(nRedline);
+ else
+ m_pWrtShell->RejectRedline(nRedline);
+ }
+ }
+ if (FN_REDLINE_ACCEPT_TONEXT == nSlot || FN_REDLINE_REJECT_TONEXT == nSlot)
+ {
+ // Go to next change after accepting or rejecting one (tdf#101977)
+ GetViewFrame().GetDispatcher()->Execute(FN_REDLINE_NEXT_CHANGE, SfxCallMode::ASYNCHRON);
+ }
+ }
+ break;
+
+ case FN_REDLINE_NEXT_CHANGE:
+ {
+ // If a parameter is provided, try going to the nth change, not to
+ // the next one.
+ SwDoc* pDoc = m_pWrtShell->GetDoc();
+ const SwRedlineTable& rRedlineTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
+ SwRedlineTable::size_type nRedline = SwRedlineTable::npos;
+ if (pArgs && pArgs->GetItemState(nSlot, false, &pItem) == SfxItemState::SET)
+ {
+ const sal_uInt32 nChangeId = static_cast<const SfxUInt32Item*>(pItem)->GetValue();
+ for (SwRedlineTable::size_type i = 0; i < rRedlineTable.size(); ++i)
+ {
+ if (nChangeId == rRedlineTable[i]->GetId())
+ nRedline = i;
+ }
+ }
+
+ const SwRangeRedline *pNext = nullptr;
+ if (nRedline < rRedlineTable.size())
+ pNext = m_pWrtShell->GotoRedline(nRedline, true);
+ else
+ pNext = m_pWrtShell->SelNextRedline();
+
+ if (pNext)
+ {
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ sal_uInt32 nRedlineId = pNext->GetId();
+ OString aPayload(".uno:CurrentTrackedChangeId=" + OString::number(nRedlineId));
+ libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED, aPayload);
+ }
+
+ m_pWrtShell->SetInSelect();
+ }
+
+ }
+ break;
+
+ case FN_REDLINE_PREV_CHANGE:
+ {
+ const SwRangeRedline *pPrev = m_pWrtShell->SelPrevRedline();
+
+ if (pPrev)
+ {
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ sal_uInt32 nRedlineId = pPrev->GetId();
+ OString aPayload(".uno:CurrentTrackedChangeId=" + OString::number(nRedlineId));
+ libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED, aPayload);
+ }
+
+ m_pWrtShell->SetInSelect();
+ }
+ }
+ break;
+
+ case SID_DOCUMENT_COMPARE:
+ case SID_DOCUMENT_MERGE:
+ {
+ OUString sFileName, sFilterName;
+ sal_Int16 nVersion = 0;
+ bool bHasFileName = false;
+ m_pViewImpl->SetParam( 0 );
+ bool bNoAcceptDialog = false;
+
+ if( pArgs )
+ {
+ if( const SfxStringItem* pFileItem = pArgs->GetItemIfSet( SID_FILE_NAME, false ))
+ sFileName = pFileItem->GetValue();
+ bHasFileName = !sFileName.isEmpty();
+
+ if( const SfxStringItem* pFilterNameItem = pArgs->GetItemIfSet( SID_FILTER_NAME, false ))
+ sFilterName = pFilterNameItem->GetValue();
+
+ if( const SfxInt16Item* pVersionItem = pArgs->GetItemIfSet( SID_VERSION, false ))
+ {
+ nVersion = pVersionItem->GetValue();
+ m_pViewImpl->SetParam( nVersion );
+ }
+ if( const SfxBoolItem* pDialogItem = pArgs->GetItemIfSet( SID_NO_ACCEPT_DIALOG, false ))
+ {
+ bNoAcceptDialog = pDialogItem->GetValue();
+ }
+ }
+
+ m_pViewImpl->InitRequest( rReq );
+ tools::Long nFound = InsertDoc( nSlot, sFileName, sFilterName, nVersion );
+
+ if ( bHasFileName )
+ {
+ rReq.SetReturnValue( SfxInt32Item( nSlot, nFound ));
+
+ if (nFound > 0 && !bNoAcceptDialog) // show Redline browser
+ {
+ SfxViewFrame& rVFrame = GetViewFrame();
+ rVFrame.ShowChildWindow(FN_REDLINE_ACCEPT);
+
+ // re-initialize the Redline dialog
+ const sal_uInt16 nId = SwRedlineAcceptChild::GetChildWindowId();
+ SwRedlineAcceptChild *pRed = static_cast<SwRedlineAcceptChild*>(
+ rVFrame.GetChildWindow(nId));
+ if (pRed)
+ pRed->ReInitDlg(GetDocShell());
+ }
+ }
+ else
+ bIgnore = true;
+ }
+ break;
+ case FN_SYNC_LABELS:
+ GetViewFrame().ShowChildWindow(nSlot);
+ break;
+ case FN_ESCAPE:
+ {
+ if ( m_pWrtShell->HasDrawViewDrag() )
+ {
+ m_pWrtShell->BreakDrag();
+ m_pWrtShell->EnterSelFrameMode();
+ }
+ else if ( m_pWrtShell->IsDrawCreate() )
+ {
+ GetDrawFuncPtr()->BreakCreate();
+ AttrChangedNotify(nullptr); // shell change if needed
+ }
+ else if ( m_pWrtShell->HasSelection() || IsDrawMode() )
+ {
+ SdrView *pSdrView = m_pWrtShell->HasDrawView() ? m_pWrtShell->GetDrawView() : nullptr;
+ if(pSdrView && pSdrView->AreObjectsMarked() &&
+ pSdrView->GetHdlList().GetFocusHdl())
+ {
+ const_cast<SdrHdlList&>(pSdrView->GetHdlList()).ResetFocusHdl();
+ }
+ else
+ {
+ if(pSdrView)
+ {
+ LeaveDrawCreate();
+ Point aPt(LONG_MIN, LONG_MIN);
+ //go out of the frame
+ m_pWrtShell->SelectObj(aPt, SW_LEAVE_FRAME);
+ SfxBindings& rBind = GetViewFrame().GetBindings();
+ rBind.Invalidate( SID_ATTR_SIZE );
+ }
+ m_pWrtShell->EnterStdMode();
+ AttrChangedNotify(nullptr); // shell change if necessary
+ }
+ }
+ else if ( GetEditWin().GetApplyTemplate() )
+ {
+ GetEditWin().SetApplyTemplate(SwApplyTemplate());
+ }
+ else if( static_cast<SfxObjectShell*>(GetDocShell())->IsInPlaceActive() )
+ {
+ Escape();
+ }
+ else if ( GetEditWin().IsChainMode() )
+ {
+ GetEditWin().SetChainMode( false );
+ }
+ else if( m_pWrtShell->GetFlyFrameFormat() )
+ {
+ const SwFrameFormat* pFormat = m_pWrtShell->GetFlyFrameFormat();
+ if(m_pWrtShell->GotoFly( pFormat->GetName(), FLYCNTTYPE_FRM ))
+ {
+ m_pWrtShell->HideCursor();
+ m_pWrtShell->EnterSelFrameMode();
+ }
+ }
+ else
+ {
+ SfxBoolItem aItem( SID_WIN_FULLSCREEN, false );
+ GetViewFrame().GetDispatcher()->ExecuteList(SID_WIN_FULLSCREEN,
+ SfxCallMode::RECORD, { &aItem });
+ bIgnore = true;
+ }
+ }
+ break;
+ case SID_ATTR_BORDER_INNER:
+ case SID_ATTR_BORDER_OUTER:
+ case SID_ATTR_BORDER_SHADOW:
+ if(pArgs)
+ m_pWrtShell->SetAttrSet(*pArgs);
+ break;
+
+ case SID_ATTR_PAGE:
+ case SID_ATTR_PAGE_SIZE:
+ case SID_ATTR_PAGE_MAXSIZE:
+ case SID_ATTR_PAGE_PAPERBIN:
+ case SID_ATTR_PAGE_EXT1:
+ case FN_PARAM_FTN_INFO:
+ {
+ if(pArgs)
+ {
+ const size_t nCurIdx = m_pWrtShell->GetCurPageDesc();
+ SwPageDesc aPageDesc( m_pWrtShell->GetPageDesc( nCurIdx ) );
+ ::ItemSetToPageDesc( *pArgs, aPageDesc );
+ // change the descriptor of the core
+ m_pWrtShell->ChgPageDesc( nCurIdx, aPageDesc );
+ }
+ }
+ break;
+ case FN_GOTO_PAGE:
+ {
+ SwGotoPageDlg aDlg(GetViewFrame().GetFrameWeld(), GetViewFrame().GetBindings());
+ if (aDlg.run() == RET_OK)
+ GetWrtShell().GotoPage(aDlg.GetPageSelection(), true);
+ }
+ break;
+ case FN_EDIT_CURRENT_TOX:
+ {
+ GetViewFrame().GetDispatcher()->Execute(
+ FN_INSERT_MULTI_TOX, SfxCallMode::ASYNCHRON);
+ }
+ break;
+ case FN_UPDATE_CUR_TOX:
+ {
+ const SwTOXBase* pBase = m_pWrtShell->GetCurTOX();
+ if(pBase)
+ {
+ // tdf#106374: don't jump view on the update
+ const bool bWasLocked = m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView(true);
+ m_pWrtShell->StartAction();
+ if(TOX_INDEX == pBase->GetType())
+ m_pWrtShell->ApplyAutoMark();
+ m_pWrtShell->UpdateTableOf( *pBase );
+ m_pWrtShell->EndAction();
+ if (!bWasLocked)
+ m_pWrtShell->LockView(false);
+ }
+ }
+ break;
+ case FN_UPDATE_TOX:
+ {
+ m_pWrtShell->StartAction();
+ m_pWrtShell->EnterStdMode();
+ bool bOldCursorInReadOnly = m_pWrtShell->IsReadOnlyAvailable();
+ m_pWrtShell->SetReadOnlyAvailable( true );
+
+ for( int i = 0; i < 2; ++i )
+ {
+ if( m_pWrtShell->GetTOXCount() == 1 )
+ ++i;
+
+ while( m_pWrtShell->GotoPrevTOXBase() )
+ ; // jump to the first "table of ..."
+
+ // if we are not in one, jump to next
+ const SwTOXBase* pBase = m_pWrtShell->GetCurTOX();
+ if( !pBase )
+ {
+ if (m_pWrtShell->GotoNextTOXBase())
+ pBase = m_pWrtShell->GetCurTOX();
+ }
+
+ bool bAutoMarkApplied = false;
+ while( pBase )
+ {
+ if(TOX_INDEX == pBase->GetType() && !bAutoMarkApplied)
+ {
+ m_pWrtShell->ApplyAutoMark();
+ bAutoMarkApplied = true;
+ }
+ // pBase is needed only for the interface. Should be changed in future! (JP 1996)
+ m_pWrtShell->UpdateTableOf( *pBase );
+
+ if( m_pWrtShell->GotoNextTOXBase() )
+ pBase = m_pWrtShell->GetCurTOX();
+ else
+ pBase = nullptr;
+ }
+ }
+ m_pWrtShell->SetReadOnlyAvailable( bOldCursorInReadOnly );
+ m_pWrtShell->EndAction();
+ }
+ break;
+ case SID_ATTR_BRUSH:
+ {
+ if(pArgs && SfxItemState::SET == pArgs->GetItemState(RES_BACKGROUND, false, &pItem))
+ {
+ const size_t nCurIdx = m_pWrtShell->GetCurPageDesc();
+ SwPageDesc aDesc( m_pWrtShell->GetPageDesc( nCurIdx ));
+ SwFrameFormat& rMaster = aDesc.GetMaster();
+ rMaster.SetFormatAttr(*pItem);
+ m_pWrtShell->ChgPageDesc( nCurIdx, aDesc);
+ }
+ }
+ break;
+ case SID_CLEARHISTORY:
+ {
+ m_pWrtShell->DelAllUndoObj();
+ }
+ break;
+ case SID_UNDO:
+ {
+ m_pShell->ExecuteSlot(rReq);
+ }
+ break;
+#if defined(_WIN32) || defined UNX
+ case SID_TWAIN_SELECT:
+ case SID_TWAIN_TRANSFER:
+ GetViewImpl()->ExecuteScan( rReq );
+ break;
+#endif
+
+ case SID_ATTR_DEFTABSTOP:
+ {
+ const SfxUInt16Item* pTabStopItem = nullptr;
+ if(pArgs && (pTabStopItem = pArgs->GetItemIfSet(SID_ATTR_DEFTABSTOP, false)))
+ {
+ SvxTabStopItem aDefTabs( 0, 0, SvxTabAdjust::Default, RES_PARATR_TABSTOP );
+ const sal_uInt16 nTab = pTabStopItem->GetValue();
+ MakeDefTabs( nTab, aDefTabs );
+ m_pWrtShell->SetDefault( aDefTabs );
+ }
+ }
+ break;
+ case SID_ATTR_LANGUAGE :
+ {
+ const SvxLanguageItem* pLangItem;
+ if(pArgs && (pLangItem = pArgs->GetItemIfSet(SID_ATTR_LANGUAGE, false)))
+ {
+ SvxLanguageItem aLang(pLangItem->GetLanguage(), RES_CHRATR_LANGUAGE);
+ m_pWrtShell->SetDefault( aLang );
+ lcl_SetAllTextToDefaultLanguage( *m_pWrtShell, RES_CHRATR_LANGUAGE );
+ }
+ }
+ break;
+ case SID_ATTR_CHAR_CTL_LANGUAGE:
+ if(pArgs && SfxItemState::SET == pArgs->GetItemState(RES_CHRATR_CTL_LANGUAGE, false, &pItem))
+ {
+ m_pWrtShell->SetDefault( *pItem );
+ lcl_SetAllTextToDefaultLanguage( *m_pWrtShell, RES_CHRATR_CTL_LANGUAGE );
+ }
+ break;
+ case SID_ATTR_CHAR_CJK_LANGUAGE:
+ if(pArgs && SfxItemState::SET == pArgs->GetItemState(RES_CHRATR_CJK_LANGUAGE, false, &pItem))
+ {
+ m_pWrtShell->SetDefault( *pItem );
+ lcl_SetAllTextToDefaultLanguage( *m_pWrtShell, RES_CHRATR_CJK_LANGUAGE );
+ }
+ break;
+ case FN_OUTLINE_LEVELS_SHOWN:
+ {
+ SwWrtShell& rSh = GetWrtShell();
+ int nOutlineLevel = -1;
+ auto nOutlinePos = rSh.GetOutlinePos();
+ if (nOutlinePos != SwOutlineNodes::npos)
+ nOutlineLevel = rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nOutlinePos);
+ SwNumberInputDlg aDlg(GetViewFrame().GetFrameWeld(),
+ SwResId(STR_OUTLINE_LEVELS_SHOWN_TITLE),
+ SwResId(STR_OUTLINE_LEVELS_SHOWN_SPIN_LABEL),
+ nOutlineLevel + 1, 1, 10,
+ SwResId(STR_OUTLINE_LEVELS_SHOWN_HELP_LABEL));
+ if (aDlg.run() == RET_OK)
+ rSh.MakeOutlineLevelsVisible(aDlg.GetNumber());
+ }
+ break;
+ case FN_TOGGLE_OUTLINE_CONTENT_VISIBILITY:
+ {
+ size_t nPos(m_pWrtShell->GetOutlinePos());
+ if (nPos != SwOutlineNodes::npos)
+ GetEditWin().ToggleOutlineContentVisibility(nPos, false);
+ }
+ break;
+ case FN_NAV_ELEMENT:
+ {
+ pArgs->GetItemState(GetPool().GetWhich(FN_NAV_ELEMENT), false, &pItem);
+ if(pItem)
+ {
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Empty);
+ sal_uInt32 nMoveType(static_cast<const SfxUInt32Item*>(pItem)->GetValue());
+ SwView::SetMoveType(nMoveType);
+ }
+ }
+ break;
+ case FN_SCROLL_PREV:
+ case FN_SCROLL_NEXT:
+ {
+ bool *pbNext = new bool(true);
+ if (nSlot == FN_SCROLL_PREV)
+ *pbNext = false;
+ MoveNavigationHdl(pbNext);
+ }
+ break;
+ case SID_JUMPTOMARK:
+ if( pArgs && SfxItemState::SET == pArgs->GetItemState(SID_JUMPTOMARK, false, &pItem))
+ JumpToSwMark( static_cast<const SfxStringItem*>(pItem)->GetValue() );
+ break;
+ case SID_GALLERY :
+ // First make sure that the sidebar is visible
+ GetViewFrame().ShowChildWindow(SID_SIDEBAR);
+
+ ::sfx2::sidebar::Sidebar::ShowPanel(
+ u"GalleryPanel",
+ GetViewFrame().GetFrame().GetFrameInterface());
+ break;
+ case SID_AVMEDIA_PLAYER :
+ GetViewFrame().ChildWindowExecute(rReq);
+ break;
+ case SID_VIEW_DATA_SOURCE_BROWSER:
+ {
+ SfxViewFrame& rVFrame = GetViewFrame();
+ rVFrame.ChildWindowExecute(rReq);
+ if(rVFrame.HasChildWindow(SID_BROWSER))
+ {
+ const SwDBData& rData = GetWrtShell().GetDBData();
+ SwModule::ShowDBObj(*this, rData);
+ }
+ }
+ break;
+ case FN_INSERT_FIELD_DATA_ONLY:
+ {
+ bool bShow = false;
+ if( pArgs &&
+ SfxItemState::SET == pArgs->GetItemState(nSlot, false, &pItem ))
+ bShow = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ if((bShow && m_bInMailMerge) != GetViewFrame().HasChildWindow(nSlot))
+ GetViewFrame().ToggleChildWindow(nSlot);
+ //if fields have been successfully inserted call the "real"
+ //mail merge dialog
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+ SwWrtShell &rSh = GetWrtShell();
+ if(m_bInMailMerge && rSh.IsAnyDatabaseFieldInDoc())
+ {
+ SwDBManager* pDBManager = rSh.GetDBManager();
+ if (pDBManager)
+ {
+ SwDBData aData = rSh.GetDBData();
+ rSh.EnterStdMode(); // force change in text shell; necessary for mixing DB fields
+ AttrChangedNotify(nullptr);
+
+ Sequence<PropertyValue> aProperties
+ {
+ comphelper::makePropertyValue("DataSourceName", aData.sDataSource),
+ comphelper::makePropertyValue("Command", aData.sCommand),
+ comphelper::makePropertyValue("CommandType", aData.nCommandType)
+ };
+ pDBManager->ExecuteFormLetter(rSh, aProperties);
+ }
+ }
+#endif
+ m_bInMailMerge &= bShow;
+ GetViewFrame().GetBindings().Invalidate(FN_INSERT_FIELD);
+ }
+ break;
+ case FN_QRY_MERGE:
+ {
+ bool bUseCurrentDocument = true;
+ bool bQuery = !pArgs || SfxItemState::SET != pArgs->GetItemState(nSlot);
+ if(bQuery)
+ {
+ SfxViewFrame& rTmpFrame = GetViewFrame();
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractMailMergeCreateFromDlg> pDlg(pFact->CreateMailMergeCreateFromDlg(rTmpFrame.GetFrameWeld()));
+ if (RET_OK == pDlg->Execute())
+ bUseCurrentDocument = pDlg->IsThisDocument();
+ else
+ break;
+ }
+ GenerateFormLetter(bUseCurrentDocument);
+ }
+ break;
+ case SID_RECHECK_DOCUMENT:
+ {
+ SwDocShell* pDocShell = GetDocShell();
+ SwDoc* pDoc = pDocShell->GetDoc();
+ uno::Reference< linguistic2::XProofreadingIterator > xGCIterator( pDoc->GetGCIterator() );
+ if( xGCIterator.is() )
+ {
+ xGCIterator->resetIgnoreRules();
+ }
+ // reset ignore lists
+ pDoc->SpellItAgainSam( true, false, false );
+ // clear ignore dictionary
+ uno::Reference< linguistic2::XDictionary > xDictionary = LinguMgr::GetIgnoreAllList();
+ if( xDictionary.is() )
+ xDictionary->clear();
+ // put cursor to the start of the document
+ m_pWrtShell->StartOfSection();
+ [[fallthrough]]; // call spell/grammar dialog
+ }
+ case FN_SPELL_GRAMMAR_DIALOG:
+ {
+ SfxViewFrame& rViewFrame = GetViewFrame();
+ if (rReq.GetArgs() != nullptr)
+ rViewFrame.SetChildWindow (FN_SPELL_GRAMMAR_DIALOG,
+ static_cast<const SfxBoolItem&>( (rReq.GetArgs()->
+ Get(FN_SPELL_GRAMMAR_DIALOG))).GetValue());
+ else
+ rViewFrame.ToggleChildWindow(FN_SPELL_GRAMMAR_DIALOG);
+
+ rViewFrame.GetBindings().Invalidate(FN_SPELL_GRAMMAR_DIALOG);
+ rReq.Ignore ();
+ }
+ break;
+ case SID_ALIGN_ANY_LEFT :
+ case SID_ALIGN_ANY_HCENTER :
+ case SID_ALIGN_ANY_RIGHT :
+ case SID_ALIGN_ANY_JUSTIFIED:
+ case SID_ALIGN_ANY_TOP :
+ case SID_ALIGN_ANY_VCENTER :
+ case SID_ALIGN_ANY_BOTTOM :
+ case SID_ALIGN_ANY_HDEFAULT :
+ case SID_ALIGN_ANY_VDEFAULT :
+ {
+ sal_uInt16 nAlias = 0;
+ if( m_nSelectionType & (SelectionType::DrawObjectEditMode|SelectionType::Text) )
+ {
+ switch( nSlot )
+ {
+ case SID_ALIGN_ANY_LEFT : nAlias = SID_ATTR_PARA_ADJUST_LEFT; break;
+ case SID_ALIGN_ANY_HCENTER : nAlias = SID_ATTR_PARA_ADJUST_CENTER; break;
+ case SID_ALIGN_ANY_RIGHT : nAlias = SID_ATTR_PARA_ADJUST_RIGHT; break;
+ case SID_ALIGN_ANY_JUSTIFIED: nAlias = SID_ATTR_PARA_ADJUST_BLOCK; break;
+ case SID_ALIGN_ANY_TOP : nAlias = SID_TABLE_VERT_NONE; break;
+ case SID_ALIGN_ANY_VCENTER : nAlias = SID_TABLE_VERT_CENTER; break;
+ case SID_ALIGN_ANY_BOTTOM : nAlias = SID_TABLE_VERT_BOTTOM; break;
+ }
+ }
+ else
+ {
+ switch( nSlot )
+ {
+ case SID_ALIGN_ANY_LEFT : nAlias = SID_OBJECT_ALIGN_LEFT ; break;
+ case SID_ALIGN_ANY_HCENTER : nAlias = SID_OBJECT_ALIGN_CENTER ; break;
+ case SID_ALIGN_ANY_RIGHT : nAlias = SID_OBJECT_ALIGN_RIGHT ; break;
+ case SID_ALIGN_ANY_TOP : nAlias = SID_OBJECT_ALIGN_UP ; break;
+ case SID_ALIGN_ANY_VCENTER : nAlias = SID_OBJECT_ALIGN_MIDDLE ; break;
+ case SID_ALIGN_ANY_BOTTOM : nAlias = SID_OBJECT_ALIGN_DOWN ; break;
+ }
+ }
+ //these slots are either re-mapped to text or object alignment
+ if (nAlias)
+ GetViewFrame().GetDispatcher()->Execute(
+ nAlias, SfxCallMode::ASYNCHRON);
+ }
+ break;
+ case SID_RESTORE_EDITING_VIEW:
+ {
+ //#i33307# restore editing position
+ Point aCursorPos;
+ bool bSelectObj;
+ if(m_pViewImpl->GetRestorePosition(aCursorPos, bSelectObj))
+ {
+ m_pWrtShell->SwCursorShell::SetCursor( aCursorPos, !bSelectObj );
+ if( bSelectObj )
+ {
+ m_pWrtShell->SelectObj( aCursorPos );
+ m_pWrtShell->EnterSelFrameMode( &aCursorPos );
+ }
+ }
+ }
+ break;
+ case SID_INSERT_GRAPHIC:
+ {
+ rReq.SetReturnValue(SfxBoolItem(nSlot, InsertGraphicDlg( rReq )));
+ }
+ break;
+ case SID_MOVE_SHAPE_HANDLE:
+ {
+ if (pArgs && pArgs->Count() >= 3)
+ {
+ SdrView *pSdrView = m_pWrtShell->HasDrawView() ? m_pWrtShell->GetDrawView() : nullptr;
+ if (pSdrView == nullptr)
+ break;
+ const SfxUInt32Item* handleNumItem = rReq.GetArg<SfxUInt32Item>(FN_PARAM_1);
+ const SfxUInt32Item* newPosXTwips = rReq.GetArg<SfxUInt32Item>(FN_PARAM_2);
+ const SfxUInt32Item* newPosYTwips = rReq.GetArg<SfxUInt32Item>(FN_PARAM_3);
+ const SfxInt32Item* OrdNum = rReq.GetArg<SfxInt32Item>(FN_PARAM_4);
+
+ const sal_uLong handleNum = handleNumItem->GetValue();
+ const sal_uLong newPosX = newPosXTwips->GetValue();
+ const sal_uLong newPosY = newPosYTwips->GetValue();
+ const Point mPoint(newPosX, newPosY);
+ const SdrHdl* handle = pSdrView->GetHdlList().GetHdl(handleNum);
+ if (!handle)
+ {
+ break;
+ }
+
+ if (handle->GetKind() == SdrHdlKind::Anchor || handle->GetKind() == SdrHdlKind::Anchor_TR)
+ m_pWrtShell->FindAnchorPos(mPoint, /*bMoveIt=*/true);
+ else
+ pSdrView->MoveShapeHandle(handleNum, mPoint, OrdNum ? OrdNum->GetValue() : -1);
+ }
+ break;
+ }
+
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ return;
+ }
+ if(!bIgnore)
+ rReq.Done();
+}
+
+bool SwView::IsConditionalFastCall( const SfxRequest &rReq )
+{
+ sal_uInt16 nId = rReq.GetSlot();
+ bool bRet = false;
+
+ if (nId == FN_REDLINE_ACCEPT_DIRECT || nId == FN_REDLINE_REJECT_DIRECT)
+ {
+ if (comphelper::LibreOfficeKit::isActive())
+ bRet = true;
+ }
+ return bRet || SfxShell::IsConditionalFastCall(rReq);
+
+}
+
+/// invalidate page numbering field
+void SwView::UpdatePageNums()
+{
+ SfxBindings &rBnd = GetViewFrame().GetBindings();
+ rBnd.Invalidate(FN_STAT_PAGE);
+}
+
+void SwView::UpdateDocStats()
+{
+ SfxBindings &rBnd = GetViewFrame().GetBindings();
+ rBnd.Invalidate( FN_STAT_WORDCOUNT );
+ rBnd.Update( FN_STAT_WORDCOUNT );
+}
+
+/// get status of the status line
+void SwView::StateStatusLine(SfxItemSet &rSet)
+{
+ SwWrtShell& rShell = GetWrtShell();
+
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ OSL_ENSURE( nWhich, "empty set");
+
+ //get section change event
+ const SwSection* CurrSect = rShell.GetCurrSection();
+ if( CurrSect )
+ {
+ const OUString& sCurrentSectionName = CurrSect->GetSectionName();
+ if(sCurrentSectionName != m_sOldSectionName)
+ {
+ SwCursorShell::FireSectionChangeEvent(2, 1);
+ }
+ m_sOldSectionName = sCurrentSectionName;
+ }
+ else if (!m_sOldSectionName.isEmpty())
+ {
+ SwCursorShell::FireSectionChangeEvent(2, 1);
+ m_sOldSectionName= OUString();
+ }
+ //get column change event
+ if(rShell.bColumnChange())
+ {
+ SwCursorShell::FireColumnChangeEvent(2, 1);
+ }
+
+ while( nWhich )
+ {
+ switch( nWhich )
+ {
+ case FN_STAT_PAGE:
+ {
+ OUString aTooltip;
+ OUString aPageStr;
+
+ SwVisiblePageNumbers aVisiblePageNumbers;
+ m_pWrtShell->GetFirstLastVisPageNumbers(aVisiblePageNumbers);
+
+ // convert to strings and define references
+ OUString sFirstPhy = OUString::number(aVisiblePageNumbers.nFirstPhy);
+ OUString sLastPhy = OUString::number(aVisiblePageNumbers.nLastPhy);
+ OUString sFirstVirt = OUString::number(aVisiblePageNumbers.nFirstVirt);
+ OUString sLastVirt = OUString::number(aVisiblePageNumbers.nLastVirt);
+ OUString& sFirstCustomPhy = aVisiblePageNumbers.sFirstCustomPhy;
+ OUString& sLastCustomPhy = aVisiblePageNumbers.sLastCustomPhy;
+ OUString& sFirstCustomVirt = aVisiblePageNumbers.sFirstCustomVirt;
+ OUString& sLastCustomVirt = aVisiblePageNumbers.sLastCustomVirt;
+ OUString sPageCount = OUString::number(m_pWrtShell->GetPageCount());
+
+ if (aVisiblePageNumbers.nFirstPhy == aVisiblePageNumbers.nFirstVirt)
+ {
+ aTooltip = SwResId(STR_BOOKCTRL_HINT);
+ if (aVisiblePageNumbers.nFirstPhy != aVisiblePageNumbers.nLastPhy)
+ {
+ if (sFirstPhy == sFirstCustomPhy && sLastPhy == sLastCustomPhy)
+ {
+ aPageStr = SwResId(STR_PAGES_COUNT);
+ aPageStr = aPageStr.replaceFirst("%1", sFirstPhy);
+ aPageStr = aPageStr.replaceFirst("%2", sLastPhy);
+ aPageStr = aPageStr.replaceFirst("%3", sPageCount);
+ }
+ else
+ {
+ aPageStr = SwResId(STR_PAGES_COUNT_CUSTOM);
+ aPageStr = aPageStr.replaceFirst("%1", sFirstPhy);
+ aPageStr = aPageStr.replaceFirst("%2", sLastPhy);
+ aPageStr = aPageStr.replaceFirst("%3", sFirstCustomPhy);
+ aPageStr = aPageStr.replaceFirst("%4", sLastCustomPhy);
+ aPageStr = aPageStr.replaceFirst("%5", sPageCount);
+ }
+ }
+ else
+ {
+ if (sFirstPhy == sFirstCustomPhy && sLastPhy == sLastCustomPhy)
+ {
+ aPageStr = SwResId(STR_PAGE_COUNT);
+ aPageStr = aPageStr.replaceFirst("%1", sFirstPhy);
+ aPageStr = aPageStr.replaceFirst("%2", sPageCount);
+ }
+ else
+ {
+ aPageStr = SwResId(STR_PAGE_COUNT_CUSTOM);
+ aPageStr = aPageStr.replaceFirst("%1", sFirstPhy);
+ aPageStr = aPageStr.replaceFirst("%2", sFirstCustomPhy);
+ aPageStr = aPageStr.replaceFirst("%3", sPageCount);
+ }
+ }
+ }
+ else
+ {
+ aTooltip = SwResId(STR_BOOKCTRL_HINT_EXTENDED);
+ if (aVisiblePageNumbers.nFirstPhy != aVisiblePageNumbers.nLastPhy)
+ {
+ if (sFirstPhy == sFirstCustomPhy && sLastPhy == sLastCustomPhy)
+ {
+ aPageStr = SwResId(STR_PAGES_COUNT_EXTENDED);
+ aPageStr = aPageStr.replaceFirst("%1", sFirstPhy);
+ aPageStr = aPageStr.replaceFirst("%2", sLastPhy);
+ aPageStr = aPageStr.replaceFirst("%3", sPageCount);
+ aPageStr = aPageStr.replaceFirst("%4", sFirstVirt);
+ aPageStr = aPageStr.replaceFirst("%5", sLastVirt);
+ }
+ else
+ {
+ aPageStr = SwResId(STR_PAGES_COUNT_CUSTOM_EXTENDED);
+ aPageStr = aPageStr.replaceFirst("%1", sFirstPhy);
+ aPageStr = aPageStr.replaceFirst("%2", sLastPhy);
+ aPageStr = aPageStr.replaceFirst("%3", sFirstCustomPhy);
+ aPageStr = aPageStr.replaceFirst("%4", sLastCustomPhy);
+ aPageStr = aPageStr.replaceFirst("%5", sPageCount);
+ aPageStr = aPageStr.replaceFirst("%6", sFirstVirt);
+ aPageStr = aPageStr.replaceFirst("%7", sLastVirt);
+ aPageStr = aPageStr.replaceFirst("%8", sFirstCustomVirt);
+ aPageStr = aPageStr.replaceFirst("%9", sLastCustomVirt);
+ }
+ }
+ else
+ {
+ if (sFirstPhy == sFirstCustomPhy && sLastPhy == sLastCustomPhy)
+ {
+ aPageStr = SwResId(STR_PAGE_COUNT_EXTENDED);
+ aPageStr = aPageStr.replaceFirst("%1", sFirstPhy);
+ aPageStr = aPageStr.replaceFirst("%2", sPageCount);
+ aPageStr = aPageStr.replaceFirst("%3", sFirstVirt);
+ }
+ else
+ {
+ aPageStr = SwResId(STR_PAGE_COUNT_CUSTOM_EXTENDED);
+ aPageStr = aPageStr.replaceFirst("%1", sFirstPhy);
+ aPageStr = aPageStr.replaceFirst("%2", sFirstCustomPhy);
+ aPageStr = aPageStr.replaceFirst("%3", sPageCount);
+ aPageStr = aPageStr.replaceFirst("%4", sFirstVirt);
+ aPageStr = aPageStr.replaceFirst("%5", sFirstCustomVirt);
+ }
+ }
+ }
+
+ // replace range indicator with two pages conjunction if applicable
+ if ((aVisiblePageNumbers.nLastPhy - aVisiblePageNumbers.nFirstPhy) == 1)
+ aPageStr = aPageStr.replaceAll("-", SwResId(STR_PAGES_TWO_CONJUNCTION));
+
+ // status bar bookmark control string and tooltip
+ std::vector<OUString> aStringList
+ {
+ aPageStr,
+ aTooltip
+ };
+ rSet.Put(SfxStringListItem(FN_STAT_PAGE, &aStringList));
+
+ //if existing page number is not equal to old page number, send out this event.
+ if (m_nOldPageNum != aVisiblePageNumbers.nFirstPhy)
+ {
+ if (m_nOldPageNum != 0)
+ SwCursorShell::FirePageChangeEvent(m_nOldPageNum, aVisiblePageNumbers.nFirstPhy);
+ m_nOldPageNum = aVisiblePageNumbers.nFirstPhy;
+ }
+ const sal_uInt16 nCnt = GetWrtShell().GetPageCnt();
+ if (m_nPageCnt != nCnt) // notify Basic
+ {
+ m_nPageCnt = nCnt;
+ SfxGetpApp()->NotifyEvent(SfxEventHint(SfxEventHintId::SwEventPageCount, SwDocShell::GetEventName(STR_SW_EVENT_PAGE_COUNT), GetViewFrame().GetObjectShell()), false);
+ }
+ }
+ break;
+
+ case FN_STAT_WORDCOUNT:
+ {
+ SwDocStat selectionStats;
+ SwDocStat documentStats;
+ rShell.CountWords(selectionStats);
+ documentStats = rShell.GetDoc()->getIDocumentStatistics().GetUpdatedDocStat( true /* complete-async */, false /* don't update fields */ );
+
+ sal_uLong nWord = selectionStats.nWord ? selectionStats.nWord : documentStats.nWord;
+ sal_uLong nChar = selectionStats.nChar ? selectionStats.nChar : documentStats.nChar;
+ TranslateId pResId = selectionStats.nWord ? STR_WORDCOUNT : STR_WORDCOUNT_NO_SELECTION;
+ TranslateNId pWordResId = selectionStats.nWord ? STR_WORDCOUNT_WORDARG : STR_WORDCOUNT_WORDARG_NO_SELECTION;
+ TranslateNId pCharResId = selectionStats.nWord ? STR_WORDCOUNT_CHARARG : STR_WORDCOUNT_CHARARG_NO_SELECTION;
+
+ const LocaleDataWrapper& rLocaleData = Application::GetSettings().GetUILocaleDataWrapper();
+ OUString aWordArg = SwResId(pWordResId, nWord).replaceAll("$1", rLocaleData.getNum(nWord, 0));
+ OUString aCharArg = SwResId(pCharResId, nChar).replaceAll("$1", rLocaleData.getNum(nChar, 0));
+ OUString aWordCount(SwResId(pResId));
+ aWordCount = aWordCount.replaceAll("$1", aWordArg);
+ aWordCount = aWordCount.replaceAll("$2", aCharArg);
+ rSet.Put( SfxStringItem( FN_STAT_WORDCOUNT, aWordCount ) );
+
+ SwPostItMgr* pPostItMgr = rShell.GetPostItMgr();
+ if (pPostItMgr)
+ selectionStats.nComments = pPostItMgr->end() - pPostItMgr->begin();
+
+ SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetViewFrame().GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
+ if (pWrdCnt)
+ pWrdCnt->SetCounts(selectionStats, documentStats);
+ }
+ break;
+ case FN_STAT_ACCESSIBILITY_CHECK:
+ {
+ std::unique_ptr<sw::OnlineAccessibilityCheck> const& rOnlineAccessibilityCheck = rShell.GetDoc()->getOnlineAccessibilityCheck();
+ if (rOnlineAccessibilityCheck)
+ {
+ sal_Int32 nIssues = rOnlineAccessibilityCheck->getNumberOfAccessibilityIssues()
+ + rOnlineAccessibilityCheck->getNumberOfDocumentLevelAccessibilityIssues();
+ rSet.Put(SfxInt32Item(FN_STAT_ACCESSIBILITY_CHECK, nIssues));
+ }
+ }
+ break;
+
+ case FN_STAT_TEMPLATE:
+ {
+ rSet.Put(SfxStringItem( FN_STAT_TEMPLATE,
+ rShell.GetCurPageStyle()));
+
+ }
+ break;
+ case SID_ATTR_ZOOM:
+ {
+ if ( ( GetDocShell()->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ) || !GetDocShell()->IsInPlaceActive() )
+ {
+ const SwViewOption* pVOpt = rShell.GetViewOptions();
+ SvxZoomType eZoom = pVOpt->GetZoomType();
+ SvxZoomItem aZoom(eZoom,
+ pVOpt->GetZoom());
+ if( pVOpt->getBrowseMode() )
+ {
+ aZoom.SetValueSet(
+ SvxZoomEnableFlags::N50|
+ SvxZoomEnableFlags::N75|
+ SvxZoomEnableFlags::N100|
+ SvxZoomEnableFlags::N150|
+ SvxZoomEnableFlags::N200);
+ }
+ rSet.Put( aZoom );
+ }
+ else
+ rSet.DisableItem( SID_ATTR_ZOOM );
+ }
+ break;
+ case SID_ATTR_VIEWLAYOUT:
+ {
+ if ( ( GetDocShell()->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ) || !GetDocShell()->IsInPlaceActive() )
+ {
+ const SwViewOption* pVOpt = rShell.GetViewOptions();
+ const sal_uInt16 nColumns = pVOpt->GetViewLayoutColumns();
+ const bool bBookMode = pVOpt->IsViewLayoutBookMode();
+ SvxViewLayoutItem aViewLayout(nColumns, bBookMode);
+ rSet.Put( aViewLayout );
+ }
+ else
+ rSet.DisableItem( SID_ATTR_VIEWLAYOUT );
+ }
+ break;
+ case SID_ATTR_ZOOMSLIDER:
+ {
+ if ( ( GetDocShell()->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ) || !GetDocShell()->IsInPlaceActive() )
+ {
+ const SwViewOption* pVOpt = rShell.GetViewOptions();
+ const sal_uInt16 nCurrentZoom = pVOpt->GetZoom();
+ SvxZoomSliderItem aZoomSliderItem( nCurrentZoom, MINZOOM, MAXZOOM );
+ aZoomSliderItem.AddSnappingPoint( 100 );
+
+ if ( !m_pWrtShell->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE) )
+ {
+ const sal_uInt16 nColumns = pVOpt->GetViewLayoutColumns();
+ const bool bAutomaticViewLayout = 0 == nColumns;
+ const SwPostItMgr* pMgr = GetPostItMgr();
+
+ // snapping points:
+ // automatic mode: 1 Page, 2 Pages, 100%
+ // n Columns mode: n Pages, 100%
+ // n Columns book mode: nPages without gaps, 100%
+ const SwRect aPageRect( m_pWrtShell->GetAnyCurRect( CurRectType::PageCalc ) );
+ const SwRect aRootRect( m_pWrtShell->GetAnyCurRect( CurRectType::PagesArea ) ); // width of columns
+ Size aPageSize( aPageRect.SSize() );
+ aPageSize.AdjustWidth(pMgr->HasNotes() && pMgr->ShowNotes() ?
+ pMgr->GetSidebarWidth() + pMgr->GetSidebarBorderWidth() :
+ 0 );
+
+ Size aRootSize( aRootRect.SSize() );
+
+ const MapMode aTmpMap( MapUnit::MapTwip );
+ const Size& rEditSize = GetEditWin().GetOutputSizePixel();
+ const Size aWindowSize( GetEditWin().PixelToLogic( rEditSize, aTmpMap ) );
+
+ const tools::Long nOf = pVOpt->GetDocumentBorder() * 2;
+ tools::Long nTmpWidth = bAutomaticViewLayout ? aPageSize.Width() : aRootSize.Width();
+ nTmpWidth += nOf;
+ aPageSize.AdjustHeight(nOf );
+ tools::Long nFac = aWindowSize.Width() * 100 / nTmpWidth;
+
+ tools::Long nVisPercent = aWindowSize.Height() * 100 / aPageSize.Height();
+ nFac = std::min( nFac, nVisPercent );
+
+ if (nFac >= MINZOOM)
+ {
+ aZoomSliderItem.AddSnappingPoint( nFac );
+ }
+
+ if ( bAutomaticViewLayout )
+ {
+ nTmpWidth += aPageSize.Width() + pVOpt->GetGapBetweenPages();
+ nFac = aWindowSize.Width() * 100 / nTmpWidth;
+ nFac = std::min( nFac, nVisPercent );
+ if (nFac >= MINZOOM)
+ {
+ aZoomSliderItem.AddSnappingPoint( nFac );
+ }
+ }
+ }
+
+ rSet.Put( aZoomSliderItem );
+ }
+ else
+ rSet.DisableItem( SID_ATTR_ZOOMSLIDER );
+ }
+ break;
+ case SID_ATTR_POSITION:
+ case SID_ATTR_SIZE:
+ {
+ if( !rShell.IsFrameSelected() && !rShell.IsObjSelected() )
+ SwBaseShell::SetFrameMode_( FLY_DRAG_END );
+ else
+ {
+ FlyMode eFrameMode = SwBaseShell::GetFrameMode();
+ if ( eFrameMode == FLY_DRAG_START || eFrameMode == FLY_DRAG )
+ {
+ if ( nWhich == SID_ATTR_POSITION )
+ rSet.Put( SfxPointItem( SID_ATTR_POSITION,
+ rShell.GetAnchorObjDiff()));
+ else
+ rSet.Put( SvxSizeItem( SID_ATTR_SIZE,
+ rShell.GetObjSize()));
+ }
+ }
+ }
+ break;
+ case SID_TABLE_CELL:
+
+ if( rShell.IsFrameSelected() || rShell.IsObjSelected() )
+ {
+ // #i39171# Don't put a SvxSizeItem into a slot which is defined as SfxStringItem.
+ // SvxPosSizeStatusBarControl no longer resets to empty display if only one slot
+ // has no item, so SID_TABLE_CELL can remain empty (the SvxSizeItem is supplied
+ // in SID_ATTR_SIZE).
+ }
+ else
+ {
+ StatusCategory eCategory(StatusCategory::NONE);
+ OUString sStr;
+ if( rShell.IsCursorInTable() )
+ {
+ // table name + cell coordinate
+ sStr = rShell.GetTableFormat()->GetName() + ":" + rShell.GetBoxNms();
+ eCategory = StatusCategory::TableCell;
+ }
+ else
+ {
+ const SwSection* pCurrSect = rShell.GetCurrSection();
+ if( pCurrSect )
+ {
+ switch( pCurrSect->GetType() )
+ {
+ case SectionType::ToxHeader:
+ case SectionType::ToxContent:
+ {
+ const SwTOXBase* pTOX = m_pWrtShell->GetCurTOX();
+ if( pTOX )
+ {
+ sStr = pTOX->GetTOXName();
+ eCategory = StatusCategory::TableOfContents;
+ }
+ else
+ {
+ OSL_ENSURE( false,
+ "Unknown kind of section" );
+ sStr = pCurrSect->GetSectionName();
+ eCategory = StatusCategory::Section;
+ }
+ }
+ break;
+ default:
+ sStr = pCurrSect->GetSectionName();
+ eCategory = StatusCategory::Section;
+ break;
+ }
+ }
+ }
+
+ const SwNumRule* pNumRule = rShell.GetNumRuleAtCurrCursorPos();
+ const bool bOutlineNum = pNumRule && pNumRule->IsOutlineRule();
+
+ if (pNumRule && !bOutlineNum ) // cursor in numbering
+ {
+ sal_uInt8 nNumLevel = rShell.GetNumLevel();
+ if ( nNumLevel < MAXLEVEL )
+ {
+ if(!pNumRule->IsAutoRule())
+ {
+ SfxItemSetFixed<RES_PARATR_NUMRULE, RES_PARATR_NUMRULE> aSet(GetPool());
+ rShell.GetCurAttr(aSet);
+ if(SfxItemState::DEFAULT <=
+ aSet.GetItemState(RES_PARATR_NUMRULE))
+ {
+ const OUString& rNumStyle =
+ aSet.Get(RES_PARATR_NUMRULE).GetValue();
+ if(!rNumStyle.isEmpty())
+ {
+ if(!sStr.isEmpty())
+ sStr += sStatusDelim;
+ if (eCategory == StatusCategory::NONE)
+ eCategory = StatusCategory::ListStyle;
+ sStr += rNumStyle;
+ }
+ }
+ }
+ if (!sStr.isEmpty())
+ sStr += sStatusDelim;
+ sStr += SwResId(STR_NUM_LEVEL) + OUString::number( nNumLevel + 1 );
+ if (eCategory == StatusCategory::NONE)
+ eCategory = StatusCategory::Numbering;
+ }
+ }
+ const int nOutlineLevel = rShell.GetCurrentParaOutlineLevel();
+ if( nOutlineLevel != 0 )
+ {
+ if (!sStr.isEmpty())
+ sStr += " , ";
+ if( bOutlineNum )
+ {
+ sStr += SwResId(STR_OUTLINE_NUMBERING) +
+ sStatusDelim + SwResId(STR_NUM_LEVEL);
+ }
+ else
+ sStr += SwResId(STR_NUM_OUTLINE);
+ sStr += OUString::number( nOutlineLevel);
+ if (eCategory == StatusCategory::NONE)
+ eCategory = StatusCategory::Numbering;
+ }
+
+ if( rShell.HasReadonlySel() )
+ {
+ if (!sStr.isEmpty())
+ sStr = sStatusDelim + sStr;
+ sStr = SwResId(SW_STR_READONLY) + sStr;
+ }
+ if (!sStr.isEmpty())
+ rSet.Put( SvxStatusItem( SID_TABLE_CELL, sStr, eCategory ));
+ }
+ break;
+ case FN_STAT_SELMODE:
+ {
+ if(rShell.IsStdMode())
+ rSet.Put(SfxUInt16Item(FN_STAT_SELMODE, 0));
+ else if(rShell.IsAddMode())
+ rSet.Put(SfxUInt16Item(FN_STAT_SELMODE, 2));
+ else if(rShell.IsBlockMode())
+ rSet.Put(SfxUInt16Item(FN_STAT_SELMODE, 3));
+ else
+ rSet.Put(SfxUInt16Item(FN_STAT_SELMODE, 1));
+ break;
+ }
+ case SID_ATTR_INSERT:
+ if( rShell.IsRedlineOn() )
+ rSet.DisableItem( nWhich );
+ else
+ {
+ rSet.Put(SfxBoolItem(SID_ATTR_INSERT,rShell.IsInsMode()));
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+/** execute method for the status line
+ *
+ * @param rReq ???
+ */
+void SwView::ExecuteStatusLine(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetWrtShell();
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem=nullptr;
+ bool bUp = false;
+ sal_uInt16 nWhich = rReq.GetSlot();
+ switch( nWhich )
+ {
+ case FN_STAT_PAGE:
+ {
+ GetViewFrame().GetDispatcher()->Execute( FN_GOTO_PAGE,
+ SfxCallMode::SYNCHRON|SfxCallMode::RECORD );
+ }
+ break;
+
+ case FN_STAT_WORDCOUNT:
+ {
+ GetViewFrame().GetDispatcher()->Execute(FN_WORDCOUNT_DIALOG,
+ SfxCallMode::SYNCHRON|SfxCallMode::RECORD );
+ }
+ break;
+
+ case FN_STAT_ACCESSIBILITY_CHECK:
+ {
+ const SfxStringItem sDeckName(SID_SIDEBAR_DECK, "A11yCheckDeck");
+ GetViewFrame().GetDispatcher()->ExecuteList(SID_SIDEBAR_DECK, SfxCallMode::RECORD,
+ { &sDeckName });
+ }
+ break;
+
+ case FN_STAT_BOOKMARK:
+ if ( pArgs )
+ {
+ if (SfxItemState::SET == pArgs->GetItemState( nWhich, true, &pItem))
+ {
+ const IDocumentMarkAccess* pMarkAccess = rSh.getIDocumentMarkAccess();
+ const sal_Int32 nIdx = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
+ if(nIdx < pMarkAccess->getBookmarksCount())
+ {
+ const IDocumentMarkAccess::const_iterator_t ppBookmark = rSh.getIDocumentMarkAccess()->getBookmarksBegin() + nIdx;
+ rSh.EnterStdMode();
+ rSh.GotoMark( *ppBookmark );
+ }
+ else
+ OSL_FAIL("SwView::ExecuteStatusLine(..)"
+ " - Ignoring out of range bookmark index");
+ }
+ }
+ break;
+
+ case FN_STAT_TEMPLATE:
+ {
+ weld::Window* pDialogParent = GetViewFrame().GetFrameWeld();
+ css::uno::Any aAny(pDialogParent->GetXWindow());
+ SfxUnoAnyItem aDialogParent(SID_DIALOG_PARENT, aAny);
+ const SfxPoolItem* pInternalItems[ 2 ];
+ pInternalItems[ 0 ] = &aDialogParent;
+ pInternalItems[ 1 ] = nullptr;
+ GetViewFrame().GetDispatcher()->Execute(FN_FORMAT_PAGE_DLG,
+ SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
+ nullptr, 0, pInternalItems);
+ }
+ break;
+ case SID_ATTR_ZOOM:
+ {
+ if ( ( GetDocShell()->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ) || !GetDocShell()->IsInPlaceActive() )
+ {
+ const SfxItemSet *pSet = nullptr;
+ ScopedVclPtr<AbstractSvxZoomDialog> pDlg;
+ if ( pArgs )
+ pSet = pArgs;
+ else
+ {
+ const SwViewOption& rViewOptions = *rSh.GetViewOptions();
+ SfxItemSetFixed<SID_ATTR_ZOOM, SID_ATTR_ZOOM, SID_ATTR_VIEWLAYOUT, SID_ATTR_VIEWLAYOUT> aCoreSet(m_pShell->GetPool());
+ SvxZoomItem aZoom( rViewOptions.GetZoomType(), rViewOptions.GetZoom() );
+
+ const bool bBrowseMode = rSh.GetViewOptions()->getBrowseMode();
+ if( bBrowseMode )
+ {
+ aZoom.SetValueSet(
+ SvxZoomEnableFlags::N50|
+ SvxZoomEnableFlags::N75|
+ SvxZoomEnableFlags::N100|
+ SvxZoomEnableFlags::N150|
+ SvxZoomEnableFlags::N200);
+ }
+ aCoreSet.Put( aZoom );
+
+ if ( !bBrowseMode )
+ {
+ const SvxViewLayoutItem aViewLayout( rViewOptions.GetViewLayoutColumns(), rViewOptions.IsViewLayoutBookMode() );
+ aCoreSet.Put( aViewLayout );
+ }
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ pDlg.disposeAndReset(pFact->CreateSvxZoomDialog(GetViewFrame().GetFrameWeld(), aCoreSet));
+ pDlg->SetLimits( MINZOOM, MAXZOOM );
+ if( pDlg->Execute() != RET_CANCEL )
+ pSet = pDlg->GetOutputItemSet();
+ }
+
+ const SvxViewLayoutItem* pViewLayoutItem = nullptr;
+ if ( pSet && (pViewLayoutItem = pSet->GetItemIfSet(SID_ATTR_VIEWLAYOUT)))
+ {
+ const sal_uInt16 nColumns = pViewLayoutItem->GetValue();
+ const bool bBookMode = pViewLayoutItem->IsBookMode();
+ SetViewLayout( nColumns, bBookMode );
+ }
+
+ const SvxZoomItem* pZoomItem = nullptr;
+ if ( pSet && (pZoomItem = pSet->GetItemIfSet(SID_ATTR_ZOOM)))
+ {
+ SvxZoomType eType = pZoomItem->GetType();
+ SetZoom( eType, pZoomItem->GetValue() );
+ }
+ bUp = true;
+ if ( pZoomItem )
+ rReq.AppendItem( *pZoomItem );
+ rReq.Done();
+ }
+ }
+ break;
+
+ case SID_ATTR_VIEWLAYOUT:
+ {
+ if ( pArgs && !rSh.getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE) &&
+ ( ( GetDocShell()->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ) || !GetDocShell()->IsInPlaceActive() ) )
+ {
+ if ( const SvxViewLayoutItem* pLayoutItem = pArgs->GetItemIfSet(SID_ATTR_VIEWLAYOUT ))
+ {
+ const sal_uInt16 nColumns = pLayoutItem->GetValue();
+ const bool bBookMode = (0 != nColumns && 0 == (nColumns % 2)) && pLayoutItem->IsBookMode();
+
+ SetViewLayout( nColumns, bBookMode );
+ }
+
+ bUp = true;
+ rReq.Done();
+
+ InvalidateRulerPos();
+ }
+ }
+ break;
+
+ case SID_ATTR_ZOOMSLIDER:
+ {
+ if ( pArgs && ( ( GetDocShell()->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ) || !GetDocShell()->IsInPlaceActive() ) )
+ {
+ if ( const SvxZoomSliderItem* pZoomItem = pArgs->GetItemIfSet(SID_ATTR_ZOOMSLIDER) )
+ {
+ const sal_uInt16 nCurrentZoom = pZoomItem->GetValue();
+ SetZoom( SvxZoomType::PERCENT, nCurrentZoom );
+ }
+
+ bUp = true;
+ rReq.Done();
+ }
+ }
+ break;
+
+ case SID_ATTR_SIZE:
+ {
+ sal_uInt16 nId = 0;
+ if( rSh.IsCursorInTable() )
+ nId = FN_FORMAT_TABLE_DLG;
+ else if( rSh.GetCurTOX() )
+ nId = FN_INSERT_MULTI_TOX;
+ else if( rSh.GetCurrSection() )
+ nId = FN_EDIT_REGION;
+ else
+ {
+ const SwNumRule* pNumRule = rSh.GetNumRuleAtCurrCursorPos();
+ if( pNumRule ) // cursor in numbering
+ {
+ if( pNumRule->IsAutoRule() )
+ nId = FN_NUMBER_BULLETS;
+ else
+ {
+ // start dialog of the painter
+ nId = 0;
+ }
+ }
+ else if( rSh.IsFrameSelected() )
+ nId = FN_FORMAT_FRAME_DLG;
+ else if( rSh.IsObjSelected() )
+ nId = SID_ATTR_TRANSFORM;
+ }
+ if( nId )
+ GetViewFrame().GetDispatcher()->Execute(nId,
+ SfxCallMode::SYNCHRON | SfxCallMode::RECORD );
+ }
+ break;
+
+ case FN_STAT_SELMODE:
+ {
+ if ( pArgs )
+ {
+ if (SfxItemState::SET == pArgs->GetItemState( nWhich, true, &pItem))
+ {
+ switch ( static_cast<const SfxUInt16Item *>(pItem)->GetValue() )
+ {
+ case 0: rSh.EnterStdMode(); break;
+ case 1: rSh.EnterExtMode(); break;
+ case 2: rSh.EnterAddMode(); break;
+ case 3: rSh.EnterBlockMode(); break;
+ }
+ }
+ }
+ bUp = true;
+ break;
+ }
+ case FN_SET_ADD_MODE:
+ rSh.ToggleAddMode();
+ nWhich = FN_STAT_SELMODE;
+ bUp = true;
+ break;
+ case FN_SET_BLOCK_MODE:
+ rSh.ToggleBlockMode();
+ nWhich = FN_STAT_SELMODE;
+ bUp = true;
+ break;
+ case FN_SET_EXT_MODE:
+ rSh.ToggleExtMode();
+ nWhich = FN_STAT_SELMODE;
+ bUp = true;
+ break;
+ case SID_ATTR_INSERT:
+ SwPostItMgr* pMgr = GetPostItMgr();
+ if ( pMgr && pMgr->HasActiveSidebarWin() )
+ {
+ pMgr->ToggleInsModeOnActiveSidebarWin();
+ }
+ else
+ rSh.ToggleInsMode();
+ bUp = true;
+ break;
+
+ }
+ if ( bUp )
+ {
+ SfxBindings &rBnd = GetViewFrame().GetBindings();
+ rBnd.Invalidate(nWhich);
+ rBnd.Update(nWhich);
+ }
+}
+
+void SwView::InsFrameMode(sal_uInt16 nCols)
+{
+ if ( m_pWrtShell->HasWholeTabSelection() )
+ {
+ SwFlyFrameAttrMgr aMgr( true, m_pWrtShell.get(), Frmmgr_Type::TEXT, nullptr );
+
+ const SwFrameFormat &rPageFormat =
+ m_pWrtShell->GetPageDesc(m_pWrtShell->GetCurPageDesc()).GetMaster();
+ SwTwips lWidth = rPageFormat.GetFrameSize().GetWidth();
+ const SvxLRSpaceItem &rLR = rPageFormat.GetLRSpace();
+ lWidth -= rLR.GetLeft() + rLR.GetRight();
+ aMgr.SetSize(Size(lWidth, aMgr.GetSize().Height()));
+ if(nCols > 1)
+ {
+ SwFormatCol aCol;
+ aCol.Init( nCols, aCol.GetGutterWidth(), aCol.GetWishWidth() );
+ aMgr.SetCol( aCol );
+ }
+ aMgr.InsertFlyFrame();
+ }
+ else
+ GetEditWin().InsFrame(nCols);
+}
+
+/// show "edit link" dialog
+void SwView::EditLinkDlg()
+{
+ if (officecfg::Office::Common::Security::Scripting::DisableActiveContent::get())
+ {
+ std::unique_ptr<weld::MessageDialog> xError(
+ Application::CreateMessageDialog(nullptr, VclMessageType::Warning, VclButtonsType::Ok,
+ SvtResId(STR_WARNING_EXTERNAL_LINK_EDIT_DISABLED)));
+ xError->run();
+ return;
+ }
+
+ bool bWeb = dynamic_cast<SwWebView*>( this ) != nullptr;
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractLinksDialog> pDlg(pFact->CreateLinksDialog(GetViewFrame().GetFrameWeld(), &GetWrtShell().GetLinkManager(), bWeb));
+ pDlg->Execute();
+}
+
+namespace sw {
+
+auto PrepareJumpToTOXMark(SwDoc const& rDoc, std::u16string_view aName)
+ -> std::optional<std::pair<SwTOXMark, sal_Int32>>
+{
+ size_t const first(aName.find(toxMarkSeparator));
+ if (first == std::u16string_view::npos)
+ {
+ SAL_WARN("sw.ui", "JumpToTOXMark: missing separator");
+ return std::optional<std::pair<SwTOXMark, sal_Int32>>();
+ }
+ sal_Int32 const counter(o3tl::toInt32(aName.substr(0, first)));
+ if (counter <= 0)
+ {
+ SAL_WARN("sw.ui", "JumpToTOXMark: invalid counter");
+ return std::optional<std::pair<SwTOXMark, sal_Int32>>();
+ }
+ size_t const second(aName.find(toxMarkSeparator, first + 1));
+ if (second == std::u16string_view::npos)
+ {
+ SAL_WARN("sw.ui", "JumpToTOXMark: missing separator");
+ return std::optional<std::pair<SwTOXMark, sal_Int32>>();
+ }
+ std::u16string_view const entry(aName.substr(first + 1, second - (first + 1)));
+ if (aName.size() < second + 2)
+ {
+ SAL_WARN("sw.ui", "JumpToTOXMark: invalid tox");
+ return std::optional<std::pair<SwTOXMark, sal_Int32>>();
+ }
+ sal_uInt16 const indexType(aName[second + 1]);
+ std::u16string_view const indexName(aName.substr(second + 2));
+ SwTOXType const* pType(nullptr);
+ switch (indexType)
+ {
+ case 'A':
+ pType = rDoc.GetTOXType(TOX_INDEX, 0);
+ assert(pType);
+ break;
+ case 'C':
+ pType = rDoc.GetTOXType(TOX_CONTENT, 0);
+ assert(pType);
+ break;
+ case 'U':
+ for (auto i = rDoc.GetTOXTypeCount(TOX_USER); 0 < i; )
+ {
+ --i;
+ auto const pTmp(rDoc.GetTOXType(TOX_USER, i));
+ if (pTmp->GetTypeName() == indexName)
+ {
+ pType = pTmp;
+ break;
+ }
+ }
+ break;
+ }
+ if (!pType)
+ {
+ SAL_WARN("sw.ui", "JumpToTOXMark: tox doesn't exist");
+ return std::optional<std::pair<SwTOXMark, sal_Int32>>();
+ }
+ // type and alt text are the search keys
+ SwTOXMark tmp(pType);
+ tmp.SetAlternativeText(OUString(entry));
+ return std::optional<std::pair<SwTOXMark, sal_Int32>>(std::pair<SwTOXMark, sal_Int32>(tmp, counter));
+}
+
+} // namespace sw
+
+static auto JumpToTOXMark(SwWrtShell & rSh, std::u16string_view aName) -> bool
+{
+ std::optional<std::pair<SwTOXMark, sal_Int32>> const tmp(
+ sw::PrepareJumpToTOXMark(*rSh.GetDoc(), aName));
+ if (!tmp)
+ {
+ return false;
+ }
+ SwTOXMark const* pMark(&tmp->first);
+ // hack: check first if one exists
+ // need simple ptr control, else UnitTest CppunitTest_sw_uiwriter3 fails
+ if (!areSfxPoolItemPtrsEqual(&tmp->first, &rSh.GetDoc()->GotoTOXMark(tmp->first, TOX_SAME_NXT, rSh.IsReadOnlyAvailable())))
+ {
+ for (sal_Int32 i = 0; i < tmp->second; ++i)
+ {
+ pMark = &rSh.GotoTOXMark(*pMark, TOX_SAME_NXT);
+ }
+ return true;
+ }
+ else
+ {
+ SAL_WARN("sw.ui", "JumpToTOXMark: tox mark doesn't exist");
+ return false;
+ }
+}
+
+bool SwView::JumpToSwMark( std::u16string_view rMark )
+{
+ bool bRet = false;
+ if( !rMark.empty() )
+ {
+ // place bookmark at top-center
+ bool bSaveCC = m_bCenterCursor;
+ bool bSaveCT = m_bTopCursor;
+ SetCursorAtTop( true );
+
+ // For scrolling the FrameSet, the corresponding shell needs to have the focus.
+ bool bHasShFocus = m_pWrtShell->HasShellFocus();
+ if( !bHasShFocus )
+ m_pWrtShell->ShellGetFocus();
+
+ const SwFormatINetFormat* pINet;
+ OUString sCmp;
+ OUString sMark( INetURLObject::decode( rMark,
+ INetURLObject::DecodeMechanism::WithCharset ));
+
+ sal_Int32 nLastPos, nPos = sMark.indexOf( cMarkSeparator );
+ if( -1 != nPos )
+ while( -1 != ( nLastPos = sMark.indexOf( cMarkSeparator, nPos + 1 )) )
+ nPos = nLastPos;
+
+ IDocumentMarkAccess::const_iterator_t ppMark;
+ IDocumentMarkAccess* const pMarkAccess = m_pWrtShell->getIDocumentMarkAccess();
+ if( -1 != nPos )
+ sCmp = sMark.copy(nPos + 1).replaceAll(" ", "");
+
+ if( !sCmp.isEmpty() )
+ {
+ OUString sName( sMark.copy( 0, nPos ) );
+ sCmp = sCmp.toAsciiLowerCase();
+ FlyCntType eFlyType = FLYCNTTYPE_ALL;
+
+ if (sCmp == "drawingobject")
+ bRet = m_pWrtShell->GotoDrawingObject(sName);
+ else if( sCmp == "region" )
+ {
+ m_pWrtShell->EnterStdMode();
+ bRet = m_pWrtShell->GotoRegion( sName );
+ }
+ else if( sCmp == "outline" )
+ {
+ m_pWrtShell->EnterStdMode();
+ bRet = m_pWrtShell->GotoOutline( sName );
+ }
+ else if( sCmp == "frame" )
+ eFlyType = FLYCNTTYPE_FRM;
+ else if( sCmp == "graphic" )
+ eFlyType = FLYCNTTYPE_GRF;
+ else if( sCmp == "ole" )
+ eFlyType = FLYCNTTYPE_OLE;
+ else if( sCmp == "table" )
+ {
+ m_pWrtShell->EnterStdMode();
+ bRet = m_pWrtShell->GotoTable( sName );
+ }
+ else if( sCmp == "sequence" )
+ {
+ m_pWrtShell->EnterStdMode();
+ sal_Int32 nNoPos = sName.indexOf( cSequenceMarkSeparator );
+ if ( nNoPos != -1 )
+ {
+ sal_uInt16 nSeqNo = o3tl::toInt32(sName.subView( nNoPos + 1 ));
+ sName = sName.copy( 0, nNoPos );
+ bRet = m_pWrtShell->GotoRefMark(sName, REF_SEQUENCEFLD, nSeqNo);
+ }
+ }
+ else if (sCmp == "toxmark")
+ {
+ bRet = JumpToTOXMark(*m_pWrtShell, sName);
+ }
+ else if( sCmp == "text" )
+ {
+ // normal text search
+ m_pWrtShell->EnterStdMode();
+
+ i18nutil::SearchOptions2 aSearchOpt(
+ 0,
+ sName, OUString(),
+ SvtSysLocale().GetLanguageTag().getLocale(),
+ 0,0,0,
+ TransliterationFlags::IGNORE_CASE,
+ SearchAlgorithms2::ABSOLUTE,
+ '\\' );
+
+ //todo/mba: assuming that notes shouldn't be searched
+ if( m_pWrtShell->SearchPattern( aSearchOpt, false/*bSearchInNotes*/, SwDocPositions::Start, SwDocPositions::End ))
+ {
+ m_pWrtShell->EnterStdMode(); // remove the selection
+ bRet = true;
+ }
+ }
+ else if( pMarkAccess->getAllMarksEnd() != (ppMark = pMarkAccess->findMark(sMark)) )
+ {
+ bRet = m_pWrtShell->GotoMark( *ppMark, false );
+ }
+ else if( nullptr != ( pINet = m_pWrtShell->FindINetAttr( sMark ) )) {
+ m_pWrtShell->addCurrentPosition();
+ bRet = m_pWrtShell->GotoINetAttr( *pINet->GetTextINetFormat() );
+ }
+
+ // for all types of Flys
+ if( FLYCNTTYPE_ALL != eFlyType && m_pWrtShell->GotoFly( sName, eFlyType ))
+ {
+ bRet = true;
+ if( FLYCNTTYPE_FRM == eFlyType )
+ {
+ // TextFrames: set Cursor in the frame
+ m_pWrtShell->UnSelectFrame();
+ m_pWrtShell->LeaveSelFrameMode();
+ }
+ else
+ {
+ m_pWrtShell->HideCursor();
+ m_pWrtShell->EnterSelFrameMode();
+ }
+ }
+ }
+ else if( pMarkAccess->getAllMarksEnd() != (ppMark = pMarkAccess->findMark(sMark)))
+ {
+ bRet = m_pWrtShell->GotoMark( *ppMark, false );
+ }
+ else if( nullptr != ( pINet = m_pWrtShell->FindINetAttr( sMark ) ))
+ bRet = m_pWrtShell->GotoINetAttr( *pINet->GetTextINetFormat() );
+
+ // make selection visible later
+ if ( m_aVisArea.IsEmpty() )
+ m_bMakeSelectionVisible = true;
+
+ // reset ViewStatus
+ SetCursorAtTop( bSaveCT, bSaveCC );
+
+ if(!m_pWrtShell->IsFrameSelected() && !m_pWrtShell->IsObjSelected())
+ m_pWrtShell->ShowCursor();
+
+ if( !bHasShFocus )
+ m_pWrtShell->ShellLoseFocus();
+ }
+ return bRet;
+}
+
+// #i67305# Undo after insert from file:
+// Undo "Insert form file" crashes with documents imported from binary filter (.sdw) => disabled
+// Undo "Insert form file" crashes with (.odt) documents crashes if these documents contains
+// page styles with active header/footer => disabled for those documents
+static size_t lcl_PageDescWithHeader( const SwDoc& rDoc )
+{
+ size_t nRet = 0;
+ size_t nCnt = rDoc.GetPageDescCnt();
+ for( size_t i = 0; i < nCnt; ++i )
+ {
+ const SwPageDesc& rPageDesc = rDoc.GetPageDesc( i );
+ const SwFrameFormat& rMaster = rPageDesc.GetMaster();
+ const SwFormatHeader* pHeaderItem = rMaster.GetAttrSet().GetItemIfSet( RES_HEADER, false );
+ const SwFormatFooter* pFooterItem = rMaster.GetAttrSet().GetItemIfSet( RES_FOOTER, false );
+ if( (pHeaderItem && pHeaderItem->IsActive()) ||
+ (pFooterItem && pFooterItem->IsActive()) )
+ ++nRet;
+ }
+ return nRet; // number of page styles with active header/footer
+}
+
+void SwView::ExecuteInsertDoc( SfxRequest& rRequest, const SfxPoolItem* pItem )
+{
+ m_pViewImpl->InitRequest( rRequest );
+ m_pViewImpl->SetParam( pItem ? 1 : 0 );
+ const sal_uInt16 nSlot = rRequest.GetSlot();
+
+ if ( !pItem )
+ {
+ InsertDoc( nSlot, "", "" );
+ }
+ else
+ {
+ OUString sFile, sFilter;
+ sFile = static_cast<const SfxStringItem *>( pItem )->GetValue();
+ if ( SfxItemState::SET == rRequest.GetArgs()->GetItemState( FN_PARAM_1, true, &pItem ) )
+ sFilter = static_cast<const SfxStringItem *>(pItem )->GetValue();
+
+ bool bHasFileName = !sFile.isEmpty();
+ tools::Long nFound = InsertDoc( nSlot, sFile, sFilter );
+
+ if ( bHasFileName )
+ {
+ rRequest.SetReturnValue( SfxBoolItem( nSlot, nFound != -1 ) );
+ rRequest.Done();
+ }
+ }
+}
+
+tools::Long SwView::InsertDoc( sal_uInt16 nSlotId, const OUString& rFileName, const OUString& rFilterName, sal_Int16 nVersion )
+{
+ std::unique_ptr<SfxMedium> pMed;
+ SwDocShell* pDocSh = GetDocShell();
+
+ if( !rFileName.isEmpty() )
+ {
+ SfxObjectFactory& rFact = pDocSh->GetFactory();
+ std::shared_ptr<const SfxFilter> pFilter = rFact.GetFilterContainer()->GetFilter4FilterName( rFilterName );
+ if ( !pFilter )
+ {
+ pMed.reset(new SfxMedium(rFileName, StreamMode::READ, nullptr, nullptr ));
+ SfxFilterMatcher aMatcher( rFact.GetFilterContainer()->GetName() );
+ pMed->UseInteractionHandler( true );
+ ErrCode nErr = aMatcher.GuessFilter(*pMed, pFilter, SfxFilterFlags::NONE);
+ if ( nErr )
+ pMed.reset();
+ else
+ pMed->SetFilter( pFilter );
+ }
+ else
+ pMed.reset(new SfxMedium(rFileName, StreamMode::READ, pFilter, nullptr));
+ }
+ else
+ {
+ m_pViewImpl->StartDocumentInserter(
+ // tdf#118578 allow inserting any Writer document except GlobalDoc
+ SwDocShell::Factory().GetFactoryName(),
+ LINK( this, SwView, DialogClosedHdl ),
+ nSlotId
+ );
+ return -1;
+ }
+
+ if( !pMed )
+ return -1;
+
+ return InsertMedium( nSlotId, std::move(pMed), nVersion );
+}
+
+tools::Long SwView::InsertMedium( sal_uInt16 nSlotId, std::unique_ptr<SfxMedium> pMedium, sal_Int16 nVersion )
+{
+ bool bInsert = false, bCompare = false;
+ tools::Long nFound = 0;
+ SwDocShell* pDocSh = GetDocShell();
+
+ switch( nSlotId )
+ {
+ case SID_DOCUMENT_MERGE: break;
+ case SID_DOCUMENT_COMPARE: bCompare = true; break;
+ case SID_INSERTDOC: bInsert = true; break;
+
+ default:
+ OSL_ENSURE( false, "unknown SlotId!" );
+ bInsert = true;
+ break;
+ }
+
+ if( bInsert )
+ {
+ uno::Reference< frame::XDispatchRecorder > xRecorder =
+ GetViewFrame().GetBindings().GetRecorder();
+ if ( xRecorder.is() )
+ {
+ SfxRequest aRequest(GetViewFrame(), SID_INSERTDOC);
+ aRequest.AppendItem(SfxStringItem(SID_INSERTDOC, pMedium->GetOrigURL()));
+ if(pMedium->GetFilter())
+ aRequest.AppendItem(SfxStringItem(FN_PARAM_1, pMedium->GetFilter()->GetName()));
+ aRequest.Done();
+ }
+
+ SfxObjectShellRef aRef( pDocSh );
+
+ ErrCode nError = SfxObjectShell::HandleFilter( pMedium.get(), pDocSh );
+ // #i16722# aborted?
+ if(nError != ERRCODE_NONE)
+ {
+ return -1;
+ }
+
+ pMedium->Download(); // start download if needed
+ if( aRef.is() && 1 < aRef->GetRefCount() ) // still a valid ref?
+ {
+ SwReaderPtr pRdr;
+ Reader *pRead = pDocSh->StartConvertFrom(*pMedium, pRdr, m_pWrtShell.get());
+ if( pRead ||
+ (pMedium->GetFilter()->GetFilterFlags() & SfxFilterFlags::STARONEFILTER) )
+ {
+ size_t nUndoCheck = 0;
+ SwDoc *pDoc = pDocSh->GetDoc();
+ if( pRead && pDocSh->GetDoc() )
+ nUndoCheck = lcl_PageDescWithHeader( *pDoc );
+ ErrCodeMsg nErrno;
+ { //Scope for SwWait-Object, to be able to execute slots
+ //outside this scope.
+ SwWait aWait( *GetDocShell(), true );
+ m_pWrtShell->StartAllAction();
+ if ( m_pWrtShell->HasSelection() )
+ m_pWrtShell->DelRight(); // delete selections
+ if( pRead )
+ {
+ nErrno = pRdr->Read( *pRead ); // and insert document
+ pRdr.reset();
+ }
+ else
+ {
+ ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
+ rtl::Reference<SwXTextRange> const xInsertPosition(
+ SwXTextRange::CreateXTextRange(*pDoc,
+ *m_pWrtShell->GetCursor()->GetPoint(), nullptr));
+ nErrno = pDocSh->ImportFrom(*pMedium, xInsertPosition)
+ ? ERRCODE_NONE : ERR_SWG_READ_ERROR;
+ }
+
+ }
+
+ // update all "table of ..." sections if needed
+ if( m_pWrtShell->IsUpdateTOX() )
+ {
+ SfxRequest aReq( FN_UPDATE_TOX, SfxCallMode::SLOT, GetPool() );
+ Execute( aReq );
+ m_pWrtShell->SetUpdateTOX( false ); // reset
+ }
+
+ if( pDoc )
+ { // Disable Undo for .sdw or
+ // if the number of page styles with header/footer has changed
+ if( !pRead || nUndoCheck != lcl_PageDescWithHeader( *pDoc ) )
+ {
+ pDoc->GetIDocumentUndoRedo().DelAllUndoObj();
+ }
+ }
+
+ m_pWrtShell->EndAllAction();
+ if( nErrno )
+ {
+ ErrorHandler::HandleError( nErrno );
+ nFound = nErrno.IsError() ? -1 : 0;
+ }
+ else
+ nFound = 0;
+ }
+ }
+ }
+ else
+ {
+ SfxObjectShellRef xDocSh;
+ SfxObjectShellLock xLockRef;
+
+ const int nRet = SwFindDocShell( xDocSh, xLockRef, pMedium->GetName(), OUString(),
+ OUString(), nVersion, pDocSh );
+ if( nRet )
+ {
+ SwWait aWait( *GetDocShell(), true );
+ m_pWrtShell->StartAllAction();
+
+ m_pWrtShell->EnterStdMode(); // delete selections
+
+ if( bCompare )
+ nFound = m_pWrtShell->CompareDoc( *static_cast<SwDocShell*>( xDocSh.get() )->GetDoc() );
+ else
+ nFound = m_pWrtShell->MergeDoc( *static_cast<SwDocShell*>( xDocSh.get() )->GetDoc() );
+
+ m_pWrtShell->EndAllAction();
+
+ if (!bCompare && !nFound)
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetEditWin().GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_NO_MERGE_ENTRY)));
+ xInfoBox->run();
+ }
+ if( nRet==2 && xDocSh.is() )
+ xDocSh->DoClose();
+ }
+ }
+
+ return nFound;
+}
+
+void SwView::EnableMailMerge()
+{
+ m_bInMailMerge = true;
+ SfxBindings& rBind = GetViewFrame().GetBindings();
+ rBind.Invalidate(FN_INSERT_FIELD_DATA_ONLY);
+ rBind.Update(FN_INSERT_FIELD_DATA_ONLY);
+}
+
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+
+namespace
+{
+ bool lcl_NeedAdditionalDataSource( const uno::Reference< XDatabaseContext >& _rDatasourceContext )
+ {
+ Sequence < OUString > aNames = _rDatasourceContext->getElementNames();
+
+ return ( !aNames.hasElements()
+ || ( ( 1 == aNames.getLength() )
+ && aNames.getConstArray()[0] == SW_MOD()->GetDBConfig()->GetBibliographySource().sDataSource
+ )
+ );
+ }
+}
+
+#endif
+
+void SwView::GenerateFormLetter(bool bUseCurrentDocument)
+{
+#if !HAVE_FEATURE_DBCONNECTIVITY || ENABLE_FUZZERS
+ (void) bUseCurrentDocument;
+#else
+ if(bUseCurrentDocument)
+ {
+ if(!GetWrtShell().IsAnyDatabaseFieldInDoc())
+ {
+ //check availability of data sources (except biblio source)
+ uno::Reference<XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
+ uno::Reference<XDatabaseContext> xDBContext = DatabaseContext::create(xContext);
+ bool bCallAddressPilot = false;
+ if ( lcl_NeedAdditionalDataSource( xDBContext ) )
+ {
+ // no data sources are available - create a new one
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/datasourcesunavailabledialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("DataSourcesUnavailableDialog"));
+ // no cancel allowed
+ if (RET_OK != xQuery->run())
+ return;
+ bCallAddressPilot = true;
+ }
+ else
+ {
+ //take an existing data source or create a new one?
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractMailMergeFieldConnectionsDlg> pConnectionsDlg(pFact->CreateMailMergeFieldConnectionsDlg(GetFrameWeld()));
+ if(RET_OK == pConnectionsDlg->Execute())
+ bCallAddressPilot = !pConnectionsDlg->IsUseExistingConnections();
+ else
+ return;
+
+ }
+ if(bCallAddressPilot)
+ {
+ GetViewFrame().GetDispatcher()->Execute(
+ SID_ADDRESS_DATA_SOURCE, SfxCallMode::SYNCHRON);
+ if ( lcl_NeedAdditionalDataSource( xDBContext ) )
+ // no additional data source has been created
+ // -> assume that the user has cancelled the pilot
+ return;
+ }
+
+ //call insert fields with database field page available, only
+ SfxViewFrame& rVFrame = GetViewFrame();
+ //at first hide the default field dialog if currently visible
+ rVFrame.SetChildWindow(FN_INSERT_FIELD, false);
+ //enable the status of the db field dialog - it is disabled in the status method
+ //to prevent creation of the dialog without mail merge active
+ EnableMailMerge();
+ //then show the "Data base only" field dialog
+ SfxBoolItem aOn(FN_INSERT_FIELD_DATA_ONLY, true);
+ rVFrame.GetDispatcher()->ExecuteList(FN_INSERT_FIELD_DATA_ONLY,
+ SfxCallMode::SYNCHRON, { &aOn });
+ return;
+ }
+ else
+ {
+ OUString sSource;
+ if(!GetWrtShell().IsFieldDataSourceAvailable(sSource))
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/warndatasourcedialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xWarning(xBuilder->weld_message_dialog("WarnDataSourceDialog"));
+ OUString sTmp(xWarning->get_primary_text());
+ xWarning->set_primary_text(sTmp.replaceFirst("%1", sSource));
+ if (RET_OK == xWarning->run())
+ {
+ SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateVclDialog( nullptr, SID_OPTIONS_DATABASES ));
+ pDlg->Execute();
+ }
+ return ;
+ }
+ }
+ SwDBManager* pDBManager = GetWrtShell().GetDBManager();
+
+ SwDBData aData;
+ SwWrtShell &rSh = GetWrtShell();
+
+ std::vector<OUString> aDBNameList;
+ std::vector<OUString> aAllDBNames;
+ rSh.GetAllUsedDB( aDBNameList, &aAllDBNames );
+ if(!aDBNameList.empty())
+ {
+ OUString sDBName(aDBNameList[0]);
+ sal_Int32 nIdx {0};
+ aData.sDataSource = sDBName.getToken(0, DB_DELIM, nIdx);
+ aData.sCommand = sDBName.getToken(0, DB_DELIM, nIdx);
+ aData.nCommandType = o3tl::toInt32(o3tl::getToken(sDBName, 0, DB_DELIM, nIdx));
+ }
+ rSh.EnterStdMode(); // force change in text shell; necessary for mixing DB fields
+ AttrChangedNotify(nullptr);
+
+ if (pDBManager)
+ {
+ Sequence<PropertyValue> aProperties
+ {
+ comphelper::makePropertyValue("DataSourceName", aData.sDataSource),
+ comphelper::makePropertyValue("Command", aData.sCommand),
+ comphelper::makePropertyValue("CommandType", aData.nCommandType),
+ };
+ pDBManager->ExecuteFormLetter(GetWrtShell(), aProperties);
+ }
+ }
+ else
+ {
+ // call documents and template dialog
+ SfxApplication* pSfxApp = SfxGetpApp();
+ weld::Window* pTopWin = pSfxApp->GetTopWindow();
+
+ SfxTemplateManagerDlg aDocTemplDlg(GetFrameWeld());
+ int nRet = aDocTemplDlg.run();
+ bool bNewWin = false;
+ if ( nRet == RET_OK )
+ {
+ if ( pTopWin != pSfxApp->GetTopWindow() )
+ {
+ // the dialogue opens a document -> a new TopWindow appears
+ pTopWin = pSfxApp->GetTopWindow();
+ bNewWin = true;
+ }
+ }
+
+ if (bNewWin)
+ {
+ // after the destruction of the dialogue its parent comes to top,
+ // but we want that the new document is on top
+ pTopWin->present();
+ }
+ }
+#endif
+}
+
+IMPL_LINK( SwView, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg, void )
+{
+ if ( ERRCODE_NONE != _pFileDlg->GetError() )
+ return;
+
+ std::unique_ptr<SfxMedium> pMed = m_pViewImpl->CreateMedium();
+ if ( !pMed )
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetEditWin().GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(RID_SVXSTR_TXTFILTER_FILTERERROR)));
+ xInfoBox->run();
+ return;
+ }
+
+ const sal_uInt16 nSlot = m_pViewImpl->GetRequest()->GetSlot();
+ tools::Long nFound = InsertMedium( nSlot, std::move(pMed), m_pViewImpl->GetParam() );
+
+ if ( SID_INSERTDOC == nSlot )
+ {
+ if ( m_pViewImpl->GetParam() == 0 )
+ {
+ m_pViewImpl->GetRequest()->SetReturnValue( SfxBoolItem( nSlot, nFound != -1 ) );
+ m_pViewImpl->GetRequest()->Ignore();
+ }
+ else
+ {
+ m_pViewImpl->GetRequest()->SetReturnValue( SfxBoolItem( nSlot, nFound != -1 ) );
+ m_pViewImpl->GetRequest()->Done();
+ }
+ }
+ else if ( SID_DOCUMENT_COMPARE == nSlot || SID_DOCUMENT_MERGE == nSlot )
+ {
+ m_pViewImpl->GetRequest()->SetReturnValue( SfxInt32Item( nSlot, nFound ) );
+
+ if ( nFound > 0 ) // show Redline browser
+ {
+ SfxViewFrame& rVFrame = GetViewFrame();
+ rVFrame.ShowChildWindow(FN_REDLINE_ACCEPT);
+
+ // re-initialize Redline dialog
+ sal_uInt16 nId = SwRedlineAcceptChild::GetChildWindowId();
+ SwRedlineAcceptChild* pRed = static_cast<SwRedlineAcceptChild*>(rVFrame.GetChildWindow( nId ));
+ if ( pRed )
+ pRed->ReInitDlg( GetDocShell() );
+ }
+ }
+}
+
+void SwView::ExecuteScan( SfxRequest& rReq )
+{
+ if (m_pViewImpl)
+ m_pViewImpl->ExecuteScan(rReq) ;
+}
+
+const OUString& SwView::GetOldGrfCat()
+{
+ return GetCachedString(OldGrfCat);
+}
+
+void SwView::SetOldGrfCat(const OUString& sStr)
+{
+ SetCachedString(OldGrfCat, sStr);
+}
+
+const OUString& SwView::GetOldTabCat()
+{
+ return GetCachedString(OldTabCat);
+}
+
+void SwView::SetOldTabCat(const OUString& sStr)
+{
+ SetCachedString(OldTabCat, sStr);
+}
+
+const OUString& SwView::GetOldFrameCat()
+{
+ return GetCachedString(OldFrameCat);
+}
+
+void SwView::SetOldFrameCat(const OUString& sStr)
+{
+ SetCachedString(OldFrameCat, sStr);
+}
+
+const OUString& SwView::GetOldDrwCat()
+{
+ return GetCachedString(OldDrwCat);
+}
+
+void SwView::SetOldDrwCat(const OUString& sStr)
+{
+ SwView::SetCachedString(OldDrwCat, sStr);
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewcoll.cxx b/sw/source/uibase/uiview/viewcoll.cxx
new file mode 100644
index 0000000000..9ee42e1e21
--- /dev/null
+++ b/sw/source/uibase/uiview/viewcoll.cxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cmdid.h>
+#include <uiitems.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/request.hxx>
+#include <svl/stritem.hxx>
+#include <svl/style.hxx>
+#include <osl/diagnose.h>
+
+#include <view.hxx>
+#include <wrtsh.hxx>
+
+void SwView::ExecColl(SfxRequest const &rReq)
+{
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem = nullptr;
+ sal_uInt16 nWhich = rReq.GetSlot();
+ switch( nWhich )
+ {
+ case FN_SET_PAGE:
+ {
+ OSL_ENSURE(false, "Not implemented");
+ }
+ break;
+ case FN_SET_PAGE_STYLE:
+ {
+ if( pArgs )
+ {
+ if (SfxItemState::SET == pArgs->GetItemState( nWhich , true, &pItem ))
+ {
+ if( static_cast<const SfxStringItem*>(pItem)->GetValue() !=
+ GetWrtShell().GetCurPageStyle() )
+ {
+ SfxStringItem aName(SID_STYLE_APPLY,
+ static_cast<const SfxStringItem*>(pItem)->GetValue());
+ SfxUInt16Item aFamItem( SID_STYLE_FAMILY,
+ sal_uInt16(SfxStyleFamily::Page));
+ SwPtrItem aShell(FN_PARAM_WRTSHELL, GetWrtShellPtr());
+ SfxRequest aReq(SID_STYLE_APPLY, SfxCallMode::SLOT, GetPool());
+ aReq.AppendItem(aName);
+ aReq.AppendItem(aFamItem);
+ aReq.AppendItem(aShell);
+ GetCurShell()->ExecuteSlot(aReq);
+ }
+ }
+ }
+ else
+ {
+ SfxRequest aReq(FN_FORMAT_PAGE_DLG, SfxCallMode::SLOT, GetPool());
+ GetCurShell()->ExecuteSlot(aReq);
+ }
+ }
+ break;
+ default:
+ OSL_FAIL("wrong CommandProcessor for Dispatch");
+ return;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewdlg.cxx b/sw/source/uibase/uiview/viewdlg.cxx
new file mode 100644
index 0000000000..041b13bf48
--- /dev/null
+++ b/sw/source/uibase/uiview/viewdlg.cxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/request.hxx>
+#include <osl/diagnose.h>
+
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <cmdid.h>
+
+void SwView::ExecDlg(SfxRequest const &rReq)
+{
+ // Thus, from the basic no dialogues for background views are called:
+ const SfxPoolItem* pItem = nullptr;
+ const SfxItemSet* pArgs = rReq.GetArgs();
+
+ sal_uInt16 nSlot = rReq.GetSlot();
+ if(pArgs)
+ pArgs->GetItemState( GetPool().GetWhich(nSlot), false, &pItem );
+
+ switch ( nSlot )
+ {
+ case FN_CHANGE_PAGENUM:
+ {
+ if ( pItem )
+ {
+ sal_uInt16 nValue = static_cast<const SfxUInt16Item *>(pItem)->GetValue();
+ sal_uInt16 nOldValue = m_pWrtShell->GetPageOffset();
+ sal_uInt16 nPage, nLogPage;
+ m_pWrtShell->GetPageNum( nPage, nLogPage,
+ m_pWrtShell->IsCursorVisible(), false);
+
+ if(nValue != nOldValue || nValue != nLogPage)
+ {
+ if(!nOldValue)
+ m_pWrtShell->SetNewPageOffset( nValue );
+ else
+ m_pWrtShell->SetPageOffset( nValue );
+ }
+ }
+ }
+ break;
+
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ return;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewdlg2.cxx b/sw/source/uibase/uiview/viewdlg2.cxx
new file mode 100644
index 0000000000..597731645e
--- /dev/null
+++ b/sw/source/uibase/uiview/viewdlg2.cxx
@@ -0,0 +1,305 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/request.hxx>
+#include <sfx2/objface.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/svdview.hxx>
+#include <osl/diagnose.h>
+#include <fldmgr.hxx>
+#include <expfld.hxx>
+#include <modcfg.hxx>
+
+#include <swmodule.hxx>
+#include <view.hxx>
+#include <wview.hxx>
+#include <wrtsh.hxx>
+#include <cmdid.h>
+#include <caption.hxx>
+#include <poolfmt.hxx>
+#include <edtwin.hxx>
+#include <SwStyleNameMapper.hxx>
+
+#include <swabstdlg.hxx>
+
+#include <strings.hrc>
+
+#include <memory>
+
+#include <svl/stritem.hxx>
+
+using namespace css;
+
+void SwView::ExecDlgExt(SfxRequest const& rReq)
+{
+ switch (rReq.GetSlot())
+ {
+ case FN_INSERT_CAPTION:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ VclPtr<VclAbstractDialog> pDialog(
+ pFact->CreateSwCaptionDialog(GetFrameWeld(), *this));
+ pDialog->StartExecuteAsync([pDialog](sal_Int32) {
+ pDialog->disposeOnce();
+ });
+ break;
+ }
+ case SID_INSERT_SIGNATURELINE:
+ case SID_EDIT_SIGNATURELINE:
+ {
+ VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
+ const uno::Reference<frame::XModel> xModel(GetCurrentDocument());
+ ScopedVclPtr<AbstractSignatureLineDialog> pDialog(pFact->CreateSignatureLineDialog(
+ GetFrameWeld(), xModel, rReq.GetSlot() == SID_EDIT_SIGNATURELINE));
+ pDialog->Execute();
+ break;
+ }
+ case SID_INSERT_QRCODE:
+ case SID_EDIT_QRCODE:
+ {
+ VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
+ const uno::Reference<frame::XModel> xModel(GetCurrentDocument());
+ VclPtr<AbstractQrCodeGenDialog> pDialog(pFact->CreateQrCodeGenDialog(
+ GetFrameWeld(), xModel, rReq.GetSlot() == SID_EDIT_QRCODE));
+ pDialog->StartExecuteAsync([pDialog](sal_Int32) {
+ pDialog->disposeOnce();
+ });
+ break;
+ }
+ case SID_ADDITIONS_DIALOG:
+ {
+ OUString sAdditionsTag = "";
+
+ const SfxStringItem* pStringArg = rReq.GetArg<SfxStringItem>(FN_PARAM_ADDITIONS_TAG);
+ if (pStringArg)
+ sAdditionsTag = pStringArg->GetValue();
+
+ VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractAdditionsDialog> pDialog(
+ pFact->CreateAdditionsDialog(GetFrameWeld(), sAdditionsTag));
+ pDialog->Execute();
+ break;
+ }
+ case SID_SIGN_SIGNATURELINE:
+ {
+ VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
+ const uno::Reference<frame::XModel> xModel(GetCurrentDocument());
+ ScopedVclPtr<AbstractSignSignatureLineDialog> pDialog(
+ pFact->CreateSignSignatureLineDialog(GetFrameWeld(), xModel));
+ pDialog->Execute();
+ break;
+ }
+ case FN_EDIT_FOOTNOTE:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractInsFootNoteDlg> pDlg(pFact->CreateInsFootNoteDlg(
+ GetFrameWeld(), *m_pWrtShell, true));
+
+ pDlg->SetHelpId(GetStaticInterface()->GetSlot(FN_EDIT_FOOTNOTE)->GetCommand());
+ pDlg->SetText( SwResId(STR_EDIT_FOOTNOTE) );
+ pDlg->Execute();
+ break;
+ }
+ }
+}
+
+bool SwView::isSignatureLineSelected() const
+{
+ SwWrtShell& rSh = GetWrtShell();
+ SdrView* pSdrView = rSh.GetDrawView();
+ if (!pSdrView)
+ return false;
+
+ if (pSdrView->GetMarkedObjectCount() != 1)
+ return false;
+
+ SdrObject* pPickObj = pSdrView->GetMarkedObjectByIndex(0);
+ if (!pPickObj)
+ return false;
+
+ SdrGrafObj* pGraphic = dynamic_cast<SdrGrafObj*>(pPickObj);
+ if (!pGraphic)
+ return false;
+
+ return pGraphic->isSignatureLine();
+}
+
+bool SwView::isSignatureLineSigned() const
+{
+ SwWrtShell& rSh = GetWrtShell();
+ SdrView* pSdrView = rSh.GetDrawView();
+ if (!pSdrView)
+ return false;
+
+ if (pSdrView->GetMarkedObjectCount() != 1)
+ return false;
+
+ SdrObject* pPickObj = pSdrView->GetMarkedObjectByIndex(0);
+ if (!pPickObj)
+ return false;
+
+ SdrGrafObj* pGraphic = dynamic_cast<SdrGrafObj*>(pPickObj);
+ if (!pGraphic)
+ return false;
+
+ return pGraphic->isSignatureLineSigned();
+}
+
+bool SwView::isQRCodeSelected() const
+{
+ SwWrtShell& rSh = GetWrtShell();
+ SdrView* pSdrView = rSh.GetDrawView();
+ if (!pSdrView)
+ return false;
+
+ if (pSdrView->GetMarkedObjectCount() != 1)
+ return false;
+
+ SdrObject* pPickObj = pSdrView->GetMarkedObjectByIndex(0);
+ if (!pPickObj)
+ return false;
+
+ SdrGrafObj* pGraphic = dynamic_cast<SdrGrafObj*>(pPickObj);
+ if (!pGraphic)
+ return false;
+
+ return pGraphic->getQrCode() != nullptr;
+}
+
+void SwView::AutoCaption(const sal_uInt16 nType, const SvGlobalName *pOleId)
+{
+ SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig();
+
+ bool bWeb = dynamic_cast<SwWebView*>( this ) != nullptr;
+ if (pModOpt->IsInsWithCaption(bWeb))
+ {
+ const InsCaptionOpt *pOpt = pModOpt->GetCapOption(bWeb, static_cast<SwCapObjType>(nType), pOleId);
+ if (pOpt && pOpt->UseCaption())
+ InsertCaption(pOpt);
+ }
+}
+
+void SwView::InsertCaption(const InsCaptionOpt *pOpt)
+{
+ if (!pOpt)
+ return;
+
+ const OUString &rName = pOpt->GetCategory();
+
+ // Is there a pool template with the same name?
+ SwWrtShell &rSh = GetWrtShell();
+ if(!rName.isEmpty())
+ {
+ sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName(rName, SwGetPoolIdFromName::TxtColl);
+ if( USHRT_MAX != nPoolId )
+ rSh.GetTextCollFromPool(nPoolId);
+ // Pool template does not exist: Does it exist on the document?
+ else if( !rSh.GetParaStyle(rName) )
+ {
+ // It also does not exist in the document: generate
+ SwTextFormatColl* pDerivedFrom = rSh.GetTextCollFromPool(RES_POOLCOLL_LABEL);
+ rSh.MakeTextFormatColl(rName, pDerivedFrom);
+ }
+ }
+
+ SelectionType eType = rSh.GetSelectionType();
+ if (eType & SelectionType::Ole)
+ eType = SelectionType::Graphic;
+
+ const SwLabelType eT = (eType & SelectionType::Table) ? SwLabelType::Table :
+ (eType & SelectionType::Frame) ? SwLabelType::Fly :
+ (eType == SelectionType::Text) ? SwLabelType::Fly :
+ (eType & SelectionType::DrawObject) ? SwLabelType::Draw :
+ SwLabelType::Object;
+
+ SwFieldMgr aMgr(&rSh);
+ SwSetExpFieldType* pFieldType =
+ static_cast<SwSetExpFieldType*>(aMgr.GetFieldType(SwFieldIds::SetExp, rName));
+ if (!pFieldType && !rName.isEmpty() )
+ {
+ // Create new field types
+ SwSetExpFieldType aSwSetExpFieldType(rSh.GetDoc(), rName, nsSwGetSetExpType::GSE_SEQ);
+ aMgr.InsertFieldType(aSwSetExpFieldType);
+ pFieldType = static_cast<SwSetExpFieldType*>(aMgr.GetFieldType(SwFieldIds::SetExp, rName));
+ }
+
+ if (!pOpt->IgnoreSeqOpts())
+ {
+ if (pFieldType)
+ {
+ pFieldType->SetDelimiter(pOpt->GetSeparator());
+ pFieldType->SetOutlineLvl( static_cast< sal_uInt8 >(pOpt->GetLevel()) );
+ }
+ }
+
+ sal_uInt16 nID = USHRT_MAX;
+ SwFieldType* pType = nullptr;
+ const size_t nCount = aMgr.GetFieldTypeCount();
+ if( !rName.isEmpty() )
+ {
+ for (size_t i = 0; i < nCount; ++i)
+ {
+ pType = aMgr.GetFieldType(SwFieldIds::Unknown, i);
+ OUString aTmpName( pType->GetName() );
+ if (aTmpName == rName && pType->Which() == SwFieldIds::SetExp)
+ {
+ nID = i;
+ OSL_ENSURE(nID==i, "Downcasting to sal_uInt16 lost information!");
+ break;
+ }
+ }
+ }
+ rSh.StartAllAction();
+
+ GetWrtShell().InsertLabel( eT,
+ pOpt->GetCaption(),
+ !pOpt->IgnoreSeqOpts() ? OUString() : pOpt->GetSeparator(),
+ pOpt->GetNumSeparator(),
+ !pOpt->GetPos(),
+ nID,
+ pOpt->GetCharacterStyle(),
+ pOpt->CopyAttributes() );
+ // Set Number Format
+ if(pType)
+ static_cast<SwSetExpFieldType*>(pType)->SetSeqFormat(pOpt->GetNumType());
+
+ rSh.UpdateExpFields( true );
+
+ rSh.EndAllAction();
+
+ if ( rSh.IsFrameSelected() )
+ {
+ GetEditWin().StopInsFrame();
+ rSh.EnterSelFrameMode();
+ }
+
+ // remember category
+ if (eType & SelectionType::Graphic)
+ SetOldGrfCat(rName);
+ else if( eType & SelectionType::Table)
+ SetOldTabCat(rName);
+ else if( eType & SelectionType::Frame)
+ SetOldFrameCat(rName);
+ else if( eType == SelectionType::Text)
+ SetOldFrameCat(rName);
+ else if( eType & SelectionType::DrawObject)
+ SetOldDrwCat(rName);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewdraw.cxx b/sw/source/uibase/uiview/viewdraw.cxx
new file mode 100644
index 0000000000..956d05f1df
--- /dev/null
+++ b/sw/source/uibase/uiview/viewdraw.cxx
@@ -0,0 +1,755 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+#include <svl/itempool.hxx>
+#include <svl/stritem.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdview.hxx>
+#include <svx/svdpage.hxx>
+#include <editeng/outliner.hxx>
+#include <svx/fmview.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <doc.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <textboxhelper.hxx>
+#include <editeng/langitem.hxx>
+#include <svx/fontworkbar.hxx>
+#include <svx/fontworkgallery.hxx>
+#include <editeng/eeitem.hxx>
+#include <svx/svdogrp.hxx>
+#include <svx/svdetc.hxx>
+#include <editeng/editstat.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <svx/svdoutl.hxx>
+#include <vcl/ptrstyle.hxx>
+#include <osl/diagnose.h>
+
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <viewopt.hxx>
+#include <cmdid.h>
+#include <drwbassh.hxx>
+#include <beziersh.hxx>
+#include <conrect.hxx>
+#include <conpoly.hxx>
+#include <conarc.hxx>
+#include <conform.hxx>
+#include <concustomshape.hxx>
+#include <dselect.hxx>
+#include <edtwin.hxx>
+
+#include <dcontact.hxx>
+
+#include <svx/svdpagv.hxx>
+#include <svx/extrusionbar.hxx>
+#include <comphelper/lok.hxx>
+#include <sfx2/lokhelper.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+using namespace ::com::sun::star;
+
+// Execute Drawing-Ids
+
+void SwView::ExecDraw(const SfxRequest& rReq)
+{
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem;
+ const SfxStringItem* pStringItem = nullptr;
+ SdrView *pSdrView = m_pWrtShell->GetDrawView();
+ bool bDeselect = false;
+
+ sal_uInt16 nSlotId = rReq.GetSlot();
+ if(pArgs && SfxItemState::SET == pArgs->GetItemState(GetPool().GetWhich(nSlotId), false, &pItem))
+ pStringItem = dynamic_cast< const SfxStringItem*>(pItem);
+
+ SdrObjKind eNewFormObjKind = SdrObjKind::NONE;
+ if (nSlotId == SID_FM_CREATE_CONTROL)
+ {
+ const SfxUInt16Item* pIdentifierItem = rReq.GetArg<SfxUInt16Item>(SID_FM_CONTROL_IDENTIFIER);
+ if (pIdentifierItem)
+ eNewFormObjKind = static_cast<SdrObjKind>(pIdentifierItem->GetValue());
+ }
+
+ if (nSlotId == SID_OBJECT_SELECT && m_nFormSfxId == nSlotId)
+ {
+ bDeselect = true;
+ }
+ else if (nSlotId == SID_FM_CREATE_CONTROL)
+ {
+ if (eNewFormObjKind == m_eFormObjKind || eNewFormObjKind == SdrObjKind::NONE)
+ {
+ bDeselect = true;
+ GetViewFrame().GetDispatcher()->Execute(SID_FM_LEAVE_CREATE); // Button should popping out
+ }
+ }
+ else if (nSlotId == SID_FM_CREATE_FIELDCONTROL)
+ {
+ FmFormView* pFormView = dynamic_cast<FmFormView*>(pSdrView);
+ if (pFormView)
+ {
+ const SfxUnoAnyItem* pDescriptorItem = rReq.GetArg<SfxUnoAnyItem>(SID_FM_DATACCESS_DESCRIPTOR);
+ OSL_ENSURE( pDescriptorItem, "SwView::ExecDraw(SID_FM_CREATE_FIELDCONTROL): invalid request args!" );
+ if( pDescriptorItem )
+ {
+ svx::ODataAccessDescriptor aDescriptor( pDescriptorItem->GetValue() );
+ rtl::Reference<SdrObject> pObj = pFormView->CreateFieldControl( aDescriptor );
+
+ if ( pObj )
+ {
+ Size aDocSize(m_pWrtShell->GetDocSize());
+ const SwRect& rVisArea = m_pWrtShell->VisArea();
+ Point aStartPos = rVisArea.Center();
+ if(rVisArea.Width() > aDocSize.Width())
+ aStartPos.setX( aDocSize.Width() / 2 + rVisArea.Left() );
+ if(rVisArea.Height() > aDocSize.Height())
+ aStartPos.setY( aDocSize.Height() / 2 + rVisArea.Top() );
+
+ //determine the size of the object
+ if(pObj->IsGroupObject())
+ {
+ const tools::Rectangle& rBoundRect = static_cast<SdrObjGroup*>(pObj.get())->GetCurrentBoundRect();
+ aStartPos.AdjustX( -(rBoundRect.GetWidth()/2) );
+ aStartPos.AdjustY( -(rBoundRect.GetHeight()/2) );
+ }
+
+ // TODO: unmark all other
+ m_pWrtShell->EnterStdMode();
+ m_pWrtShell->SwFEShell::InsertDrawObj( *pObj, aStartPos );
+ }
+ }
+ }
+ }
+ else if ( nSlotId == SID_FONTWORK_GALLERY_FLOATER )
+ {
+ vcl::Window& rWin = m_pWrtShell->GetView().GetViewFrame().GetWindow();
+
+ rWin.EnterWait();
+
+ if( !m_pWrtShell->HasDrawView() )
+ m_pWrtShell->MakeDrawView();
+
+ pSdrView = m_pWrtShell->GetDrawView();
+ if (pSdrView)
+ {
+ std::shared_ptr<svx::FontWorkGalleryDialog> pDlg = std::make_shared<svx::FontWorkGalleryDialog>(rWin.GetFrameWeld(), *pSdrView);
+ pDlg->SetSdrObjectRef(&pSdrView->GetModel());
+ weld::DialogController::runAsync(pDlg, [this, pDlg](int) {
+ vcl::Window& rWin2 = m_pWrtShell->GetView().GetViewFrame().GetWindow();
+
+ SdrObject* pObj = pDlg->GetSdrObjectRef();
+ if ( pObj )
+ {
+ Size aDocSize( m_pWrtShell->GetDocSize() );
+ const SwRect& rVisArea = comphelper::LibreOfficeKit::isActive() ?
+ SwRect(m_pWrtShell->getLOKVisibleArea()) : m_pWrtShell->VisArea();
+ Point aPos( rVisArea.Center() );
+ tools::Rectangle aObjRect( pObj->GetLogicRect() );
+
+ if ( rVisArea.Width() > aDocSize.Width())
+ aPos.setX( aDocSize.Width() / 2 + rVisArea.Left() );
+ else if (aPos.getX() > aObjRect.GetWidth() / 2)
+ aPos.AdjustX( -(aObjRect.GetWidth() / 2) );
+
+ if (rVisArea.Height() > aDocSize.Height())
+ aPos.setY( aDocSize.Height() / 2 + rVisArea.Top() );
+ else if (aPos.getY() > aObjRect.GetHeight() / 2)
+ aPos.AdjustY( -(aObjRect.GetHeight() / 2) );
+
+ m_pWrtShell->EnterStdMode();
+ m_pWrtShell->SwFEShell::InsertDrawObj( *pObj, aPos );
+ }
+
+ rWin2.LeaveWait();
+ });
+ }
+ else
+ rWin.LeaveWait();
+ }
+ else if ( m_nFormSfxId != USHRT_MAX )
+ GetViewFrame().GetDispatcher()->Execute( SID_FM_LEAVE_CREATE );
+
+ if( nSlotId == SID_DRAW_CS_ID )
+ {
+ //deselect if same custom shape is selected again
+ SwDrawBase* pFuncPtr = GetDrawFuncPtr();
+ if( pFuncPtr && pFuncPtr->GetSlotId() == SID_DRAW_CS_ID )
+ {
+ ConstCustomShape* pConstCustomShape = static_cast<ConstCustomShape*>(pFuncPtr);
+ OUString aNew = ConstCustomShape::GetShapeTypeFromRequest( rReq );
+ const OUString& aOld = pConstCustomShape->GetShapeType();
+ if( aNew == aOld )
+ {
+ bDeselect = true;
+ }
+ }
+ }
+
+ //deselect if same shape is selected again (but different custom shapes do have same slot id)
+ if ( bDeselect || (nSlotId == m_nDrawSfxId &&
+ (!pStringItem || (pStringItem->GetValue() == m_sDrawCustom))
+ && (nSlotId != SID_DRAW_CS_ID) ) )
+ {
+ if (GetDrawFuncPtr())
+ {
+ GetDrawFuncPtr()->Deactivate();
+ SetDrawFuncPtr(nullptr);
+ }
+
+ if (m_pWrtShell->IsObjSelected() && !m_pWrtShell->IsSelFrameMode())
+ m_pWrtShell->EnterSelFrameMode();
+ LeaveDrawCreate();
+
+ AttrChangedNotify(nullptr);
+ return;
+ }
+
+ LeaveDrawCreate();
+
+ if (m_pWrtShell->IsFrameSelected())
+ m_pWrtShell->EnterStdMode(); // because bug #45639
+
+ std::unique_ptr<SwDrawBase> pFuncPtr;
+
+ // for LibreOfficeKit - choosing a shape should construct it directly
+ bool bCreateDirectly = false;
+
+ switch (nSlotId)
+ {
+ case SID_OBJECT_SELECT:
+ case SID_DRAW_SELECT:
+ pFuncPtr.reset( new DrawSelection(m_pWrtShell.get(), m_pEditWin, this) );
+ m_nDrawSfxId = m_nFormSfxId = SID_OBJECT_SELECT;
+ m_sDrawCustom.clear();
+ break;
+
+ case SID_LINE_ARROW_END:
+ case SID_LINE_ARROW_CIRCLE:
+ case SID_LINE_ARROW_SQUARE:
+ case SID_LINE_ARROW_START:
+ case SID_LINE_CIRCLE_ARROW:
+ case SID_LINE_SQUARE_ARROW:
+ case SID_LINE_ARROWS:
+ case SID_DRAW_LINE:
+ case SID_DRAW_XLINE:
+ case SID_DRAW_MEASURELINE:
+ case SID_DRAW_RECT:
+ case SID_DRAW_ELLIPSE:
+ case SID_DRAW_TEXT:
+ case SID_DRAW_TEXT_VERTICAL:
+ case SID_DRAW_TEXT_MARQUEE:
+ case SID_DRAW_CAPTION:
+ case SID_DRAW_CAPTION_VERTICAL:
+ pFuncPtr.reset( new ConstRectangle(m_pWrtShell.get(), m_pEditWin, this) );
+ bCreateDirectly = comphelper::LibreOfficeKit::isActive();
+ m_nDrawSfxId = nSlotId;
+ m_sDrawCustom.clear();
+ break;
+
+ case SID_DRAW_XPOLYGON_NOFILL:
+ case SID_DRAW_XPOLYGON:
+ case SID_DRAW_POLYGON_NOFILL:
+ case SID_DRAW_POLYGON:
+ case SID_DRAW_BEZIER_NOFILL:
+ case SID_DRAW_BEZIER_FILL:
+ case SID_DRAW_FREELINE_NOFILL:
+ case SID_DRAW_FREELINE:
+ pFuncPtr.reset( new ConstPolygon(m_pWrtShell.get(), m_pEditWin, this) );
+ m_nDrawSfxId = nSlotId;
+ m_sDrawCustom.clear();
+ break;
+
+ case SID_DRAW_ARC:
+ case SID_DRAW_PIE:
+ case SID_DRAW_CIRCLECUT:
+ pFuncPtr.reset( new ConstArc(m_pWrtShell.get(), m_pEditWin, this) );
+ m_nDrawSfxId = nSlotId;
+ m_sDrawCustom.clear();
+ break;
+
+ case SID_FM_CREATE_CONTROL:
+ {
+ pFuncPtr.reset(new ConstFormControl(m_pWrtShell.get(), m_pEditWin, this, eNewFormObjKind));
+ m_nFormSfxId = nSlotId;
+ m_eFormObjKind = eNewFormObjKind;
+ }
+ break;
+
+ case SID_DRAWTBX_CS_BASIC :
+ case SID_DRAWTBX_CS_SYMBOL :
+ case SID_DRAWTBX_CS_ARROW :
+ case SID_DRAWTBX_CS_FLOWCHART :
+ case SID_DRAWTBX_CS_CALLOUT :
+ case SID_DRAWTBX_CS_STAR :
+ case SID_DRAW_CS_ID :
+ {
+ pFuncPtr.reset( new ConstCustomShape(m_pWrtShell.get(), m_pEditWin, this, rReq ) );
+
+ bCreateDirectly = comphelper::LibreOfficeKit::isActive();
+
+ m_nDrawSfxId = nSlotId;
+ if ( nSlotId != SID_DRAW_CS_ID )
+ {
+ if ( pStringItem )
+ {
+ m_sDrawCustom = pStringItem->GetValue();
+ SfxBindings& rBind = GetViewFrame().GetBindings();
+ rBind.Invalidate( nSlotId );
+ rBind.Update( nSlotId );
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ GetViewFrame().GetBindings().Invalidate(SID_ATTRIBUTES_AREA);
+
+ bool bEndTextEdit = true;
+ if (pFuncPtr)
+ {
+ if (GetDrawFuncPtr())
+ {
+ GetDrawFuncPtr()->Deactivate();
+ }
+
+ auto pTempFuncPtr = pFuncPtr.get();
+ SetDrawFuncPtr(std::move(pFuncPtr));
+ AttrChangedNotify(nullptr);
+
+ pTempFuncPtr->Activate(nSlotId);
+ NoRotate();
+ if(rReq.GetModifier() == KEY_MOD1 || bCreateDirectly)
+ {
+ if (bCreateDirectly)
+ GetViewFrame().GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON);
+ if(SID_OBJECT_SELECT == m_nDrawSfxId )
+ {
+ m_pWrtShell->GotoObj(true);
+ }
+ else if (dynamic_cast<ConstCustomShape*>(pTempFuncPtr))
+ {
+ pTempFuncPtr->CreateDefaultObject();
+ }
+ else
+ {
+ pTempFuncPtr->CreateDefaultObject();
+ pTempFuncPtr->Deactivate();
+ SetDrawFuncPtr(nullptr);
+ LeaveDrawCreate();
+ m_pWrtShell->EnterStdMode();
+ SdrView *pTmpSdrView = m_pWrtShell->GetDrawView();
+ const SdrMarkList& rMarkList = pTmpSdrView->GetMarkedObjectList();
+ if(rMarkList.GetMarkCount() == 1 &&
+ (SID_DRAW_TEXT == nSlotId || SID_DRAW_TEXT_VERTICAL == nSlotId ||
+ SID_DRAW_TEXT_MARQUEE == nSlotId ))
+ {
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ BeginTextEdit(pObj);
+ bEndTextEdit = false;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (m_pWrtShell->IsObjSelected() && !m_pWrtShell->IsSelFrameMode())
+ m_pWrtShell->EnterSelFrameMode();
+ }
+
+ if(bEndTextEdit && pSdrView && pSdrView->IsTextEdit())
+ pSdrView->SdrEndTextEdit( true );
+
+ AttrChangedNotify(nullptr);
+}
+
+// End drawing
+
+void SwView::ExitDraw()
+{
+ NoRotate();
+
+ if(!m_pShell)
+ return;
+
+ // the shell may be invalid at close/reload/SwitchToViewShell
+ SfxDispatcher* pDispatch = GetViewFrame().GetDispatcher();
+ sal_uInt16 nIdx = 0;
+ SfxShell* pTest = nullptr;
+ do
+ {
+ pTest = pDispatch->GetShell(nIdx++);
+ }
+ while( pTest && pTest != this && pTest != m_pShell);
+ if(!(pTest == m_pShell &&
+ // don't call LeaveSelFrameMode() etc. for the below,
+ // because objects may still be selected:
+ dynamic_cast< const SwDrawBaseShell *>( m_pShell ) == nullptr &&
+ dynamic_cast< const SwBezierShell *>( m_pShell ) == nullptr &&
+ dynamic_cast< const svx::ExtrusionBar *>( m_pShell ) == nullptr &&
+ dynamic_cast< const svx::FontworkBar *>( m_pShell ) == nullptr))
+ return;
+
+ SdrView *pSdrView = m_pWrtShell->GetDrawView();
+
+ if (pSdrView && pSdrView->IsGroupEntered())
+ {
+ pSdrView->LeaveOneGroup();
+ pSdrView->UnmarkAll();
+ GetViewFrame().GetBindings().Invalidate(SID_ENTER_GROUP);
+ }
+
+ if (GetDrawFuncPtr())
+ {
+ if (m_pWrtShell->IsSelFrameMode())
+ m_pWrtShell->LeaveSelFrameMode();
+ GetDrawFuncPtr()->Deactivate();
+
+ SetDrawFuncPtr(nullptr);
+ LeaveDrawCreate();
+
+ GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW);
+ }
+ GetEditWin().SetPointer(PointerStyle::Text);
+}
+
+// Disable rotate mode
+
+void SwView::NoRotate()
+{
+ if (IsDrawRotate())
+ {
+ m_pWrtShell->SetDragMode(SdrDragMode::Move);
+ FlipDrawRotate();
+
+ const SfxBoolItem aTmp( SID_OBJECT_ROTATE, false );
+ GetViewFrame().GetBindings().SetState( aTmp );
+ }
+}
+
+// Enable DrawTextEditMode
+
+static bool lcl_isTextBox(SdrObject const * pObject)
+{
+ if (SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(pObject->GetUserCall()))
+ {
+ if (SwFrameFormat* pFormat = pDrawContact->GetFormat())
+ return SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT);
+ }
+ return false;
+}
+
+bool SwView::EnterDrawTextMode(const Point& aDocPos)
+{
+ SwWrtShell *pSh = &GetWrtShell();
+ SdrView *pSdrView = pSh->GetDrawView();
+ OSL_ENSURE( pSdrView, "EnterDrawTextMode without DrawView?" );
+
+ bool bReturn = false;
+
+ sal_uInt16 nOld = pSdrView->GetHitTolerancePixel();
+ pSdrView->SetHitTolerancePixel( 2 );
+
+ SdrObject* pObj = nullptr;
+ SdrPageView* pPV = nullptr;
+ if (pSdrView->IsMarkedHit(aDocPos) && !pSdrView->PickHandle(aDocPos) && IsTextTool())
+ pObj = pSdrView->PickObj(aDocPos, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::PICKTEXTEDIT);
+
+ if (pObj)
+ {
+ // To allow SwDrawVirtObj text objects to be activated, allow their type, too.
+ auto pVirtObj = dynamic_cast<SwDrawVirtObj*>( pObj );
+ if ( (pVirtObj && DynCastSdrTextObj(&pVirtObj->GetReferencedObj() ) != nullptr &&
+ m_pWrtShell->IsSelObjProtected(FlyProtectFlags::Content) == FlyProtectFlags::NONE) ||
+ DynCastSdrTextObj( pObj ) != nullptr )
+ {
+ // Refuse to edit editeng text of the shape if it has textbox attached.
+ if (!lcl_isTextBox(pObj))
+ bReturn = BeginTextEdit( pObj, pPV, m_pEditWin );
+ }
+ }
+
+ pSdrView->SetHitTolerancePixel( nOld );
+
+ return bReturn;
+}
+
+bool SwView::EnterShapeDrawTextMode(SdrObject* pObject)
+{
+ SdrView* pSdrView = GetWrtShell().GetDrawView();
+ SdrPageView* pPageView = pSdrView->GetSdrPageView();
+ return BeginTextEdit(pObject, pPageView, m_pEditWin);
+}
+
+// Enable DrawTextEditMode
+
+bool SwView::BeginTextEdit(SdrObject* pObj, SdrPageView* pPV, vcl::Window* pWin,
+ bool bIsNewObj, bool bSetSelectionToStart)
+{
+ SwWrtShell *pSh = &GetWrtShell();
+ SdrView *pSdrView = pSh->GetDrawView();
+ std::unique_ptr<SdrOutliner> pOutliner = ::SdrMakeOutliner(OutlinerMode::TextObject, pSdrView->GetModel());
+ uno::Reference< linguistic2::XSpellChecker1 > xSpell( ::GetSpellChecker() );
+ if (pOutliner)
+ {
+ pOutliner->SetRefDevice(pSh->getIDocumentDeviceAccess().getReferenceDevice(false));
+ pOutliner->SetSpeller(xSpell);
+ uno::Reference<linguistic2::XHyphenator> xHyphenator( ::GetHyphenator() );
+ pOutliner->SetHyphenator( xHyphenator );
+ pSh->SetCalcFieldValueHdl(pOutliner.get());
+
+ EEControlBits nCntrl = pOutliner->GetControlWord();
+ nCntrl |= EEControlBits::ALLOWBIGOBJS;
+
+ const SwViewOption *pOpt = pSh->GetViewOptions();
+
+ if (pOpt->IsFieldShadings())
+ nCntrl |= EEControlBits::MARKFIELDS;
+ else
+ nCntrl &= ~EEControlBits::MARKFIELDS;
+
+ if (pOpt->IsOnlineSpell())
+ nCntrl |= EEControlBits::ONLINESPELLING;
+ else
+ nCntrl &= ~EEControlBits::ONLINESPELLING;
+
+ pOutliner->SetControlWord(nCntrl);
+ const SvxLanguageItem& rItem = pSh->GetDoc()->GetDefault(RES_CHRATR_LANGUAGE);
+ pOutliner->SetDefaultLanguage(rItem.GetLanguage());
+
+ if( bIsNewObj )
+ pOutliner->SetVertical( SID_DRAW_TEXT_VERTICAL == m_nDrawSfxId ||
+ SID_DRAW_CAPTION_VERTICAL == m_nDrawSfxId );
+
+ // set default horizontal text direction at outliner
+ EEHorizontalTextDirection aDefHoriTextDir =
+ pSh->IsShapeDefaultHoriTextDirR2L() ? EEHorizontalTextDirection::R2L : EEHorizontalTextDirection::L2R;
+ pOutliner->SetDefaultHorizontalTextDirection( aDefHoriTextDir );
+ }
+
+ // To allow editing the referenced object from a SwDrawVirtObj here
+ // the original needs to be fetched eventually. This ATM activates the
+ // text edit mode for the original object.
+ SdrObject* pToBeActivated = pObj;
+
+ // Always the original object is edited. To allow the TextEdit to happen
+ // where the VirtObj is positioned, on demand an occurring offset is set at
+ // the TextEdit object. That offset is used for creating and managing the
+ // OutlinerView.
+ Point aNewTextEditOffset(0, 0);
+
+ if (SwDrawVirtObj* pVirtObj = dynamic_cast<SwDrawVirtObj *>(pObj))
+ {
+ pToBeActivated = &const_cast<SdrObject&>(pVirtObj->GetReferencedObj());
+ aNewTextEditOffset = pVirtObj->GetOffset();
+ }
+
+ // set in each case, thus it will be correct for all objects
+ static_cast<SdrTextObj*>(pToBeActivated)->SetTextEditOffset(aNewTextEditOffset);
+
+ bool bRet(pSdrView->SdrBeginTextEdit( pToBeActivated, pPV, pWin, true, pOutliner.release(), nullptr, false, false, false ));
+
+ // #i7672#
+ // Since SdrBeginTextEdit actually creates the OutlinerView and thus also
+ // sets the background color, an own background color needs to be set
+ // after TextEditing was started. This is now done here.
+ if(bRet)
+ {
+ OutlinerView* pView = pSdrView->GetTextEditOutlinerView();
+
+ if(pView)
+ {
+ Color aBackground(pSh->GetShapeBackground());
+ pView->SetBackgroundColor(aBackground);
+ }
+
+ // editing should start at the end of text, spell checking at the beginning ...
+ ESelection aNewSelection(EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND, EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND);
+ if (bSetSelectionToStart)
+ aNewSelection = ESelection();
+ if (pView)
+ {
+ pView->SetSelection(aNewSelection);
+
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ OString sRect = pView->GetOutputArea().toString();
+ SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_VIEW_LOCK, "rectangle", sRect);
+ }
+ }
+ }
+
+ return bRet;
+}
+
+// Is a DrawTextObject selected?
+bool SwView::IsTextTool() const
+{
+ SdrObjKind nId;
+ SdrInventor nInvent;
+ SdrView *pSdrView = GetWrtShell().GetDrawView();
+ OSL_ENSURE( pSdrView, "IsTextTool without DrawView?" );
+
+ if (pSdrView->IsCreateMode())
+ pSdrView->SetCreateMode(false);
+
+ pSdrView->TakeCurrentObj(nId,nInvent);
+ return nInvent == SdrInventor::Default;
+}
+
+SdrView* SwView::GetDrawView() const
+{
+ return GetWrtShell().GetDrawView();
+}
+
+bool SwView::IsBezierEditMode() const
+{
+ return (!IsDrawSelMode() && GetWrtShell().GetDrawView()->HasMarkablePoints());
+}
+
+bool SwView::IsFormMode() const
+{
+ if (GetDrawFuncPtr() && GetDrawFuncPtr()->IsCreateObj())
+ {
+ return GetDrawFuncPtr()->IsInsertForm();
+ }
+
+ return AreOnlyFormsSelected();
+}
+
+void SwView::SetDrawFuncPtr(std::unique_ptr<SwDrawBase> pFuncPtr)
+{
+ m_pDrawActual = std::move(pFuncPtr);
+}
+
+void SwView::SetSelDrawSlot()
+{
+ m_nDrawSfxId = SID_OBJECT_SELECT;
+ m_sDrawCustom.clear();
+}
+
+bool SwView::AreOnlyFormsSelected() const
+{
+ if ( GetWrtShell().IsFrameSelected() )
+ return false;
+
+ bool bForm = true;
+
+ SdrView* pSdrView = GetWrtShell().GetDrawView();
+
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ const size_t nCount = rMarkList.GetMarkCount();
+
+ if (nCount)
+ {
+ for (size_t i = 0; i < nCount; ++i)
+ {
+ // Except controls, are still normal draw objects selected?
+ SdrObject *pSdrObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
+ if (!pSdrObj)
+ continue;
+
+ if (!HasOnlyObj(pSdrObj, SdrInventor::FmForm))
+ {
+ bForm = false;
+ break;
+ }
+ }
+ }
+ else
+ bForm = false;
+
+ return bForm;
+}
+
+bool SwView::HasOnlyObj(SdrObject const *pSdrObj, SdrInventor eObjInventor) const
+{
+ bool bRet = false;
+
+ if (pSdrObj->IsGroupObject())
+ {
+ SdrObjList* pList = pSdrObj->GetSubList();
+ for (const rtl::Reference<SdrObject>& pObj : *pList)
+ {
+ bRet = HasOnlyObj(pObj.get(), eObjInventor);
+ if (!bRet)
+ break;
+ }
+ }
+ else if (eObjInventor == pSdrObj->GetObjInventor())
+ return true;
+
+ return bRet;
+}
+
+//#i87414# mod
+IMPL_LINK(SwView, OnlineSpellCallback, SpellCallbackInfo&, rInfo, void)
+{
+ if (rInfo.nCommand == SpellCallbackCommand::STARTSPELLDLG)
+ GetViewFrame().GetDispatcher()->Execute( FN_SPELL_GRAMMAR_DIALOG, SfxCallMode::ASYNCHRON);
+ else if (rInfo.nCommand == SpellCallbackCommand::AUTOCORRECT_OPTIONS)
+ GetViewFrame().GetDispatcher()->Execute( SID_AUTO_CORRECT_DLG, SfxCallMode::ASYNCHRON );
+}
+
+bool SwView::ExecDrwTextSpellPopup(const Point& rPt)
+{
+ bool bRet = false;
+ SdrView *pSdrView = m_pWrtShell->GetDrawView();
+ OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
+ Point aPos( GetEditWin().LogicToPixel( rPt ) );
+
+ if (pOLV->IsWrongSpelledWordAtPos( aPos ))
+ {
+ bRet = true;
+ Link<SpellCallbackInfo&,void> aLink = LINK(this, SwView, OnlineSpellCallback);
+ pOLV->ExecuteSpellPopup(aPos, aLink);
+ }
+ return bRet;
+}
+
+bool SwView::IsDrawTextHyphenate()
+{
+ SdrView *pSdrView = m_pWrtShell->GetDrawView();
+ bool bHyphenate = false;
+
+ SfxItemSetFixed<EE_PARA_HYPHENATE, EE_PARA_HYPHENATE> aNewAttr( pSdrView->GetModel().GetItemPool() );
+ pSdrView->GetAttributes( aNewAttr );
+ if( aNewAttr.GetItemState( EE_PARA_HYPHENATE ) >= SfxItemState::DEFAULT )
+ bHyphenate = aNewAttr.Get( EE_PARA_HYPHENATE ).GetValue();
+
+ return bHyphenate;
+}
+
+void SwView::HyphenateDrawText()
+{
+ SdrView *pSdrView = m_pWrtShell->GetDrawView();
+ bool bHyphenate = IsDrawTextHyphenate();
+
+ SfxItemSetFixed<EE_PARA_HYPHENATE, EE_PARA_HYPHENATE> aSet( GetPool() );
+ aSet.Put( SfxBoolItem( EE_PARA_HYPHENATE, !bHyphenate ) );
+ pSdrView->SetAttributes( aSet );
+ GetViewFrame().GetBindings().Invalidate(FN_HYPHENATE_OPT_DLG);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewfunc.hxx b/sw/source/uibase/uiview/viewfunc.hxx
new file mode 100644
index 0000000000..38320f6f39
--- /dev/null
+++ b/sw/source/uibase/uiview/viewfunc.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_UIVIEW_VIEWFUNC_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_UIVIEW_VIEWFUNC_HXX
+
+#include <vcl/outdev.hxx>
+
+#include <IDocumentDeviceAccess.hxx>
+
+class ImageButton;
+class Point;
+class SfxItemSet;
+class SfxPrinter;
+class SfxTabPage;
+class Size;
+class SvxRuler;
+class SwScrollbar;
+class SwViewShell;
+namespace vcl { class Window; }
+
+// The following functions are available in viewprt.cxx
+void SetPrinter( IDocumentDeviceAccess*, SfxPrinter const *, bool bWeb );
+void SetAppPrintOptions( SwViewShell* pSh, bool bWeb );
+
+// The following functions are available in viewport.cxx
+void ViewResizePixel( const vcl::RenderContext &rRef,
+ const Point &rOfst,
+ const Size &rSize,
+ const Size &rEditSz,
+ SwScrollbar& rVScrollbar,
+ SwScrollbar& rHScrollbar,
+ SvxRuler* pVRuler = nullptr,
+ SvxRuler* pHRuler = nullptr,
+ bool bVRulerRight = false );
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewling.cxx b/sw/source/uibase/uiview/viewling.cxx
new file mode 100644
index 0000000000..a9f64d7bf7
--- /dev/null
+++ b/sw/source/uibase/uiview/viewling.cxx
@@ -0,0 +1,856 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/linguistic2/XThesaurus.hpp>
+#include <com/sun/star/linguistic2/ProofreadingResult.hpp>
+#include <com/sun/star/linguistic2/XLinguProperties.hpp>
+#include <com/sun/star/i18n/TextConversionOption.hpp>
+#include <comphelper/lok.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/scopeguard.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/weld.hxx>
+#include <svtools/ehdl.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/request.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/svxerr.hxx>
+#include <svx/svxdlg.hxx>
+#include <osl/diagnose.h>
+#include <swwait.hxx>
+#include <uitool.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <viewopt.hxx>
+#include <swundo.hxx>
+#include <hyp.hxx>
+#include <olmenu.hxx>
+#include <pam.hxx>
+#include <edtwin.hxx>
+#include <ndtxt.hxx>
+#include <txtfrm.hxx>
+#include <cmdid.h>
+#include <strings.hrc>
+#include <hhcwrp.hxx>
+
+#include <boost/property_tree/json_parser.hpp>
+
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/ui/ContextMenuExecuteEvent.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/XPopupMenuController.hpp>
+#include <com/sun/star/awt/PopupMenuDirection.hpp>
+#include <com/sun/star/awt/XVclWindowPeer.hpp>
+#include <com/sun/star/util/URL.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/util/URLTransformer.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+
+#include <vcl/svapp.hxx>
+#include <rtl/ustring.hxx>
+
+#include <cppuhelper/bootstrap.hxx>
+#include <svtools/langtab.hxx>
+
+#include <editeng/editerr.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+#include <memory>
+
+using namespace sw::mark;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::linguistic2;
+
+// Lingu-Dispatcher
+
+void SwView::ExecLingu(SfxRequest &rReq)
+{
+ switch(rReq.GetSlot())
+ {
+ case SID_THESAURUS:
+ StartThesaurus();
+ rReq.Ignore();
+ break;
+ case SID_HANGUL_HANJA_CONVERSION:
+ StartTextConversion( LANGUAGE_KOREAN, LANGUAGE_KOREAN, nullptr,
+ i18n::TextConversionOption::CHARACTER_BY_CHARACTER, true );
+ break;
+ case SID_CHINESE_CONVERSION:
+ {
+ //open ChineseTranslationDialog
+ Reference< XComponentContext > xContext(
+ ::cppu::defaultBootstrap_InitialComponentContext() ); //@todo get context from calc if that has one
+ if(xContext.is())
+ {
+ Reference< lang::XMultiComponentFactory > xMCF( xContext->getServiceManager() );
+ if(xMCF.is())
+ {
+ Reference< ui::dialogs::XExecutableDialog > xDialog(
+ xMCF->createInstanceWithContext(
+ "com.sun.star.linguistic2.ChineseTranslationDialog", xContext),
+ UNO_QUERY);
+ Reference< lang::XInitialization > xInit( xDialog, UNO_QUERY );
+ if( xInit.is() )
+ {
+ Reference<awt::XWindow> xParentWindow;
+ if (weld::Window* pParentWindow = rReq.GetFrameWeld())
+ xParentWindow = pParentWindow->GetXWindow();
+ // initialize dialog
+ uno::Sequence<uno::Any> aSeq(comphelper::InitAnyPropertySequence(
+ {
+ {"ParentWindow", uno::Any(xParentWindow)}
+ }));
+ xInit->initialize( aSeq );
+
+ //execute dialog
+ sal_Int16 nDialogRet = xDialog->execute();
+ if( RET_OK == nDialogRet )
+ {
+ //get some parameters from the dialog
+ bool bToSimplified = true;
+ bool bUseVariants = true;
+ bool bCommonTerms = true;
+ Reference< beans::XPropertySet > xProp( xDialog, UNO_QUERY );
+ if( xProp.is() )
+ {
+ try
+ {
+ xProp->getPropertyValue( "IsDirectionToSimplified" ) >>= bToSimplified;
+ xProp->getPropertyValue( "IsUseCharacterVariants" ) >>= bUseVariants;
+ xProp->getPropertyValue( "IsTranslateCommonTerms" ) >>= bCommonTerms;
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+
+ //execute translation
+ LanguageType nSourceLang = bToSimplified ? LANGUAGE_CHINESE_TRADITIONAL : LANGUAGE_CHINESE_SIMPLIFIED;
+ LanguageType nTargetLang = bToSimplified ? LANGUAGE_CHINESE_SIMPLIFIED : LANGUAGE_CHINESE_TRADITIONAL;
+ sal_Int32 nOptions = bUseVariants ? i18n::TextConversionOption::USE_CHARACTER_VARIANTS : 0;
+ if( !bCommonTerms )
+ nOptions = nOptions | i18n::TextConversionOption::CHARACTER_BY_CHARACTER;
+
+ vcl::Font aTargetFont = OutputDevice::GetDefaultFont( DefaultFontType::CJK_TEXT,
+ nTargetLang, GetDefaultFontFlags::OnlyOne );
+
+ // disallow formatting, updating the view, ... while
+ // converting the document. (saves time)
+ // Also remember the current view and cursor position for later
+ m_pWrtShell->StartAction();
+
+ // remember cursor position data for later restoration of the cursor
+ const SwPosition *pPoint = m_pWrtShell->GetCursor()->GetPoint();
+ bool bRestoreCursor = pPoint->GetNode().IsTextNode();
+ const SwNodeIndex aPointNodeIndex( pPoint->GetNode() );
+ sal_Int32 nPointIndex = pPoint->GetContentIndex();
+
+ // since this conversion is not interactive the whole converted
+ // document should be undone in a single undo step.
+ m_pWrtShell->StartUndo( SwUndoId::OVERWRITE );
+
+ StartTextConversion( nSourceLang, nTargetLang, &aTargetFont, nOptions, false );
+
+ m_pWrtShell->EndUndo( SwUndoId::OVERWRITE );
+
+ if (bRestoreCursor)
+ {
+ SwTextNode *pTextNode = aPointNodeIndex.GetNode().GetTextNode();
+ // check for unexpected error case
+ OSL_ENSURE(pTextNode && pTextNode->GetText().getLength() >= nPointIndex,
+ "text missing: corrupted node?" );
+ // restore cursor to its original position
+ if (!pTextNode || pTextNode->GetText().getLength() < nPointIndex)
+ m_pWrtShell->GetCursor()->GetPoint()->Assign( aPointNodeIndex );
+ else
+ m_pWrtShell->GetCursor()->GetPoint()->Assign( *pTextNode, nPointIndex );
+ }
+
+ // enable all, restore view and cursor position
+ m_pWrtShell->EndAction();
+ }
+ }
+ Reference< lang::XComponent > xComponent( xDialog, UNO_QUERY );
+ if( xComponent.is() )
+ xComponent->dispose();
+ }
+ }
+ break;
+ }
+ case FN_HYPHENATE_OPT_DLG:
+ HyphenateDocument();
+ break;
+ default:
+ OSL_ENSURE(false, "wrong Dispatcher");
+ return;
+ }
+}
+
+// start language specific text conversion
+
+void SwView::StartTextConversion(
+ LanguageType nSourceLang,
+ LanguageType nTargetLang,
+ const vcl::Font *pTargetFont,
+ sal_Int32 nOptions,
+ bool bIsInteractive )
+{
+ // do not do text conversion if it is active elsewhere
+ if (SwEditShell::HasConvIter())
+ {
+ return;
+ }
+
+ SpellContext();
+
+ const SwViewOption* pVOpt = m_pWrtShell->GetViewOptions();
+ const bool bOldIdle = pVOpt->IsIdle();
+ pVOpt->SetIdle( false );
+
+ bool bOldIns = m_pWrtShell->IsInsMode();
+ m_pWrtShell->SetInsMode();
+
+ const bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection() ||
+ m_pWrtShell->GetCursor() != m_pWrtShell->GetCursor()->GetNext();
+
+ const bool bStart = bSelection || m_pWrtShell->IsStartOfDoc();
+ const bool bOther = !bSelection && !(m_pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY);
+
+ {
+ const uno::Reference< uno::XComponentContext > xContext(
+ comphelper::getProcessComponentContext() );
+ SwHHCWrapper aWrap( this, xContext, nSourceLang, nTargetLang, pTargetFont,
+ nOptions, bIsInteractive,
+ bStart, bOther, bSelection );
+ aWrap.Convert();
+ }
+
+ m_pWrtShell->SetInsMode( bOldIns );
+ pVOpt->SetIdle( bOldIdle );
+ SpellContext(false);
+}
+
+// spellcheck and text conversion related stuff
+
+void SwView::SpellStart( SvxSpellArea eWhich,
+ bool bStartDone, bool bEndDone,
+ SwConversionArgs *pConvArgs )
+{
+ Reference< XLinguProperties > xProp = ::GetLinguPropertySet();
+ bool bIsWrapReverse = !pConvArgs && xProp.is() && xProp->getIsWrapReverse();
+
+ SwDocPositions eStart = SwDocPositions::Start;
+ SwDocPositions eEnd = SwDocPositions::End;
+ SwDocPositions eCurr = SwDocPositions::Curr;
+ switch ( eWhich )
+ {
+ case SvxSpellArea::Body:
+ if( bIsWrapReverse )
+ eCurr = SwDocPositions::End;
+ else
+ eCurr = SwDocPositions::Start;
+ break;
+ case SvxSpellArea::BodyEnd:
+ if( bIsWrapReverse )
+ {
+ if( bStartDone )
+ eStart = SwDocPositions::Curr;
+ eCurr = SwDocPositions::End;
+ }
+ else if( bStartDone )
+ eCurr = SwDocPositions::Start;
+ break;
+ case SvxSpellArea::BodyStart:
+ if( !bIsWrapReverse )
+ {
+ if( bEndDone )
+ eEnd = SwDocPositions::Curr;
+ eCurr = SwDocPositions::Start;
+ }
+ else if( bEndDone )
+ eCurr = SwDocPositions::End;
+ break;
+ case SvxSpellArea::Other:
+ if( bIsWrapReverse )
+ {
+ eStart = SwDocPositions::OtherStart;
+ eEnd = SwDocPositions::OtherEnd;
+ eCurr = SwDocPositions::OtherEnd;
+ }
+ else
+ {
+ eStart = SwDocPositions::OtherStart;
+ eEnd = SwDocPositions::OtherEnd;
+ eCurr = SwDocPositions::OtherStart;
+ }
+ break;
+ default:
+ OSL_ENSURE( false, "SpellStart with unknown Area" );
+ }
+ m_pWrtShell->SpellStart( eStart, eEnd, eCurr, pConvArgs );
+}
+
+// Error message while Spelling
+
+// The passed pointer nlang is itself the value
+void SwView::SpellError(LanguageType eLang)
+{
+ int nPend = 0;
+
+ if ( m_pWrtShell->ActionPend() )
+ {
+ m_pWrtShell->Push();
+ m_pWrtShell->ClearMark();
+ do
+ {
+ m_pWrtShell->EndAction();
+ ++nPend;
+ }
+ while( m_pWrtShell->ActionPend() );
+ }
+ OUString aErr(SvtLanguageTable::GetLanguageString( eLang ) );
+
+ SwEditWin &rEditWin = GetEditWin();
+ int nWaitCnt = 0;
+ while( rEditWin.IsWait() )
+ {
+ rEditWin.LeaveWait();
+ ++nWaitCnt;
+ }
+ if ( LANGUAGE_NONE == eLang )
+ ErrorHandler::HandleError( ERRCODE_SVX_LINGU_NOLANGUAGE );
+ else
+ ErrorHandler::HandleError( ErrCodeMsg( ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS, aErr ) );
+
+ while( nWaitCnt )
+ {
+ rEditWin.EnterWait();
+ --nWaitCnt;
+ }
+
+ if ( nPend )
+ {
+ while( nPend-- )
+ m_pWrtShell->StartAction();
+ m_pWrtShell->Combine();
+ }
+}
+
+// Finish spelling and restore cursor
+
+void SwView::SpellEnd( SwConversionArgs const *pConvArgs )
+{
+ m_pWrtShell->SpellEnd( pConvArgs );
+ if( m_pWrtShell->IsExtMode() )
+ m_pWrtShell->SetMark();
+}
+
+void SwView::HyphStart( SvxSpellArea eWhich )
+{
+ switch ( eWhich )
+ {
+ case SvxSpellArea::Body:
+ m_pWrtShell->HyphStart( SwDocPositions::Start, SwDocPositions::End );
+ break;
+ case SvxSpellArea::BodyEnd:
+ m_pWrtShell->HyphStart( SwDocPositions::Curr, SwDocPositions::End );
+ break;
+ case SvxSpellArea::BodyStart:
+ m_pWrtShell->HyphStart( SwDocPositions::Start, SwDocPositions::Curr );
+ break;
+ case SvxSpellArea::Other:
+ m_pWrtShell->HyphStart( SwDocPositions::OtherStart, SwDocPositions::OtherEnd );
+ break;
+ default:
+ OSL_ENSURE( false, "HyphStart with unknown Area" );
+ }
+}
+
+// Interactive separation
+
+void SwView::HyphenateDocument()
+{
+ // do not hyphenate if interactive hyphenation is active elsewhere
+ if (SwEditShell::HasHyphIter())
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetEditWin().GetFrameWeld(),
+ VclMessageType::Warning, VclButtonsType::Ok, SwResId(STR_MULT_INTERACT_HYPH_WARN)));
+ xBox->set_title(SwResId(STR_HYPH_TITLE));
+ xBox->run();
+ return;
+ }
+
+ SfxErrorContext aContext( ERRCTX_SVX_LINGU_HYPHENATION, OUString(), m_pEditWin->GetFrameWeld(),
+ RID_SVXERRCTX, SvxResLocale() );
+
+ Reference< XHyphenator > xHyph( ::GetHyphenator() );
+ if (!xHyph.is())
+ {
+ ErrorHandler::HandleError( ERRCODE_SVX_LINGU_LINGUNOTEXISTS );
+ return;
+ }
+
+ if (m_pWrtShell->GetSelectionType() & (SelectionType::DrawObjectEditMode|SelectionType::DrawObject))
+ {
+ // Hyphenation in a Draw object
+ HyphenateDrawText();
+ }
+ else
+ {
+ SwViewOption* pVOpt = const_cast<SwViewOption*>(m_pWrtShell->GetViewOptions());
+ bool bOldIdle = pVOpt->IsIdle();
+ pVOpt->SetIdle( false );
+
+ Reference< XLinguProperties > xProp( ::GetLinguPropertySet() );
+
+ m_pWrtShell->StartUndo(SwUndoId::INSATTR); // valid later
+
+ bool bHyphSpecial = xProp.is() && xProp->getIsHyphSpecial();
+ bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection() ||
+ m_pWrtShell->GetCursor() != m_pWrtShell->GetCursor()->GetNext();
+ bool bOther = m_pWrtShell->HasOtherCnt() && bHyphSpecial && !bSelection;
+ bool bStart = bSelection || ( !bOther && m_pWrtShell->IsStartOfDoc() );
+ bool bStop = false;
+ if( !bOther && !(m_pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY) && !bSelection )
+ // turned on no special area
+ {
+ // I want also in special areas hyphenation
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetEditWin().GetFrameWeld(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ SwResId(STR_QUERY_SPECIAL_FORCED)));
+ if (xBox->run() == RET_YES)
+ {
+ bOther = true;
+ if (xProp.is())
+ {
+ xProp->setIsHyphSpecial( true );
+ }
+ }
+ else
+ bStop = true; // No hyphenation
+ }
+
+ if( !bStop )
+ {
+ SwHyphWrapper aWrap( this, xHyph, bStart, bOther, bSelection );
+ aWrap.SpellDocument();
+ m_pWrtShell->EndUndo(SwUndoId::INSATTR);
+ }
+ pVOpt->SetIdle( bOldIdle );
+ }
+}
+
+bool SwView::IsValidSelectionForThesaurus() const
+{
+ // must not be a multi-selection, and if it is a selection it needs
+ // to be within a single paragraph
+
+ const bool bMultiSel = m_pWrtShell->GetCursor()->IsMultiSelection();
+ const bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection();
+ return !bMultiSel && (!bSelection || m_pWrtShell->IsSelOnePara() );
+}
+
+OUString SwView::GetThesaurusLookUpText( bool bSelection ) const
+{
+ return bSelection ? m_pWrtShell->GetSelText() : m_pWrtShell->GetCurWord();
+}
+
+void SwView::InsertThesaurusSynonym( const OUString &rSynonmText, const OUString &rLookUpText, bool bSelection )
+{
+ bool bOldIns = m_pWrtShell->IsInsMode();
+ m_pWrtShell->SetInsMode();
+
+ m_pWrtShell->StartAllAction();
+ m_pWrtShell->StartUndo(SwUndoId::DELETE);
+
+ if( !bSelection )
+ {
+ if(m_pWrtShell->IsEndWrd())
+ m_pWrtShell->Left(SwCursorSkipMode::Cells, false, 1, false );
+
+ m_pWrtShell->SelWrd();
+
+ // make sure the selection build later from the data below does not
+ // include "in word" character to the left and right in order to
+ // preserve those. Therefore count those "in words" in order to modify
+ // the selection accordingly.
+ const sal_Unicode* pChar = rLookUpText.getStr();
+ sal_Int32 nLeft = 0;
+ while (*pChar++ == CH_TXTATR_INWORD)
+ ++nLeft;
+ pChar = rLookUpText.getLength() ? rLookUpText.getStr() + rLookUpText.getLength() - 1 : nullptr;
+ sal_Int32 nRight = 0;
+ while (pChar && *pChar-- == CH_TXTATR_INWORD)
+ ++nRight;
+
+ // adjust existing selection
+ SwPaM *pCursor = m_pWrtShell->GetCursor();
+ pCursor->GetPoint()->AdjustContent(-nRight);
+ pCursor->GetMark()->AdjustContent(nLeft);
+ }
+
+ m_pWrtShell->Insert( rSynonmText );
+
+ m_pWrtShell->EndUndo(SwUndoId::DELETE);
+ m_pWrtShell->EndAllAction();
+
+ m_pWrtShell->SetInsMode( bOldIns );
+}
+
+// Start thesaurus
+
+void SwView::StartThesaurus()
+{
+ if (!IsValidSelectionForThesaurus())
+ return;
+
+ SfxErrorContext aContext( ERRCTX_SVX_LINGU_THESAURUS, OUString(), m_pEditWin->GetFrameWeld(),
+ RID_SVXERRCTX, SvxResLocale() );
+
+ // Determine language
+ LanguageType eLang = m_pWrtShell->GetCurLang();
+ if( LANGUAGE_SYSTEM == eLang )
+ eLang = GetAppLanguage();
+
+ if( eLang == LANGUAGE_DONTKNOW || eLang == LANGUAGE_NONE )
+ {
+ SpellError( LANGUAGE_NONE );
+ return;
+ }
+
+ SwViewOption* pVOpt = const_cast<SwViewOption*>(m_pWrtShell->GetViewOptions());
+ const bool bOldIdle = pVOpt->IsIdle();
+ pVOpt->SetIdle( false );
+ comphelper::ScopeGuard guard([&]() { pVOpt->SetIdle(bOldIdle); }); // restore when leaving scope
+
+ // get initial LookUp text
+ const bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection();
+ OUString aTmp = GetThesaurusLookUpText( bSelection );
+
+ Reference< XThesaurus > xThes( ::GetThesaurus() );
+
+ if ( !xThes.is() || !xThes->hasLocale( LanguageTag::convertToLocale( eLang ) ) )
+ SpellError( eLang );
+ else
+ {
+ VclPtr<AbstractThesaurusDialog> pDlg;
+ // create dialog
+ { //Scope for SwWait-Object
+ SwWait aWait( *GetDocShell(), true );
+ // load library with dialog only on demand ...
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ pDlg.reset(pFact->CreateThesaurusDialog(GetEditWin().GetFrameWeld(), xThes, aTmp, eLang));
+ }
+
+ if (pDlg)
+ {
+ guard.dismiss(); // ignore, we'll call SetIdle() explicitly after the dialog ends
+
+ pDlg->StartExecuteAsync([aTmp, bSelection, bOldIdle, pDlg, pVOpt, this](sal_Int32 nResult){
+ if (nResult == RET_OK )
+ InsertThesaurusSynonym(pDlg->GetWord(), aTmp, bSelection);
+
+ pVOpt->SetIdle(bOldIdle);
+ pDlg->disposeOnce();
+ });
+ }
+ }
+}
+
+// Offer online suggestions
+
+namespace {
+
+//!! Start of extra code for context menu modifying extensions
+struct ExecuteInfo
+{
+ uno::Reference< frame::XDispatch > xDispatch;
+ util::URL aTargetURL;
+ uno::Sequence< PropertyValue > aArgs;
+};
+
+class AsyncExecute
+{
+public:
+ DECL_STATIC_LINK( AsyncExecute, ExecuteHdl_Impl, void*, void );
+};
+
+}
+
+IMPL_STATIC_LINK( AsyncExecute, ExecuteHdl_Impl, void*, p, void )
+{
+ ExecuteInfo* pExecuteInfo = static_cast<ExecuteInfo*>(p);
+ SolarMutexReleaser aReleaser;
+ try
+ {
+ // Asynchronous execution as this can lead to our own destruction!
+ // Framework can recycle our current frame and the layout manager disposes all user interface
+ // elements if a component gets detached from its frame!
+ pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
+ }
+ catch (const Exception&)
+ {
+ }
+
+ delete pExecuteInfo;
+}
+//!! End of extra code for context menu modifying extensions
+
+bool SwView::ExecSpellPopup(const Point& rPt)
+{
+ bool bRet = false;
+ const SwViewOption* pVOpt = m_pWrtShell->GetViewOptions();
+ if( pVOpt->IsOnlineSpell() &&
+ !m_pWrtShell->IsSelection())
+ {
+ if (m_pWrtShell->GetSelectionType() & SelectionType::DrawObjectEditMode)
+ bRet = ExecDrwTextSpellPopup(rPt);
+ else if (!m_pWrtShell->IsSelFrameMode())
+ {
+ const bool bOldViewLock = m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView( true );
+ if (!comphelper::LibreOfficeKit::isActive())
+ m_pWrtShell->Push();
+ SwRect aToFill;
+
+ SwCursorShell *pCursorShell = m_pWrtShell.get();
+ SwPaM *pCursor = pCursorShell->GetCursor();
+ SwPosition aPoint(*pCursor->GetPoint());
+ const SwTextNode *pNode = aPoint.GetNode().GetTextNode();
+
+ // Spell-check in case the idle jobs haven't had a chance to kick in.
+ // This makes it possible to suggest spelling corrections for
+ // wrong words independent of the spell-checking idle job.
+ if (pNode && pNode->IsWrongDirty() &&
+ !pCursorShell->IsTableMode() &&
+ !pCursor->HasMark() && !pCursor->IsMultiSelection())
+ {
+ std::pair<Point, bool> const tmp(rPt, false);
+ SwContentFrame *const pContentFrame = pCursor->GetPointContentNode()->getLayoutFrame(
+ pCursorShell->GetLayout(),
+ &aPoint, &tmp);
+ if (pContentFrame)
+ {
+ SwRect aRepaint(static_cast<SwTextFrame*>(pContentFrame)->AutoSpell_(
+ *pCursor->GetPointContentNode()->GetTextNode(), 0));
+ if (aRepaint.HasArea())
+ m_pWrtShell->InvalidateWindows(aRepaint);
+ }
+ }
+
+ // decide which variant of the context menu to use...
+ // if neither spell checking nor grammar checking provides suggestions use the
+ // default context menu.
+ bool bUseGrammarContext = false;
+ Reference< XSpellAlternatives > xAlt( m_pWrtShell->GetCorrection(&rPt, aToFill) );
+ ProofreadingResult aGrammarCheckRes;
+ sal_Int32 nErrorInResult = -1;
+ uno::Sequence< OUString > aSuggestions;
+ bool bCorrectionRes = false;
+ if (!xAlt.is() || !xAlt->getAlternatives().hasElements())
+ {
+ sal_Int32 nErrorPosInText = -1;
+ bCorrectionRes = m_pWrtShell->GetGrammarCorrection( aGrammarCheckRes, nErrorPosInText, nErrorInResult, aSuggestions, &rPt, aToFill );
+ OUString aMessageText;
+ if (nErrorInResult >= 0)
+ aMessageText = aGrammarCheckRes.aErrors[ nErrorInResult ].aShortComment;
+ // we like to use the grammar checking context menu if we either get
+ // some suggestions or at least a comment about the error found...
+ bUseGrammarContext = bCorrectionRes &&
+ (aSuggestions.hasElements() || !aMessageText.isEmpty());
+ }
+
+ // open respective context menu for spell check or grammar errors with correction suggestions...
+ if ((!bUseGrammarContext && xAlt.is()) ||
+ (bUseGrammarContext && bCorrectionRes && aGrammarCheckRes.aErrors.hasElements()))
+ {
+ // get paragraph text
+ OUString aParaText;
+ if (pNode)
+ {
+ pCursorShell->Push();
+ if (!pCursorShell->IsSttPara())
+ {
+ pCursorShell->MovePara(GoCurrPara, fnParaStart);
+ }
+ pCursorShell->SetMark();
+ if (!pCursorShell->IsEndPara())
+ {
+ pCursorShell->MovePara(GoCurrPara, fnParaEnd);
+ }
+ aParaText = pCursorShell->GetSelText();
+ pCursorShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
+ }
+ else
+ {
+ OSL_FAIL("text node expected but not found" );
+ }
+
+ bRet = true;
+ m_pWrtShell->SttSelect();
+ std::unique_ptr<SwSpellPopup> xPopup(bUseGrammarContext ?
+ new SwSpellPopup(m_pWrtShell.get(), aGrammarCheckRes, nErrorInResult, aSuggestions, aParaText) :
+ new SwSpellPopup(m_pWrtShell.get(), xAlt, aParaText));
+ ui::ContextMenuExecuteEvent aEvent;
+ const Point aPixPos = GetEditWin().LogicToPixel( rPt );
+
+ aEvent.SourceWindow = VCLUnoHelper::GetInterface( m_pEditWin );
+ aEvent.ExecutePosition.X = aPixPos.X();
+ aEvent.ExecutePosition.Y = aPixPos.Y();
+ rtl::Reference<VCLXPopupMenu> xMenu;
+
+ OUString sMenuName = bUseGrammarContext ?
+ OUString("private:resource/GrammarContextMenu") : OUString("private:resource/SpellContextMenu");
+ rtl::Reference<VCLXPopupMenu> xMenuInterface = xPopup->CreateMenuInterface();
+ if (TryContextMenuInterception(xMenuInterface, sMenuName, xMenu, aEvent))
+ {
+ //! happy hacking for context menu modifying extensions of this
+ //! 'custom made' menu... *sigh* (code copied from sfx2 and framework)
+ if (xMenu.is())
+ {
+ css::uno::Reference<css::awt::XWindowPeer> xParent(aEvent.SourceWindow, css::uno::UNO_QUERY);
+ const sal_uInt16 nId = xMenu->execute(xParent, css::awt::Rectangle(aPixPos.X(), aPixPos.Y(), 1, 1),
+ css::awt::PopupMenuDirection::EXECUTE_DOWN);
+ OUString aCommand = xMenu->getCommand(nId);
+ if (aCommand.isEmpty() )
+ {
+ if (!ExecuteMenuCommand(xMenu, GetViewFrame(), nId))
+ xPopup->Execute(nId);
+ }
+ else
+ {
+ SfxViewFrame& rSfxViewFrame = GetViewFrame();
+ uno::Reference<frame::XFrame> xFrame = rSfxViewFrame.GetFrame().GetFrameInterface();
+ css::util::URL aURL;
+ uno::Reference< frame::XDispatchProvider > xDispatchProvider( xFrame, UNO_QUERY );
+
+ try
+ {
+ uno::Reference< frame::XDispatch > xDispatch;
+ uno::Reference< util::XURLTransformer > xURLTransformer = util::URLTransformer::create(comphelper::getProcessComponentContext());
+
+ aURL.Complete = aCommand;
+ xURLTransformer->parseStrict(aURL);
+ uno::Sequence< beans::PropertyValue > aArgs;
+ xDispatch = xDispatchProvider->queryDispatch( aURL, OUString(), 0 );
+
+ if (xDispatch.is())
+ {
+ // Execute dispatch asynchronously
+ ExecuteInfo* pExecuteInfo = new ExecuteInfo;
+ pExecuteInfo->xDispatch = xDispatch;
+ pExecuteInfo->aTargetURL = aURL;
+ pExecuteInfo->aArgs = aArgs;
+ Application::PostUserEvent( LINK(nullptr, AsyncExecute , ExecuteHdl_Impl), pExecuteInfo );
+ }
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+ }
+ else
+ {
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ if (SfxViewShell* pViewShell = SfxViewShell::Current())
+ {
+ boost::property_tree::ptree aMenu = SfxDispatcher::fillPopupMenu(xMenuInterface);
+ boost::property_tree::ptree aRoot;
+ aRoot.add_child("menu", aMenu);
+
+ std::stringstream aStream;
+ boost::property_tree::write_json(aStream, aRoot, true);
+ pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CONTEXT_MENU, OString(aStream.str()));
+ }
+ }
+ else
+ {
+ xPopup->Execute(aToFill.SVRect(), m_pEditWin);
+ }
+ }
+ }
+ }
+
+ if (!comphelper::LibreOfficeKit::isActive())
+ m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
+ m_pWrtShell->LockView( bOldViewLock );
+ }
+ }
+ return bRet;
+}
+
+/** Function: ExecSmartTagPopup
+
+ This function shows the popup menu for smarttag
+ actions.
+*/
+void SwView::ExecSmartTagPopup( const Point& rPt )
+{
+ const bool bOldViewLock = m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView( true );
+ m_pWrtShell->Push();
+
+ css::uno::Sequence< css::uno::Any > aArgs{
+ css::uno::Any(comphelper::makePropertyValue( "Frame", GetDispatcher().GetFrame()->GetFrame().GetFrameInterface() )),
+ css::uno::Any(comphelper::makePropertyValue( "CommandURL", OUString( ".uno:OpenSmartTagMenuOnCursor" ) ))
+ };
+
+ css::uno::Reference< css::uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
+ css::uno::Reference< css::frame::XPopupMenuController > xPopupController(
+ xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ "com.sun.star.comp.svx.SmartTagMenuController", aArgs, xContext ), css::uno::UNO_QUERY );
+
+ css::uno::Reference< css::awt::XPopupMenu > xPopupMenu( xContext->getServiceManager()->createInstanceWithContext(
+ "com.sun.star.awt.PopupMenu", xContext ), css::uno::UNO_QUERY );
+
+ if ( xPopupController.is() && xPopupMenu.is() )
+ {
+ xPopupController->setPopupMenu( xPopupMenu );
+
+ SwRect aToFill;
+ m_pWrtShell->GetSmartTagRect( rPt, aToFill );
+ m_pWrtShell->SttSelect();
+
+ if ( aToFill.HasArea() )
+ xPopupMenu->execute( m_pEditWin->GetComponentInterface(),
+ VCLUnoHelper::ConvertToAWTRect( m_pEditWin->LogicToPixel( aToFill.SVRect() ) ), css::awt::PopupMenuDirection::EXECUTE_DOWN );
+
+ css::uno::Reference< css::lang::XComponent > xComponent( xPopupController, css::uno::UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+
+ m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
+ m_pWrtShell->LockView( bOldViewLock );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewmdi.cxx b/sw/source/uibase/uiview/viewmdi.cxx
new file mode 100644
index 0000000000..f07c25e2df
--- /dev/null
+++ b/sw/source/uibase/uiview/viewmdi.cxx
@@ -0,0 +1,791 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svx/ruler.hxx>
+#include <editeng/lrspitem.hxx>
+#include <o3tl/safeint.hxx>
+#include <svl/srchitem.hxx>
+#include <svl/stritem.hxx>
+#include <sfx2/request.hxx>
+#include <swmodule.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <viewopt.hxx>
+#include <frmatr.hxx>
+#include <edtwin.hxx>
+#include <pagedesc.hxx>
+#include <IMark.hxx>
+#include <fldbas.hxx>
+#include <workctrl.hxx>
+#include <usrpref.hxx>
+#include <scroll.hxx>
+#include <wview.hxx>
+
+#include <cmdid.h>
+
+#include <PostItMgr.hxx>
+#include <AnnotationWin.hxx>
+
+#include <svx/srchdlg.hxx>
+#include <svx/svdview.hxx>
+
+#include <vcl/uitest/logger.hxx>
+#include <vcl/uitest/eventdescription.hxx>
+
+sal_uInt16 SwView::s_nMoveType = NID_PGE;
+sal_Int32 SwView::s_nActMark = 0;
+
+using namespace ::com::sun::star::uno;
+
+namespace {
+
+void collectUIInformation(const OUString& aFactor)
+{
+ EventDescription aDescription;
+ aDescription.aID = "writer_edit";
+ aDescription.aParameters = {{"ZOOM", aFactor}};
+ aDescription.aAction = "SET";
+ aDescription.aKeyWord = "SwEditWinUIObject";
+ aDescription.aParent = "MainWindow";
+ UITestLogger::getInstance().logEvent(aDescription);
+}
+
+}
+
+void SwView::SetZoom( SvxZoomType eZoomType, short nFactor, bool bViewOnly )
+{
+ bool const bCursorIsVisible(m_pWrtShell->IsCursorVisible());
+ SetZoom_( GetEditWin().GetOutputSizePixel(), eZoomType, nFactor, bViewOnly );
+ // fdo#40465 force the cursor to stay in view whilst zooming
+ if (bCursorIsVisible)
+ m_pWrtShell->ShowCursor();
+
+ Invalidate(SID_ZOOM_IN);
+ Invalidate(SID_ZOOM_OUT);
+
+ collectUIInformation(OUString::number(nFactor));
+}
+
+void SwView::SetZoom_( const Size &rEditSize, SvxZoomType eZoomType,
+ short nFactor, bool bViewOnly )
+{
+ bool bUnLockView = !m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView( true );
+ m_pWrtShell->LockPaint(LockPaintReason::SetZoom);
+
+ { // start of SwActContext scope
+ SwActContext aActContext(m_pWrtShell.get());
+
+ tools::Long nFac = nFactor;
+
+ const bool bWeb = dynamic_cast< const SwWebView *>( this ) != nullptr;
+ SwMasterUsrPref *pUsrPref = const_cast<SwMasterUsrPref*>(SW_MOD()->GetUsrPref(bWeb));
+
+ const SwPageDesc &rDesc = m_pWrtShell->GetPageDesc( m_pWrtShell->GetCurPageDesc() );
+ const SvxLRSpaceItem &rLRSpace = rDesc.GetMaster().GetLRSpace();
+ const SwViewOption *pOpt = m_pWrtShell->GetViewOptions();
+ tools::Long lLeftMargin = 0;
+
+ if( eZoomType != SvxZoomType::PERCENT )
+ {
+ const bool bAutomaticViewLayout = 0 == pOpt->GetViewLayoutColumns();
+
+ const SwRect aPageRect( m_pWrtShell->GetAnyCurRect( CurRectType::PageCalc ) );
+ const SwRect aRootRect( m_pWrtShell->GetAnyCurRect( CurRectType::PagesArea ) );
+ Size aPageSize( aPageRect.SSize() );
+ Size aRootSize( aRootRect.SSize() );
+
+ //mod #i6193# added sidebar width
+ SwPostItMgr* pPostItMgr = GetPostItMgr();
+ if (pPostItMgr->HasNotes() && pPostItMgr->ShowNotes())
+ aPageSize.AdjustWidth(pPostItMgr->GetSidebarWidth() + pPostItMgr->GetSidebarBorderWidth() );
+
+ const MapMode aTmpMap( MapUnit::MapTwip );
+ const Size aWindowSize( GetEditWin().PixelToLogic( rEditSize, aTmpMap ) );
+
+ if( SvxZoomType::OPTIMAL == eZoomType )
+ {
+ // unclear if this is useful for OPTIMAL, or completely useless?
+ if( UseOnPage::Mirror == rDesc.GetUseOn() ) // mirrored pages
+ {
+ const SvxLRSpaceItem &rLeftLRSpace = rDesc.GetLeft().GetLRSpace();
+ aPageSize.AdjustWidth(std::abs( rLeftLRSpace.GetLeft() - rLRSpace.GetLeft() ) );
+ }
+
+ if (!pPostItMgr->HasNotes() || !pPostItMgr->ShowNotes())
+ aPageSize.AdjustWidth( -( rLRSpace.GetLeft() + rLRSpace.GetRight() + nLeftOfst * 2 ) );
+ lLeftMargin = rLRSpace.GetLeft() + DOCUMENTBORDER + nLeftOfst;
+ nFac = aWindowSize.Width() * 100 / aPageSize.Width();
+ }
+ else if(SvxZoomType::WHOLEPAGE == eZoomType || SvxZoomType::PAGEWIDTH == eZoomType )
+ {
+ const tools::Long nOf = DOCUMENTBORDER * 2;
+ tools::Long nTmpWidth = bAutomaticViewLayout ? aPageSize.Width() : aRootSize.Width();
+ nTmpWidth += nOf;
+ aPageSize.AdjustHeight(nOf );
+ nFac = aWindowSize.Width() * 100 / nTmpWidth;
+
+ if ( SvxZoomType::WHOLEPAGE == eZoomType )
+ {
+ tools::Long nVisPercent = aWindowSize.Height() * 100 / aPageSize.Height();
+ nFac = std::min( nFac, nVisPercent );
+ }
+ }
+ else
+ {
+ const tools::Long nTmpWidth = bAutomaticViewLayout ? aPageSize.Width() : aRootSize.Width();
+ nFac = aWindowSize.Width() * 100 / nTmpWidth;
+ }
+ }
+
+ nFac = std::max( tools::Long( MINZOOM ), nFac );
+ const sal_uInt16 nZoomFac = o3tl::narrowing<sal_uInt16>(nFac);
+
+ SwViewOption aOpt( *pOpt );
+ if ( !GetViewFrame().GetFrame().IsInPlace() )
+ {
+ //Update MasterUsrPrefs and after that update the ViewOptions of the current View.
+ if ( !bViewOnly &&
+ (nZoomFac != pUsrPref->GetZoom() ||
+ eZoomType != pUsrPref->GetZoomType()) )
+ {
+ pUsrPref->SetZoom(nZoomFac);
+ pUsrPref->SetZoomType(eZoomType);
+ SW_MOD()->ApplyUsrPref(*pUsrPref, nullptr);
+ pUsrPref->SetModified();
+ }
+ if ( pOpt->GetZoom() != nZoomFac )
+ {
+ aOpt.SetZoom(nZoomFac);
+ aOpt.SetReadonly(pOpt->IsReadonly());
+ m_pWrtShell->ApplyViewOptions( aOpt );
+ }
+ if ( eZoomType != SvxZoomType::PERCENT )
+ {
+ Point aPos;
+
+ if ( eZoomType == SvxZoomType::WHOLEPAGE )
+ aPos.setY( m_pWrtShell->GetAnyCurRect(CurRectType::Page).Top() - DOCUMENTBORDER );
+ else
+ {
+ // Make sure that the cursor is in the visible range, so that
+ // the scrolling will be performed only once.
+ aPos.setX( lLeftMargin );
+ const SwRect &rCharRect = m_pWrtShell->GetCharRect();
+ if ( rCharRect.Top() > GetVisArea().Bottom() ||
+ rCharRect.Bottom() < aPos.Y() )
+ aPos.setY( rCharRect.Top() - rCharRect.Height() );
+ else
+ aPos.setY( GetVisArea().Top() );
+ }
+ SetVisArea( aPos );
+ }
+ // Compromise solution - Under certain circumstances SetZoom is called
+ // in CalcVisAreas again and thus be set wrong values.
+ const_cast<SwViewOption*>(m_pWrtShell->GetViewOptions())->SetZoomType( eZoomType );
+ CalcVisArea( rEditSize ); // for the recalculation of the viewable area
+ }
+ else if ( nZoomFac != pOpt->GetZoom() )
+ {
+ aOpt.SetZoom( nZoomFac );
+ m_pWrtShell->ApplyViewOptions( aOpt );
+ }
+
+ const Fraction aFrac( nFac, 100 );
+ m_pVRuler->SetZoom( aFrac );
+ m_pVRuler->ForceUpdate();
+ m_pHRuler->SetZoom( aFrac );
+ m_pHRuler->ForceUpdate();
+ const_cast<SwViewOption*>(m_pWrtShell->GetViewOptions())->SetZoomType( eZoomType );
+ } // end of SwActContext scope
+
+ m_pWrtShell->UnlockPaint();
+ if( bUnLockView )
+ m_pWrtShell->LockView( false );
+}
+
+void SwView::SetViewLayout( sal_uInt16 nColumns, bool bBookMode, bool bViewOnly )
+{
+ const bool bUnLockView = !m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView( true );
+ m_pWrtShell->LockPaint(LockPaintReason::ViewLayout);
+
+ {
+
+ SwActContext aActContext(m_pWrtShell.get());
+
+ if ( !GetViewFrame().GetFrame().IsInPlace() && !bViewOnly )
+ {
+ const bool bWeb = dynamic_cast< const SwWebView *>( this ) != nullptr;
+ SwMasterUsrPref *pUsrPref = const_cast<SwMasterUsrPref*>(SW_MOD()->GetUsrPref(bWeb));
+
+ // Update MasterUsrPrefs and after that update the ViewOptions of the current View.
+ if ( nColumns != pUsrPref->GetViewLayoutColumns() ||
+ bBookMode != pUsrPref->IsViewLayoutBookMode() )
+ {
+ pUsrPref->SetViewLayoutColumns(nColumns);
+ pUsrPref->SetViewLayoutBookMode(bBookMode);
+ SW_MOD()->ApplyUsrPref(*pUsrPref, nullptr);
+ pUsrPref->SetModified();
+ }
+ }
+
+ const SwViewOption *pOpt = m_pWrtShell->GetViewOptions();
+
+ if ( nColumns != pOpt->GetViewLayoutColumns() ||
+ bBookMode != pOpt->IsViewLayoutBookMode() )
+ {
+ SwViewOption aOpt( *pOpt );
+ aOpt.SetViewLayoutColumns( nColumns );
+ aOpt.SetViewLayoutBookMode( bBookMode );
+ m_pWrtShell->ApplyViewOptions( aOpt );
+ }
+
+ m_pVRuler->ForceUpdate();
+ m_pHRuler->ForceUpdate();
+
+ }
+
+ m_pWrtShell->UnlockPaint();
+ if( bUnLockView )
+ m_pWrtShell->LockView( false );
+
+ SfxBindings& rBnd = GetViewFrame().GetBindings();
+ rBnd.Invalidate( SID_ATTR_VIEWLAYOUT );
+ rBnd.Invalidate( SID_ATTR_ZOOMSLIDER);
+}
+
+// Scrollbar - Handler
+
+IMPL_LINK( SwView, WindowChildEventListener, VclWindowEvent&, rEvent, void )
+{
+ OSL_ENSURE( rEvent.GetWindow(), "Window???" );
+ vcl::Window* pChildWin = static_cast< vcl::Window* >( rEvent.GetData() );
+
+ switch ( rEvent.GetId() )
+ {
+ case VclEventId::WindowHide:
+ if( pChildWin == m_pHScrollbar )
+ ShowHScrollbar( false );
+ else if( pChildWin == m_pVScrollbar )
+ ShowVScrollbar( false );
+ break;
+ case VclEventId::WindowShow:
+ if( pChildWin == m_pHScrollbar )
+ ShowHScrollbar( true );
+ else if( pChildWin == m_pVScrollbar )
+ ShowVScrollbar( true );
+ break;
+ default: break;
+ }
+}
+
+void SwView::CreateScrollbar( bool bHori )
+{
+ vcl::Window *pMDI = &GetViewFrame().GetWindow();
+ VclPtr<SwScrollbar>& ppScrollbar = bHori ? m_pHScrollbar : m_pVScrollbar;
+
+ assert(!ppScrollbar); //check beforehand!
+
+ ppScrollbar = VclPtr<SwScrollbar>::Create( pMDI, bHori );
+ UpdateScrollbars();
+ if(bHori)
+ ppScrollbar->SetScrollHdl( LINK( this, SwView, HoriScrollHdl ));
+ else
+ ppScrollbar->SetScrollHdl( LINK( this, SwView, VertScrollHdl ));
+
+ if(GetWindow())
+ InvalidateBorder();
+
+ if (!m_bShowAtResize)
+ ppScrollbar->ExtendedShow();
+}
+
+IMPL_LINK( SwView, MoveNavigationHdl, void*, p, void )
+{
+ bool* pbNext = static_cast<bool*>(p);
+ if ( !pbNext )
+ return;
+ const bool bNext = *pbNext;
+ SwWrtShell& rSh = GetWrtShell();
+ if ( NID_SRCH_REP != s_nMoveType)
+ {
+ if ( rSh.GetDrawView()->IsTextEdit() )
+ rSh.EndTextEdit();
+ if ( IsDrawMode() )
+ LeaveDrawCreate();
+ }
+ if ( NID_POSTIT != s_nMoveType && m_pPostItMgr )
+ {
+ sw::annotation::SwAnnotationWin* pActiveSidebarWin = m_pPostItMgr->GetActiveSidebarWin();
+ if (pActiveSidebarWin)
+ pActiveSidebarWin->SwitchToFieldPos();
+ }
+ if (NID_RECENCY != s_nMoveType && NID_PGE != s_nMoveType && NID_SRCH_REP != s_nMoveType)
+ rSh.addCurrentPosition();
+ switch( s_nMoveType )
+ {
+ case NID_PGE:
+ {
+ tools::Long nYPos;
+ SwVisiblePageNumbers aVisiblePageNumbers;
+ rSh.GetFirstLastVisPageNumbers(aVisiblePageNumbers);
+ if ((bNext && aVisiblePageNumbers.nLastPhy + 1 > rSh.GetPageCnt()) ||
+ (!bNext && aVisiblePageNumbers.nFirstPhy == 1))
+ {
+ nYPos = rSh.GetPagePos(bNext ? 1 : rSh.GetPageCnt()).Y();
+ SvxSearchDialogWrapper::SetSearchLabel(bNext ? SearchLabel::EndWrapped :
+ SearchLabel::StartWrapped);
+ }
+ else
+ {
+ auto nPage = bNext ? aVisiblePageNumbers.nLastPhy + 1 :
+ aVisiblePageNumbers.nFirstPhy - 1;
+ nYPos = rSh.GetPagePos(nPage).Y();
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Empty);
+ }
+ const Point aPt(GetVisArea().Left(), nYPos);
+ Point aAlPt(AlignToPixel(aPt));
+ // If there is a difference, has been truncated --> then add one pixel,
+ // so that no residue of the previous page is visible.
+ if(aPt.Y() != aAlPt.Y())
+ aAlPt.AdjustY(3 * GetEditWin().PixelToLogic(Size(0, 1)).Height());
+ SetVisArea(aAlPt);
+ }
+ break;
+ case NID_TBL :
+ rSh.EnterStdMode();
+ if(bNext)
+ rSh.MoveTable(GotoNextTable, fnTableStart);
+ else
+ rSh.MoveTable(GotoPrevTable, fnTableStart);
+ break;
+ case NID_FRM :
+ case NID_GRF:
+ case NID_OLE:
+ {
+ GotoObjFlags eType = GotoObjFlags::FlyFrame;
+ if(s_nMoveType == NID_GRF)
+ eType = GotoObjFlags::FlyGrf;
+ else if(s_nMoveType == NID_OLE)
+ eType = GotoObjFlags::FlyOLE;
+ bool bSuccess = bNext ?
+ rSh.GotoNextFly(eType) :
+ rSh.GotoPrevFly(eType);
+ if(bSuccess)
+ {
+ rSh.HideCursor();
+ rSh.EnterSelFrameMode();
+ }
+ }
+ break;
+ case NID_CTRL:
+ if (!rSh.GetView().IsDesignMode())
+ rSh.GetView().GetFormShell()->SetDesignMode(true);
+ [[fallthrough]];
+ case NID_DRW:
+ {
+ bool bSuccess = rSh.GotoObj(bNext,
+ s_nMoveType == NID_DRW ?
+ GotoObjFlags::DrawSimple :
+ GotoObjFlags::DrawControl);
+ if(bSuccess)
+ {
+ rSh.HideCursor();
+ rSh.EnterSelFrameMode();
+ }
+ }
+ break;
+ case NID_REG :
+ rSh.EnterStdMode();
+ if(bNext)
+ rSh.MoveRegion(GotoNextRegion, fnRegionStart);
+ else
+ rSh.MoveRegion(GotoPrevRegion, fnRegionStart);
+
+ break;
+ case NID_BKM :
+ rSh.EnterStdMode();
+ GetViewFrame().GetDispatcher()->Execute(bNext ?
+ FN_NEXT_BOOKMARK :
+ FN_PREV_BOOKMARK);
+ break;
+ case NID_FIELD:
+ {
+ rSh.EnterStdMode();
+ rSh.StartAction();
+ SearchLabel eSearchLabel = SearchLabel::Empty;
+ if (!rSh.MoveFieldType(nullptr, bNext, SwFieldIds::Unknown))
+ {
+ // no field found in the move direction
+ // wrap and try again
+ SwShellCursor* pCursor = rSh.GetCursor_();
+ SwCursorSaveState aSaveState(*pCursor);
+ rSh.SttEndDoc(bNext);
+ // document might have a field at the start of the document
+ SwField* pField = rSh.GetCurField();
+ if ((bNext && pField && pField->GetTypeId() != SwFieldTypesEnum::Postit) ||
+ rSh.MoveFieldType(nullptr, bNext, SwFieldIds::Unknown))
+ {
+ eSearchLabel = bNext ? SearchLabel::EndWrapped : SearchLabel::StartWrapped;
+ }
+ else
+ {
+ // no visible fields found
+ pCursor->RestoreSavePos();
+ eSearchLabel = SearchLabel::NavElementNotFound;
+ }
+ }
+ SvxSearchDialogWrapper::SetSearchLabel(eSearchLabel);
+ rSh.EndAction();
+ }
+ break;
+ case NID_FIELD_BYTYPE:
+ {
+ // see: SwFieldMgr::GoNextPrev
+ SwField* pCurField = rSh.GetCurField(true);
+ if (!pCurField)
+ break;
+ rSh.EnterStdMode();
+ SwFieldType* pTyp = nullptr;
+ const SwFieldTypesEnum nTypeId = pCurField->GetTypeId();
+ if (SwFieldTypesEnum::SetInput == nTypeId || SwFieldTypesEnum::UserInput == nTypeId)
+ pTyp = rSh.GetFieldType(0, SwFieldIds::Input);
+ else
+ pTyp = pCurField->GetTyp();
+ if (pTyp)
+ {
+ if (pTyp->Which() == SwFieldIds::Database)
+ rSh.MoveFieldType(nullptr, bNext, SwFieldIds::Database);
+ else
+ rSh.MoveFieldType(pTyp, bNext);
+ }
+ }
+ break;
+ case NID_OUTL:
+ rSh.EnterStdMode();
+ bNext ? rSh.GotoNextOutline() : rSh.GotoPrevOutline();
+ break;
+ case NID_SEL :
+ rSh.GoNextPrevCursorSetSearchLabel(bNext);
+ break;
+ case NID_FTN:
+ {
+ bool bFrameTypeFootnote(rSh.GetFrameType(nullptr, false) & FrameTypeFlags::FOOTNOTE);
+
+ if (bFrameTypeFootnote)
+ {
+ rSh.LockView(true);
+ rSh.GotoFootnoteAnchor();
+ }
+
+ rSh.EnterStdMode();
+ bNext ?
+ rSh.GotoNextFootnoteAnchor() :
+ rSh.GotoPrevFootnoteAnchor();
+
+ if (bFrameTypeFootnote)
+ {
+ rSh.LockView(false);
+ rSh.GotoFootnoteText();
+ }
+ }
+ break;
+ case NID_MARK:
+ {
+ // unselect
+ rSh.MoveCursor();
+ rSh.EnterStdMode();
+
+ // collect and sort navigator reminder names
+ IDocumentMarkAccess* const pMarkAccess = rSh.getIDocumentMarkAccess();
+ std::vector< OUString > vNavMarkNames;
+ for(IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getAllMarksBegin();
+ ppMark != pMarkAccess->getAllMarksEnd();
+ ++ppMark)
+ {
+ if( IDocumentMarkAccess::GetType(**ppMark) == IDocumentMarkAccess::MarkType::NAVIGATOR_REMINDER )
+ vNavMarkNames.push_back((*ppMark)->GetName());
+ }
+ std::sort(vNavMarkNames.begin(), vNavMarkNames.end());
+
+ // move
+ if(!vNavMarkNames.empty())
+ {
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
+
+ if(bNext)
+ {
+ s_nActMark++;
+ if (s_nActMark >= MAX_MARKS || s_nActMark >= static_cast<sal_Int32>(vNavMarkNames.size()))
+ {
+ s_nActMark = 0;
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::ReminderEndWrapped );
+ }
+ }
+ else
+ {
+ s_nActMark--;
+ if (s_nActMark < 0 || o3tl::make_unsigned(s_nActMark) >= vNavMarkNames.size())
+ {
+ s_nActMark = vNavMarkNames.size()-1;
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::ReminderStartWrapped );
+ }
+ }
+ rSh.GotoMark(vNavMarkNames[s_nActMark]);
+ }
+ else
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
+ }
+ break;
+
+ case NID_POSTIT:
+ {
+ if (m_pPostItMgr->HasNotes())
+ {
+ rSh.EnterStdMode();
+ m_pPostItMgr->AssureStdModeAtShell();
+ m_pPostItMgr->SetActiveSidebarWin(nullptr);
+ GetEditWin().GrabFocus();
+ SwShellCursor* pCursor = rSh.GetCursor_();
+ SwCursorSaveState aSaveState(*pCursor);
+ SwFieldType* pFieldType = rSh.GetFieldType(0, SwFieldIds::Postit);
+ bool bWrapped = false;
+ bool bFound = false;
+ rSh.StartAction();
+ while (!bFound)
+ {
+ if (!rSh.MoveFieldType(pFieldType, bNext))
+ {
+ if (bWrapped)
+ break;
+ bWrapped = true;
+ rSh.SttEndDoc(bNext);
+ continue;
+ }
+ do
+ {
+ auto pAnnotationWin = m_pPostItMgr->GetAnnotationWin(
+ rSh.GetPostItFieldAtCursor());
+ if (pAnnotationWin && pAnnotationWin->IsVisible())
+ bFound = true;
+ } while (!bFound && rSh.MoveFieldType(pFieldType, bNext));
+ }
+ if (!bFound)
+ {
+ pCursor->RestoreSavePos();
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NavElementNotFound);
+ }
+ rSh.EndAction();
+ if (bFound)
+ {
+ GetViewFrame().GetDispatcher()->Execute(FN_POSTIT);
+ if (bWrapped)
+ SvxSearchDialogWrapper::SetSearchLabel(bNext ? SearchLabel::EndWrapped :
+ SearchLabel::StartWrapped);
+ else
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Empty);
+ }
+ }
+ else
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NavElementNotFound);
+ }
+ break;
+
+ case NID_SRCH_REP:
+ if(s_pSrchItem)
+ {
+ bool bBackward = s_pSrchItem->GetBackward();
+ if (rSh.HasSelection() && bNext != rSh.IsCursorPtAtEnd())
+ rSh.SwapPam();
+ s_pSrchItem->SetBackward(!bNext);
+ SfxRequest aReq(FN_REPEAT_SEARCH, SfxCallMode::SLOT, GetPool());
+ ExecSearch(aReq);
+ s_pSrchItem->SetBackward(bBackward);
+ }
+ break;
+ case NID_INDEX_ENTRY:
+ rSh.GotoNxtPrvTOXMark(bNext);
+ break;
+
+ case NID_TABLE_FORMULA:
+ rSh.GotoNxtPrvTableFormula( bNext );
+ break;
+
+ case NID_TABLE_FORMULA_ERROR:
+ rSh.GotoNxtPrvTableFormula( bNext, true );
+ break;
+
+ case NID_RECENCY :
+ rSh.EnterStdMode();
+ bNext ? rSh.GetNavigationMgr().goForward() : rSh.GetNavigationMgr().goBack();
+ break;
+ }
+ if (NID_POSTIT != s_nMoveType)
+ m_pEditWin->GrabFocus();
+ delete pbNext;
+}
+
+void SwView::CreateTab()
+{
+ m_pHRuler->SetActive(GetFrame() && IsActive());
+
+ m_pHRuler->Show();
+ InvalidateBorder();
+}
+
+void SwView::KillTab()
+{
+ m_pHRuler->Hide();
+ InvalidateBorder();
+}
+
+void SwView::ChangeTabMetric( FieldUnit eUnit )
+{
+ if(m_pHRuler->GetUnit() != eUnit )
+ {
+ m_pHRuler->SetUnit( eUnit );
+ m_pHRuler->Invalidate();
+ }
+}
+
+void SwView::ChangeVRulerMetric( FieldUnit eUnit )
+{
+ if(m_pVRuler->GetUnit() != eUnit)
+ {
+ m_pVRuler->SetUnit( eUnit );
+ m_pVRuler->Invalidate();
+ }
+}
+
+void SwView::GetVRulerMetric(FieldUnit& eToFill) const
+{
+ eToFill = m_pVRuler->GetUnit();
+}
+
+void SwView::GetHRulerMetric(FieldUnit& eToFill) const
+{
+ eToFill = m_pHRuler->GetUnit();
+}
+
+void SwView::CreateVRuler()
+{
+ m_pHRuler->SetBorderPos( m_pVRuler->GetSizePixel().Width()-1 );
+
+ m_pVRuler->SetActive(GetFrame() && IsActive());
+ m_pVRuler->Show();
+ InvalidateBorder();
+}
+
+void SwView::KillVRuler()
+{
+ m_pVRuler->Hide();
+ m_pHRuler->SetBorderPos();
+ InvalidateBorder();
+}
+
+IMPL_LINK( SwView, ExecRulerClick, Ruler *, pRuler, void )
+{
+ OUString sDefPage;
+ TypedWhichId<SfxStringItem> nDefDlg = SID_PARA_DLG;
+ switch( pRuler->GetClickType() )
+ {
+ case RulerType::DontKnow:
+ case RulerType::Outside:
+ sDefPage="labelTP_BORDER";
+ break;
+ case RulerType::Indent:
+ sDefPage="labelTP_PARA_STD";
+ break;
+ case RulerType::Margin1:
+ case RulerType::Margin2:
+ nDefDlg= FN_FORMAT_PAGE_DLG;
+ sDefPage = "page";
+ break;
+ default:
+ sDefPage = "labelTP_TABULATOR";
+
+ }
+
+ SfxStringItem aDefPage(nDefDlg, sDefPage);
+ GetViewFrame().GetDispatcher()->ExecuteList(nDefDlg,
+ SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
+ { &aDefPage });
+}
+
+sal_uInt16 SwView::GetMoveType()
+{
+ return s_nMoveType;
+}
+
+void SwView::SetMoveType(sal_uInt16 nSet)
+{
+ s_nMoveType = nSet;
+}
+
+void SwView::SetActMark(sal_Int32 nSet)
+{
+ s_nActMark = nSet;
+}
+
+void SwView::ShowHScrollbar(bool bShow)
+{
+ assert(m_pHScrollbar && "Scrollbar invalid");
+ m_pHScrollbar->ExtendedShow(bShow);
+}
+
+bool SwView::IsHScrollbarVisible()const
+{
+ assert(m_pHScrollbar && "Scrollbar invalid");
+ return m_pHScrollbar->IsScrollbarVisible(false) || m_pHScrollbar->IsAuto();
+}
+
+void SwView::ShowVScrollbar(bool bShow)
+{
+ assert(m_pVScrollbar && "Scrollbar invalid");
+ m_pVScrollbar->ExtendedShow(bShow);
+}
+
+bool SwView::IsVScrollbarVisible()const
+{
+ assert(m_pVScrollbar && "Scrollbar invalid");
+ return m_pVScrollbar->IsScrollbarVisible(false);
+}
+
+void SwView::EnableHScrollbar(bool bEnable)
+{
+ if (m_bHScrollbarEnabled != bEnable)
+ {
+ m_bHScrollbarEnabled = bEnable;
+ InvalidateBorder();
+ }
+}
+
+void SwView::EnableVScrollbar(bool bEnable)
+{
+ if (m_bVScrollbarEnabled != bEnable)
+ {
+ m_bVScrollbarEnabled = bEnable;
+ InvalidateBorder();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewport.cxx b/sw/source/uibase/uiview/viewport.cxx
new file mode 100644
index 0000000000..08d9b0c393
--- /dev/null
+++ b/sw/source/uibase/uiview/viewport.cxx
@@ -0,0 +1,1262 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/commandevent.hxx>
+#include <vcl/help.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/syswin.hxx>
+
+#include <svx/ruler.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <viewopt.hxx>
+#include <docsh.hxx>
+#include <cmdid.h>
+#include <edtwin.hxx>
+#include <scroll.hxx>
+
+#include <PostItMgr.hxx>
+
+#include <basegfx/utils/zoomtools.hxx>
+#include <comphelper/lok.hxx>
+#include <vcl/weld.hxx>
+#include <tools/svborder.hxx>
+#include <osl/diagnose.h>
+
+#include "viewfunc.hxx"
+
+#include <FrameControlsManager.hxx>
+
+// The SetVisArea of the DocShell must not be called from InnerResizePixel.
+// But our adjustments must take place.
+static bool bProtectDocShellVisArea = false;
+
+static sal_uInt16 nPgNum = 0;
+
+bool SwView::IsDocumentBorder()
+{
+ if (GetDocShell()->GetCreateMode() == SfxObjectCreateMode::EMBEDDED)
+ return true;
+
+ if (!m_pWrtShell)
+ return false;
+
+ return m_pWrtShell->GetViewOptions()->getBrowseMode() ||
+ SvxZoomType::PAGEWIDTH_NOBORDER == m_pWrtShell->GetViewOptions()->GetZoomType();
+}
+
+static tools::Long GetLeftMargin( SwView const &rView )
+{
+ SvxZoomType eType = rView.GetWrtShell().GetViewOptions()->GetZoomType();
+ tools::Long lRet = rView.GetWrtShell().GetAnyCurRect(CurRectType::PagePrt).Left();
+ return eType == SvxZoomType::PERCENT ? lRet + DOCUMENTBORDER :
+ eType == SvxZoomType::PAGEWIDTH || eType == SvxZoomType::PAGEWIDTH_NOBORDER ? 0 :
+ lRet + DOCUMENTBORDER + nLeftOfst;
+}
+
+static void lcl_GetPos(SwView const * pView,
+ Point& rPos,
+ const weld::Scrollbar& rScrollbar,
+ bool bHori,
+ bool bBorder)
+{
+ SwWrtShell &rSh = pView->GetWrtShell();
+ const Size aDocSz( rSh.GetDocSize() );
+
+ const tools::Long lBorder = bBorder ? DOCUMENTBORDER : DOCUMENTBORDER * 2;
+
+ const tools::Long lPos = rScrollbar.adjustment_get_value() + (bBorder ? DOCUMENTBORDER : 0);
+
+ tools::Long lDelta = lPos - (bHori ? rSh.VisArea().Pos().X() : rSh.VisArea().Pos().Y());
+
+ const tools::Long lSize = (bHori ? aDocSz.Width() : aDocSz.Height()) + lBorder;
+ // Should right or below are too much space,
+ // then they must be subtracted out of the VisArea!
+ tools::Long nTmp = pView->GetVisArea().Right()+lDelta;
+ if ( bHori && nTmp > lSize )
+ lDelta -= nTmp - lSize;
+ nTmp = pView->GetVisArea().Bottom()+lDelta;
+ if ( !bHori && nTmp > lSize )
+ lDelta -= nTmp - lSize;
+
+ bHori ? rPos.AdjustX(lDelta) : rPos.AdjustY(lDelta);
+ if ( bBorder && (bHori ? rPos.X() : rPos.Y()) < DOCUMENTBORDER )
+ bHori ? rPos.setX(DOCUMENTBORDER) : rPos.setY(DOCUMENTBORDER);
+}
+
+// Set zero ruler
+
+void SwView::InvalidateRulerPos()
+{
+ static sal_uInt16 aInval[] =
+ {
+ SID_ATTR_PARA_LRSPACE, SID_RULER_BORDERS, SID_RULER_PAGE_POS,
+ SID_RULER_LR_MIN_MAX, SID_ATTR_LONG_ULSPACE, SID_ATTR_LONG_LRSPACE,
+ SID_RULER_BORDER_DISTANCE,
+ SID_ATTR_PARA_LRSPACE_VERTICAL, SID_RULER_BORDERS_VERTICAL,
+ SID_RULER_TEXT_RIGHT_TO_LEFT,
+ SID_RULER_ROWS, SID_RULER_ROWS_VERTICAL, FN_STAT_PAGE,
+ 0
+ };
+
+ GetViewFrame().GetBindings().Invalidate(aInval);
+
+ assert(m_pHRuler && "Why is the ruler not there?");
+ m_pHRuler->ForceUpdate();
+ m_pVRuler->ForceUpdate();
+}
+
+// Limits the scrolling so far that only a quarter of the
+// screen can be scrolled up before the end of the document.
+
+tools::Long SwView::SetHScrollMax( tools::Long lMax )
+{
+ const tools::Long lBorder = IsDocumentBorder() ? DOCUMENTBORDER : DOCUMENTBORDER * 2;
+ const tools::Long lSize = GetDocSz().Width() + lBorder - m_aVisArea.GetWidth();
+
+ // At negative values the document is completely visible.
+ // In this case, no scrolling.
+ return std::clamp( lSize, tools::Long(0), lMax );
+}
+
+tools::Long SwView::SetVScrollMax( tools::Long lMax )
+{
+ const tools::Long lBorder = IsDocumentBorder() ? DOCUMENTBORDER : DOCUMENTBORDER * 2;
+ tools::Long lSize = GetDocSz().Height() + lBorder - m_aVisArea.GetHeight();
+ return std::clamp( lSize, tools::Long(0), lMax ); // see horizontal
+}
+
+Point SwView::AlignToPixel(const Point &rPt) const
+{
+ return GetEditWin().PixelToLogic( GetEditWin().LogicToPixel( rPt ) );
+}
+
+// Document size has changed.
+
+void SwView::DocSzChgd(const Size &rSz)
+{
+ m_aDocSz = rSz;
+
+ if( !m_pWrtShell || m_aVisArea.IsEmpty() ) // no shell -> no change
+ {
+ bDocSzUpdated = false;
+ return;
+ }
+
+ //If text has been deleted, it may be that the VisArea points behind the visible range.
+ tools::Rectangle aNewVisArea( m_aVisArea );
+ bool bModified = false;
+ SwTwips lGreenOffset = IsDocumentBorder() ? DOCUMENTBORDER : DOCUMENTBORDER * 2;
+ SwTwips lTmp = m_aDocSz.Width() + lGreenOffset;
+
+ if ( aNewVisArea.Right() >= lTmp )
+ {
+ lTmp = aNewVisArea.Right() - lTmp;
+ aNewVisArea.AdjustRight( -lTmp );
+ aNewVisArea.AdjustLeft( -lTmp );
+ bModified = true;
+ }
+
+ lTmp = m_aDocSz.Height() + lGreenOffset;
+ if ( aNewVisArea.Bottom() >= lTmp )
+ {
+ lTmp = aNewVisArea.Bottom() - lTmp;
+ aNewVisArea.AdjustBottom( -lTmp );
+ aNewVisArea.AdjustTop( -lTmp );
+ bModified = true;
+ }
+
+ if ( bModified )
+ SetVisArea( aNewVisArea, false );
+
+ if ( UpdateScrollbars() && !m_bInOuterResizePixel && !m_bInInnerResizePixel &&
+ !GetViewFrame().GetFrame().IsInPlace())
+ OuterResizePixel( Point(),
+ GetViewFrame().GetWindow().GetOutputSizePixel() );
+}
+
+// Set VisArea newly
+
+void SwView::SetVisArea( const tools::Rectangle &rRect, bool bUpdateScrollbar )
+{
+ Size aOldSz( m_aVisArea.GetSize() );
+ if (comphelper::LibreOfficeKit::isActive() && m_pWrtShell)
+ // If m_pWrtShell's visible area is the whole document, do the same here.
+ aOldSz = m_pWrtShell->VisArea().SSize();
+
+ if( rRect == m_aVisArea )
+ return;
+
+ const SwTwips lMin = IsDocumentBorder() ? DOCUMENTBORDER : 0;
+
+ // No negative position, no negative size
+ tools::Rectangle aLR = rRect;
+ if( aLR.Top() < lMin )
+ {
+ aLR.AdjustBottom(lMin - aLR.Top() );
+ aLR.SetTop( lMin );
+ }
+ if( aLR.Left() < lMin )
+ {
+ aLR.AdjustRight(lMin - aLR.Left() );
+ aLR.SetLeft( lMin );
+ }
+ if( aLR.Right() < 0 )
+ aLR.SetRight( 0 );
+ if( aLR.Bottom() < 0 )
+ aLR.SetBottom( 0 );
+
+ if( aLR == m_aVisArea )
+ return;
+
+ const Size aSize( aLR.GetSize() );
+ if( aSize.IsEmpty() )
+ return;
+
+ // Before the data can be changed, call an update if necessary. This
+ // ensures that adjacent Paints in document coordinates are converted
+ // correctly.
+ // As a precaution, we do this only when an action is running in the
+ // shell, because then it is not really drawn but the rectangles will
+ // be only marked (in document coordinates).
+ if ( m_pWrtShell && m_pWrtShell->ActionPend() )
+ m_pWrtShell->GetWin()->PaintImmediately();
+
+ m_aVisArea = aLR;
+
+ const bool bOuterResize = bUpdateScrollbar && UpdateScrollbars();
+
+ if ( m_pWrtShell )
+ {
+ m_pWrtShell->VisPortChgd( SwRect(m_aVisArea) );
+ if ( aOldSz != m_pWrtShell->VisArea().SSize() &&
+ ( std::abs(aOldSz.Width() - m_pWrtShell->VisArea().Width()) > 2 ||
+ std::abs(aOldSz.Height() - m_pWrtShell->VisArea().Height()) > 2 ) )
+ m_pWrtShell->InvalidateLayout( false );
+ }
+
+ if ( !bProtectDocShellVisArea )
+ {
+ // If the size of VisArea is unchanged, we extend the size of the VisArea
+ // InternalObject on. By that the transport of errors shall be avoided.
+ tools::Rectangle aVis( m_aVisArea );
+ if ( aVis.GetSize() == aOldSz )
+ aVis.SetSize( GetDocShell()->SfxObjectShell::GetVisArea(ASPECT_CONTENT).GetSize() );
+ // TODO/LATER: why casting?!
+ //GetDocShell()->SfxInPlaceObject::GetVisArea().GetSize() );
+
+ // With embedded always with modify...
+ // TODO/LATER: why casting?!
+ GetDocShell()->SfxObjectShell::SetVisArea( aVis );
+ /*
+ if ( GetDocShell()->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
+ GetDocShell()->SfxInPlaceObject::SetVisArea( aVis );
+ else
+ GetDocShell()->SvEmbeddedObject::SetVisArea( aVis );*/
+ }
+
+ SfxViewShell::VisAreaChanged();
+
+ InvalidateRulerPos();
+
+ if ( bOuterResize && !m_bInOuterResizePixel && !m_bInInnerResizePixel)
+ OuterResizePixel( Point(),
+ GetViewFrame().GetWindow().GetOutputSizePixel() );
+}
+
+// Set Pos VisArea
+
+void SwView::SetVisArea( const Point &rPt, bool bUpdateScrollbar )
+{
+ // Align once, so brushes will be inserted correctly.
+ // This goes wrong in the BrowseView, because the entire document may
+ // not be visible. Since the content in frames is fitting exactly,
+ // align is not possible (better idea?!?!)
+ // (fix: Bild.de, 200%) It does not work completely without alignment
+ // Let's see how far we get with half BrushSize.
+ Point aPt = GetEditWin().LogicToPixel( rPt );
+#if HAVE_FEATURE_DESKTOP
+ const tools::Long nTmp = 8;
+ aPt.AdjustX( -(aPt.X() % nTmp) );
+ aPt.AdjustY( -(aPt.Y() % nTmp) );
+#endif
+ aPt = GetEditWin().PixelToLogic( aPt );
+
+ if ( aPt == m_aVisArea.TopLeft() )
+ return;
+
+ if (GetWrtShell().GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ GetEditWin().GetFrameControlsManager().HideControls(FrameControlType::Outline);
+
+ const tools::Long lXDiff = m_aVisArea.Left() - aPt.X();
+ const tools::Long lYDiff = m_aVisArea.Top() - aPt.Y();
+ SetVisArea( tools::Rectangle( aPt,
+ Point( m_aVisArea.Right() - lXDiff, m_aVisArea.Bottom() - lYDiff ) ),
+ bUpdateScrollbar);
+}
+
+void SwView::CheckVisArea()
+{
+ if (m_pHScrollbar)
+ m_pHScrollbar->SetAuto( m_pWrtShell->GetViewOptions()->getBrowseMode() &&
+ !GetViewFrame().GetFrame().IsInPlace() );
+ if ( IsDocumentBorder() )
+ {
+ if ( m_aVisArea.Left() != DOCUMENTBORDER ||
+ m_aVisArea.Top() != DOCUMENTBORDER )
+ {
+ tools::Rectangle aNewVisArea( m_aVisArea );
+ aNewVisArea.Move( DOCUMENTBORDER - m_aVisArea.Left(),
+ DOCUMENTBORDER - m_aVisArea.Top() );
+ SetVisArea( aNewVisArea );
+ }
+ }
+}
+
+/// Calculate the visible range.
+
+// OUT Point *pPt: new position of the visible area
+
+// IN Rectangle &rRect: Rectangle, which should be located
+// within the new visible area.
+// sal_uInt16 nRange optional accurate indication of the
+// range by which to scroll if necessary.
+
+void SwView::CalcPt( Point *pPt, const tools::Rectangle &rRect,
+ sal_uInt16 nRangeX, sal_uInt16 nRangeY)
+{
+
+ const SwTwips lMin = IsDocumentBorder() ? DOCUMENTBORDER : 0;
+
+ tools::Long nYScroll = GetYScroll();
+ tools::Long nDesHeight = rRect.GetHeight();
+ tools::Long nCurHeight = m_aVisArea.GetHeight();
+ nYScroll = std::min(nYScroll, nCurHeight - nDesHeight); // If it is scarce, then scroll not too much.
+ if(nDesHeight > nCurHeight) // the height is not sufficient, then nYScroll is no longer of interest
+ {
+ pPt->setY( rRect.Top() );
+ pPt->setY( std::max( lMin, SwTwips(pPt->Y()) ) );
+ }
+ else if ( rRect.Top() < m_aVisArea.Top() ) // Upward shift
+ {
+ pPt->setY( rRect.Top() - (nRangeY != USHRT_MAX ? nRangeY : nYScroll) );
+ pPt->setY( std::max( lMin, SwTwips(pPt->Y()) ) );
+ }
+ else if( rRect.Bottom() > m_aVisArea.Bottom() ) // Downward shift
+ {
+ pPt->setY( rRect.Bottom() -
+ (m_aVisArea.GetHeight()) + ( nRangeY != USHRT_MAX ?
+ nRangeY : nYScroll ) );
+ pPt->setY( SetVScrollMax( pPt->Y() ) );
+ }
+ tools::Long nXScroll = GetXScroll();
+ if ( rRect.Right() > m_aVisArea.Right() ) // Shift right
+ {
+ pPt->setX( rRect.Right() -
+ (m_aVisArea.GetWidth()) +
+ (nRangeX != USHRT_MAX ? nRangeX : nXScroll) );
+ pPt->setX( SetHScrollMax( pPt->X() ) );
+ }
+ else if ( rRect.Left() < m_aVisArea.Left() ) // Shift left
+ {
+ pPt->setX( rRect.Left() - (nRangeX != USHRT_MAX ? nRangeX : nXScroll) );
+ pPt->setX( std::max( ::GetLeftMargin( *this ) + nLeftOfst, pPt->X() ) );
+ pPt->setX( std::min( rRect.Left() - nScrollX, pPt->X() ) );
+ pPt->setX( std::max( tools::Long(0), pPt->X() ) );
+ }
+}
+
+// Scrolling
+
+bool SwView::IsScroll( const tools::Rectangle &rRect ) const
+{
+ return m_bCenterCursor || m_bTopCursor || !m_aVisArea.Contains(rRect);
+}
+
+void SwView::Scroll( const tools::Rectangle &rRect, sal_uInt16 nRangeX, sal_uInt16 nRangeY )
+{
+ if ( m_aVisArea.IsEmpty() )
+ return;
+
+ tools::Rectangle aOldVisArea( m_aVisArea );
+ tools::Long nDiffY = 0;
+
+ weld::Window* pCareDialog = SwViewShell::GetCareDialog(GetWrtShell());
+ if (pCareDialog)
+ {
+ int x, y, width, height;
+ tools::Rectangle aDlgRect;
+ if (pCareDialog->get_extents_relative_to(*GetEditWin().GetFrameWeld(), x, y, width, height))
+ {
+ AbsoluteScreenPixelPoint aTopLeftAbs(GetEditWin().GetSystemWindow()->OutputToAbsoluteScreenPixel(Point(x, y)));
+ Point aTopLeft = GetEditWin().AbsoluteScreenToOutputPixel(aTopLeftAbs);
+ aDlgRect = GetEditWin().PixelToLogic(tools::Rectangle(aTopLeft, Size(width, height)));
+ }
+
+ // Only if the dialogue is not the VisArea right or left:
+ if ( aDlgRect.Left() < m_aVisArea.Right() &&
+ aDlgRect.Right() > m_aVisArea.Left() )
+ {
+ // If we are not supposed to be centered, lying in the VisArea
+ // and are not covered by the dialogue ...
+ if ( !m_bCenterCursor && aOldVisArea.Contains( rRect )
+ && ( rRect.Left() > aDlgRect.Right()
+ || rRect.Right() < aDlgRect.Left()
+ || rRect.Top() > aDlgRect.Bottom()
+ || rRect.Bottom() < aDlgRect.Top() ) )
+ return;
+
+ // Is above or below the dialogue more space?
+ tools::Long nTopDiff = aDlgRect.Top() - m_aVisArea.Top();
+ tools::Long nBottomDiff = m_aVisArea.Bottom() - aDlgRect.Bottom();
+ if ( nTopDiff < nBottomDiff )
+ {
+ if ( nBottomDiff > 0 ) // Is there room below at all?
+ { // then we move the upper edge and we remember this
+ nDiffY = aDlgRect.Bottom() - m_aVisArea.Top();
+ m_aVisArea.AdjustTop(nDiffY );
+ }
+ }
+ else
+ {
+ if ( nTopDiff > 0 ) // Is there room below at all?
+ m_aVisArea.SetBottom( aDlgRect.Top() ); // Modify the lower edge
+ }
+ }
+ }
+
+ //s.o. !IsScroll()
+ if( !(m_bCenterCursor || m_bTopCursor) && m_aVisArea.Contains( rRect ) )
+ {
+ m_aVisArea = aOldVisArea;
+ return;
+ }
+ // If the rectangle is larger than the visible area -->
+ // upper left corner
+ Size aSize( rRect.GetSize() );
+ const Size aVisSize( m_aVisArea.GetSize() );
+ if( !m_aVisArea.IsEmpty() && (
+ aSize.Width() + GetXScroll() > aVisSize.Width() ||
+ aSize.Height()+ GetYScroll() > aVisSize.Height() ))
+ {
+ Point aPt( m_aVisArea.TopLeft() );
+ aSize.setWidth( std::min( aSize.Width(), aVisSize.Width() ) );
+ aSize.setHeight( std::min( aSize.Height(),aVisSize.Height()) );
+
+ CalcPt( &aPt, tools::Rectangle( rRect.TopLeft(), aSize ),
+ static_cast< sal_uInt16 >((aVisSize.Width() - aSize.Width()) / 2),
+ static_cast< sal_uInt16 >((aVisSize.Height()- aSize.Height())/ 2) );
+
+ if( m_bTopCursor )
+ {
+ const tools::Long nBorder = IsDocumentBorder() ? DOCUMENTBORDER : 0;
+ aPt.setY( std::min( std::max( nBorder, rRect.Top() ),
+ m_aDocSz.Height() + nBorder -
+ m_aVisArea.GetHeight() ) );
+ }
+ aPt.AdjustY( -nDiffY );
+ m_aVisArea = aOldVisArea;
+ SetVisArea( aPt );
+ return;
+ }
+ if( !m_bCenterCursor )
+ {
+ Point aPt( m_aVisArea.TopLeft() );
+ CalcPt( &aPt, rRect, nRangeX, nRangeY );
+
+ if( m_bTopCursor )
+ {
+ const tools::Long nBorder = IsDocumentBorder() ? DOCUMENTBORDER : 0;
+ aPt.setY( std::min( std::max( nBorder, rRect.Top() ),
+ m_aDocSz.Height() + nBorder -
+ m_aVisArea.GetHeight() ) );
+ }
+
+ aPt.AdjustY( -nDiffY );
+ m_aVisArea = aOldVisArea;
+ SetVisArea( aPt );
+ return;
+ }
+
+ //Center cursor
+ Point aPnt( m_aVisArea.TopLeft() );
+ // ... in Y-direction in any case
+ aPnt.AdjustY(( rRect.Top() + rRect.Bottom()
+ - m_aVisArea.Top() - m_aVisArea.Bottom() ) / 2 - nDiffY );
+ // ... in X-direction, only if the rectangle protrudes over the right or left of the VisArea.
+ if ( rRect.Right() > m_aVisArea.Right() || rRect.Left() < m_aVisArea.Left() )
+ {
+ aPnt.AdjustX(( rRect.Left() + rRect.Right()
+ - m_aVisArea.Left() - m_aVisArea.Right() ) / 2 );
+ aPnt.setX( SetHScrollMax( aPnt.X() ) );
+ const SwTwips lMin = IsDocumentBorder() ? DOCUMENTBORDER : 0;
+ aPnt.setX( std::max( (GetLeftMargin( *this ) - lMin) + nLeftOfst, aPnt.X() ) );
+ }
+ m_aVisArea = aOldVisArea;
+ if (pCareDialog)
+ {
+ // If we want to avoid only a dialogue, we do
+ // not want to go beyond the end of the document.
+ aPnt.setY( SetVScrollMax( aPnt.Y() ) );
+ }
+ SetVisArea( aPnt );
+}
+
+/// Scroll page by page
+// Returns the value by which to be scrolled with PageUp / Down
+
+bool SwView::GetPageScrollUpOffset( SwTwips &rOff ) const
+{
+ // in the LOK case, force the value set by the API
+ if (comphelper::LibreOfficeKit::isActive() && m_nLOKPageUpDownOffset > 0)
+ {
+ rOff = -m_nLOKPageUpDownOffset;
+ return true;
+ }
+
+ if ( !m_aVisArea.Top() || !m_aVisArea.GetHeight() )
+ return false;
+ tools::Long nYScrl = GetYScroll() / 2;
+ rOff = -(m_aVisArea.GetHeight() - nYScrl);
+ // Do not scroll before the beginning of the document.
+ if( m_aVisArea.Top() - rOff < 0 )
+ rOff = rOff - m_aVisArea.Top();
+ else if( GetWrtShell().GetCharRect().Top() < (m_aVisArea.Top() + nYScrl))
+ rOff += nYScrl;
+
+ return true;
+}
+
+bool SwView::GetPageScrollDownOffset( SwTwips &rOff ) const
+{
+ // in the LOK case, force the value set by the API
+ if (comphelper::LibreOfficeKit::isActive() && m_nLOKPageUpDownOffset > 0)
+ {
+ rOff = m_nLOKPageUpDownOffset;
+ return true;
+ }
+
+ if ( !m_aVisArea.GetHeight() ||
+ (m_aVisArea.GetHeight() > m_aDocSz.Height()) )
+ return false;
+ tools::Long nYScrl = GetYScroll() / 2;
+ rOff = m_aVisArea.GetHeight() - nYScrl;
+ // Do not scroll past the end of the document.
+ if ( m_aVisArea.Top() + rOff > m_aDocSz.Height() )
+ rOff = m_aDocSz.Height() - m_aVisArea.Bottom();
+ else if( GetWrtShell().GetCharRect().Bottom() >
+ ( m_aVisArea.Bottom() - nYScrl ))
+ rOff -= nYScrl;
+
+ return rOff > 0;
+}
+
+// Scroll page by page
+bool SwView::PageUp()
+{
+ if (!m_aVisArea.GetHeight())
+ return false;
+
+ Point aPos(m_aVisArea.TopLeft());
+ aPos.AdjustY( -(m_aVisArea.GetHeight() - (GetYScroll() / 2)) );
+ aPos.setY( std::max(tools::Long(0), aPos.Y()) );
+ SetVisArea( aPos );
+ return true;
+}
+
+bool SwView::PageDown()
+{
+ if ( !m_aVisArea.GetHeight() )
+ return false;
+ Point aPos( m_aVisArea.TopLeft() );
+ aPos.AdjustY(m_aVisArea.GetHeight() - (GetYScroll() / 2) );
+ aPos.setY( SetVScrollMax( aPos.Y() ) );
+ SetVisArea( aPos );
+ return true;
+}
+
+void SwView::PhyPageUp()
+{
+ // Check for the currently visible page, do not format
+ sal_uInt16 nActPage = m_pWrtShell->GetNextPrevPageNum( false );
+
+ if( USHRT_MAX != nActPage )
+ {
+ const Point aPt( m_aVisArea.Left(),
+ m_pWrtShell->GetPagePos( nActPage ).Y() );
+ Point aAlPt( AlignToPixel( aPt ) );
+ // If there is a difference, has been truncated --> then add one pixel,
+ // so that no residue of the previous page is visible.
+ if( aPt.Y() != aAlPt.Y() )
+ aAlPt.AdjustY(3 * GetEditWin().PixelToLogic( Size( 0, 1 ) ).Height() );
+ SetVisArea( aAlPt );
+ }
+}
+
+void SwView::PhyPageDown()
+{
+ // Check for the currently visible page, do not format
+ sal_uInt16 nActPage = m_pWrtShell->GetNextPrevPageNum();
+ // If the last page of the document is visible, do nothing.
+ if( USHRT_MAX != nActPage )
+ {
+ const Point aPt( m_aVisArea.Left(),
+ m_pWrtShell->GetPagePos( nActPage ).Y() );
+ Point aAlPt( AlignToPixel( aPt ) );
+ // If there is a difference, has been truncated --> then add one pixel,
+ // so that no residue of the previous page is visible.
+ if( aPt.Y() != aAlPt.Y() )
+ aAlPt.AdjustY(3 * GetEditWin().PixelToLogic( Size( 0, 1 ) ).Height() );
+ SetVisArea( aAlPt );
+ }
+}
+
+bool SwView::PageUpCursor( bool bSelect )
+{
+ if ( !bSelect )
+ {
+ const FrameTypeFlags eType = m_pWrtShell->GetFrameType(nullptr,true);
+ if ( eType & FrameTypeFlags::FOOTNOTE )
+ {
+ m_pWrtShell->MoveCursor();
+ m_pWrtShell->GotoFootnoteAnchor();
+ m_pWrtShell->Right(SwCursorSkipMode::Chars, false, 1, false );
+ return true;
+ }
+ }
+
+ SwTwips lOff = 0;
+ if ( GetPageScrollUpOffset( lOff ) &&
+ (m_pWrtShell->IsCursorReadonly() ||
+ !m_pWrtShell->PageCursor( lOff, bSelect )) &&
+ PageUp() )
+ {
+ m_pWrtShell->ResetCursorStack();
+ return true;
+ }
+ return false;
+}
+
+bool SwView::PageDownCursor(bool bSelect)
+{
+ SwTwips lOff = 0;
+ if ( GetPageScrollDownOffset( lOff ) &&
+ (m_pWrtShell->IsCursorReadonly() ||
+ !m_pWrtShell->PageCursor( lOff, bSelect )) &&
+ PageDown() )
+ {
+ m_pWrtShell->ResetCursorStack();
+ return true;
+ }
+ return false;
+}
+
+static void HideQuickHelp(vcl::Window* pParent) { Help::ShowQuickHelp(pParent, {}, {}); }
+
+// Handler of the scrollbars
+IMPL_LINK(SwView, VertScrollHdl, weld::Scrollbar&, rScrollbar, void)
+{
+ if ( GetWrtShell().ActionPend() )
+ return;
+
+ if (rScrollbar.get_scroll_type() == ScrollType::Drag)
+ m_pWrtShell->EnableSmooth( false );
+
+ bool bHidePending = nPgNum != 0;
+ nPgNum = 0; // avoid flicker from hiding then showing help window again
+ EndScrollHdl(rScrollbar, false);
+
+ if (!m_pWrtShell->GetViewOptions()->getBrowseMode() &&
+ rScrollbar.get_scroll_type() == ScrollType::Drag)
+ {
+ if ( !m_bWheelScrollInProgress && Help::IsQuickHelpEnabled() &&
+ m_pWrtShell->GetViewOptions()->IsShowScrollBarTips())
+ {
+
+ Point aPos( m_aVisArea.TopLeft() );
+ lcl_GetPos(this, aPos, rScrollbar, false, IsDocumentBorder());
+
+ sal_uInt16 nPhNum = 1;
+ sal_uInt16 nVirtNum = 1;
+
+ OUString sDisplay;
+ if(m_pWrtShell->GetPageNumber( aPos.Y(), false, nPhNum, nVirtNum, sDisplay ))
+ {
+ //QuickHelp:
+ if( m_pWrtShell->GetPageCnt() > 1 )
+ {
+ tools::Rectangle aRect;
+ aRect.SetLeft( m_pVScrollbar->GetParent()->OutputToScreenPixel(
+ m_pVScrollbar->GetPosPixel() ).X() -8 );
+ aRect.SetTop( m_pVScrollbar->OutputToScreenPixel(
+ m_pVScrollbar->GetPointerPosPixel() ).Y() );
+ aRect.SetRight( aRect.Left() );
+ aRect.SetBottom( aRect.Top() );
+
+ OUString sPageStr( GetPageStr( nPhNum, nVirtNum, sDisplay ));
+ SwContentAtPos aCnt(IsAttrAtPos::Outline | IsAttrAtPos::AllowContaining);
+ bool bSuccess = m_pWrtShell->GetContentAtPos(aPos, aCnt);
+ if (bSuccess && !aCnt.sStr.isEmpty())
+ {
+ sal_Int32 nChunkLen = std::min<sal_Int32>(aCnt.sStr.getLength(), 80);
+ std::u16string_view sChunk = aCnt.sStr.subView(0, nChunkLen);
+ sPageStr = sPageStr + " - " + sChunk;
+ sPageStr = sPageStr.replace('\t', ' ').replace(0x0a, ' ');
+ }
+
+ Help::ShowQuickHelp(m_pVScrollbar, aRect, sPageStr,
+ QuickHelpFlags::Right|QuickHelpFlags::VCenter);
+ bHidePending = false;
+ nPgNum = nPhNum;
+ }
+ }
+ }
+ }
+
+ if (bHidePending)
+ HideQuickHelp(m_pVScrollbar);
+
+ if (rScrollbar.get_scroll_type() == ScrollType::Drag)
+ m_pWrtShell->EnableSmooth( true );
+}
+
+// Handler of the scrollbars
+void SwView::EndScrollHdl(weld::Scrollbar& rScrollbar, bool bHorizontal)
+{
+ if ( GetWrtShell().ActionPend() )
+ return;
+
+ if(nPgNum)
+ {
+ nPgNum = 0;
+ HideQuickHelp(bHorizontal ? m_pHScrollbar : m_pVScrollbar);
+ }
+ Point aPos( m_aVisArea.TopLeft() );
+ bool bBorder = IsDocumentBorder();
+ lcl_GetPos(this, aPos, rScrollbar, bHorizontal, bBorder);
+ if ( bBorder && aPos == m_aVisArea.TopLeft() )
+ UpdateScrollbars();
+ else
+ SetVisArea( aPos, false );
+
+ GetViewFrame().GetBindings().Update(FN_STAT_PAGE);
+}
+
+IMPL_LINK(SwView, HoriScrollHdl, weld::Scrollbar&, rScrollBar, void)
+{
+ EndScrollHdl(rScrollBar, true);
+}
+
+// Calculates the size of the m_aVisArea in dependency of the size of
+// EditWin on the screen.
+
+void SwView::CalcVisArea( const Size &rOutPixel )
+{
+ Point aTopLeft;
+ tools::Rectangle aRect( aTopLeft, rOutPixel );
+ aRect = GetEditWin().PixelToLogic(aRect);
+
+ // The shifts to the right and/or below can now be incorrect
+ // (e.g. change zoom level, change view size).
+ const tools::Long lBorder = IsDocumentBorder() ? DOCUMENTBORDER : DOCUMENTBORDER*2;
+ if ( aRect.Left() )
+ {
+ const tools::Long lWidth = GetWrtShell().GetDocSize().Width() + lBorder;
+ if ( aRect.Right() > lWidth )
+ {
+ tools::Long lDelta = aRect.Right() - lWidth;
+ aRect.AdjustLeft( -lDelta );
+ aRect.AdjustRight( -lDelta );
+ }
+ }
+ if ( aRect.Top() )
+ {
+ const tools::Long lHeight = GetWrtShell().GetDocSize().Height() + lBorder;
+ if ( aRect.Bottom() > lHeight )
+ {
+ tools::Long lDelta = aRect.Bottom() - lHeight;
+ aRect.AdjustTop( -lDelta );
+ aRect.AdjustBottom( -lDelta );
+ }
+ }
+ SetVisArea( aRect );
+ GetViewFrame().GetBindings().Invalidate( SID_ATTR_ZOOM );
+ GetViewFrame().GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER ); // for snapping points
+}
+
+// Rearrange control elements
+
+void SwView::CalcAndSetBorderPixel( SvBorder &rToFill )
+{
+ bool bRightVRuler = m_pWrtShell->GetViewOptions()->IsVRulerRight();
+ if ( m_pVRuler->IsVisible() )
+ {
+ tools::Long nWidth = m_pVRuler->GetSizePixel().Width();
+ if(bRightVRuler)
+ rToFill.Right() = nWidth;
+ else
+ rToFill.Left() = nWidth;
+ }
+
+ OSL_ENSURE(m_pHRuler, "Why is the ruler not present?");
+ if ( m_pHRuler->IsVisible() )
+ rToFill.Top() = m_pHRuler->GetSizePixel().Height();
+
+ const StyleSettings &rSet = GetEditWin().GetSettings().GetStyleSettings();
+ const tools::Long nTmp = rSet.GetScrollBarSize();
+ if( m_pVScrollbar->IsScrollbarVisible(true) )
+ {
+ if(bRightVRuler)
+ rToFill.Left() = nTmp;
+ else
+ rToFill.Right() = nTmp;
+ }
+ if ( m_pHScrollbar->IsScrollbarVisible(true) )
+ rToFill.Bottom() = nTmp;
+
+ SetBorderPixel( rToFill );
+}
+
+void ViewResizePixel( const vcl::RenderContext &rRef,
+ const Point &rOfst,
+ const Size &rSize,
+ const Size &rEditSz,
+ SwScrollbar& rVScrollbar,
+ SwScrollbar& rHScrollbar,
+ SvxRuler* pVRuler,
+ SvxRuler* pHRuler,
+ bool bVRulerRight )
+{
+// ViewResizePixel is also used by Preview!!!
+
+ const bool bHRuler = pHRuler && pHRuler->IsVisible();
+ const tools::Long nHLinSzHeight = bHRuler ?
+ pHRuler->GetSizePixel().Height() : 0;
+ const bool bVRuler = pVRuler && pVRuler->IsVisible();
+ const tools::Long nVLinSzWidth = bVRuler ?
+ pVRuler->GetSizePixel().Width() : 0;
+
+ const tools::Long nScrollBarSize = rRef.GetSettings().GetStyleSettings().GetScrollBarSize();
+ const tools::Long nHBSzHeight = rHScrollbar.IsScrollbarVisible(true) ? nScrollBarSize : 0;
+ const tools::Long nVBSzWidth = rVScrollbar.IsScrollbarVisible(true) ? nScrollBarSize : 0;
+
+ if(pVRuler)
+ {
+ WinBits nStyle = pVRuler->GetStyle()&~WB_RIGHT_ALIGNED;
+ Point aPos( rOfst.X(), rOfst.Y()+nHLinSzHeight );
+ if(bVRulerRight)
+ {
+ aPos.AdjustX(rSize.Width() - nVLinSzWidth );
+ nStyle |= WB_RIGHT_ALIGNED;
+ }
+ Size aSize( nVLinSzWidth, rEditSz.Height() );
+ if(!aSize.Width())
+ aSize.setWidth( pVRuler->GetSizePixel().Width() );
+ pVRuler->SetStyle(nStyle);
+ pVRuler->SetPosSizePixel( aPos, aSize );
+ if(!pVRuler->IsVisible())
+ pVRuler->Resize();
+ }
+ // Ruler needs a resize, otherwise it will not work in the invisible condition
+ if(pHRuler)
+ {
+ Size aSize( rSize.Width(), nHLinSzHeight );
+ if ( nVBSzWidth && !bVRulerRight)
+ aSize.AdjustWidth( -nVBSzWidth );
+ if(!aSize.Height())
+ aSize.setHeight( pHRuler->GetSizePixel().Height() );
+ pHRuler->SetPosSizePixel( rOfst, aSize );
+ // VCL calls no resize on invisible windows
+ // but that is not a good idea for the ruler
+ if(!pHRuler->IsVisible())
+ pHRuler->Resize();
+ }
+
+ // Arrange scrollbars and SizeBox
+ Point aScrollFillPos;
+ {
+ Point aPos( rOfst.X(),
+ rOfst.Y()+rSize.Height()-nHBSzHeight );
+ if(bVRulerRight)
+ {
+ aPos.AdjustX(nVBSzWidth );
+ }
+
+ Size aSize( rSize.Width(), nHBSzHeight );
+ if ( nVBSzWidth )
+ aSize.AdjustWidth( -nVBSzWidth );
+ rHScrollbar.SetPosSizePixel( aPos, aSize );
+ aScrollFillPos.setY( aPos.Y() );
+ }
+ {
+ Point aPos( rOfst.X()+rSize.Width()-nVBSzWidth,
+ rOfst.Y() );
+ Size aSize( nVBSzWidth, rSize.Height() );
+ if(bVRulerRight)
+ {
+ aPos.setX( rOfst.X() );
+ if(bHRuler)
+ {
+ aPos.AdjustY(nHLinSzHeight );
+ aSize.AdjustHeight( -nHLinSzHeight );
+ }
+ }
+
+ if ( nHBSzHeight )
+ aSize.AdjustHeight( -nHBSzHeight );
+ rVScrollbar.SetPosSizePixel( aPos, aSize );
+
+ aPos.AdjustY(aSize.Height() );
+
+ aScrollFillPos.setX( aPos.X() );
+ }
+}
+
+void SwView::ShowAtResize()
+{
+ m_bShowAtResize = false;
+ if ( m_pWrtShell->GetViewOptions()->IsViewHRuler() )
+ m_pHRuler->Show();
+}
+
+void SwView::InnerResizePixel( const Point &rOfst, const Size &rSize, bool )
+{
+ Size aObjSize = GetObjectShell()->GetVisArea().GetSize();
+ if ( !aObjSize.IsEmpty() )
+ {
+ SvBorder aBorder( GetBorderPixel() );
+ Size aSize( rSize );
+ aSize.AdjustWidth( -(aBorder.Left() + aBorder.Right()) );
+ aSize.AdjustHeight( -(aBorder.Top() + aBorder.Bottom()) );
+ Size aObjSizePixel = GetWindow()->LogicToPixel(aObjSize, MapMode(MapUnit::MapTwip));
+ SfxViewShell::SetZoomFactor( Fraction( aSize.Width(), aObjSizePixel.Width() ),
+ Fraction( aSize.Height(), aObjSizePixel.Height() ) );
+ }
+
+ m_bInInnerResizePixel = true;
+ const bool bHScrollVisible = m_pHScrollbar->IsScrollbarVisible(true);
+ const bool bVScrollVisible = m_pVScrollbar->IsScrollbarVisible(true);
+ bool bRepeat = false;
+ do
+ {
+ Size aSz( rSize );
+ SvBorder aBorder;
+ CalcAndSetBorderPixel( aBorder );
+ if ( GetViewFrame().GetFrame().IsInPlace() )
+ {
+ Size aViewSize( aSz );
+ Point aViewPos( rOfst );
+ aViewSize.AdjustHeight( -(aBorder.Top() + aBorder.Bottom()) );
+ aViewSize.AdjustWidth( -(aBorder.Left() + aBorder.Right()) );
+ aViewPos.AdjustX(aBorder.Left() );
+ aViewPos.AdjustY(aBorder.Top() );
+ GetEditWin().SetPosSizePixel( aViewPos, aViewSize );
+ }
+ else
+ {
+ aSz.AdjustHeight(aBorder.Top() + aBorder.Bottom() );
+ aSz.AdjustWidth(aBorder.Left() + aBorder.Right() );
+ }
+
+ Size aEditSz( GetEditWin().GetOutputSizePixel() );
+ ViewResizePixel( *GetEditWin().GetOutDev(), rOfst, aSz, aEditSz, *m_pVScrollbar,
+ *m_pHScrollbar, m_pVRuler, m_pHRuler,
+ m_pWrtShell->GetViewOptions()->IsVRulerRight());
+ if ( m_bShowAtResize )
+ ShowAtResize();
+
+ if( m_pHRuler->IsVisible() || m_pVRuler->IsVisible() )
+ {
+ const Fraction& rFrac = GetEditWin().GetMapMode().GetScaleX();
+ tools::Long nZoom = 100;
+ if (rFrac.IsValid())
+ nZoom = tools::Long(rFrac * 100);
+
+ const Fraction aFrac( nZoom, 100 );
+ m_pVRuler->SetZoom( aFrac );
+ m_pHRuler->SetZoom( aFrac );
+ InvalidateRulerPos(); // Invalidate content.
+ }
+ // Reset the cursor stack because the cursor positions for PageUp/Down
+ // no longer fit the currently visible area.
+ m_pWrtShell->ResetCursorStack();
+
+ // EditWin never set!
+
+ // Set VisArea, but do not call the SetVisArea of the Docshell there!
+ bProtectDocShellVisArea = true;
+ CalcVisArea( aEditSz );
+ // Visibility changes of the automatic horizontal scrollbar
+ // require to repeat the ViewResizePixel() call - but only once!
+ if(bRepeat)
+ bRepeat = false;
+ else if(bHScrollVisible != m_pHScrollbar->IsScrollbarVisible(true) ||
+ bVScrollVisible != m_pVScrollbar->IsScrollbarVisible(true))
+ bRepeat = true;
+ }while( bRepeat );
+ bProtectDocShellVisArea = false;
+ m_bInInnerResizePixel = false;
+}
+
+void SwView::OuterResizePixel( const Point &rOfst, const Size &rSize )
+{
+ // #i16909# return, if no size (caused by minimize window).
+ if ( m_bInOuterResizePixel || ( !rSize.Width() && !rSize.Height() ) )
+ return;
+ m_bInOuterResizePixel = true;
+
+ // Determine whether scroll bars may be displayed.
+ bool bShowH = true,
+ bShowV = true,
+ bAuto = true,
+ bHAuto = true;
+
+ const SwViewOption *pVOpt = m_pWrtShell->GetViewOptions();
+ if ( !pVOpt->IsReadonly() || pVOpt->IsStarOneSetting() )
+ {
+ bShowH = pVOpt->IsViewHScrollBar();
+ bShowV = pVOpt->IsViewVScrollBar();
+ }
+
+ if (!m_bHScrollbarEnabled)
+ {
+ bHAuto = bShowH = false;
+ }
+ if (!m_bVScrollbarEnabled)
+ {
+ bAuto = bShowV = false;
+ }
+
+ SwDocShell* pDocSh = GetDocShell();
+ bool bIsPreview = pDocSh->IsPreview();
+ if( bIsPreview )
+ {
+ bShowH = bShowV = bHAuto = bAuto = false;
+ }
+ if(m_pHScrollbar->IsScrollbarVisible(false) != bShowH && !bHAuto)
+ ShowHScrollbar(bShowH);
+ m_pHScrollbar->SetAuto( bHAuto );
+ if(m_pVScrollbar->IsScrollbarVisible(false) != bShowV && !bAuto)
+ ShowVScrollbar(bShowV);
+ m_pVScrollbar->SetAuto(bAuto);
+
+ CurrShell aCurr( m_pWrtShell.get() );
+ bool bRepeat = false;
+ tools::Long nCnt = 0;
+
+ bool bUnLockView = !m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView( true );
+ m_pWrtShell->LockPaint(LockPaintReason::OuterResize);
+
+ do {
+ ++nCnt;
+ const bool bScroll1 = m_pVScrollbar->IsScrollbarVisible(true);
+ const bool bScroll2 = m_pHScrollbar->IsScrollbarVisible(true);
+ SvBorder aBorder;
+ CalcAndSetBorderPixel( aBorder );
+ const Size aEditSz( GetEditWin().GetOutputSizePixel() );
+ ViewResizePixel( *GetEditWin().GetOutDev(), rOfst, rSize, aEditSz, *m_pVScrollbar,
+ *m_pHScrollbar, m_pVRuler, m_pHRuler,
+ m_pWrtShell->GetViewOptions()->IsVRulerRight() );
+ if ( m_bShowAtResize )
+ ShowAtResize();
+
+ if( m_pHRuler->IsVisible() || m_pVRuler->IsVisible() )
+ InvalidateRulerPos(); // Invalidate content.
+
+ // Reset the cursor stack because the cursor positions for PageUp/Down
+ // no longer fit the currently visible area.
+ m_pWrtShell->ResetCursorStack();
+
+ OSL_ENSURE( !GetEditWin().IsVisible() ||
+ !aEditSz.IsEmpty() || !m_aVisArea.IsEmpty(), "Small world, isn't it?" );
+
+ // Never set EditWin!
+
+ // Of course the VisArea must also be set.
+ // Now is the right time to re-calculate the zoom if it is not a simple factor.
+ m_pWrtShell->StartAction();
+ CalcVisArea( aEditSz );
+
+ //Thus also in the outplace editing the page width will be adjusted immediately.
+ //TODO/LATER: is that still necessary?!
+ /*
+ if ( pDocSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
+ pDocSh->SetVisArea(
+ pDocSh->SfxInPlaceObject::GetVisArea() );*/
+ if ( m_pWrtShell->GetViewOptions()->GetZoomType() != SvxZoomType::PERCENT &&
+ !m_pWrtShell->GetViewOptions()->getBrowseMode() )
+ SetZoom_( aEditSz, m_pWrtShell->GetViewOptions()->GetZoomType(), 100, true );
+ m_pWrtShell->EndAction();
+
+ bRepeat = bScroll1 != m_pVScrollbar->IsScrollbarVisible(true);
+ if ( !bRepeat )
+ bRepeat = bScroll2 != m_pHScrollbar->IsScrollbarVisible(true);
+
+ // Do no infinite loops.
+ // If possible stop when the (auto-) scroll bars are visible.
+ if ( bRepeat &&
+ ( nCnt > 10 || ( nCnt > 3 && bHAuto && bAuto ) )
+ )
+ {
+ bRepeat = false;
+ }
+
+ } while ( bRepeat );
+
+ m_pWrtShell->UnlockPaint();
+ if( bUnLockView )
+ m_pWrtShell->LockView( false );
+
+ m_bInOuterResizePixel = false;
+
+ if ( m_pPostItMgr )
+ {
+ m_pPostItMgr->CalcRects();
+ m_pPostItMgr->LayoutPostIts();
+ }
+}
+
+void SwView::SetZoomFactor( const Fraction &rX, const Fraction &rY )
+{
+ const Fraction &rFrac = rX < rY ? rX : rY;
+ SetZoom( SvxZoomType::PERCENT, static_cast<short>(tools::Long(rFrac * Fraction( 100, 1 ))) );
+
+ // To minimize rounding errors we also adjust the odd values
+ // of the base class if necessary.
+ SfxViewShell::SetZoomFactor( rX, rY );
+}
+
+bool SwView::UpdateScrollbars()
+{
+ bool bRet = false;
+ if ( !m_aVisArea.IsEmpty() )
+ {
+ const bool bBorder = IsDocumentBorder();
+ tools::Rectangle aTmpRect( m_aVisArea );
+ if ( bBorder )
+ {
+ Point aPt( DOCUMENTBORDER, DOCUMENTBORDER );
+ aPt = AlignToPixel( aPt );
+ aTmpRect.Move( -aPt.X(), -aPt.Y() );
+ }
+
+ Size aTmpSz( m_aDocSz );
+ const tools::Long lOfst = bBorder ? 0 : DOCUMENTBORDER * 2;
+ aTmpSz.AdjustWidth(lOfst ); aTmpSz.AdjustHeight(lOfst );
+
+ {
+ const bool bVScrollVisible = m_pVScrollbar->IsScrollbarVisible(true);
+ m_pVScrollbar->DocSzChgd( aTmpSz );
+ m_pVScrollbar->ViewPortChgd( aTmpRect );
+ if ( bVScrollVisible != m_pVScrollbar->IsScrollbarVisible(true) )
+ bRet = true;
+ }
+ {
+ const bool bHScrollVisible = m_pHScrollbar->IsScrollbarVisible(true);
+ m_pHScrollbar->DocSzChgd( aTmpSz );
+ m_pHScrollbar->ViewPortChgd( aTmpRect );
+ if ( bHScrollVisible != m_pHScrollbar->IsScrollbarVisible(true) )
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+void SwView::Move()
+{
+ if ( GetWrtShell().IsInSelect() )
+ GetWrtShell().EndSelect();
+ SfxViewShell::Move();
+}
+
+bool SwView::HandleWheelCommands( const CommandEvent& rCEvt )
+{
+ bool bOk = false;
+ const CommandWheelData* pWData = rCEvt.GetWheelData();
+ if (pWData && CommandWheelMode::ZOOM == pWData->GetMode())
+ {
+ sal_uInt16 nFact = m_pWrtShell->GetViewOptions()->GetZoom();
+ if( 0L > pWData->GetDelta() )
+ nFact = std::max(MIN_ZOOM_PERCENT, basegfx::zoomtools::zoomOut( nFact ));
+ else
+ nFact = std::min(MAX_ZOOM_PERCENT, basegfx::zoomtools::zoomIn( nFact ));
+
+ SetZoom( SvxZoomType::PERCENT, nFact );
+ bOk = true;
+ }
+ else
+ {
+ if (pWData && pWData->GetMode()==CommandWheelMode::SCROLL)
+ {
+ // This influences whether quick help is shown
+ m_bWheelScrollInProgress=true;
+ }
+
+ if (pWData && (CommandWheelMode::SCROLL==pWData->GetMode()) &&
+ (COMMAND_WHEEL_PAGESCROLL == pWData->GetScrollLines()))
+ {
+ if (pWData->GetDelta()<0)
+ PhyPageDown();
+ else
+ PhyPageUp();
+ bOk = true;
+ }
+ else
+ bOk = m_pEditWin->HandleScrollCommand(rCEvt, m_pHScrollbar, m_pVScrollbar);
+
+ // Restore default state for case when scroll command comes from dragging scrollbar handle
+ m_bWheelScrollInProgress=false;
+ }
+ return bOk;
+}
+
+bool SwView::HandleGestureZoomCommand(const CommandEvent& rCEvt)
+{
+ const CommandGestureZoomData* pData = rCEvt.GetGestureZoomData();
+
+ if (pData->meEventType == GestureEventZoomType::Begin)
+ {
+ m_fLastZoomScale = pData->mfScaleDelta;
+ return true;
+ }
+
+ if (pData->meEventType == GestureEventZoomType::Update)
+ {
+ double deltaBetweenEvents = (pData->mfScaleDelta - m_fLastZoomScale) / m_fLastZoomScale;
+ m_fLastZoomScale = pData->mfScaleDelta;
+
+ // Accumulate fractional zoom to avoid small zoom changes from being ignored
+ m_fAccumulatedZoom += deltaBetweenEvents;
+ int nZoomChangePercent = m_fAccumulatedZoom * 100;
+ m_fAccumulatedZoom -= nZoomChangePercent / 100.0;
+
+ sal_uInt16 nFact = m_pWrtShell->GetViewOptions()->GetZoom();
+ nFact += nZoomChangePercent;
+ nFact = std::clamp<sal_uInt16>(nFact, MIN_ZOOM_PERCENT, MAX_ZOOM_PERCENT);
+ SetZoom(SvxZoomType::PERCENT, nFact);
+
+ return true;
+ }
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewprt.cxx b/sw/source/uibase/uiview/viewprt.cxx
new file mode 100644
index 0000000000..bc9c5e19b8
--- /dev/null
+++ b/sw/source/uibase/uiview/viewprt.cxx
@@ -0,0 +1,376 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <libxml/xmlwriter.h>
+#include <cmdid.h>
+#include <officecfg/Office/Common.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/stdtext.hxx>
+#include <vcl/weld.hxx>
+#include <sfx2/printer.hxx>
+#include <editeng/paperinf.hxx>
+#include <sfx2/dispatch.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/strings.hrc>
+#include <svl/eitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/flagitem.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <osl/diagnose.h>
+#include <svtools/colorcfg.hxx>
+#include <o3tl/unreachable.hxx>
+
+#include <modcfg.hxx>
+#include <edtwin.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <viewopt.hxx>
+#include <prtopt.hxx>
+#include <cfgitems.hxx>
+#include "viewfunc.hxx"
+#include <swmodule.hxx>
+#include <wview.hxx>
+#include <IDocumentDeviceAccess.hxx>
+
+#include <globals.hrc>
+#include <strings.hrc>
+#include <swabstdlg.hxx>
+
+#include <uivwimp.hxx>
+
+using namespace ::com::sun::star;
+
+// Hand over the printer to Sfx
+
+SfxPrinter* SwView::GetPrinter( bool bCreate )
+{
+ const IDocumentDeviceAccess& rIDDA = GetWrtShell().getIDocumentDeviceAccess();
+ SfxPrinter *pOld = rIDDA.getPrinter( false );
+ SfxPrinter *pPrt = rIDDA.getPrinter( bCreate );
+ if ( pOld != pPrt )
+ {
+ bool bWeb = dynamic_cast<SwWebView*>(this) != nullptr;
+ ::SetAppPrintOptions( &GetWrtShell(), bWeb );
+ }
+ return pPrt;
+}
+
+// Propagate printer change
+
+void SetPrinter( IDocumentDeviceAccess* pIDDA, SfxPrinter const * pNew, bool bWeb )
+{
+ SwPrintOptions* pOpt = SW_MOD()->GetPrtOptions(bWeb);
+ if( !pOpt)
+ return;
+
+ // Reading Application own printing options from SfxPrinter
+ const SfxItemSet& rSet = pNew->GetOptions();
+
+ const SwAddPrinterItem* pAddPrinterAttr =
+ rSet.GetItemIfSet( FN_PARAM_ADDPRINTER, false );
+ if( pAddPrinterAttr )
+ {
+ if( pIDDA )
+ pIDDA->setPrintData( *pAddPrinterAttr );
+ if( !pAddPrinterAttr->GetFaxName().isEmpty() )
+ pOpt->SetFaxName(pAddPrinterAttr->GetFaxName());
+ }
+}
+
+sal_uInt16 SwView::SetPrinter(SfxPrinter* pNew, SfxPrinterChangeFlags nDiffFlags )
+{
+ SwWrtShell &rSh = GetWrtShell();
+ SfxPrinter* pOld = rSh.getIDocumentDeviceAccess().getPrinter( false );
+ if ( pOld && pOld->IsPrinting() )
+ return SFX_PRINTERROR_BUSY;
+
+ if ( (SfxPrinterChangeFlags::JOBSETUP | SfxPrinterChangeFlags::PRINTER) & nDiffFlags )
+ {
+ rSh.getIDocumentDeviceAccess().setPrinter( pNew, true, true );
+ if ( nDiffFlags & SfxPrinterChangeFlags::PRINTER )
+ rSh.SetModified();
+ }
+ bool bWeb = dynamic_cast< const SwWebView *>( this ) != nullptr;
+ if ( nDiffFlags & SfxPrinterChangeFlags::OPTIONS )
+ ::SetPrinter( &rSh.getIDocumentDeviceAccess(), pNew, bWeb );
+
+ const bool bChgOri = bool(nDiffFlags & SfxPrinterChangeFlags::CHG_ORIENTATION);
+ const bool bChgSize = bool(nDiffFlags & SfxPrinterChangeFlags::CHG_SIZE);
+ if ( bChgOri || bChgSize )
+ {
+ rSh.StartAllAction();
+ if ( bChgOri )
+ rSh.ChgAllPageOrientation( pNew->GetOrientation() );
+ if ( bChgSize )
+ {
+ Size aSz( SvxPaperInfo::GetPaperSize( pNew ) );
+ rSh.ChgAllPageSize( aSz );
+ }
+ rSh.SetModified();
+ rSh.EndAllAction();
+ InvalidateRulerPos();
+ }
+ return 0;
+}
+
+bool SwView::HasPrintOptionsPage() const
+{
+ return true;
+}
+
+namespace
+{
+ class SvxPrtQryBox
+ {
+ private:
+ std::unique_ptr<weld::MessageDialog> m_xQueryBox;
+ public:
+ SvxPrtQryBox(weld::Window* pParent)
+ : m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Question, VclButtonsType::NONE, SvxResId(RID_SVXSTR_QRY_PRINT_MSG)))
+ {
+ m_xQueryBox->set_title(SvxResId(RID_SVXSTR_QRY_PRINT_TITLE));
+
+ m_xQueryBox->add_button(SvxResId(RID_SVXSTR_QRY_PRINT_SELECTION), RET_OK);
+ m_xQueryBox->add_button(SvxResId(RID_SVXSTR_QRY_PRINT_ALL), 2);
+ m_xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL);
+ m_xQueryBox->set_default_response(RET_OK);
+ }
+ short run() { return m_xQueryBox->run(); }
+ };
+}
+
+// TabPage for application-specific print options
+
+std::unique_ptr<SfxTabPage> SwView::CreatePrintOptionsPage(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet& rSet)
+{
+ return ::CreatePrintOptionsPage(pPage, pController, rSet, false);
+}
+
+// Print dispatcher
+
+void SwView::ExecutePrint(SfxRequest& rReq)
+{
+ bool bWeb = dynamic_cast<SwWebView*>( this ) != nullptr;
+ ::SetAppPrintOptions( &GetWrtShell(), bWeb );
+ switch (rReq.GetSlot())
+ {
+ case FN_FAX:
+ {
+ SwPrintOptions* pPrintOptions = SW_MOD()->GetPrtOptions(bWeb);
+ const OUString& sFaxName(pPrintOptions->GetFaxName());
+ if (!sFaxName.isEmpty())
+ {
+ SfxStringItem aPrinterName(SID_PRINTER_NAME, sFaxName);
+ SfxBoolItem aSilent( SID_SILENT, true );
+ GetViewFrame().GetDispatcher()->ExecuteList(SID_PRINTDOC,
+ SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
+ { &aPrinterName, &aSilent });
+ }
+ else
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetEditWin().GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_ERR_NO_FAX)));
+ TranslateId pResId = bWeb ? STR_WEBOPTIONS : STR_TEXTOPTIONS;
+ xInfoBox->set_primary_text(xInfoBox->get_primary_text().replaceFirst("%1", SwResId(pResId)));
+ xInfoBox->run();
+ SfxUInt16Item aDefPage(SID_SW_EDITOPTIONS, TP_OPTPRINT_PAGE);
+ GetViewFrame().GetDispatcher()->ExecuteList(SID_SW_EDITOPTIONS,
+ SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
+ { &aDefPage });
+ }
+ }
+ break;
+ case SID_PRINTDOC:
+ case SID_PRINTDOCDIRECT:
+ {
+ SwWrtShell* pSh = &GetWrtShell();
+ const SfxBoolItem* pSilentItem = rReq.GetArg<SfxBoolItem>(SID_SILENT);
+ bool bSilent = pSilentItem && pSilentItem->GetValue();
+ const SfxBoolItem* pPrintFromMergeItem = rReq.GetArg<SfxBoolItem>(FN_QRY_MERGE);
+ if(pPrintFromMergeItem)
+ rReq.RemoveItem(FN_QRY_MERGE);
+ bool bFromMerge = pPrintFromMergeItem && pPrintFromMergeItem->GetValue();
+ bool bPrintSelection = false;
+ if(!bSilent && !bFromMerge &&
+ SW_MOD()->GetModuleConfig()->IsAskForMailMerge() && pSh->IsAnyDatabaseFieldInDoc())
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetEditWin().GetFrameWeld(), "modules/swriter/ui/printmergedialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("PrintMergeDialog"));
+ short nRet = xBox->run();
+ if(RET_NO != nRet)
+ {
+ if(RET_YES == nRet)
+ {
+ SfxBoolItem aBool(FN_QRY_MERGE, true);
+ GetViewFrame().GetDispatcher()->ExecuteList(
+ FN_QRY_MERGE, SfxCallMode::ASYNCHRON,
+ { &aBool });
+ rReq.Ignore();
+ }
+ return;
+ }
+ }
+ else if( rReq.GetSlot() == SID_PRINTDOCDIRECT && ! bSilent )
+ {
+ if( pSh->IsSelection() || pSh->IsFrameSelected() || pSh->IsObjSelected() )
+ {
+ SvxPrtQryBox aBox(GetEditWin().GetFrameWeld());
+ short nBtn = aBox.run();
+ if( RET_CANCEL == nBtn )
+ return;
+
+ if( RET_OK == nBtn )
+ bPrintSelection = true;
+ }
+ }
+
+ //#i61455# if master documents are printed silently without loaded links then update the links now
+ if( bSilent && pSh->IsGlobalDoc() && !pSh->IsGlblDocSaveLinks() )
+ {
+ pSh->GetLinkManager().UpdateAllLinks( false, false, nullptr );
+ }
+ SfxRequest aReq( rReq );
+ SfxBoolItem aBool(SID_SELECTION, bPrintSelection);
+ aReq.AppendItem( aBool );
+ SfxViewShell::ExecuteSlot( aReq, SfxViewShell::GetInterface() );
+ return;
+ }
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ return;
+ }
+}
+
+int SwView::getPart() const
+{
+ return 0;
+}
+
+void SwView::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwView"));
+ SfxViewShell::dumpAsXml(pWriter);
+ if (m_pWrtShell)
+ m_pWrtShell->dumpAsXml(pWriter);
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+void SwView::SetRedlineAuthor(const OUString& rAuthor)
+{
+ m_pViewImpl->m_sRedlineAuthor = rAuthor;
+}
+
+const OUString& SwView::GetRedlineAuthor() const
+{
+ return m_pViewImpl->m_sRedlineAuthor;
+}
+
+void SwView::NotifyCursor(SfxViewShell* pViewShell) const
+{
+ m_pWrtShell->NotifyCursor(pViewShell);
+}
+
+::Color SwView::GetColorConfigColor(svtools::ColorConfigEntry nColorType) const
+{
+ if (const SwViewOption* pViewOptions = GetWrtShell().GetViewOptions())
+ {
+ switch (nColorType)
+ {
+ case svtools::ColorConfigEntry::DOCCOLOR:
+ {
+ return pViewOptions->GetDocColor();
+ }
+ // Should never be called for an unimplemented color type
+ default:
+ {
+ O3TL_UNREACHABLE;
+ }
+ }
+ }
+ else
+ {
+ SAL_WARN("sw", "GetViewOptions() returned nullptr");
+ }
+
+ return {};
+}
+
+// Create page printer/additions for SwView and SwPagePreview
+
+std::unique_ptr<SfxTabPage> CreatePrintOptionsPage(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet &rOptions,
+ bool bPreview)
+{
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+
+ ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc(TP_OPTPRINT_PAGE);
+ OSL_ENSURE(pFact, "No Page Creator");
+ if (!fnCreatePage)
+ return nullptr;
+
+ std::unique_ptr<SfxTabPage> xSfxPage = fnCreatePage(pPage, pController, &rOptions);
+ OSL_ENSURE(xSfxPage, "No page");
+ if (!xSfxPage)
+ return nullptr;
+
+ SfxAllItemSet aSet(*(rOptions.GetPool()));
+ aSet.Put(SfxBoolItem(SID_PREVIEWFLAG_TYPE, bPreview));
+ aSet.Put(SfxBoolItem(SID_FAX_LIST, true));
+ xSfxPage->PageCreated(aSet);
+ return xSfxPage;
+}
+
+void SetAppPrintOptions( SwViewShell* pSh, bool bWeb )
+{
+ const IDocumentDeviceAccess& rIDDA = pSh->getIDocumentDeviceAccess();
+ const SwPrintData& aPrtData = rIDDA.getPrintData();
+
+ if( !rIDDA.getPrinter( false ) )
+ return;
+
+ // Close application own printing options in SfxPrinter.
+ SwAddPrinterItem aAddPrinterItem(aPrtData);
+ SfxItemSetFixed<
+ SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
+ SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
+ SID_HTML_MODE, SID_HTML_MODE,
+ FN_PARAM_ADDPRINTER, FN_PARAM_ADDPRINTER> aSet( pSh->GetAttrPool() );
+
+ if(bWeb)
+ aSet.Put(SfxUInt16Item(SID_HTML_MODE,
+ ::GetHtmlMode(static_cast<SwWrtShell*>(pSh)->GetView().GetDocShell())));
+ aSet.Put(SfxBoolItem(SID_PRINTER_NOTFOUND_WARN,
+ officecfg::Office::Common::Print::Warning::NotFound::get() ));
+ aSet.Put(aAddPrinterItem);
+ aSet.Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC,
+ static_cast<int>(officecfg::Office::Common::Print::Warning::PaperSize::get()
+ ? SfxPrinterChangeFlags::CHG_SIZE : SfxPrinterChangeFlags::NONE) |
+ static_cast<int>(officecfg::Office::Common::Print::Warning::PaperOrientation::get()
+ ? SfxPrinterChangeFlags::CHG_ORIENTATION : SfxPrinterChangeFlags::NONE )));
+
+ rIDDA.getPrinter( true )->SetOptions( aSet );
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewsrch.cxx b/sw/source/uibase/uiview/viewsrch.cxx
new file mode 100644
index 0000000000..5fc92d517b
--- /dev/null
+++ b/sw/source/uibase/uiview/viewsrch.cxx
@@ -0,0 +1,895 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <string>
+
+#include <memory>
+#include <boost/property_tree/json_parser.hpp>
+
+#include <hintids.hxx>
+
+#include <sal/log.hxx>
+#include <svl/cjkoptions.hxx>
+#include <svl/ctloptions.hxx>
+#include <svx/pageitem.hxx>
+#include <svl/whiter.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/eitem.hxx>
+#include <svl/srchitem.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/lokhelper.hxx>
+#include <svx/srchdlg.hxx>
+#include <swmodule.hxx>
+#include <swwait.hxx>
+#include <workctrl.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <swundo.hxx>
+#include <uitool.hxx>
+#include <cmdid.h>
+#include <docsh.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <comphelper/lok.hxx>
+#include <comphelper/string.hxx>
+
+#include <strings.hrc>
+#include <SwRewriter.hxx>
+
+#include <PostItMgr.hxx>
+
+using namespace com::sun::star;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+
+//Search Parameter
+
+struct SwSearchOptions
+{
+ SwDocPositions eStart, eEnd;
+ bool bDontWrap;
+
+ SwSearchOptions( SwWrtShell const * pSh, bool bBackward );
+};
+
+/// Adds rMatches using rKey as a key to the rTree tree.
+static void lcl_addContainerToJson(boost::property_tree::ptree& rTree, const OString& rKey, const std::vector<OString>& rMatches)
+{
+ boost::property_tree::ptree aChildren;
+
+ for (const OString& rMatch : rMatches)
+ {
+ boost::property_tree::ptree aChild;
+ aChild.put("part", "0");
+ aChild.put("rectangles", rMatch.getStr());
+ aChildren.push_back(std::make_pair("", aChild));
+ }
+
+ rTree.add_child(rKey.getStr(), aChildren);
+}
+
+/// Emits LOK callbacks (count, selection) for search results.
+static void lcl_emitSearchResultCallbacks(SvxSearchItem const * pSearchItem, SwWrtShell const * pWrtShell, bool bHighlightAll)
+{
+ // Emit a callback also about the selection rectangles, grouped by matches.
+ SwPaM* pPaM = pWrtShell->GetCursor();
+ if (!pPaM)
+ return;
+
+ std::vector<OString> aMatches;
+ for (SwPaM& rPaM : pPaM->GetRingContainer())
+ {
+ if (SwShellCursor* pShellCursor = dynamic_cast<SwShellCursor*>(&rPaM))
+ {
+ std::vector<OString> aSelectionRectangles;
+ pShellCursor->SwSelPaintRects::Show(&aSelectionRectangles);
+ std::vector<OString> aRect;
+ for (const OString & rSelectionRectangle : aSelectionRectangles)
+ {
+ if (rSelectionRectangle.isEmpty())
+ continue;
+ aRect.push_back(rSelectionRectangle);
+ }
+ OString sRect = comphelper::string::join("; ", aRect);
+ aMatches.push_back(sRect);
+ }
+ }
+ boost::property_tree::ptree aTree;
+ aTree.put("searchString", pSearchItem->GetSearchString().toUtf8().getStr());
+ aTree.put("highlightAll", bHighlightAll);
+ lcl_addContainerToJson(aTree, "searchResultSelection"_ostr, aMatches);
+
+ std::stringstream aStream;
+ boost::property_tree::write_json(aStream, aTree);
+ OString aPayload( aStream.str() );
+
+ pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_RESULT_SELECTION, aPayload);
+
+ if(bHighlightAll)
+ { // FindAll disables this during find, do it once when done.
+ SfxLokHelper::notifyUpdate(pWrtShell->GetSfxViewShell(),LOK_CALLBACK_TEXT_SELECTION);
+ SfxLokHelper::notifyOtherViewsUpdatePerViewId(pWrtShell->GetSfxViewShell(), LOK_CALLBACK_TEXT_VIEW_SELECTION);
+ }
+}
+
+void SwView::ExecSearch(SfxRequest& rReq)
+{
+ GetWrtShell().addCurrentPosition();
+
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem = nullptr;
+ bool bQuiet = false;
+ if(pArgs && SfxItemState::SET == pArgs->GetItemState(SID_SEARCH_QUIET, false, &pItem))
+ bQuiet = static_cast<const SfxBoolItem*>( pItem)->GetValue();
+
+ sal_uInt16 nSlot = rReq.GetSlot();
+ if (nSlot == FN_REPEAT_SEARCH && !s_pSrchItem)
+ {
+ if(bQuiet)
+ {
+ rReq.SetReturnValue(SfxBoolItem(nSlot, false));
+ nSlot = 0;
+ }
+ }
+ if( m_pWrtShell->IsBlockMode() )
+ m_pWrtShell->LeaveBlockMode();
+ switch (nSlot)
+ {
+ // for now do nothing
+ case SID_SEARCH_ITEM:
+ {
+ delete s_pSrchItem;
+ s_pSrchItem = pArgs->Get(SID_SEARCH_ITEM).Clone();
+ }
+ break;
+
+ case FID_SEARCH_ON:
+ s_bJustOpened = true;
+ GetViewFrame().GetBindings().Invalidate(SID_SEARCH_ITEM);
+ break;
+
+ case FID_SEARCH_OFF:
+ if(pArgs)
+ {
+ // Unregister dialog
+ delete s_pSrchItem;
+ s_pSrchItem = pArgs->Get(SID_SEARCH_ITEM).Clone();
+
+ s_xSearchList.reset();
+ s_xReplaceList.reset();
+
+ SvxSearchDialog *const pSrchDlg(GetSearchDialog());
+ if (pSrchDlg)
+ {
+ // We will remember the search-/replace items.
+ const SearchAttrItemList* pList = pSrchDlg->GetSearchItemList();
+ if( nullptr != pList && pList->Count() )
+ s_xSearchList.reset(new SearchAttrItemList( *pList ));
+
+ pList = pSrchDlg->GetReplaceItemList();
+ if (nullptr != pList && pList->Count())
+ s_xReplaceList.reset(new SearchAttrItemList( *pList ));
+ }
+ }
+ break;
+
+ case FN_REPEAT_SEARCH:
+ case FID_SEARCH_NOW:
+ {
+ sal_uInt16 nMoveType = SwView::GetMoveType();
+ {
+ if(FID_SEARCH_NOW == nSlot && !rReq.IsAPI())
+ SwView::SetMoveType(NID_SRCH_REP);
+ }
+
+ SvxSearchDialog * pSrchDlg(GetSearchDialog());
+ if (pSrchDlg)
+ {
+ s_xSearchList.reset();
+ s_xReplaceList.reset();
+
+ const SearchAttrItemList* pList = pSrchDlg->GetSearchItemList();
+ if( nullptr != pList && pList->Count() )
+ s_xSearchList.reset(new SearchAttrItemList( *pList ));
+
+ pList = pSrchDlg->GetReplaceItemList();
+ if (nullptr != pList && pList->Count())
+ s_xReplaceList.reset(new SearchAttrItemList( *pList ));
+ }
+
+ if (nSlot == FN_REPEAT_SEARCH)
+ {
+ OSL_ENSURE(s_pSrchItem, "SearchItem missing");
+ if( !s_pSrchItem )
+ s_pSrchItem = new SvxSearchItem(SID_SEARCH_ITEM);
+ }
+ else
+ {
+ // Get SearchItem from request
+ OSL_ENSURE(pArgs, "Args missing");
+ if ( pArgs )
+ {
+ delete s_pSrchItem;
+ s_pSrchItem = pArgs->Get(SID_SEARCH_ITEM).Clone();
+ }
+ }
+ SvxSearchCmd eCommand = s_pSrchItem->GetCommand();
+ switch (eCommand)
+ {
+ case SvxSearchCmd::FIND:
+ {
+ bool bRet = SearchAndWrap(bQuiet);
+ if( bRet )
+ {
+ Scroll(m_pWrtShell->GetCharRect().SVRect());
+ if (comphelper::LibreOfficeKit::isActive())
+ lcl_emitSearchResultCallbacks(s_pSrchItem, m_pWrtShell.get(), /* bHighlightAll = */ false);
+ }
+ rReq.SetReturnValue(SfxBoolItem(nSlot, bRet));
+
+ GetDocShell()->Broadcast(SfxHint(SfxHintId::SwNavigatorUpdateTracking));
+ }
+ break;
+ case SvxSearchCmd::FIND_ALL:
+ {
+ // Disable LOK selection notifications during search.
+ m_pWrtShell->GetSfxViewShell()->setTiledSearching(true);
+ const auto nFound = SearchAll();
+ m_pWrtShell->GetSfxViewShell()->setTiledSearching(false);
+
+ GetDocShell()->Broadcast(
+ SfxHint(SfxHintId::SwNavigatorUpdateTracking));
+ GetDocShell()->Broadcast(
+ SfxHint(SfxHintId::SwNavigatorSelectOutlinesWithSelections));
+
+ if (nFound == 0)
+ {
+#if HAVE_FEATURE_DESKTOP
+ if( !bQuiet )
+ {
+ m_pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND, s_pSrchItem->GetSearchString().toUtf8());
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound);
+ }
+#endif
+ s_bFound = false;
+ }
+ else
+ {
+ if (comphelper::LibreOfficeKit::isActive())
+ lcl_emitSearchResultCallbacks(s_pSrchItem, m_pWrtShell.get(), /* bHighlightAll = */ true);
+ if (!bQuiet)
+ {
+ OUString sText(SwResId(STR_SEARCH_KEY_FOUND_TIMES));
+ sText = sText.replaceFirst("%1", OUString::number(nFound));
+ SvxSearchDialogWrapper::SetSearchLabel(sText);
+ }
+ }
+ rReq.SetReturnValue(SfxBoolItem(nSlot, nFound != 0));
+ }
+ break;
+ case SvxSearchCmd::REPLACE:
+ {
+
+ // 1) Replace selection (Not if only attributes should be replaced)
+//JP 27.04.95: Why?
+// what if you only want to assign attributes to the found??
+
+ SvxSearchCmd nCmd = SvxSearchCmd::FIND;
+ if( !s_pSrchItem->GetReplaceString().isEmpty() ||
+ !s_xReplaceList )
+ {
+ // Prevent, that the replaced string will be found again
+ // if the replacement string is containing the search string.
+ bool bBack = s_pSrchItem->GetBackward();
+ if (bBack)
+ m_pWrtShell->Push();
+ OUString aReplace( s_pSrchItem->GetReplaceString() );
+ i18nutil::SearchOptions2 aTmp( s_pSrchItem->GetSearchOptions() );
+ std::optional<OUString> xBackRef = sw::ReplaceBackReferences(aTmp,
+ m_pWrtShell->GetCursor(), m_pWrtShell->GetLayout());
+ if( xBackRef )
+ s_pSrchItem->SetReplaceString( *xBackRef );
+ Replace();
+ if( xBackRef )
+ {
+ s_pSrchItem->SetReplaceString( aReplace );
+ }
+ if (bBack)
+ {
+ m_pWrtShell->Pop();
+ m_pWrtShell->SwapPam();
+ }
+ }
+ else if( s_xReplaceList )
+ nCmd = SvxSearchCmd::REPLACE;
+
+ // 2) Search further (without replacing!)
+
+ SvxSearchCmd nOldCmd = s_pSrchItem->GetCommand();
+ s_pSrchItem->SetCommand( nCmd );
+ bool bRet = SearchAndWrap(bQuiet);
+ if( bRet )
+ Scroll( m_pWrtShell->GetCharRect().SVRect());
+ s_pSrchItem->SetCommand( nOldCmd );
+ rReq.SetReturnValue(SfxBoolItem(nSlot, bRet));
+ }
+ break;
+
+ case SvxSearchCmd::REPLACE_ALL:
+ {
+ SwSearchOptions aOpts( m_pWrtShell.get(), s_pSrchItem->GetBackward() );
+ s_bExtra = false;
+ sal_uLong nFound;
+
+ { //Scope for SwWait-Object
+ SwWait aWait( *GetDocShell(), true );
+ m_pWrtShell->StartAllAction();
+
+ // i#8288 "replace all" should not change cursor
+ // position, so save current cursor
+ m_pWrtShell->Push();
+
+ if (!s_pSrchItem->GetSelection())
+ {
+ // if we don't want to search in the selection...
+ m_pWrtShell->KillSelection(nullptr, false);
+ if (SwDocPositions::Start == aOpts.eEnd)
+ {
+ m_pWrtShell->EndOfSection();
+ }
+ else
+ {
+ m_pWrtShell->StartOfSection();
+ }
+ }
+ nFound = FUNC_Search( aOpts );
+ // create it just to overwrite it with stack cursor
+ m_pWrtShell->CreateCursor();
+ // i#8288 restore the original cursor position
+ m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
+ m_pWrtShell->EndAllAction();
+ }
+
+ rReq.SetReturnValue(SfxBoolItem(nSlot, nFound != 0 && ULONG_MAX != nFound));
+ if( !nFound )
+ {
+#if HAVE_FEATURE_DESKTOP
+ if( !bQuiet )
+ {
+ m_pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND, s_pSrchItem->GetSearchString().toUtf8());
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound);
+ }
+#endif
+ s_bFound = false;
+ SwView::SetMoveType(nMoveType);
+ return;
+ }
+
+ if( !bQuiet && ULONG_MAX != nFound)
+ {
+ OUString sText( SwResId( STR_NB_REPLACED ) );
+ sText = sText.replaceFirst("XX", OUString::number( nFound ));
+ SvxSearchDialogWrapper::SetSearchLabel(sText);
+ }
+ }
+ break;
+ }
+
+ uno::Reference< frame::XDispatchRecorder > xRecorder =
+ GetViewFrame().GetBindings().GetRecorder();
+ //prevent additional dialogs in recorded macros
+ if ( xRecorder.is() )
+ rReq.AppendItem(SfxBoolItem(SID_SEARCH_QUIET, true));
+
+ rReq.Done();
+ m_eLastSearchCommand = s_pSrchItem->GetCommand();
+ SwView::SetMoveType(nMoveType);
+ }
+ break;
+ case FID_SEARCH_SEARCHSET:
+ case FID_SEARCH_REPLACESET:
+ {
+ static const WhichRangesContainer aNormalAttr(svl::Items<
+/* 0 */ RES_CHRATR_CASEMAP, RES_CHRATR_CASEMAP,
+/* 2 */ RES_CHRATR_COLOR, RES_CHRATR_POSTURE,
+/* 4 */ RES_CHRATR_SHADOWED, RES_CHRATR_WORDLINEMODE,
+/* 6 */ RES_CHRATR_BLINK, RES_CHRATR_BLINK,
+/* 8 */ RES_CHRATR_BACKGROUND, RES_CHRATR_BACKGROUND,
+/*10 */ RES_CHRATR_ROTATE, RES_CHRATR_ROTATE,
+/*12 */ RES_CHRATR_SCALEW, RES_CHRATR_RELIEF,
+/*14 */ RES_CHRATR_OVERLINE, RES_CHRATR_OVERLINE,
+/*16 */ RES_PARATR_LINESPACING, RES_PARATR_HYPHENZONE,
+/*18 */ RES_PARATR_REGISTER, RES_PARATR_REGISTER,
+/*20 */ RES_PARATR_VERTALIGN, RES_PARATR_VERTALIGN,
+ RES_MARGIN_FIRSTLINE, RES_MARGIN_RIGHT,
+ RES_UL_SPACE, RES_UL_SPACE,
+/*24 */ SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP
+ >);
+
+ SfxItemSet aSet(m_pWrtShell->GetAttrPool(), aNormalAttr);
+
+ if( SvtCTLOptions::IsCTLFontEnabled() )
+ {
+ aSet.MergeRange(RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_WEIGHT);
+ }
+ if( SvtCJKOptions::IsAnyEnabled() )
+ {
+ aSet.MergeRange(RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_WEIGHT);
+ aSet.MergeRange(RES_CHRATR_EMPHASIS_MARK, RES_CHRATR_TWO_LINES);
+ aSet.MergeRange(RES_PARATR_SCRIPTSPACE, RES_PARATR_FORBIDDEN_RULES);
+ }
+
+ TypedWhichId<SvxSetItem> nWhich = SID_SEARCH_SEARCHSET;
+
+ if ( FID_SEARCH_REPLACESET == nSlot )
+ {
+ nWhich = SID_SEARCH_REPLACESET;
+
+ if ( s_xReplaceList )
+ {
+ s_xReplaceList->Get( aSet );
+ s_xReplaceList.reset();
+ }
+ }
+ else if ( s_xSearchList )
+ {
+ s_xSearchList->Get( aSet );
+ s_xSearchList.reset();
+ }
+ rReq.SetReturnValue( SvxSetItem( nWhich, aSet ) );
+ }
+ break;
+ default:
+ SAL_WARN_IF( nSlot, "sw", "nSlot: " << nSlot << " wrong Dispatcher (viewsrch.cxx)" );
+ return;
+ }
+}
+
+bool SwView::SearchAndWrap(bool bApi)
+{
+ SwSearchOptions aOpts( m_pWrtShell.get(), s_pSrchItem->GetBackward() );
+
+ // Remember starting position of the search for wraparound
+ // Start- / EndAction perhaps because existing selections of 'search all'
+ m_pWrtShell->StartAllAction();
+ m_pWrtShell->Push();
+
+ // After a search all action we place the cursor at the beginning of
+ // the document so that the single search selects the first matching
+ // occurrence in the document instead of the second.
+ if( m_eLastSearchCommand == SvxSearchCmd::FIND_ALL )
+ {
+ if( SwDocPositions::Start == aOpts.eEnd )
+ m_pWrtShell->EndOfSection();
+ else
+ m_pWrtShell->StartOfSection();
+ }
+
+ // fdo#65014 : Ensure that the point of the cursor is at the extremity of the
+ // selection closest to the end being searched to as to exclude the selected
+ // region from the search. (This doesn't work in the case of multiple
+ // selected regions as the cursor doesn't mark the selection in that case.)
+ m_pWrtShell->GetCursor()->Normalize( s_pSrchItem->GetBackward() );
+
+ if (!m_pWrtShell->HasSelection() && (s_pSrchItem->HasStartPoint()))
+ {
+ // No selection -> but we have a start point (top left corner of the
+ // current view), start searching from there, not from the current
+ // cursor position.
+ SwEditShell& rShell = GetWrtShell();
+ Point aPosition(s_pSrchItem->GetStartPointX(), s_pSrchItem->GetStartPointY());
+ rShell.SetCursor(aPosition);
+ }
+
+ // If you want to search in selected areas, they must not be unselected.
+ if (!s_pSrchItem->GetSelection())
+ m_pWrtShell->KillSelection(nullptr, false);
+
+ std::optional<SwWait> oWait( std::in_place, *GetDocShell(), true );
+ if( FUNC_Search( aOpts ) )
+ {
+ s_bFound = true;
+ if(m_pWrtShell->IsSelFrameMode())
+ {
+ m_pWrtShell->UnSelectFrame();
+ m_pWrtShell->LeaveSelFrameMode();
+ }
+ m_pWrtShell->Pop();
+ m_pWrtShell->EndAllAction();
+ return true;
+ }
+ oWait.reset();
+
+ // Search in the specialized areas when no search is present in selections.
+ // When searching selections will already searched in these special areas.
+ bool bHasSrchInOther = s_bExtra;
+ if (!s_pSrchItem->GetSelection() && !s_bExtra )
+ {
+ s_bExtra = true;
+ if( FUNC_Search( aOpts ) )
+ {
+ s_bFound = true;
+ m_pWrtShell->Pop();
+ m_pWrtShell->EndAllAction();
+ return true;
+ }
+ s_bExtra = false;
+ }
+ else
+ s_bExtra = !s_bExtra;
+
+ // If starting position is at the end or beginning of the document.
+ if (aOpts.bDontWrap)
+ {
+ m_pWrtShell->EndAllAction();
+ if( !bApi )
+ {
+#if HAVE_FEATURE_DESKTOP
+ m_pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND, s_pSrchItem->GetSearchString().toUtf8());
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound);
+#endif
+ }
+ s_bFound = false;
+ m_pWrtShell->Pop();
+ return false;
+ }
+ m_pWrtShell->EndAllAction();
+ // Try again with WrapAround?
+
+ m_pWrtShell->StartAllAction();
+ m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
+ oWait.emplace( *GetDocShell(), true );
+
+ bool bSrchBkwrd = SwDocPositions::Start == aOpts.eEnd;
+
+ aOpts.eEnd = bSrchBkwrd ? SwDocPositions::Start : SwDocPositions::End;
+ aOpts.eStart = bSrchBkwrd ? SwDocPositions::End : SwDocPositions::Start;
+
+ if (bHasSrchInOther)
+ {
+ m_pWrtShell->ClearMark();
+ // Select the start or the end of the entire document
+ if (bSrchBkwrd)
+ m_pWrtShell->SttEndDoc(false);
+ else
+ m_pWrtShell->SttEndDoc(true);
+ }
+
+ s_bFound = bool(FUNC_Search( aOpts ));
+
+ // If WrapAround found no matches in the body text, search in the special
+ // sections, too.
+ if (!s_bFound && !s_pSrchItem->GetSelection() && !s_bExtra)
+ {
+ s_bExtra = true;
+ if (FUNC_Search(aOpts))
+ s_bFound = true;
+ else
+ s_bExtra = false;
+ }
+
+ m_pWrtShell->EndAllAction();
+ oWait.reset();
+#if HAVE_FEATURE_DESKTOP
+ if (s_bFound)
+ {
+ if (!bSrchBkwrd)
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::End);
+ else
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Start);
+ }
+ else if(!bApi)
+ {
+ m_pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND, s_pSrchItem->GetSearchString().toUtf8());
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound);
+ }
+#endif
+ return s_bFound;
+}
+
+sal_uInt16 SwView::SearchAll()
+{
+ SwWait aWait( *GetDocShell(), true );
+ m_pWrtShell->StartAllAction();
+
+ SwSearchOptions aOpts( m_pWrtShell.get(), s_pSrchItem->GetBackward() );
+
+ if (!s_pSrchItem->GetSelection())
+ {
+ // Cancel existing selections, if should not be sought in selected areas.
+ m_pWrtShell->KillSelection(nullptr, false);
+
+ if( SwDocPositions::Start == aOpts.eEnd )
+ m_pWrtShell->EndOfSection();
+ else
+ m_pWrtShell->StartOfSection();
+ }
+ s_bExtra = false;
+ sal_uInt16 nFound = o3tl::narrowing<sal_uInt16>(FUNC_Search( aOpts ));
+ s_bFound = 0 != nFound;
+
+ m_pWrtShell->EndAllAction();
+ return nFound;
+}
+
+void SwView::Replace()
+{
+ SwWait aWait( *GetDocShell(), true );
+
+ m_pWrtShell->StartAllAction();
+
+ if( s_pSrchItem->GetPattern() ) // Templates?
+ {
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, s_pSrchItem->GetSearchString());
+ aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
+ aRewriter.AddRule(UndoArg3, s_pSrchItem->GetReplaceString());
+
+ m_pWrtShell->StartUndo(SwUndoId::UI_REPLACE_STYLE, &aRewriter);
+
+ m_pWrtShell->SetTextFormatColl( m_pWrtShell->GetParaStyle(
+ s_pSrchItem->GetReplaceString(),
+ SwWrtShell::GETSTYLE_CREATESOME ));
+
+ m_pWrtShell->EndUndo();
+ }
+ else
+ {
+ if (GetPostItMgr()->HasActiveSidebarWin())
+ GetPostItMgr()->Replace(s_pSrchItem);
+
+ bool bReqReplace = true;
+
+ if(m_pWrtShell->HasSelection())
+ {
+ /* check that the selection match the search string*/
+ //save state
+ SwPosition aStartPos = * m_pWrtShell->GetCursor()->Start();
+ SwPosition aEndPos = * m_pWrtShell->GetCursor()->End();
+ bool bHasSelection = s_pSrchItem->GetSelection();
+ SvxSearchCmd nOldCmd = s_pSrchItem->GetCommand();
+
+ //set state for checking if current selection has a match
+ s_pSrchItem->SetCommand( SvxSearchCmd::FIND );
+ s_pSrchItem->SetSelection(true);
+
+ //check if it matches
+ SwSearchOptions aOpts( m_pWrtShell.get(), s_pSrchItem->GetBackward() );
+ if( ! FUNC_Search(aOpts) )
+ {
+
+ //no matching therefore should not replace selection
+ // => remove selection
+
+ if(! s_pSrchItem->GetBackward() )
+ {
+ (* m_pWrtShell->GetCursor()->Start()) = aStartPos;
+ (* m_pWrtShell->GetCursor()->End()) = aEndPos;
+ }
+ else
+ {
+ (* m_pWrtShell->GetCursor()->Start()) = aEndPos;
+ (* m_pWrtShell->GetCursor()->End()) = aStartPos;
+ }
+ bReqReplace = false;
+ }
+
+ //set back old search state
+ s_pSrchItem->SetCommand( nOldCmd );
+ s_pSrchItem->SetSelection(bHasSelection);
+ }
+ /*
+ * remove current selection
+ * otherwise it is always replaced
+ * no matter if the search string exists or not in the selection
+ * Now the selection is removed and the next matching string is selected
+ */
+
+ if( bReqReplace )
+ {
+
+ bool bReplaced = m_pWrtShell->SwEditShell::Replace( s_pSrchItem->GetReplaceString(),
+ s_pSrchItem->GetRegExp());
+ if( bReplaced && s_xReplaceList && s_xReplaceList->Count() && m_pWrtShell->HasSelection() )
+ {
+ SfxItemSet aReplSet( m_pWrtShell->GetAttrPool(),
+ aTextFormatCollSetRange );
+ if( s_xReplaceList->Get( aReplSet ).Count() )
+ {
+ ::SfxToSwPageDescAttr( *m_pWrtShell, aReplSet );
+ m_pWrtShell->SwEditShell::SetAttrSet( aReplSet );
+ }
+ }
+ }
+ }
+
+ m_pWrtShell->EndAllAction();
+}
+
+SwSearchOptions::SwSearchOptions( SwWrtShell const * pSh, bool bBackward )
+ : eStart(SwDocPositions::Curr)
+{
+ if( bBackward )
+ {
+ eEnd = SwDocPositions::Start;
+ bDontWrap = pSh->IsEndOfDoc();
+ }
+ else
+ {
+ eEnd = SwDocPositions::End;
+ bDontWrap = pSh->IsStartOfDoc();
+ }
+}
+
+sal_uLong SwView::FUNC_Search( const SwSearchOptions& rOptions )
+{
+#if HAVE_FEATURE_DESKTOP
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Empty);
+#endif
+ bool bDoReplace = s_pSrchItem->GetCommand() == SvxSearchCmd::REPLACE ||
+ s_pSrchItem->GetCommand() == SvxSearchCmd::REPLACE_ALL;
+
+ FindRanges eRanges = s_pSrchItem->GetSelection()
+ ? FindRanges::InSel
+ : s_bExtra
+ ? FindRanges::InOther : FindRanges::InBody;
+ if (s_pSrchItem->GetCommand() == SvxSearchCmd::FIND_ALL ||
+ s_pSrchItem->GetCommand() == SvxSearchCmd::REPLACE_ALL)
+ eRanges |= FindRanges::InSelAll;
+
+ m_pWrtShell->SttSelect();
+
+ static const WhichRangesContainer aSearchAttrRange(svl::Items<
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_PARATR_BEGIN, RES_PARATR_END-1,
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP
+ >);
+
+ SfxItemSet aSrchSet( m_pWrtShell->GetAttrPool(), aSearchAttrRange);
+ if( s_xSearchList && s_xSearchList->Count() )
+ {
+ s_xSearchList->Get( aSrchSet );
+
+ // -- Page break with page template
+ ::SfxToSwPageDescAttr( *m_pWrtShell, aSrchSet );
+ }
+
+ std::optional<SfxItemSet> xReplSet;
+ if( bDoReplace && s_xReplaceList && s_xReplaceList->Count() )
+ {
+ xReplSet.emplace( m_pWrtShell->GetAttrPool(), aSearchAttrRange );
+ s_xReplaceList->Get( *xReplSet );
+
+ // -- Page break with page template
+ ::SfxToSwPageDescAttr( *m_pWrtShell, *xReplSet );
+
+ if( !xReplSet->Count() ) // too bad, we don't know
+ xReplSet.reset(); // the attributes
+ }
+
+ // build SearchOptions to be used
+
+ i18nutil::SearchOptions2 aSearchOpt( s_pSrchItem->GetSearchOptions() );
+ aSearchOpt.Locale = GetAppLanguageTag().getLocale();
+ if( !bDoReplace )
+ aSearchOpt.replaceString.clear();
+
+ sal_Int32 nFound;
+ if( aSrchSet.Count() || ( xReplSet && xReplSet->Count() ))
+ {
+ nFound = m_pWrtShell->SearchAttr(
+ aSrchSet,
+ !s_pSrchItem->GetPattern(),
+ rOptions.eStart,
+ rOptions.eEnd,
+ eRanges,
+ !s_pSrchItem->GetSearchString().isEmpty() ? &aSearchOpt : nullptr,
+ xReplSet ? &*xReplSet : nullptr );
+ }
+ else if( s_pSrchItem->GetPattern() )
+ {
+ // Searching (and replacing) templates
+ const OUString& sRplStr( s_pSrchItem->GetReplaceString() );
+ nFound = m_pWrtShell->SearchTempl( s_pSrchItem->GetSearchString(),
+ rOptions.eStart,
+ rOptions.eEnd,
+ eRanges,
+ bDoReplace ? &sRplStr : nullptr );
+ }
+ else
+ {
+ // Normal search
+ nFound = m_pWrtShell->SearchPattern(aSearchOpt, s_pSrchItem->GetNotes(),
+ rOptions.eStart,
+ rOptions.eEnd,
+ eRanges,
+ bDoReplace );
+ }
+ m_pWrtShell->EndSelect();
+ return nFound;
+}
+
+SvxSearchDialog* SwView::GetSearchDialog()
+{
+#if HAVE_FEATURE_DESKTOP
+ const sal_uInt16 nId = SvxSearchDialogWrapper::GetChildWindowId();
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if (!pViewFrm)
+ return nullptr;
+ SvxSearchDialogWrapper *pWrp = static_cast<SvxSearchDialogWrapper*>(pViewFrm->GetChildWindow(nId));
+ if (!pWrp)
+ return nullptr;
+ return pWrp->getDialog();
+#else
+ return nullptr;
+#endif
+}
+
+void SwView::StateSearch(SfxItemSet &rSet)
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while(nWhich)
+ {
+ switch(nWhich)
+ {
+ case SID_SEARCH_OPTIONS:
+ {
+ SearchOptionFlags nOpt = SearchOptionFlags::ALL;
+ if( GetDocShell()->IsReadOnly() )
+ nOpt &= ~SearchOptionFlags( SearchOptionFlags::REPLACE |
+ SearchOptionFlags::REPLACE_ALL );
+ rSet.Put( SfxUInt16Item( SID_SEARCH_OPTIONS, static_cast<sal_uInt16>(nOpt) ));
+ }
+ break;
+ case SID_SEARCH_ITEM:
+ {
+ if ( !s_pSrchItem )
+ {
+ s_pSrchItem = new SvxSearchItem( SID_SEARCH_ITEM );
+ s_pSrchItem->SetFamily(SfxStyleFamily::Para);
+ s_pSrchItem->SetSearchString( m_pWrtShell->GetSelText() );
+ }
+
+ if( s_bJustOpened && m_pWrtShell->IsSelection() )
+ {
+ OUString aText;
+ if( 1 == m_pWrtShell->GetCursorCnt() &&
+ !( aText = m_pWrtShell->SwCursorShell::GetSelText() ).isEmpty() )
+ {
+ s_pSrchItem->SetSearchString( aText );
+ s_pSrchItem->SetSelection( false );
+ }
+ else
+ s_pSrchItem->SetSelection( true );
+ }
+
+ s_bJustOpened = false;
+ rSet.Put( *s_pSrchItem );
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewstat.cxx b/sw/source/uibase/uiview/viewstat.cxx
new file mode 100644
index 0000000000..3c624274f4
--- /dev/null
+++ b/sw/source/uibase/uiview/viewstat.cxx
@@ -0,0 +1,691 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+
+#include <hintids.hxx>
+#include <com/sun/star/linguistic2/XThesaurus.hpp>
+#include <svl/whiter.hxx>
+#include <svl/cjkoptions.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/imageitm.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <sfx2/htmlmode.hxx>
+#include <swmodule.hxx>
+#include <tox.hxx>
+#include <sfx2/dispatch.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <uitool.hxx>
+#include <viewopt.hxx>
+#include <pagedesc.hxx>
+#include <wview.hxx>
+#include <globdoc.hxx>
+#include <svl/stritem.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <comphelper/lok.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <svl/visitem.hxx>
+#include <redline.hxx>
+#include <rootfrm.hxx>
+#include <docary.hxx>
+#include <sfx2/infobar.hxx>
+#include <docsh.hxx>
+#include <strings.hrc>
+
+#include <cmdid.h>
+#include <IDocumentRedlineAccess.hxx>
+
+#include <doc.hxx>
+#include <workctrl.hxx>
+
+using namespace ::com::sun::star;
+
+void SwView::GetState(SfxItemSet &rSet)
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ FrameTypeFlags eFrameType = FrameTypeFlags::NONE;
+ bool bGetFrameType = false;
+ bool bWeb = dynamic_cast<SwWebView*>( this ) != nullptr;
+
+ while(nWhich)
+ {
+ switch(nWhich)
+ {
+ case SID_ZOOM_IN:
+ case SID_ZOOM_OUT:
+ {
+ tools::Long nFact = m_pWrtShell->GetViewOptions()->GetZoom();
+ if ((SID_ZOOM_IN == nWhich && nFact >= tools::Long(600)) ||
+ (SID_ZOOM_OUT == nWhich && nFact <= tools::Long(20)))
+ {
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+ case FN_TOGGLE_OUTLINE_CONTENT_VISIBILITY:
+ {
+ bool bDisable(true);
+ if (m_pWrtShell->GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ {
+ SwOutlineNodes::size_type nPos = m_pWrtShell->GetOutlinePos();
+ if (nPos != SwOutlineNodes::npos)
+ bDisable = false;
+ }
+ if (bDisable)
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case FN_NAV_ELEMENT:
+ // used to update all instances of this control
+ rSet.InvalidateItem( nWhich );
+ break;
+ case FN_SCROLL_PREV:
+ case FN_SCROLL_NEXT:
+ {
+ if (s_nMoveType == NID_RECENCY)
+ {
+ if (!m_pWrtShell->GetNavigationMgr().forwardEnabled())
+ rSet.DisableItem(FN_SCROLL_NEXT);
+ if (!m_pWrtShell->GetNavigationMgr().backEnabled())
+ rSet.DisableItem(FN_SCROLL_PREV);
+ }
+ }
+ break;
+ case FN_EDIT_LINK_DLG:
+ if( m_pWrtShell->GetLinkManager().GetLinks().empty() )
+ rSet.DisableItem(nWhich);
+ else if( m_pWrtShell->IsSelFrameMode() &&
+ m_pWrtShell->IsSelObjProtected(FlyProtectFlags::Content) != FlyProtectFlags::NONE)
+ {
+ rSet.DisableItem(nWhich);
+ }
+ break;
+
+ case SID_DRAWTBX_LINES:
+ if ( bWeb )
+ rSet.DisableItem(nWhich);
+ break;
+
+ case SID_INSERT_GRAPHIC:
+ if( m_pWrtShell->CursorInsideInputField() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_INSERT_SIGNATURELINE:
+ if( !( m_nSelectionType & SelectionType::Text ||
+ m_nSelectionType & SelectionType::NumberList ) )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_EDIT_SIGNATURELINE:
+ case SID_SIGN_SIGNATURELINE:
+ if (!isSignatureLineSelected() || isSignatureLineSigned())
+ rSet.DisableItem(nWhich);
+ break;
+ case SID_INSERT_QRCODE:
+ if( !( m_nSelectionType & SelectionType::Text ||
+ m_nSelectionType & SelectionType::NumberList ) )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_EDIT_QRCODE:
+ if (!isQRCodeSelected())
+ rSet.DisableItem(nWhich);
+ break;
+ case FN_INSERT_CAPTION:
+ {
+ // There are captions for graphics, OLE objects, frames and tables
+ if( !bGetFrameType )
+ {
+ eFrameType = m_pWrtShell->GetFrameType(nullptr, true);
+ bGetFrameType = true;
+ }
+ if (! ( ((eFrameType & FrameTypeFlags::FLY_ANY) && m_nSelectionType != SelectionType::DrawObjectEditMode)||
+ m_nSelectionType & SelectionType::Table ||
+ m_nSelectionType & SelectionType::DrawObject) )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ else if((m_pWrtShell->IsObjSelected() || m_pWrtShell->IsFrameSelected()) &&
+ (m_pWrtShell->IsSelObjProtected( FlyProtectFlags::Parent) != FlyProtectFlags::NONE ||
+ m_pWrtShell->IsSelObjProtected( FlyProtectFlags::Content ) != FlyProtectFlags::NONE))
+ {
+ rSet.DisableItem(nWhich);
+ }
+ else if( m_pWrtShell->IsTableMode()
+ || isSignatureLineSelected()
+ || m_pWrtShell->CursorInsideInputField() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+
+ case FN_EDIT_FOOTNOTE:
+ {
+ if( !m_pWrtShell->GetCurFootnote() )
+ rSet.DisableItem(nWhich);
+ }
+ break;
+
+ case FN_CHANGE_PAGENUM:
+ {
+ FrameTypeFlags nType = m_pWrtShell->GetFrameType(nullptr,true);
+ if( ( FrameTypeFlags::FLY_ANY | FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER |
+ FrameTypeFlags::FOOTNOTE | FrameTypeFlags::DRAWOBJ ) & nType )
+ rSet.DisableItem(nWhich);
+ else
+ rSet.Put(SfxUInt16Item(nWhich, m_pWrtShell->GetPageOffset()));
+ }
+ break;
+ case SID_PRINTDOC:
+ case SID_PRINTDOCDIRECT:
+ GetSlotState( nWhich, SfxViewShell::GetInterface(), &rSet );
+ break;
+ case SID_ATTR_PAGE_ORIENTATION:
+ case SID_ATTR_PAGE:
+ case SID_ATTR_PAGE_SIZE:
+ case SID_ATTR_PAGE_PAPERBIN:
+ case RES_PAPER_BIN:
+ case FN_PARAM_FTN_INFO:
+ {
+ const size_t nCurIdx = m_pWrtShell->GetCurPageDesc();
+ const SwPageDesc& rDesc = m_pWrtShell->GetPageDesc( nCurIdx );
+
+ // set correct parent to get the XFILL_NONE FillStyle as needed
+ if(!rSet.GetParent())
+ {
+ const SwFrameFormat& rMaster = rDesc.GetMaster();
+
+ rSet.SetParent(&rMaster.GetDoc()->GetDfltFrameFormat()->GetAttrSet());
+ }
+
+ ::PageDescToItemSet( rDesc, rSet);
+
+ if (nWhich == SID_ATTR_PAGE_ORIENTATION && comphelper::LibreOfficeKit::isActive())
+ {
+ OString aPayload = ".uno:Orientation="_ostr;
+ if (rDesc.GetLandscape())
+ {
+ aPayload += "IsLandscape";
+ }
+ else
+ {
+ aPayload += "IsPortrait";
+ }
+ libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED, aPayload);
+ }
+ }
+ break;
+ case RES_BACKGROUND:
+ case SID_ATTR_BRUSH:
+ {
+ const size_t nCurIdx = m_pWrtShell->GetCurPageDesc();
+ const SwPageDesc& rDesc = m_pWrtShell->GetPageDesc( nCurIdx );
+ const SwFrameFormat& rMaster = rDesc.GetMaster();
+ const SvxBrushItem& rBrush = rMaster.GetFormatAttr(RES_BACKGROUND);
+ rSet.Put(rBrush);
+ }
+ break;
+ case SID_CLEARHISTORY:
+ {
+ rSet.Put(SfxBoolItem(nWhich, m_pWrtShell->GetLastUndoInfo(nullptr, nullptr)));
+ }
+ break;
+ case SID_UNDO:
+ {
+ // which must not be present, so let them create:
+ if( !m_pShell )
+ SelectShell();
+
+ const SfxPoolItemHolder aResult(m_pShell->GetSlotState(SID_UNDO));
+ if(nullptr != aResult.getItem())
+ rSet.Put(*aResult.getItem());
+ else
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case FN_INSERT_OBJ_CTRL:
+ if( bWeb
+ || m_pWrtShell->CursorInsideInputField() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ break;
+
+ case FN_UPDATE_TOX:
+ if(!m_pWrtShell->GetTOXCount())
+ rSet.DisableItem(nWhich);
+ break;
+ case FN_EDIT_CURRENT_TOX:
+ case FN_UPDATE_CUR_TOX:
+ {
+ const SwTOXBase* pBase = nullptr;
+ if(nullptr == (pBase = m_pWrtShell->GetCurTOX()) ||
+ (FN_EDIT_CURRENT_TOX == nWhich && pBase->IsTOXBaseInReadonly()))
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_TWAIN_SELECT:
+ case SID_TWAIN_TRANSFER:
+#if defined(_WIN32) || defined UNX
+ {
+ if(!SW_MOD()->GetScannerManager().is())
+ rSet.DisableItem(nWhich);
+ }
+#endif
+ break;
+ case RES_PARATR_TABSTOP:
+ case SID_ATTR_DEFTABSTOP:
+ {
+ const SvxTabStopItem& rDefTabs = m_pWrtShell->GetDefault(RES_PARATR_TABSTOP);
+ rSet.Put( SfxUInt16Item( nWhich,
+ o3tl::narrowing<sal_uInt16>(::GetTabDist(rDefTabs))));
+ }
+ break;
+ case SID_ATTR_LANGUAGE:
+ {
+ rSet.Put(m_pWrtShell->GetDefault(RES_CHRATR_LANGUAGE).CloneSetWhich(SID_ATTR_LANGUAGE));
+ }
+ break;
+ case RES_CHRATR_CJK_LANGUAGE:
+ {
+ rSet.Put(m_pWrtShell->GetDefault(RES_CHRATR_CJK_LANGUAGE)
+ .CloneSetWhich(RES_CHRATR_CJK_LANGUAGE));
+ }
+ break;
+ case RES_CHRATR_CTL_LANGUAGE:
+ {
+ rSet.Put(m_pWrtShell->GetDefault(RES_CHRATR_CTL_LANGUAGE)
+ .CloneSetWhich(RES_CHRATR_CTL_LANGUAGE));
+ }
+ break;
+ case FN_REDLINE_ON:
+ rSet.Put( SfxBoolItem( nWhich, GetDocShell()->IsChangeRecording() ) );
+ // When the view is new (e.g. on load), show the Hidden Track Changes infobar
+ // if Show Changes is disabled, but recording of changes is enabled
+ // or hidden tracked changes are there already in the document.
+ // Note: the infobar won't be shown, if the Track Changes toolbar is already
+ // enabled, see in sfx2.
+ if ( m_bForceChangesToolbar && m_pWrtShell->GetLayout()->IsHideRedlines() )
+ {
+ bool isRecording = GetDocShell()->IsChangeRecording();
+ bool hasRecorded =
+ m_pWrtShell->GetDoc()->getIDocumentRedlineAccess().GetRedlineTable().size();
+ if ( isRecording || hasRecorded )
+ {
+ GetDocShell()->AppendInfoBarWhenReady(
+ "hiddentrackchanges", SwResId(STR_HIDDEN_CHANGES),
+ SwResId( (isRecording && hasRecorded)
+ ? STR_HIDDEN_CHANGES_DETAIL
+ : isRecording
+ ? STR_HIDDEN_CHANGES_DETAIL2
+ : STR_HIDDEN_CHANGES_DETAIL3 ),
+ InfobarType::INFO);
+ }
+ }
+ m_bForceChangesToolbar = false;
+ break;
+ case FN_REDLINE_PROTECT :
+ rSet.Put( SfxBoolItem( nWhich, GetDocShell()->HasChangeRecordProtection() ) );
+ break;
+ case FN_REDLINE_SHOW:
+ {
+ rSet.Put(SfxBoolItem(nWhich, !m_pWrtShell->GetLayout()->IsHideRedlines()));
+ }
+ break;
+ case SID_AVMEDIA_PLAYER :
+ case FN_REDLINE_ACCEPT :
+ {
+ SfxViewFrame& rVFrame = GetViewFrame();
+ if (rVFrame.KnowsChildWindow(nWhich))
+ rSet.Put(SfxBoolItem( nWhich, rVFrame.HasChildWindow(nWhich)));
+ else
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case FN_REDLINE_ACCEPT_DIRECT:
+ case FN_REDLINE_REJECT_DIRECT:
+ case FN_REDLINE_ACCEPT_TONEXT:
+ case FN_REDLINE_REJECT_TONEXT:
+ {
+ SwDoc *pDoc = m_pWrtShell->GetDoc();
+ SwPaM *pCursor = m_pWrtShell->GetCursor();
+ bool bDisable = false;
+ if (GetDocShell()->HasChangeRecordProtection())
+ bDisable = true;
+ else if (pCursor->HasMark())
+ {
+ // If the selection does not contain redlines, disable accepting/rejecting changes.
+ SwRedlineTable::size_type index = 0;
+ const SwRedlineTable& table = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
+ const SwRangeRedline* redline = table.FindAtPosition( *pCursor->Start(), index );
+ if( redline != nullptr && *redline->Start() == *pCursor->End())
+ redline = nullptr;
+ if( redline == nullptr )
+ {
+ // for table selections, GetCursor() gives only PaM of the first cell,
+ // so extend the redline limit to end of last cell of the selection
+ // TODO: adjust this for column selections, where the selected columns
+ // don't contain any redlines and any tracked row changes, but the
+ // adjacent not selected columns do to avoid false Enable
+ std::optional<SwPosition> oSelectionEnd;
+ if ( m_pWrtShell->IsTableMode() &&
+ m_pWrtShell->GetTableCursor()->GetSelectedBoxesCount() )
+ {
+ const SwSelBoxes& rBoxes = m_pWrtShell->GetTableCursor()->GetSelectedBoxes();
+ const SwStartNode *pSttNd = rBoxes.back()->GetSttNd();
+ const SwNode* pEndNode = pSttNd->GetNodes()[pSttNd->EndOfSectionIndex()];
+ oSelectionEnd.emplace(*pEndNode);
+ }
+ else
+ oSelectionEnd.emplace(*pCursor->End());
+
+ for(; index < table.size(); ++index )
+ {
+ const SwRangeRedline* tmp = table[ index ];
+ if( *tmp->Start() >= *oSelectionEnd )
+ break;
+ if( tmp->HasMark() && tmp->IsVisible())
+ {
+ redline = tmp;
+ break;
+ }
+ }
+ }
+ if( redline == nullptr )
+ bDisable = true;
+ }
+ else
+ {
+ // If the cursor position isn't on a redline, disable
+ // accepting/rejecting changes.
+ SwTableBox* pTableBox;
+ if (nullptr == pDoc->getIDocumentRedlineAccess().GetRedline(*pCursor->Start(), nullptr) &&
+ // except in the case of an inserted or deleted table row
+ ( !m_pWrtShell->IsCursorInTable() ||
+ (pTableBox = pCursor->Start()->GetNode().GetTableBox() ) == nullptr ||
+ (RedlineType::None == pTableBox->GetRedlineType() &&
+ RedlineType::None == pTableBox->GetUpper()->GetRedlineType()) ) )
+ {
+ bDisable = true;
+ }
+ }
+
+ // LibreOfficeKit wants to handle changes by index, so always allow here.
+ if (bDisable)
+ rSet.DisableItem(nWhich);
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ OString aPayload(".uno:TrackedChangeIndex="_ostr);
+ SwRedlineTable::size_type nRedline = 0;
+ if (pDoc->getIDocumentRedlineAccess().GetRedline(*pCursor->Start(), &nRedline))
+ aPayload += OString::number(nRedline);
+ libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED, aPayload);
+ }
+ }
+ break;
+
+ case FN_REDLINE_NEXT_CHANGE:
+ case FN_REDLINE_PREV_CHANGE:
+ {
+ // Enable change navigation if we have any redlines. Ideally we should disable
+ // "Next Change" if we're at or past the last change, and similarly for
+ // "Previous Change"
+ if (0 == m_pWrtShell->GetRedlineCount())
+ rSet.DisableItem(nWhich);
+ }
+ break;
+
+ case SID_THESAURUS:
+ {
+ SwWrtShell &rSh = GetWrtShell();
+ if (2 <= rSh.GetCursorCnt()) // multi selection?
+ rSet.DisableItem(nWhich);
+ else
+ {
+ LanguageType nLang = rSh.GetCurLang();
+
+ // disable "Thesaurus" (menu entry and key shortcut) if the
+ // language is not supported (by default it is enabled)
+ uno::Reference< linguistic2::XThesaurus > xThes( ::GetThesaurus() );
+ if (!xThes.is() || nLang == LANGUAGE_NONE ||
+ !xThes->hasLocale( LanguageTag::convertToLocale( nLang ) ))
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+ case SID_HANGUL_HANJA_CONVERSION:
+ case SID_CHINESE_CONVERSION:
+ {
+ if (!SvtCJKOptions::IsAnyEnabled())
+ {
+ GetViewFrame().GetBindings().SetVisibleState( nWhich, false );
+ rSet.DisableItem(nWhich);
+ }
+ else
+ GetViewFrame().GetBindings().SetVisibleState( nWhich, true );
+ }
+ break;
+ case SID_MAIL_SCROLLBODY_PAGEDOWN:
+ {
+ const tools::Long nBottom = m_pWrtShell->GetDocSize().Height() + DOCUMENTBORDER;
+ const tools::Long nAct = GetVisArea().Bottom();
+ rSet.Put(SfxBoolItem(SID_MAIL_SCROLLBODY_PAGEDOWN, nAct < nBottom ));
+ }
+ break;
+
+ case SID_DOCUMENT_COMPARE:
+ case SID_DOCUMENT_MERGE:
+ if( dynamic_cast<const SwGlobalDocShell* >(GetDocShell()) != nullptr||
+ (SID_DOCUMENT_MERGE == nWhich && m_pWrtShell->getIDocumentRedlineAccess().GetRedlinePassword().hasElements()))
+ rSet.DisableItem(nWhich);
+ break;
+ case SID_VIEW_DATA_SOURCE_BROWSER:
+ if ( !SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) )
+ rSet.Put( SfxVisibilityItem( nWhich, false ) );
+ else
+ rSet.Put( SfxBoolItem( nWhich, GetViewFrame().HasChildWindow( SID_BROWSER ) ) );
+ break;
+ case SID_READONLY_MODE:
+ rSet.Put(SfxBoolItem(nWhich,
+ m_pWrtShell->HasReadonlySel()||GetDocShell()->IsReadOnly()));
+ break;
+ case SID_IMAGE_ORIENTATION:
+ {
+ SfxImageItem aImageItem(nWhich);
+ if(m_pWrtShell->IsInVerticalText())
+ aImageItem.SetRotation( 2700_deg10 );
+ if(m_pWrtShell->IsInRightToLeftText())
+ aImageItem.SetMirrored( true );
+ rSet.Put(aImageItem);
+ }
+ break;
+ case FN_INSERT_FIELD_DATA_ONLY :
+ if(!m_bInMailMerge && !GetViewFrame().HasChildWindow(nWhich))
+ rSet.DisableItem(nWhich);
+ break;
+ case FN_MAILMERGE_SENDMAIL_CHILDWINDOW:
+ break;
+ case SID_ALIGN_ANY_LEFT :
+ case SID_ALIGN_ANY_HCENTER :
+ case SID_ALIGN_ANY_RIGHT :
+ case SID_ALIGN_ANY_JUSTIFIED:
+ case SID_ALIGN_ANY_TOP :
+ case SID_ALIGN_ANY_VCENTER :
+ case SID_ALIGN_ANY_BOTTOM :
+ case SID_ALIGN_ANY_HDEFAULT :
+ case SID_ALIGN_ANY_VDEFAULT :
+ {
+ if( !m_pShell )
+ SelectShell();
+ sal_uInt16 nAlias = 0;
+ if( m_nSelectionType & (SelectionType::DrawObjectEditMode|SelectionType::Text) )
+ {
+ switch( nWhich )
+ {
+ case SID_ALIGN_ANY_LEFT : nAlias = SID_ATTR_PARA_ADJUST_LEFT; break;
+ case SID_ALIGN_ANY_HCENTER : nAlias = SID_ATTR_PARA_ADJUST_CENTER; break;
+ case SID_ALIGN_ANY_RIGHT : nAlias = SID_ATTR_PARA_ADJUST_RIGHT; break;
+ case SID_ALIGN_ANY_JUSTIFIED: nAlias = SID_ATTR_PARA_ADJUST_BLOCK; break;
+ case SID_ALIGN_ANY_TOP : nAlias = SID_TABLE_VERT_NONE; break;
+ case SID_ALIGN_ANY_VCENTER : nAlias = SID_TABLE_VERT_CENTER; break;
+ case SID_ALIGN_ANY_BOTTOM : nAlias = SID_TABLE_VERT_BOTTOM; break;
+ }
+ }
+ else
+ {
+ switch( nWhich )
+ {
+ case SID_ALIGN_ANY_LEFT : nAlias = SID_OBJECT_ALIGN_LEFT ; break;
+ case SID_ALIGN_ANY_HCENTER : nAlias = SID_OBJECT_ALIGN_CENTER ; break;
+ case SID_ALIGN_ANY_RIGHT : nAlias = SID_OBJECT_ALIGN_RIGHT ; break;
+ case SID_ALIGN_ANY_TOP : nAlias = SID_OBJECT_ALIGN_UP ; break;
+ case SID_ALIGN_ANY_VCENTER : nAlias = SID_OBJECT_ALIGN_MIDDLE ; break;
+ case SID_ALIGN_ANY_BOTTOM : nAlias = SID_OBJECT_ALIGN_DOWN ; break;
+ }
+ }
+ //these slots are either re-mapped to text or object alignment
+ SfxPoolItemHolder aResult;
+ if(nAlias)
+ GetViewFrame().GetDispatcher()->QueryState(nAlias, aResult);
+ if(nullptr != aResult.getItem())
+ {
+ if (!(m_nSelectionType & SelectionType::DrawObject))
+ {
+ rSet.Put(aResult.getItem()->CloneSetWhich(nWhich));
+ }
+ }
+ else
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwView::GetDrawState(SfxItemSet &rSet)
+{
+ SfxWhichIter aIter(rSet);
+ bool bWeb = dynamic_cast<SwWebView*>( this ) != nullptr;
+
+ for( sal_uInt16 nWhich = aIter.FirstWhich(); nWhich;
+ nWhich = aIter.NextWhich() )
+ switch(nWhich)
+ {
+ case SID_DRAW_LINE:
+ case SID_DRAW_XLINE:
+ case SID_LINE_ARROW_END:
+ case SID_LINE_ARROW_CIRCLE:
+ case SID_LINE_ARROW_SQUARE:
+ case SID_LINE_ARROW_START:
+ case SID_LINE_CIRCLE_ARROW:
+ case SID_LINE_SQUARE_ARROW:
+ case SID_LINE_ARROWS:
+ case SID_DRAW_MEASURELINE:
+ case SID_DRAW_RECT:
+ case SID_DRAW_ELLIPSE:
+ case SID_DRAW_XPOLYGON_NOFILL:
+ case SID_DRAW_XPOLYGON:
+ case SID_DRAW_POLYGON_NOFILL:
+ case SID_DRAW_POLYGON:
+ case SID_DRAW_BEZIER_NOFILL:
+ case SID_DRAW_BEZIER_FILL:
+ case SID_DRAW_FREELINE_NOFILL:
+ case SID_DRAW_FREELINE:
+ case SID_DRAW_ARC:
+ case SID_DRAW_PIE:
+ case SID_DRAW_CIRCLECUT:
+ case SID_DRAW_TEXT:
+ case SID_DRAW_CAPTION:
+ if ( bWeb )
+ rSet.DisableItem( nWhich );
+ else
+ if (nWhich != SID_DRAW_TEXT) //tdf#113171
+ rSet.Put( SfxBoolItem( nWhich, m_nDrawSfxId == nWhich ) );
+ break;
+
+ case SID_DRAW_TEXT_VERTICAL:
+ case SID_DRAW_CAPTION_VERTICAL:
+ if ( bWeb || !SvtCJKOptions::IsVerticalTextEnabled() )
+ rSet.DisableItem( nWhich );
+ else
+ if (nWhich != SID_DRAW_TEXT_VERTICAL) //tdf#113171
+ rSet.Put( SfxBoolItem( nWhich, m_nDrawSfxId == nWhich ) );
+ break;
+
+ case SID_DRAW_TEXT_MARQUEE:
+ if (::GetHtmlMode(GetDocShell()) & HTMLMODE_SOME_STYLES)
+ rSet.Put( SfxBoolItem(nWhich, m_nDrawSfxId == nWhich));
+ else
+ rSet.DisableItem(nWhich);
+ break;
+ case SID_OBJECT_SELECT:
+ rSet.Put( SfxBoolItem(nWhich, m_nDrawSfxId == nWhich ||
+ m_nFormSfxId == nWhich));
+ break;
+
+ case SID_INSERT_DRAW:
+ case SID_FONTWORK_GALLERY_FLOATER :
+ case SID_DRAWTBX_ARROWS:
+ {
+ if ( bWeb )
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case SID_DRAWTBX_CS_BASIC :
+ case SID_DRAWTBX_CS_SYMBOL :
+ case SID_DRAWTBX_CS_ARROW :
+ case SID_DRAWTBX_CS_FLOWCHART :
+ case SID_DRAWTBX_CS_CALLOUT :
+ case SID_DRAWTBX_CS_STAR :
+ {
+ if ( bWeb )
+ rSet.DisableItem( nWhich );
+ else
+ rSet.Put( SfxStringItem( nWhich, m_nDrawSfxId == nWhich ? m_sDrawCustom : OUString() ) );
+ }
+ break;
+
+ }
+}
+
+bool SwView::HasUIFeature(SfxShellFeature nFeature) const
+{
+ assert((nFeature & ~SfxShellFeature::SwMask) == SfxShellFeature::NONE);
+ switch(nFeature)
+ {
+ case SfxShellFeature::SwChildWindowLabel:
+ return m_pWrtShell->IsLabelDoc();
+ default:
+ return false;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewtab.cxx b/sw/source/uibase/uiview/viewtab.cxx
new file mode 100644
index 0000000000..52a26eabb6
--- /dev/null
+++ b/sw/source/uibase/uiview/viewtab.cxx
@@ -0,0 +1,2562 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+#include <uitool.hxx>
+#include <svx/rulritem.hxx>
+#include <svx/xflclit.hxx>
+#include <svx/xflgrit.hxx>
+#include <svx/xflhtit.hxx>
+#include <svx/xbtmpit.hxx>
+#include <svx/xfillit0.hxx>
+#include <tools/UnitConversion.hxx>
+#include <editeng/tstpitem.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <svl/eitem.hxx>
+#include <svl/whiter.hxx>
+#include <svx/ruler.hxx>
+#include <editeng/protitem.hxx>
+#include <svl/rectitem.hxx>
+#include <sfx2/bindings.hxx>
+#include <fmtfsize.hxx>
+#include <fmthdft.hxx>
+#include <fmtclds.hxx>
+#include <fmtornt.hxx>
+#include <frmatr.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <cmdid.h>
+#include <viewopt.hxx>
+#include <tabcol.hxx>
+#include <frmfmt.hxx>
+#include <pagedesc.hxx>
+#include <wview.hxx>
+#include <fmtcol.hxx>
+#include <section.hxx>
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <comphelper/lok.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <boost/property_tree/json_parser.hpp>
+#include <osl/diagnose.h>
+
+#include <IDocumentSettingAccess.hxx>
+
+using namespace ::com::sun::star;
+
+// Pack columns
+static void lcl_FillSvxColumn(const SwFormatCol& rCol,
+ tools::Long nTotalWidth,
+ SvxColumnItem& rColItem,
+ tools::Long nDistance)
+{
+ const SwColumns& rCols = rCol.GetColumns();
+
+ bool bOrtho = rCol.IsOrtho() && !rCols.empty();
+ tools::Long nInnerWidth = 0;
+ if( bOrtho )
+ {
+ nInnerWidth = nTotalWidth;
+ for (const auto & i : rCols)
+ {
+ nInnerWidth -= i.GetLeft() + i.GetRight();
+ }
+ if( nInnerWidth < 0 )
+ nInnerWidth = 0;
+ else
+ nInnerWidth /= rCols.size();
+ }
+
+ tools::Long nWidth = 0;
+ for ( size_t i = 0; i < rCols.size(); ++i )
+ {
+ const SwColumn* pCol = &rCols[i];
+ const tools::Long nStart = pCol->GetLeft() + nWidth + nDistance;
+ if( bOrtho )
+ nWidth += nInnerWidth + pCol->GetLeft() + pCol->GetRight();
+ else
+ nWidth += rCol.CalcColWidth(i, static_cast< sal_uInt16 >(nTotalWidth));
+ const tools::Long nEnd = nWidth - pCol->GetRight() + nDistance;
+
+ SvxColumnDescription aColDesc(nStart, nEnd, true);
+ rColItem.Append(aColDesc);
+ }
+}
+
+// Transfer ColumnItem in ColumnInfo
+static void lcl_ConvertToCols(const SvxColumnItem& rColItem,
+ tools::Long nTotalWidth,
+ SwFormatCol& rCols)
+{
+ OSL_ENSURE( rCols.GetNumCols() == rColItem.Count(), "Column count mismatch" );
+ // ruler executes that change the columns shortly after the selection has changed
+ // can result in a crash
+ if(rCols.GetNumCols() != rColItem.Count())
+ return;
+
+ sal_uInt16 nLeft = 0;
+ SwTwips nSumAll= 0; // Sum up all columns and margins
+
+ SwColumns& rArr = rCols.GetColumns();
+
+ // Tabcols sequentially
+ for( sal_uInt16 i=0; i < rColItem.Count()-1; ++i )
+ {
+ OSL_ENSURE(rColItem[i+1].nStart >= rColItem[i].nEnd,"overlapping columns" );
+ const tools::Long nStart = std::max(rColItem[i+1].nStart, rColItem[i].nEnd);
+ const sal_uInt16 nRight = o3tl::narrowing<sal_uInt16>((nStart - rColItem[i].nEnd) / 2);
+
+ const tools::Long nWidth = rColItem[i].nEnd - rColItem[i].nStart + nLeft + nRight;
+
+ SwColumn* pCol = &rArr[i];
+ pCol->SetWishWidth( sal_uInt16(tools::Long(rCols.GetWishWidth()) * nWidth / nTotalWidth ));
+ pCol->SetLeft( nLeft );
+ pCol->SetRight( nRight );
+ nSumAll += pCol->GetWishWidth();
+
+ nLeft = nRight;
+ }
+ rArr[rColItem.Count()-1].SetLeft( nLeft );
+
+ // The difference between the total sum of the desired width and the so far
+ // calculated columns and margins should result in the width of the last column.
+ rArr[rColItem.Count()-1].SetWishWidth( rCols.GetWishWidth() - o3tl::narrowing<sal_uInt16>(nSumAll) );
+
+ rCols.SetOrtho(false, 0, 0 );
+}
+
+// Delete tabs
+static void lcl_EraseDefTabs(SvxTabStopItem& rTabStops)
+{
+ // Delete DefTabs
+ for ( sal_uInt16 i = 0; i < rTabStops.Count(); )
+ {
+ // Here also throw out the DefTab to zero
+ if ( SvxTabAdjust::Default == rTabStops[i].GetAdjustment() ||
+ rTabStops[i].GetTabPos() == 0 )
+ {
+ rTabStops.Remove(i);
+ continue;
+ }
+ ++i;
+ }
+}
+
+// Flip page margin
+void SwView::SwapPageMargin(const SwPageDesc& rDesc, SvxLRSpaceItem& rLRSpace)
+{
+ sal_uInt16 nPhyPage, nVirPage;
+ GetWrtShell().GetPageNum( nPhyPage, nVirPage );
+
+ if ( rDesc.GetUseOn() == UseOnPage::Mirror && (nPhyPage % 2) == 0 )
+ {
+ tools::Long nTmp = rLRSpace.GetRight();
+ rLRSpace.SetRight( rLRSpace.GetLeft() );
+ rLRSpace.SetLeft( nTmp );
+ }
+}
+
+// If the frame border is moved, the column separator
+// should stay in the same absolute position.
+static void lcl_Scale(tools::Long& nVal, tools::Long nScale)
+{
+ nVal *= nScale;
+ nVal >>= 8;
+}
+
+static void ResizeFrameCols(SwFormatCol& rCol,
+ tools::Long nOldWidth,
+ tools::Long nNewWidth,
+ tools::Long nLeftDelta )
+{
+ SwColumns& rArr = rCol.GetColumns();
+ tools::Long nWishSum = static_cast<tools::Long>(rCol.GetWishWidth());
+ tools::Long nWishDiff = (nWishSum * 100/nOldWidth * nNewWidth) / 100 - nWishSum;
+ tools::Long nNewWishWidth = nWishSum + nWishDiff;
+ if(nNewWishWidth > 0xffffl)
+ {
+ // If the desired width is getting too large, then all values
+ // must be scaled appropriately.
+ tools::Long nScale = (0xffffl << 8)/ nNewWishWidth;
+ for(SwColumn & i : rArr)
+ {
+ SwColumn* pCol = &i;
+ tools::Long nVal = pCol->GetWishWidth();
+ lcl_Scale(nVal, nScale);
+ pCol->SetWishWidth(o3tl::narrowing<sal_uInt16>(nVal));
+ nVal = pCol->GetLeft();
+ lcl_Scale(nVal, nScale);
+ pCol->SetLeft(o3tl::narrowing<sal_uInt16>(nVal));
+ nVal = pCol->GetRight();
+ lcl_Scale(nVal, nScale);
+ pCol->SetRight(o3tl::narrowing<sal_uInt16>(nVal));
+ }
+ lcl_Scale(nNewWishWidth, nScale);
+ lcl_Scale(nWishDiff, nScale);
+ }
+ rCol.SetWishWidth( o3tl::narrowing<sal_uInt16>(nNewWishWidth) );
+
+ if( nLeftDelta >= 2 || nLeftDelta <= -2)
+ rArr.front().SetWishWidth(rArr.front().GetWishWidth() + o3tl::narrowing<sal_uInt16>(nWishDiff));
+ else
+ rArr.back().SetWishWidth(rArr.back().GetWishWidth() + o3tl::narrowing<sal_uInt16>(nWishDiff));
+ // Reset auto width
+ rCol.SetOrtho(false, 0, 0 );
+}
+
+// Here all changes to the tab bar will be shot again into the model.
+void SwView::ExecTabWin( SfxRequest const & rReq )
+{
+ SwWrtShell &rSh = GetWrtShell();
+ const FrameTypeFlags nFrameType = rSh.IsObjSelected() ?
+ FrameTypeFlags::DRAWOBJ :
+ rSh.GetFrameType(nullptr,true);
+ const bool bFrameSelection = rSh.IsFrameSelected();
+ const bool bBrowse = rSh.GetViewOptions()->getBrowseMode();
+
+ const sal_uInt16 nSlot = rReq.GetSlot();
+ const SfxItemSet* pReqArgs = rReq.GetArgs();
+ const size_t nDescId = rSh.GetCurPageDesc();
+ const SwPageDesc& rDesc = rSh.GetPageDesc( nDescId );
+
+ const bool bVerticalWriting = rSh.IsInVerticalText();
+ const SwFormatHeader& rHeaderFormat = rDesc.GetMaster().GetHeader();
+ SwFrameFormat *pHeaderFormat = const_cast<SwFrameFormat*>(rHeaderFormat.GetHeaderFormat());
+
+ const SwFormatFooter& rFooterFormat = rDesc.GetMaster().GetFooter();
+ SwFrameFormat *pFooterFormat = const_cast<SwFrameFormat*>(rFooterFormat.GetFooterFormat());
+
+ const SwFormatFrameSize &rFrameSize = rDesc.GetMaster().GetFrameSize();
+
+ const SwRect& rPageRect = rSh.GetAnyCurRect(CurRectType::Page);
+ const tools::Long nPageWidth = bBrowse ? rPageRect.Width() : rFrameSize.GetWidth();
+ const tools::Long nPageHeight = bBrowse ? rPageRect.Height() : rFrameSize.GetHeight();
+
+ bool bUnlockView = false;
+ rSh.StartAllAction();
+ bool bSect = bool(nFrameType & FrameTypeFlags::COLSECT);
+
+ switch (nSlot)
+ {
+ case SID_ATTR_LONG_LRSPACE:
+ if ( pReqArgs )
+ {
+ SvxLongLRSpaceItem aLongLR( pReqArgs->Get( SID_ATTR_LONG_LRSPACE ) );
+ SvxLRSpaceItem aLR(RES_LR_SPACE);
+ if ( !bSect && (bFrameSelection || nFrameType & FrameTypeFlags::FLY_ANY) )
+ {
+ SwFrameFormat* pFormat = rSh.GetFlyFrameFormat();
+ const SwRect &rRect = rSh.GetAnyCurRect(CurRectType::FlyEmbedded);
+
+ bool bVerticalFrame(false);
+ {
+ bool bRTL;
+ bool bVertL2R;
+ bVerticalFrame = ( bFrameSelection &&
+ rSh.IsFrameVertical(true, bRTL, bVertL2R) ) ||
+ ( !bFrameSelection && bVerticalWriting);
+ }
+ tools::Long nDeltaX = bVerticalFrame ?
+ rRect.Right() - rPageRect.Right() + aLongLR.GetRight() :
+ rPageRect.Left() + aLongLR.GetLeft() - rRect.Left();
+
+ SfxItemSetFixed<RES_FRM_SIZE, RES_FRM_SIZE,
+ RES_VERT_ORIENT, RES_HORI_ORIENT,
+ RES_COL, RES_COL> aSet( GetPool() );
+
+ if(bVerticalFrame)
+ {
+ SwFormatVertOrient aVertOrient(pFormat->GetVertOrient());
+ aVertOrient.SetVertOrient(text::VertOrientation::NONE);
+ aVertOrient.SetPos(aVertOrient.GetPos() + nDeltaX );
+ aSet.Put( aVertOrient );
+ }
+ else
+ {
+ SwFormatHoriOrient aHoriOrient( pFormat->GetHoriOrient() );
+ aHoriOrient.SetHoriOrient( text::HoriOrientation::NONE );
+ aHoriOrient.SetPos( aHoriOrient.GetPos() + nDeltaX );
+ aSet.Put( aHoriOrient );
+ }
+
+ SwFormatFrameSize aSize( pFormat->GetFrameSize() );
+ tools::Long nOldWidth = aSize.GetWidth();
+
+ if(aSize.GetWidthPercent())
+ {
+ SwRect aRect;
+ rSh.CalcBoundRect(aRect, RndStdIds::FLY_AS_CHAR);
+ tools::Long nPrtWidth = aRect.Width();
+ aSize.SetWidthPercent(sal_uInt8((nPageWidth - aLongLR.GetLeft() - aLongLR.GetRight()) * 100 /nPrtWidth));
+ }
+ else
+ aSize.SetWidth( nPageWidth -
+ (aLongLR.GetLeft() + aLongLR.GetRight()));
+
+ if( nFrameType & FrameTypeFlags::COLUMN )
+ {
+ SwFormatCol aCol(pFormat->GetCol());
+
+ ::ResizeFrameCols(aCol, nOldWidth, aSize.GetWidth(), nDeltaX );
+ aSet.Put(aCol);
+ }
+
+ aSet.Put( aSize );
+
+ rSh.StartAction();
+ rSh.Push();
+ rSh.SetFlyFrameAttr( aSet );
+ // Cancel the frame selection
+ if(!bFrameSelection && rSh.IsFrameSelected())
+ {
+ rSh.UnSelectFrame();
+ rSh.LeaveSelFrameMode();
+ }
+ rSh.Pop();
+ rSh.EndAction();
+ }
+ else if ( nFrameType & ( FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER ))
+ {
+ // Subtract out page margins
+ tools::Long nOld = rDesc.GetMaster().GetLRSpace().GetLeft();
+ aLongLR.SetLeft( nOld > aLongLR.GetLeft() ? 0 : aLongLR.GetLeft() - nOld );
+
+ nOld = rDesc.GetMaster().GetLRSpace().GetRight();
+ aLongLR.SetRight( nOld > aLongLR.GetRight() ? 0 : aLongLR.GetRight() - nOld );
+ aLR.SetLeft(aLongLR.GetLeft());
+ aLR.SetRight(aLongLR.GetRight());
+
+ if ( nFrameType & FrameTypeFlags::HEADER && pHeaderFormat )
+ pHeaderFormat->SetFormatAttr( aLR );
+ else if( nFrameType & FrameTypeFlags::FOOTER && pFooterFormat )
+ pFooterFormat->SetFormatAttr( aLR );
+ }
+ else if( nFrameType == FrameTypeFlags::DRAWOBJ)
+ {
+ SwRect aRect( rSh.GetObjRect() );
+ aRect.Left( aLongLR.GetLeft() + rPageRect.Left() );
+ aRect.Right( rPageRect.Right() - aLongLR.GetRight());
+ rSh.SetObjRect( aRect );
+ }
+ else if(bSect || rSh.IsDirectlyInSection())
+ {
+ //change the section indents and the columns if available
+ //at first determine the changes
+ SwRect aSectRect = rSh.GetAnyCurRect(CurRectType::SectionPrt);
+ const SwRect aTmpRect = rSh.GetAnyCurRect(CurRectType::Section);
+ aSectRect.Pos() += aTmpRect.Pos();
+ tools::Long nLeftDiff = aLongLR.GetLeft() - static_cast<tools::Long>(aSectRect.Left() - rPageRect.Left() );
+ tools::Long nRightDiff = aLongLR.GetRight() - static_cast<tools::Long>( rPageRect.Right() - aSectRect.Right());
+ //change the LRSpaceItem of the section accordingly
+ const SwSection* pCurrSect = rSh.GetCurrSection();
+ const SwSectionFormat* pSectFormat = pCurrSect->GetFormat();
+ SvxLRSpaceItem aLRTmp = pSectFormat->GetLRSpace();
+ aLRTmp.SetLeft(aLRTmp.GetLeft() + nLeftDiff);
+ aLRTmp.SetRight(aLRTmp.GetRight() + nRightDiff);
+ SfxItemSetFixed<RES_LR_SPACE, RES_LR_SPACE, RES_COL, RES_COL> aSet(rSh.GetAttrPool());
+ aSet.Put(aLRTmp);
+ //change the first/last column
+ if(bSect)
+ {
+ SwFormatCol aCols( pSectFormat->GetCol() );
+ tools::Long nDiffWidth = nLeftDiff + nRightDiff;
+ ::ResizeFrameCols(aCols, aSectRect.Width(), aSectRect.Width() - nDiffWidth, nLeftDiff );
+ aSet.Put( aCols );
+ }
+ SwSectionData aData(*pCurrSect);
+ rSh.UpdateSection(rSh.GetSectionFormatPos(*pSectFormat), aData, &aSet);
+ }
+ else
+ { // Adjust page margins
+ aLR.SetLeft(aLongLR.GetLeft());
+ aLR.SetRight(aLongLR.GetRight());
+ SwapPageMargin( rDesc, aLR );
+ SwPageDesc aDesc( rDesc );
+ aDesc.GetMaster().SetFormatAttr( aLR );
+ rSh.ChgPageDesc( nDescId, aDesc );
+ }
+ }
+ break;
+
+ // apply new left and right margins to current page style
+ case SID_ATTR_PAGE_LRSPACE:
+ if ( pReqArgs )
+ {
+ const SvxLongLRSpaceItem& aLongLR( pReqArgs->Get( SID_ATTR_PAGE_LRSPACE ) );
+
+ SwPageDesc aDesc( rDesc );
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetLeft(aLongLR.GetLeft());
+ aLR.SetRight(aLongLR.GetRight());
+ SwapPageMargin( rDesc, aLR );
+ aDesc.GetMaster().SetFormatAttr( aLR );
+ }
+ rSh.ChgPageDesc( nDescId, aDesc );
+ }
+ break;
+
+ case SID_ATTR_LONG_ULSPACE:
+ if ( pReqArgs )
+ {
+ SvxLongULSpaceItem aLongULSpace( pReqArgs->Get( SID_ATTR_LONG_ULSPACE ) );
+
+ if( bFrameSelection || nFrameType & FrameTypeFlags::FLY_ANY )
+ {
+ SwFrameFormat* pFormat = rSh.GetFlyFrameFormat();
+ const SwRect &rRect = rSh.GetAnyCurRect(CurRectType::FlyEmbedded);
+ const tools::Long nDeltaY = rPageRect.Top() + aLongULSpace.GetUpper() - rRect.Top();
+ const tools::Long nHeight = nPageHeight - (aLongULSpace.GetUpper() + aLongULSpace.GetLower());
+
+ SfxItemSetFixed<RES_FRM_SIZE, RES_FRM_SIZE,
+ RES_VERT_ORIENT, RES_HORI_ORIENT> aSet( GetPool() );
+ //which of the orientation attributes is to be put depends on the frame's environment
+ bool bRTL;
+ bool bVertL2R;
+ if ( ( bFrameSelection &&
+ rSh.IsFrameVertical(true, bRTL, bVertL2R ) ) ||
+ ( !bFrameSelection && bVerticalWriting ) )
+ {
+ SwFormatHoriOrient aHoriOrient(pFormat->GetHoriOrient());
+ aHoriOrient.SetHoriOrient(text::HoriOrientation::NONE);
+ aHoriOrient.SetPos(aHoriOrient.GetPos() + nDeltaY );
+ aSet.Put( aHoriOrient );
+ }
+ else
+ {
+ SwFormatVertOrient aVertOrient(pFormat->GetVertOrient());
+ aVertOrient.SetVertOrient(text::VertOrientation::NONE);
+ aVertOrient.SetPos(aVertOrient.GetPos() + nDeltaY );
+ aSet.Put( aVertOrient );
+ }
+ SwFormatFrameSize aSize(pFormat->GetFrameSize());
+ if(aSize.GetHeightPercent())
+ {
+ SwRect aRect;
+ rSh.CalcBoundRect(aRect, RndStdIds::FLY_AS_CHAR);
+ tools::Long nPrtHeight = aRect.Height();
+ aSize.SetHeightPercent(sal_uInt8(nHeight * 100 /nPrtHeight));
+ }
+ else
+ aSize.SetHeight(nHeight );
+
+ aSet.Put( aSize );
+ rSh.SetFlyFrameAttr( aSet );
+ }
+ else if( nFrameType == FrameTypeFlags::DRAWOBJ )
+ {
+ SwRect aRect( rSh.GetObjRect() );
+ aRect.Top( aLongULSpace.GetUpper() + rPageRect.Top() );
+ aRect.Bottom( rPageRect.Bottom() - aLongULSpace.GetLower() );
+ rSh.SetObjRect( aRect ) ;
+ }
+ else if(bVerticalWriting && (bSect || rSh.IsDirectlyInSection()))
+ {
+ //change the section indents and the columns if available
+ //at first determine the changes
+ SwRect aSectRect = rSh.GetAnyCurRect(CurRectType::SectionPrt);
+ const SwRect aTmpRect = rSh.GetAnyCurRect(CurRectType::Section);
+ aSectRect.Pos() += aTmpRect.Pos();
+ const tools::Long nLeftDiff = aLongULSpace.GetUpper() - static_cast<tools::Long>(aSectRect.Top() - rPageRect.Top());
+ const tools::Long nRightDiff = aLongULSpace.GetLower() - static_cast<tools::Long>(nPageHeight - aSectRect.Bottom() + rPageRect.Top());
+ //change the LRSpaceItem of the section accordingly
+ const SwSection* pCurrSect = rSh.GetCurrSection();
+ const SwSectionFormat* pSectFormat = pCurrSect->GetFormat();
+ SvxLRSpaceItem aLR = pSectFormat->GetLRSpace();
+ aLR.SetLeft(aLR.GetLeft() + nLeftDiff);
+ aLR.SetRight(aLR.GetRight() + nRightDiff);
+ SfxItemSetFixed<RES_LR_SPACE, RES_LR_SPACE, RES_COL, RES_COL> aSet(rSh.GetAttrPool());
+ aSet.Put(aLR);
+ //change the first/last column
+ if(bSect)
+ {
+ SwFormatCol aCols( pSectFormat->GetCol() );
+ tools::Long nDiffWidth = nLeftDiff + nRightDiff;
+ ::ResizeFrameCols(aCols, aSectRect.Height(), aSectRect.Height() - nDiffWidth, nLeftDiff );
+ aSet.Put( aCols );
+ }
+ SwSectionData aData(*pCurrSect);
+ rSh.UpdateSection(rSh.GetSectionFormatPos(*pSectFormat), aData, &aSet);
+ }
+ else
+ { SwPageDesc aDesc( rDesc );
+
+ if ( nFrameType & ( FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER ))
+ {
+
+ const bool bHead = bool(nFrameType & FrameTypeFlags::HEADER);
+ SvxULSpaceItem aUL( rDesc.GetMaster().GetULSpace() );
+ if ( bHead )
+ aUL.SetUpper( o3tl::narrowing<sal_uInt16>(aLongULSpace.GetUpper()) );
+ else
+ aUL.SetLower( o3tl::narrowing<sal_uInt16>(aLongULSpace.GetLower()) );
+ aDesc.GetMaster().SetFormatAttr( aUL );
+
+ if( (bHead && pHeaderFormat) || (!bHead && pFooterFormat) )
+ {
+ SwFormatFrameSize aSz( bHead ? pHeaderFormat->GetFrameSize() :
+ pFooterFormat->GetFrameSize() );
+ aSz.SetHeightSizeType( SwFrameSize::Fixed );
+ aSz.SetHeight(nPageHeight - aLongULSpace.GetLower() -
+ aLongULSpace.GetUpper() );
+ if ( bHead )
+ pHeaderFormat->SetFormatAttr( aSz );
+ else
+ pFooterFormat->SetFormatAttr( aSz );
+ }
+ }
+ else
+ {
+ SvxULSpaceItem aUL(RES_UL_SPACE);
+ aUL.SetUpper(o3tl::narrowing<sal_uInt16>(aLongULSpace.GetUpper()));
+ aUL.SetLower(o3tl::narrowing<sal_uInt16>(aLongULSpace.GetLower()));
+ aDesc.GetMaster().SetFormatAttr(aUL);
+ }
+
+ rSh.ChgPageDesc( nDescId, aDesc );
+ }
+ }
+ break;
+
+ // apply new top and bottom margins to current page style
+ case SID_ATTR_PAGE_ULSPACE:
+ if ( pReqArgs )
+ {
+ const SvxLongULSpaceItem& aLongULSpace( pReqArgs->Get( SID_ATTR_PAGE_ULSPACE ) );
+
+ SwPageDesc aDesc( rDesc );
+ {
+ SvxULSpaceItem aUL(RES_UL_SPACE);
+ aUL.SetUpper(o3tl::narrowing<sal_uInt16>(aLongULSpace.GetUpper()));
+ aUL.SetLower(o3tl::narrowing<sal_uInt16>(aLongULSpace.GetLower()));
+ aDesc.GetMaster().SetFormatAttr(aUL);
+ }
+ rSh.ChgPageDesc( nDescId, aDesc );
+ }
+ break;
+
+ case SID_ATTR_PAGE_COLUMN:
+ if ( pReqArgs )
+ {
+ const SfxInt16Item aColumnItem( static_cast<const SfxInt16Item&>(pReqArgs->Get(nSlot)) );
+ const sal_uInt16 nPageColumnType = aColumnItem.GetValue();
+
+ // nPageColumnType =
+ // 1 - single-columned page
+ // 2 - two-columned page
+ // 3 - three-columned page
+ // 4 - two-columned page with left column width of 2/3 of page width
+ // 5 - two-columned page with right column width of 2/3 of page width
+
+ sal_uInt16 nCount = 2;
+ if ( nPageColumnType == 1 )
+ {
+ nCount = 0;
+ }
+ else if ( nPageColumnType == 3 )
+ {
+ nCount = 3;
+ }
+
+ const sal_uInt16 nGutterWidth = 0;
+
+ const SvxLRSpaceItem aLR( rDesc.GetMaster().GetLRSpace() );
+ const tools::Long nLeft = aLR.GetLeft();
+ const tools::Long nRight = aLR.GetRight();
+ const tools::Long nWidth = nPageWidth - nLeft - nRight;
+
+ SwFormatCol aCols( rDesc.GetMaster().GetCol() );
+ aCols.Init( nCount, nGutterWidth, nWidth );
+ aCols.SetWishWidth( nWidth );
+ aCols.SetGutterWidth( nGutterWidth, nWidth );
+ aCols.SetOrtho( false, nGutterWidth, nWidth );
+
+ tools::Long nColumnLeft = 0;
+ tools::Long nColumnRight = 0;
+ if ( nPageColumnType == 4 )
+ {
+ nColumnRight = static_cast<tools::Long>(nWidth/3);
+ nColumnLeft = nWidth - nColumnRight;
+ aCols.GetColumns()[0].SetWishWidth( nColumnLeft );
+ aCols.GetColumns()[1].SetWishWidth( nColumnRight );
+ }
+ else if ( nPageColumnType == 5 )
+ {
+ nColumnLeft = static_cast<tools::Long>(nWidth/3);
+ nColumnRight = nWidth - nColumnLeft;
+ aCols.GetColumns()[0].SetWishWidth( nColumnLeft );
+ aCols.GetColumns()[1].SetWishWidth( nColumnRight );
+ }
+
+ SwPageDesc aDesc( rDesc );
+ aDesc.GetMaster().SetFormatAttr( aCols );
+ rSh.ChgPageDesc( rSh.GetCurPageDesc(), aDesc );
+ }
+ break;
+
+ case SID_ATTR_TABSTOP_VERTICAL:
+ case SID_ATTR_TABSTOP:
+ if (pReqArgs)
+ {
+ const sal_uInt16 nWhich = GetPool().GetWhich(nSlot);
+ SvxTabStopItem aTabStops( static_cast<const SvxTabStopItem&>(pReqArgs->
+ Get( nWhich )));
+ aTabStops.SetWhich(RES_PARATR_TABSTOP);
+ const SvxTabStopItem& rDefTabs = rSh.GetDefault(RES_PARATR_TABSTOP);
+
+ // Default tab at pos 0
+ SfxItemSetFixed<RES_MARGIN_FIRSTLINE, RES_MARGIN_FIRSTLINE> aSet(GetPool());
+ rSh.GetCurAttr( aSet );
+ const SvxFirstLineIndentItem & rFirstLine(aSet.Get(RES_MARGIN_FIRSTLINE));
+
+ if (rFirstLine.GetTextFirstLineOffset() < 0)
+ {
+ SvxTabStop aSwTabStop( 0, SvxTabAdjust::Default );
+ aTabStops.Insert( aSwTabStop );
+ }
+
+ // Populate with default tabs.
+ ::MakeDefTabs( ::GetTabDist( rDefTabs ), aTabStops );
+
+ SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
+ if( pColl && pColl->IsAutoUpdateOnDirectFormat() )
+ {
+ SfxItemSetFixed<RES_PARATR_TABSTOP, RES_PARATR_TABSTOP> aTmp(GetPool());
+ aTmp.Put(aTabStops);
+ rSh.AutoUpdatePara( pColl, aTmp );
+ }
+ else
+ rSh.SetAttrItem( aTabStops );
+ }
+ break;
+ case SID_TABSTOP_ADD_OR_CHANGE:
+ if (pReqArgs)
+ {
+ const auto aIndexItem = static_cast<const SfxInt32Item&>(pReqArgs->Get(SID_TABSTOP_ATTR_INDEX));
+ const auto aPositionItem = static_cast<const SfxInt32Item&>(pReqArgs->Get(SID_TABSTOP_ATTR_POSITION));
+ const auto aRemoveItem = static_cast<const SfxBoolItem&>(pReqArgs->Get(SID_TABSTOP_ATTR_REMOVE));
+ const sal_Int32 nIndex = aIndexItem.GetValue();
+ const sal_Int32 nPosition = aPositionItem.GetValue();
+ const bool bRemove = aRemoveItem.GetValue();
+
+
+
+ SfxItemSetFixed<RES_PARATR_TABSTOP, RES_PARATR_TABSTOP> aItemSet(GetPool());
+ rSh.GetCurAttr(aItemSet);
+ SvxTabStopItem aTabStopItem(aItemSet.Get(RES_PARATR_TABSTOP));
+ lcl_EraseDefTabs(aTabStopItem);
+
+ if (nIndex < aTabStopItem.Count())
+ {
+ if (nIndex == -1)
+ {
+ SvxTabStop aSwTabStop(0, SvxTabAdjust::Default);
+ aTabStopItem.Insert(aSwTabStop);
+
+ const SvxTabStopItem& rDefaultTabs = rSh.GetDefault(RES_PARATR_TABSTOP);
+ MakeDefTabs(GetTabDist(rDefaultTabs), aTabStopItem);
+
+ SvxTabStop aTabStop(nPosition);
+ aTabStopItem.Insert(aTabStop);
+ }
+ else
+ {
+ SvxTabStop aTabStop = aTabStopItem.At(nIndex);
+ aTabStopItem.Remove(nIndex);
+ if (!bRemove)
+ {
+ aTabStop.GetTabPos() = nPosition;
+ aTabStopItem.Insert(aTabStop);
+
+ SvxTabStop aSwTabStop(0, SvxTabAdjust::Default);
+ aTabStopItem.Insert(aSwTabStop);
+ }
+ const SvxTabStopItem& rDefaultTabs = rSh.GetDefault(RES_PARATR_TABSTOP);
+ MakeDefTabs(GetTabDist(rDefaultTabs), aTabStopItem);
+ }
+ rSh.SetAttrItem(aTabStopItem);
+ }
+ }
+ break;
+ case SID_PARAGRAPH_CHANGE_STATE:
+ {
+ if (pReqArgs)
+ {
+ SfxItemSetFixed<RES_MARGIN_FIRSTLINE, RES_MARGIN_RIGHT> aLRSpaceSet(GetPool());
+ rSh.GetCurAttr( aLRSpaceSet );
+
+ if (const SfxStringItem *fLineIndent = pReqArgs->GetItemIfSet(SID_PARAGRAPH_FIRST_LINE_INDENT))
+ {
+ SvxFirstLineIndentItem firstLine(aLRSpaceSet.Get(RES_MARGIN_FIRSTLINE));
+ const OUString ratio = fLineIndent->GetValue();
+ firstLine.SetTextFirstLineOffset(nPageWidth * ratio.toFloat());
+ rSh.SetAttrItem(firstLine);
+ }
+ else if (const SfxStringItem *pLeftIndent = pReqArgs->GetItemIfSet(SID_PARAGRAPH_LEFT_INDENT))
+ {
+ SvxTextLeftMarginItem leftMargin(aLRSpaceSet.Get(RES_MARGIN_TEXTLEFT));
+ const OUString ratio = pLeftIndent->GetValue();
+ // this used to call SetLeft() but was probably a bug
+ leftMargin.SetTextLeft(nPageWidth * ratio.toFloat());
+ rSh.SetAttrItem(leftMargin);
+ }
+ else if (const SfxStringItem *pRightIndent = pReqArgs->GetItemIfSet(SID_PARAGRAPH_RIGHT_INDENT))
+ {
+ SvxRightMarginItem rightMargin(aLRSpaceSet.Get(RES_MARGIN_RIGHT));
+ const OUString ratio = pRightIndent->GetValue();
+ rightMargin.SetRight(nPageWidth * ratio.toFloat());
+ rSh.SetAttrItem(rightMargin);
+ }
+ }
+ break;
+ }
+ case SID_HANGING_INDENT:
+ {
+ SfxItemSetFixed<RES_MARGIN_FIRSTLINE, RES_MARGIN_RIGHT> aLRSpaceSet(GetPool());
+ rSh.GetCurAttr( aLRSpaceSet );
+ SvxFirstLineIndentItem firstLine(aLRSpaceSet.Get(RES_MARGIN_FIRSTLINE));
+ SvxTextLeftMarginItem leftMargin(aLRSpaceSet.Get(RES_MARGIN_TEXTLEFT));
+ leftMargin.SetTextLeft(leftMargin.GetTextLeft() + firstLine.GetTextFirstLineOffset());
+ firstLine.SetTextFirstLineOffset((firstLine.GetTextFirstLineOffset()) * -1);
+ firstLine.SetAutoFirst(false); // old code would do this, is it wanted?
+ rSh.SetAttrItem(firstLine);
+ rSh.SetAttrItem(leftMargin);
+ break;
+ }
+
+ case SID_ATTR_PARA_LRSPACE_VERTICAL:
+ case SID_ATTR_PARA_LRSPACE:
+ if ( pReqArgs )
+ {
+ SvxLRSpaceItem aParaMargin(static_cast<const SvxLRSpaceItem&>(pReqArgs->Get(nSlot)));
+
+ aParaMargin.SetRight( aParaMargin.GetRight() - m_nRightBorderDistance );
+ aParaMargin.SetTextLeft(aParaMargin.GetTextLeft() - m_nLeftBorderDistance );
+
+ aParaMargin.SetWhich( RES_LR_SPACE );
+ SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
+
+ SvxFirstLineIndentItem firstLine(RES_MARGIN_FIRSTLINE);
+ firstLine.SetTextFirstLineOffset(aParaMargin.GetTextFirstLineOffset(), aParaMargin.GetPropTextFirstLineOffset());
+ firstLine.SetAutoFirst(aParaMargin.IsAutoFirst());
+ SvxTextLeftMarginItem const leftMargin(aParaMargin.GetTextLeft(), RES_MARGIN_TEXTLEFT);
+ SvxRightMarginItem const rightMargin(aParaMargin.GetRight(), RES_MARGIN_RIGHT);
+
+ // #i23726#
+ if (m_pNumRuleNodeFromDoc)
+ {
+ // --> #i42922# Mouse move of numbering label
+ // has to consider the left indent of the paragraph
+ SfxItemSetFixed<RES_MARGIN_TEXTLEFT, RES_MARGIN_TEXTLEFT> aSet( GetPool() );
+ rSh.GetCurAttr( aSet );
+ const SvxTextLeftMarginItem & rLeftMargin(aSet.Get(RES_MARGIN_TEXTLEFT));
+
+ SwPosition aPos(*m_pNumRuleNodeFromDoc);
+ // #i90078#
+ rSh.SetIndent(static_cast<short>(aParaMargin.GetTextLeft() - rLeftMargin.GetTextLeft()), aPos);
+ // #i42921# invalidate state of indent in order to get a ruler update.
+ aParaMargin.SetWhich( nSlot );
+ GetViewFrame().GetBindings().SetState( aParaMargin );
+ }
+ else if( pColl && pColl->IsAutoUpdateOnDirectFormat() )
+ {
+ SfxItemSetFixed<RES_MARGIN_FIRSTLINE, RES_MARGIN_RIGHT> aSet(GetPool());
+ aSet.Put(firstLine);
+ aSet.Put(leftMargin);
+ aSet.Put(rightMargin);
+ rSh.AutoUpdatePara( pColl, aSet);
+ }
+ else
+ {
+ rSh.SetAttrItem(firstLine);
+ rSh.SetAttrItem(leftMargin);
+ rSh.SetAttrItem(rightMargin);
+ }
+
+ if ( aParaMargin.GetTextFirstLineOffset() < 0 )
+ {
+ SfxItemSetFixed<RES_PARATR_TABSTOP, RES_PARATR_TABSTOP> aSet( GetPool() );
+
+ rSh.GetCurAttr( aSet );
+ const SvxTabStopItem& rTabStops = aSet.Get(RES_PARATR_TABSTOP);
+
+ // Do we have a tab at position zero?
+ sal_uInt16 i;
+
+ for ( i = 0; i < rTabStops.Count(); ++i )
+ if ( rTabStops[i].GetTabPos() == 0 )
+ break;
+
+ if ( i >= rTabStops.Count() )
+ {
+ // No DefTab
+ std::unique_ptr<SvxTabStopItem> aTabStops(rTabStops.Clone());
+
+ ::lcl_EraseDefTabs(*aTabStops);
+
+ SvxTabStop aSwTabStop( 0, SvxTabAdjust::Default );
+ aTabStops->Insert(aSwTabStop);
+
+ const SvxTabStopItem& rDefTabs = rSh.GetDefault(RES_PARATR_TABSTOP);
+ ::MakeDefTabs( ::GetTabDist(rDefTabs), *aTabStops );
+
+ if( pColl && pColl->IsAutoUpdateOnDirectFormat())
+ {
+ SfxItemSetFixed<RES_PARATR_TABSTOP, RES_PARATR_TABSTOP> aSetTmp(GetPool());
+ aSetTmp.Put(std::move(aTabStops));
+ rSh.AutoUpdatePara( pColl, aSetTmp );
+ }
+ else
+ rSh.SetAttrItem( *aTabStops );
+ }
+ }
+ }
+ break;
+
+ case SID_ATTR_PARA_ULSPACE:
+ if ( pReqArgs )
+ {
+ SvxULSpaceItem aParaMargin(static_cast<const SvxULSpaceItem&>(pReqArgs->Get(nSlot)));
+
+ aParaMargin.SetUpper( aParaMargin.GetUpper() );
+ aParaMargin.SetLower(aParaMargin.GetLower());
+
+ aParaMargin.SetWhich( RES_UL_SPACE );
+ SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
+ if( pColl && pColl->IsAutoUpdateOnDirectFormat() )
+ {
+ SfxItemSetFixed<RES_UL_SPACE, RES_UL_SPACE> aSet(GetPool());
+ aSet.Put(aParaMargin);
+ rSh.AutoUpdatePara( pColl, aSet);
+ }
+ else
+ rSh.SetAttrItem( aParaMargin );
+ }
+ break;
+ case SID_PARASPACE_INCREASE:
+ case SID_PARASPACE_DECREASE:
+ {
+ SfxItemSetFixed<RES_UL_SPACE, RES_UL_SPACE> aULSpaceSet( GetPool() );
+ rSh.GetCurAttr( aULSpaceSet );
+ SvxULSpaceItem aULSpace( aULSpaceSet.Get( RES_UL_SPACE ) );
+ sal_uInt16 nUpper = aULSpace.GetUpper();
+ sal_uInt16 nLower = aULSpace.GetLower();
+
+ if ( nSlot == SID_PARASPACE_INCREASE )
+ {
+ nUpper = std::min< sal_uInt16 >( nUpper + 57, 5670 );
+ nLower = std::min< sal_uInt16 >( nLower + 57, 5670 );
+ }
+ else
+ {
+ nUpper = std::max< sal_Int16 >( nUpper - 57, 0 );
+ nLower = std::max< sal_Int16 >( nLower - 57, 0 );
+ }
+
+ aULSpace.SetUpper( nUpper );
+ aULSpace.SetLower( nLower );
+
+ SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
+ if( pColl && pColl->IsAutoUpdateOnDirectFormat() )
+ {
+ aULSpaceSet.Put( aULSpace );
+ rSh.AutoUpdatePara( pColl, aULSpaceSet );
+ }
+ else
+ rSh.SetAttrItem( aULSpace, SetAttrMode::DEFAULT, true );
+ }
+ break;
+
+ case SID_RULER_CHANGE_STATE:
+ if (pReqArgs)
+ {
+ if ( const SfxStringItem *pMargin1 = pReqArgs->GetItemIfSet(SID_RULER_MARGIN1) )
+ {
+ const OUString ratio = pMargin1->GetValue();
+ GetHRuler().SetValues(RulerChangeType::MARGIN1, GetHRuler().GetPageWidth() * ratio.toFloat());
+ }
+ else if ( const SfxStringItem *pMargin2 = pReqArgs->GetItemIfSet(SID_RULER_MARGIN2) )
+ {
+ const OUString ratio = pMargin2->GetValue();
+ GetHRuler().SetValues(RulerChangeType::MARGIN2, GetHRuler().GetPageWidth() * ratio.toFloat());
+ }
+ }
+ break;
+ case SID_RULER_BORDERS_VERTICAL:
+ case SID_RULER_BORDERS:
+ if ( pReqArgs )
+ {
+ SvxColumnItem aColItem(static_cast<const SvxColumnItem&>(pReqArgs->Get(nSlot)));
+
+ if( m_bSetTabColFromDoc || (!bSect && rSh.GetTableFormat()) )
+ {
+ OSL_ENSURE(aColItem.Count(), "ColDesc is empty!!");
+
+ const bool bSingleLine = rReq.
+ GetArgs()->Get(SID_RULER_ACT_LINE_ONLY).GetValue();
+
+ SwTabCols aTabCols;
+ if ( m_bSetTabColFromDoc )
+ rSh.GetMouseTabCols( aTabCols, m_aTabColFromDocPos );
+ else
+ rSh.GetTabCols(aTabCols);
+
+ // left table border
+ tools::Long nBorder = static_cast<tools::Long>(aColItem.GetLeft() - aTabCols.GetLeftMin());
+ aTabCols.SetLeft( nBorder );
+
+ nBorder = (bVerticalWriting ? nPageHeight : nPageWidth) - aTabCols.GetLeftMin() - aColItem.GetRight();
+
+ if ( aColItem.GetRight() > 0 )
+ aTabCols.SetRight( nBorder );
+
+ // Tabcols sequentially
+ // The last column is defined by the edge.
+ // Columns in right-to-left tables need to be mirrored
+ bool bIsTableRTL =
+ IsTabColFromDoc() ?
+ rSh.IsMouseTableRightToLeft(m_aTabColFromDocPos)
+ : rSh.IsTableRightToLeft();
+ const size_t nColCount = aColItem.Count() - 1;
+ if(bIsTableRTL)
+ {
+ for ( size_t i = 0; i < nColCount && i < aTabCols.Count(); ++i )
+ {
+ const SvxColumnDescription& rCol = aColItem[nColCount - i];
+ aTabCols[i] = aTabCols.GetRight() - rCol.nStart;
+ aTabCols.SetHidden( i, !rCol.bVisible );
+ }
+ }
+ else
+ {
+ for ( size_t i = 0; i < nColCount && i < aTabCols.Count(); ++i )
+ {
+ const SvxColumnDescription& rCol = aColItem[i];
+ aTabCols[i] = rCol.nEnd + aTabCols.GetLeft();
+ aTabCols.SetHidden( i, !rCol.bVisible );
+ }
+ }
+
+ if ( m_bSetTabColFromDoc )
+ {
+ if( !rSh.IsViewLocked() )
+ {
+ bUnlockView = true;
+ rSh.LockView( true );
+ }
+ rSh.SetMouseTabCols( aTabCols, bSingleLine,
+ m_aTabColFromDocPos );
+ }
+ else
+ rSh.SetTabCols(aTabCols, bSingleLine);
+
+ }
+ else
+ {
+ if ( bFrameSelection || nFrameType & FrameTypeFlags::FLY_ANY || bSect)
+ {
+ SwSectionFormat *pSectFormat = nullptr;
+ SfxItemSetFixed<RES_COL, RES_COL> aSet( GetPool() );
+ if(bSect)
+ {
+ SwSection *pSect = rSh.GetAnySection();
+ OSL_ENSURE( pSect, "Which section?");
+ pSectFormat = pSect->GetFormat();
+ }
+ else
+ {
+ rSh.GetFlyFrameAttr( aSet );
+ }
+ SwFormatCol aCols(
+ bSect ?
+ pSectFormat->GetCol() :
+ aSet.Get( RES_COL, false ));
+ SwRect aCurRect = rSh.GetAnyCurRect(bSect ? CurRectType::SectionPrt : CurRectType::FlyEmbeddedPrt);
+ const tools::Long lWidth = bVerticalWriting ? aCurRect.Height() : aCurRect.Width();
+ ::lcl_ConvertToCols( aColItem, lWidth, aCols );
+ aSet.Put( aCols );
+ if(bSect)
+ rSh.SetSectionAttr( aSet, pSectFormat );
+ else
+ {
+ rSh.StartAction();
+ rSh.Push();
+ rSh.SetFlyFrameAttr( aSet );
+ // Cancel the frame selection again
+ if(!bFrameSelection && rSh.IsFrameSelected())
+ {
+ rSh.UnSelectFrame();
+ rSh.LeaveSelFrameMode();
+ }
+ rSh.Pop();
+ rSh.EndAction();
+ }
+ }
+ else
+ {
+ SwFormatCol aCols( rDesc.GetMaster().GetCol() );
+ const SwRect aPrtRect = rSh.GetAnyCurRect(CurRectType::PagePrt);
+ ::lcl_ConvertToCols( aColItem,
+ bVerticalWriting ? aPrtRect.Height() : aPrtRect.Width(),
+ aCols );
+ SwPageDesc aDesc( rDesc );
+ aDesc.GetMaster().SetFormatAttr( aCols );
+ rSh.ChgPageDesc( rSh.GetCurPageDesc(), aDesc );
+ }
+ }
+ }
+ break;
+
+ case SID_RULER_ROWS :
+ case SID_RULER_ROWS_VERTICAL:
+ if (pReqArgs)
+ {
+ SvxColumnItem aColItem(static_cast<const SvxColumnItem&>(pReqArgs->Get(nSlot)));
+
+ if( m_bSetTabColFromDoc || (!bSect && rSh.GetTableFormat()) )
+ {
+ OSL_ENSURE(aColItem.Count(), "ColDesc is empty!!");
+
+ SwTabCols aTabCols;
+ if ( m_bSetTabRowFromDoc )
+ rSh.GetMouseTabRows( aTabCols, m_aTabColFromDocPos );
+ else
+ rSh.GetTabRows(aTabCols);
+
+ if ( bVerticalWriting )
+ {
+ aTabCols.SetRight(nPageWidth - aColItem.GetRight() - aColItem.GetLeft());
+ aTabCols.SetLeftMin(aColItem.GetLeft());
+ }
+ else
+ {
+ tools::Long nBorder = nPageHeight - aTabCols.GetLeftMin() - aColItem.GetRight();
+ aTabCols.SetRight( nBorder );
+ }
+
+ const size_t nColItems = aColItem.Count() - 1;
+ if(bVerticalWriting)
+ {
+ for ( size_t i = nColItems; i; --i )
+ {
+ const SvxColumnDescription& rCol = aColItem[i - 1];
+ tools::Long nColumnPos = aTabCols.GetRight() - rCol.nEnd ;
+ aTabCols[i - 1] = nColumnPos;
+ aTabCols.SetHidden( i - 1, !rCol.bVisible );
+ }
+ }
+ else
+ {
+ for ( size_t i = 0; i < nColItems; ++i )
+ {
+ const SvxColumnDescription& rCol = aColItem[i];
+ aTabCols[i] = rCol.nEnd + aTabCols.GetLeft();
+ aTabCols.SetHidden( i, !rCol.bVisible );
+ }
+ }
+ bool bSingleLine = false;
+ if( const SfxBoolItem* pSingleLine = rReq.GetArgs()->GetItemIfSet(SID_RULER_ACT_LINE_ONLY, false) )
+ bSingleLine = pSingleLine->GetValue();
+ if ( m_bSetTabRowFromDoc )
+ {
+ if( !rSh.IsViewLocked() )
+ {
+ bUnlockView = true;
+ rSh.LockView( true );
+ }
+ rSh.SetMouseTabRows( aTabCols, bSingleLine, m_aTabColFromDocPos );
+ }
+ else
+ rSh.SetTabRows(aTabCols, bSingleLine);
+ }
+ }
+ break;
+ case SID_TABLE_CHANGE_CURRENT_BORDER_POSITION:
+ {
+ if (pReqArgs)
+ {
+ const SfxStringItem *pBorderType = pReqArgs->GetItemIfSet(SID_TABLE_BORDER_TYPE);
+ const SfxUInt16Item *pIndex = pReqArgs->GetItemIfSet(SID_TABLE_BORDER_INDEX);
+ const SfxInt32Item *pOffset = pReqArgs->GetItemIfSet(SID_TABLE_BORDER_OFFSET);
+ constexpr tools::Long constDistanceOffset = 40;
+
+ if (pBorderType && pIndex && pOffset)
+ {
+ const OUString sType = pBorderType->GetValue();
+ const sal_uInt16 nIndex = pIndex->GetValue();
+ const sal_Int32 nOffset = pOffset->GetValue();
+
+ if (sType.startsWith("column"))
+ {
+ SwTabCols aTabCols;
+ rSh.GetTabCols(aTabCols);
+
+ if (sType == "column-left")
+ {
+ tools::Long nNewPosition = aTabCols.GetLeft() + nOffset;
+ if(aTabCols.Count() > 0)
+ {
+ auto & rEntry = aTabCols.GetEntry(0);
+ nNewPosition = std::min(nNewPosition, rEntry.nPos - constDistanceOffset);
+ }
+ aTabCols.SetLeft(nNewPosition);
+ }
+ else if (sType == "column-right")
+ {
+ tools::Long nNewPosition = aTabCols.GetRight() + nOffset;
+ if(aTabCols.Count() > 0)
+ {
+ auto & rEntry = aTabCols.GetEntry(aTabCols.Count() - 1);
+ nNewPosition = std::max(nNewPosition, rEntry.nPos + constDistanceOffset);
+ }
+ aTabCols.SetRight(nNewPosition);
+ }
+ else if (sType == "column-middle" && nIndex < aTabCols.Count())
+ {
+ auto & rEntry = aTabCols.GetEntry(nIndex);
+ tools::Long nNewPosition = rEntry.nPos + nOffset;
+ nNewPosition = std::clamp(nNewPosition, rEntry.nMin, rEntry.nMax - constDistanceOffset);
+ rEntry.nPos = nNewPosition;
+ }
+
+ rSh.SetTabCols(aTabCols, false);
+ }
+ else if (sType.startsWith("row"))
+ {
+ SwTabCols aTabRows;
+ rSh.GetTabRows(aTabRows);
+
+ if (sType == "row-left")
+ {
+ auto & rEntry = aTabRows.GetEntry(0);
+ tools::Long nNewPosition = aTabRows.GetLeft() + nOffset;
+ nNewPosition = std::min(nNewPosition, rEntry.nPos - constDistanceOffset);
+ aTabRows.SetLeft(nNewPosition);
+ }
+ else if (sType == "row-right")
+ {
+ tools::Long nNewPosition = aTabRows.GetRight() + nOffset;
+ if(aTabRows.Count() > 0)
+ {
+ auto & rEntry = aTabRows.GetEntry(aTabRows.Count() - 1);
+ nNewPosition = std::max(nNewPosition, rEntry.nPos + constDistanceOffset);
+ }
+ aTabRows.SetRight(nNewPosition);
+ }
+ else if (sType == "row-middle" && nIndex < aTabRows.Count())
+ {
+ auto & rEntry = aTabRows.GetEntry(nIndex);
+ tools::Long nNewPosition = rEntry.nPos + nOffset;
+ nNewPosition = std::clamp(nNewPosition, rEntry.nMin, rEntry.nMax - constDistanceOffset);
+ rEntry.nPos = nNewPosition;
+ }
+
+ rSh.SetTabRows(aTabRows, false);
+ }
+ }
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_HEADER:
+ {
+ if ( pReqArgs )
+ {
+ const bool bHeaderOn = static_cast<const SfxBoolItem&>(pReqArgs->Get(SID_ATTR_PAGE_HEADER)).GetValue();
+ SwPageDesc aDesc(rDesc);
+ SwFrameFormat &rMaster = aDesc.GetMaster();
+ rMaster.SetFormatAttr( SwFormatHeader( bHeaderOn ));
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_HEADER_LRMARGIN:
+ {
+ if ( pReqArgs && rDesc.GetMaster().GetHeader().IsActive() )
+ {
+ const SvxLongLRSpaceItem& aLongLR = pReqArgs->Get(SID_ATTR_PAGE_HEADER_LRMARGIN);
+ SvxLRSpaceItem aLR(RES_LR_SPACE);
+ SwPageDesc aDesc(rDesc);
+ aLR.SetLeft(aLongLR.GetLeft());
+ aLR.SetRight(aLongLR.GetRight());
+ SwFrameFormat* pFormat = const_cast<SwFrameFormat*>(aDesc.GetMaster().GetHeader().GetHeaderFormat());
+ pFormat->SetFormatAttr( aLR );
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_HEADER_SPACING:
+ {
+ if ( pReqArgs && rDesc.GetMaster().GetHeader().IsActive())
+ {
+ const SvxLongULSpaceItem& aLongUL = pReqArgs->Get(SID_ATTR_PAGE_HEADER_SPACING);
+ SwPageDesc aDesc(rDesc);
+ SvxULSpaceItem aUL(0, aLongUL.GetLower(), RES_UL_SPACE );
+ SwFrameFormat* pFormat = const_cast<SwFrameFormat*>(aDesc.GetMaster().GetHeader().GetHeaderFormat());
+ pFormat->SetFormatAttr( aUL );
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_HEADER_LAYOUT:
+ {
+ if ( pReqArgs && rDesc.GetMaster().GetHeader().IsActive())
+ {
+ const SfxInt16Item& aLayoutItem = pReqArgs->Get(SID_ATTR_PAGE_HEADER_LAYOUT);
+ sal_uInt16 nLayout = aLayoutItem.GetValue();
+ SwPageDesc aDesc(rDesc);
+ aDesc.ChgHeaderShare((nLayout>>1) == 0);
+ aDesc.ChgFirstShare((nLayout % 2) == 0); // FIXME control changes for both header footer - tdf#100287
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_FOOTER:
+ {
+ if ( pReqArgs )
+ {
+ const bool bFooterOn = static_cast<const SfxBoolItem&>(pReqArgs->Get(SID_ATTR_PAGE_FOOTER)).GetValue();
+ SwPageDesc aDesc(rDesc);
+ SwFrameFormat &rMaster = aDesc.GetMaster();
+ rMaster.SetFormatAttr( SwFormatFooter( bFooterOn ));
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_FOOTER_LRMARGIN:
+ {
+ if ( pReqArgs && rDesc.GetMaster().GetFooter().IsActive() )
+ {
+ const SvxLongLRSpaceItem& aLongLR = pReqArgs->Get(SID_ATTR_PAGE_FOOTER_LRMARGIN);
+ SvxLRSpaceItem aLR(RES_LR_SPACE);
+ SwPageDesc aDesc(rDesc);
+ aLR.SetLeft(aLongLR.GetLeft());
+ aLR.SetRight(aLongLR.GetRight());
+ SwFrameFormat* pFormat = const_cast<SwFrameFormat*>(aDesc.GetMaster().GetFooter().GetFooterFormat());
+ pFormat->SetFormatAttr( aLR );
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_FOOTER_SPACING:
+ {
+ if ( pReqArgs && rDesc.GetMaster().GetFooter().IsActive())
+ {
+ const SvxLongULSpaceItem& aLongUL = pReqArgs->Get(SID_ATTR_PAGE_FOOTER_SPACING);
+ SwPageDesc aDesc(rDesc);
+ SvxULSpaceItem aUL(aLongUL.GetUpper(), 0, RES_UL_SPACE );
+ SwFrameFormat* pFormat = const_cast<SwFrameFormat*>(aDesc.GetMaster().GetFooter().GetFooterFormat());
+ pFormat->SetFormatAttr( aUL );
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_FOOTER_LAYOUT:
+ {
+ if ( pReqArgs && rDesc.GetMaster().GetFooter().IsActive())
+ {
+ const SfxInt16Item& aLayoutItem = pReqArgs->Get(SID_ATTR_PAGE_FOOTER_LAYOUT);
+ sal_uInt16 nLayout = aLayoutItem.GetValue();
+ SwPageDesc aDesc(rDesc);
+ aDesc.ChgFooterShare((nLayout>>1) == 0);
+ aDesc.ChgFirstShare((nLayout % 2) == 0); // FIXME control changes for both header footer - tdf#100287
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+
+ case SID_ATTR_PAGE_COLOR:
+ case SID_ATTR_PAGE_FILLSTYLE:
+ case SID_ATTR_PAGE_GRADIENT:
+ case SID_ATTR_PAGE_HATCH:
+ case SID_ATTR_PAGE_BITMAP:
+ {
+ if(pReqArgs)
+ {
+ SwPageDesc aDesc(rDesc);
+ SwFrameFormat &rMaster = aDesc.GetMaster();
+ switch (nSlot)
+ {
+ case SID_ATTR_PAGE_FILLSTYLE:
+ {
+ XFillStyleItem aFSItem( pReqArgs->Get( XATTR_FILLSTYLE ) );
+ drawing::FillStyle eXFS = aFSItem.GetValue();
+
+ if ( eXFS == drawing::FillStyle_NONE )
+ rMaster.SetFormatAttr( XFillStyleItem( eXFS ) );
+ }
+ break;
+
+ case SID_ATTR_PAGE_COLOR:
+ {
+ XFillColorItem aColorItem( pReqArgs->Get( XATTR_FILLCOLOR ) );
+ rMaster.SetFormatAttr( XFillStyleItem( drawing::FillStyle_SOLID ) );
+ rMaster.SetFormatAttr( aColorItem );
+ }
+ break;
+
+ case SID_ATTR_PAGE_GRADIENT:
+ {
+ XFillGradientItem aGradientItem( pReqArgs->Get( XATTR_FILLGRADIENT ) );
+ rMaster.SetFormatAttr( XFillStyleItem( drawing::FillStyle_GRADIENT ) );
+ rMaster.SetFormatAttr( aGradientItem );
+ }
+ break;
+
+ case SID_ATTR_PAGE_HATCH:
+ {
+ XFillHatchItem aHatchItem( pReqArgs->Get( XATTR_FILLHATCH ) );
+ rMaster.SetFormatAttr( XFillStyleItem( drawing::FillStyle_HATCH ) );
+ rMaster.SetFormatAttr( aHatchItem );
+ }
+ break;
+
+ case SID_ATTR_PAGE_BITMAP:
+ {
+ XFillBitmapItem aBitmapItem( pReqArgs->Get( XATTR_FILLBITMAP ) );
+ rMaster.SetFormatAttr( XFillStyleItem( drawing::FillStyle_BITMAP ) );
+ rMaster.SetFormatAttr( aBitmapItem );
+ }
+ break;
+
+ default:
+ break;
+ }
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+
+ default:
+ OSL_ENSURE( false, "wrong SlotId");
+ }
+ rSh.EndAllAction();
+
+ if( bUnlockView )
+ rSh.LockView( false );
+
+ m_bSetTabColFromDoc = m_bSetTabRowFromDoc = m_bTabColFromDoc = m_bTabRowFromDoc = false;
+ SetNumRuleNodeFromDoc(nullptr);
+}
+
+// Here the status of the tab bar will be determined.
+// This means that all relevant attributes at the CursorPos
+// will be submitted to the tab bar.
+void SwView::StateTabWin(SfxItemSet& rSet)
+{
+ SwWrtShell &rSh = GetWrtShell();
+
+ const Point* pPt = IsTabColFromDoc() || IsTabRowFromDoc() ? &m_aTabColFromDocPos : nullptr;
+ const FrameTypeFlags nFrameType = rSh.IsObjSelected()
+ ? FrameTypeFlags::DRAWOBJ
+ : rSh.GetFrameType( pPt, true );
+
+ const bool bFrameSelection = rSh.IsFrameSelected();
+ const bool bBrowse = rSh.GetViewOptions()->getBrowseMode();
+ // PageOffset/limiter
+ const SwRect& rPageRect = rSh.GetAnyCurRect( CurRectType::Page, pPt );
+ const SwRect& rPagePrtRect = rSh.GetAnyCurRect( CurRectType::PagePrt, pPt );
+ const tools::Long nPageWidth = rPageRect.Width();
+ const tools::Long nPageHeight = rPageRect.Height();
+
+ const SwPageDesc& rDesc = rSh.GetPageDesc(
+ IsTabColFromDoc() || m_bTabRowFromDoc ?
+ rSh.GetMousePageDesc(m_aTabColFromDocPos) : rSh.GetCurPageDesc() );
+
+ const SvxFrameDirectionItem& rFrameDir = rDesc.GetMaster().GetFrameDir();
+ const bool bVerticalWriting = rSh.IsInVerticalText();
+
+ //enable tab stop display on the rulers depending on the writing direction
+ WinBits nRulerStyle = m_pHRuler->GetStyle() & ~WB_EXTRAFIELD;
+ m_pHRuler->SetStyle(bVerticalWriting||bBrowse ? nRulerStyle : nRulerStyle|WB_EXTRAFIELD);
+ nRulerStyle = m_pVRuler->GetStyle() & ~WB_EXTRAFIELD;
+ m_pVRuler->SetStyle(bVerticalWriting ? nRulerStyle|WB_EXTRAFIELD : nRulerStyle);
+
+ //#i24363# tab stops relative to indent
+ bool bRelative = rSh.getIDocumentSettingAccess().get(DocumentSettingId::TABS_RELATIVE_TO_INDENT);
+ m_pHRuler->SetTabsRelativeToIndent( bRelative );
+ m_pVRuler->SetTabsRelativeToIndent( bRelative );
+
+ SvxLRSpaceItem aPageLRSpace( rDesc.GetMaster().GetLRSpace() );
+ SwapPageMargin( rDesc, aPageLRSpace );
+
+ SfxItemSetFixed<RES_PARATR_TABSTOP, RES_PARATR_TABSTOP,
+ RES_MARGIN_FIRSTLINE, RES_MARGIN_RIGHT,
+ RES_UL_SPACE, RES_UL_SPACE> aCoreSet( GetPool() );
+ // get also the list level indent values, if needed.
+ rSh.GetCurAttr( aCoreSet, true );
+ const SelectionType nSelType = rSh.GetSelectionType();
+
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while ( nWhich )
+ {
+ switch ( nWhich )
+ {
+
+ case SID_ATTR_PAGE_COLUMN:
+ {
+ sal_uInt16 nColumnType = 0;
+
+ const SwFrameFormat& rMaster = rDesc.GetMaster();
+ const SwFormatCol& aCol(rMaster.GetCol());
+ const sal_uInt16 nCols = aCol.GetNumCols();
+ if ( nCols == 0 )
+ {
+ nColumnType = 1;
+ }
+ else if ( nCols == 2 )
+ {
+ const sal_uInt16 nColLeft = aCol.CalcPrtColWidth(0, aCol.GetWishWidth());
+ const sal_uInt16 nColRight = aCol.CalcPrtColWidth(1, aCol.GetWishWidth());
+
+ if ( abs(nColLeft - nColRight) <= 10 )
+ {
+ nColumnType = 2;
+ }
+ else if( abs(nColLeft - nColRight*2) < 20 )
+ {
+ nColumnType = 4;
+ }
+ else if( abs(nColLeft*2 - nColRight) < 20 )
+ {
+ nColumnType = 5;
+ }
+ }
+ else if( nCols == 3 )
+ {
+ nColumnType = 3;
+ }
+ else
+ nColumnType = nCols;
+
+ rSet.Put( SfxInt16Item( SID_ATTR_PAGE_COLUMN, nColumnType ) );
+ }
+ break;
+
+ case SID_ATTR_LONG_LRSPACE:
+ {
+ SvxLongLRSpaceItem aLongLR( aPageLRSpace.GetLeft(),
+ aPageLRSpace.GetRight(),
+ SID_ATTR_LONG_LRSPACE);
+ if(bBrowse)
+ {
+ aLongLR.SetLeft(rPagePrtRect.Left());
+ aLongLR.SetRight(nPageWidth - rPagePrtRect.Right());
+ }
+ if ( ( nFrameType & FrameTypeFlags::HEADER || nFrameType & FrameTypeFlags::FOOTER ) &&
+ !(nFrameType & FrameTypeFlags::COLSECT) )
+ {
+ SwFrameFormat *pFormat = const_cast<SwFrameFormat*>((nFrameType & FrameTypeFlags::HEADER) ?
+ rDesc.GetMaster().GetHeader().GetHeaderFormat() :
+ rDesc.GetMaster().GetFooter().GetFooterFormat());
+ if( pFormat )// #i80890# if rDesc is not the one belonging to the current page is might crash
+ {
+ SwRect aRect( rSh.GetAnyCurRect( CurRectType::HeaderFooter, pPt));
+ aRect.Pos() -= rSh.GetAnyCurRect( CurRectType::Page, pPt ).Pos();
+ const SvxLRSpaceItem& aLR = pFormat->GetLRSpace();
+ aLongLR.SetLeft ( aLR.GetLeft() + aRect.Left() );
+ aLongLR.SetRight( nPageWidth - aRect.Right() + aLR.GetRight() );
+ }
+ }
+ else
+ {
+ SwRect aRect;
+ if( !bFrameSelection && ((nFrameType & FrameTypeFlags::COLSECT) || rSh.IsDirectlyInSection()) )
+ {
+ aRect = rSh.GetAnyCurRect(CurRectType::SectionPrt, pPt);
+ const SwRect aTmpRect = rSh.GetAnyCurRect(CurRectType::Section, pPt);
+ aRect.Pos() += aTmpRect.Pos();
+ }
+
+ else if ( bFrameSelection || nFrameType & FrameTypeFlags::FLY_ANY )
+ aRect = rSh.GetAnyCurRect(CurRectType::FlyEmbedded, pPt);
+ else if( nFrameType & FrameTypeFlags::DRAWOBJ)
+ aRect = rSh.GetObjRect();
+
+ if( aRect.Width() )
+ {
+ // make relative to page position:
+ aLongLR.SetLeft(aRect.Left() - rPageRect.Left());
+ aLongLR.SetRight(rPageRect.Right() - aRect.Right());
+ }
+ }
+ rSet.Put( aLongLR );
+ }
+ break;
+
+ // provide left and right margins of current page style
+ case SID_ATTR_PAGE_LRSPACE:
+ {
+ const SvxLRSpaceItem aTmpPageLRSpace( rDesc.GetMaster().GetLRSpace() );
+ const SvxLongLRSpaceItem aLongLR(
+ aTmpPageLRSpace.GetLeft(),
+ aTmpPageLRSpace.GetRight(),
+ SID_ATTR_PAGE_LRSPACE );
+ rSet.Put( aLongLR );
+ }
+ break;
+
+ case SID_ATTR_LONG_ULSPACE:
+ {
+ // Page margin top bottom
+ SvxULSpaceItem aUL( rDesc.GetMaster().GetULSpace() );
+ SvxLongULSpaceItem aLongUL( static_cast<tools::Long>(aUL.GetUpper()),
+ static_cast<tools::Long>(aUL.GetLower()),
+ SID_ATTR_LONG_ULSPACE);
+
+ if ( bFrameSelection || nFrameType & FrameTypeFlags::FLY_ANY )
+ {
+ // Convert document coordinates into page coordinates.
+ const SwRect &rRect = rSh.GetAnyCurRect(CurRectType::FlyEmbedded, pPt);
+ aLongUL.SetUpper(rRect.Top() - rPageRect.Top());
+ aLongUL.SetLower(rPageRect.Bottom() - rRect.Bottom());
+ }
+ else if ( nFrameType & FrameTypeFlags::HEADER || nFrameType & FrameTypeFlags::FOOTER )
+ {
+ SwRect aRect( rSh.GetAnyCurRect( CurRectType::HeaderFooter, pPt));
+ aRect.Pos() -= rSh.GetAnyCurRect( CurRectType::Page, pPt ).Pos();
+ aLongUL.SetUpper( aRect.Top() );
+ aLongUL.SetLower( nPageHeight - aRect.Bottom() );
+ }
+ else if( nFrameType & FrameTypeFlags::DRAWOBJ)
+ {
+ const SwRect &rRect = rSh.GetObjRect();
+ aLongUL.SetUpper(rRect.Top() - rPageRect.Top());
+ aLongUL.SetLower(rPageRect.Bottom() - rRect.Bottom());
+ }
+ else if(bBrowse)
+ {
+ aLongUL.SetUpper(rPagePrtRect.Top());
+ aLongUL.SetLower(nPageHeight - rPagePrtRect.Bottom());
+ }
+ rSet.Put( aLongUL );
+ }
+ break;
+
+ // provide top and bottom margins of current page style
+ case SID_ATTR_PAGE_ULSPACE:
+ {
+ const SvxULSpaceItem aUL( rDesc.GetMaster().GetULSpace() );
+ SvxLongULSpaceItem aLongUL(
+ static_cast<tools::Long>(aUL.GetUpper()),
+ static_cast<tools::Long>(aUL.GetLower()),
+ SID_ATTR_PAGE_ULSPACE );
+
+ rSet.Put( aLongUL );
+ }
+ break;
+
+ case SID_ATTR_TABSTOP_VERTICAL :
+ case RES_PARATR_TABSTOP:
+ {
+ if ( dynamic_cast< const SwWebView *>( this ) != nullptr ||
+ IsTabColFromDoc() ||
+ IsTabRowFromDoc() ||
+ ( nSelType & SelectionType::Graphic ) ||
+ ( nSelType & SelectionType::Frame ) ||
+ ( nSelType & SelectionType::Ole ) ||
+ (aCoreSet.GetItemState(RES_MARGIN_FIRSTLINE) < SfxItemState::DEFAULT) ||
+ (aCoreSet.GetItemState(RES_MARGIN_TEXTLEFT) < SfxItemState::DEFAULT) ||
+ (!bVerticalWriting && (SID_ATTR_TABSTOP_VERTICAL == nWhich) ) ||
+ ( bVerticalWriting && (RES_PARATR_TABSTOP == nWhich))
+ )
+ rSet.DisableItem( nWhich );
+ else
+ {
+ SvxTabStopItem aTabStops(aCoreSet.Get( RES_PARATR_TABSTOP ));
+
+ const SvxTabStopItem& rDefTabs = rSh.GetDefault(RES_PARATR_TABSTOP);
+
+ OSL_ENSURE(m_pHRuler, "why is there no ruler?");
+ const tools::Long nDefTabDist = ::GetTabDist(rDefTabs);
+ m_pHRuler->SetDefTabDist( nDefTabDist );
+ m_pVRuler->SetDefTabDist( nDefTabDist );
+ ::lcl_EraseDefTabs(aTabStops);
+ aTabStops.SetWhich(nWhich);
+ rSet.Put(aTabStops);
+
+ if (comphelper::LibreOfficeKit::isActive() && nWhich == RES_PARATR_TABSTOP)
+ {
+ boost::property_tree::ptree aRootTree;
+ boost::property_tree::ptree aEntries;
+
+ for (sal_uInt16 i = 0; i < aTabStops.Count(); ++i)
+ {
+ SvxTabStop const & rTabStop = aTabStops[i];
+ boost::property_tree::ptree aEntry;
+ aEntry.put("position", convertTwipToMm100(rTabStop.GetTabPos()));
+ aEntry.put("type", sal_uInt16(rTabStop.GetAdjustment()));
+ aEntry.put("decimal", OUString(rTabStop.GetDecimal()));
+ aEntry.put("fill", OUString(rTabStop.GetFill()));
+ aEntries.push_back(std::make_pair("", aEntry));
+ }
+ aRootTree.push_back(std::make_pair("tabstops", aEntries));
+
+ std::stringstream aStream;
+ boost::property_tree::write_json(aStream, aRootTree);
+ rSh.GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TAB_STOP_LIST, OString(aStream.str()));
+ }
+ }
+ break;
+ }
+
+ case SID_HANGING_INDENT:
+ {
+ SfxItemState e = aCoreSet.GetItemState(RES_MARGIN_FIRSTLINE);
+ if( e == SfxItemState::DISABLED )
+ rSet.DisableItem(nWhich);
+ break;
+ }
+
+ case SID_ATTR_PARA_LRSPACE_VERTICAL:
+ case SID_ATTR_PARA_LRSPACE:
+ case SID_ATTR_PARA_LEFTSPACE:
+ case SID_ATTR_PARA_RIGHTSPACE:
+ case SID_ATTR_PARA_FIRSTLINESPACE:
+ {
+ if ( nSelType & SelectionType::Graphic ||
+ nSelType & SelectionType::Frame ||
+ nSelType & SelectionType::Ole ||
+ nFrameType == FrameTypeFlags::DRAWOBJ ||
+ (!bVerticalWriting && (SID_ATTR_PARA_LRSPACE_VERTICAL == nWhich)) ||
+ ( bVerticalWriting && (SID_ATTR_PARA_LRSPACE == nWhich))
+ )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ else
+ {
+ std::shared_ptr<SvxLRSpaceItem> aLR(std::make_shared<SvxLRSpaceItem>(RES_LR_SPACE));
+ if ( !IsTabColFromDoc() )
+ {
+ SvxFirstLineIndentItem const& rFirstLine(aCoreSet.Get(RES_MARGIN_FIRSTLINE));
+ SvxTextLeftMarginItem const& rLeftMargin(aCoreSet.Get(RES_MARGIN_TEXTLEFT));
+ SvxRightMarginItem const& rRightMargin(aCoreSet.Get(RES_MARGIN_RIGHT));
+ aLR->SetTextFirstLineOffset(rFirstLine.GetTextFirstLineOffset(), rFirstLine.GetPropTextFirstLineOffset());
+ aLR->SetAutoFirst(rFirstLine.IsAutoFirst());
+ aLR->SetTextLeft(rLeftMargin.GetTextLeft(), rLeftMargin.GetPropLeft());
+ aLR->SetRight(rRightMargin.GetRight(), rRightMargin.GetPropRight());
+
+ // #i23726#
+ if (m_pNumRuleNodeFromDoc)
+ {
+ short nOffset = static_cast< short >(aLR->GetTextLeft() +
+ // #i42922# Mouse move of numbering label
+ // has to consider the left indent of the paragraph
+ m_pNumRuleNodeFromDoc->GetLeftMarginWithNum( true ) );
+
+ short nFLOffset;
+ m_pNumRuleNodeFromDoc->GetFirstLineOfsWithNum( nFLOffset );
+
+ aLR->SetLeft( nOffset + nFLOffset );
+ }
+ }
+ aLR->SetWhich(nWhich);
+ rSet.Put(*aLR);
+ }
+ break;
+ }
+
+ case SID_ATTR_PARA_ULSPACE:
+ case SID_ATTR_PARA_ABOVESPACE:
+ case SID_ATTR_PARA_BELOWSPACE:
+ case SID_PARASPACE_INCREASE:
+ case SID_PARASPACE_DECREASE:
+ {
+ SvxULSpaceItem aUL = aCoreSet.Get(RES_UL_SPACE);
+ SfxItemState e = aCoreSet.GetItemState(RES_UL_SPACE);
+ if( e >= SfxItemState::DEFAULT )
+ {
+ if ( !aUL.GetUpper() && !aUL.GetLower() )
+ rSet.DisableItem( SID_PARASPACE_DECREASE );
+ else if ( aUL.GetUpper() >= 5670 && aUL.GetLower() >= 5670 )
+ rSet.DisableItem( SID_PARASPACE_INCREASE );
+ if ( nWhich == SID_ATTR_PARA_ULSPACE
+ || nWhich == SID_ATTR_PARA_ABOVESPACE
+ || nWhich == SID_ATTR_PARA_BELOWSPACE
+ )
+ {
+ aUL.SetWhich( nWhich );
+ rSet.Put( aUL );
+ }
+ }
+ else
+ {
+ rSet.DisableItem( SID_PARASPACE_INCREASE );
+ rSet.DisableItem( SID_PARASPACE_DECREASE );
+ rSet.InvalidateItem( SID_ATTR_PARA_ULSPACE );
+ rSet.InvalidateItem( SID_ATTR_PARA_ABOVESPACE );
+ rSet.InvalidateItem( SID_ATTR_PARA_BELOWSPACE );
+ }
+ }
+ break;
+
+ case SID_RULER_BORDER_DISTANCE:
+ {
+ m_nLeftBorderDistance = 0;
+ m_nRightBorderDistance = 0;
+ SfxItemSetFixed<RES_BOX, RES_BOX,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER> aCoreSet2(GetPool());
+ if ( nSelType & SelectionType::Graphic ||
+ nSelType & SelectionType::Frame ||
+ nSelType & SelectionType::Ole ||
+ nFrameType == FrameTypeFlags::DRAWOBJ )
+ rSet.DisableItem(SID_RULER_BORDER_DISTANCE);
+ else
+ {
+ SvxLRSpaceItem aDistLR(SID_RULER_BORDER_DISTANCE);
+ if(nFrameType & FrameTypeFlags::FLY_ANY)
+ {
+ if( IsTabColFromDoc() )
+ {
+ const SwRect& rFlyPrtRect = rSh.GetAnyCurRect( CurRectType::FlyEmbeddedPrt, pPt );
+ aDistLR.SetLeft(rFlyPrtRect.Left());
+ aDistLR.SetRight(rFlyPrtRect.Left());
+ rSet.Put(aDistLR);
+ }
+ else
+ {
+ SvxBoxInfoItem aBoxInfo( SID_ATTR_BORDER_INNER );
+ aCoreSet2.Put(aBoxInfo);
+ rSh.GetFlyFrameAttr(aCoreSet2);
+ const SvxBoxItem& rBox = aCoreSet2.Get(RES_BOX);
+ aDistLR.SetLeft(rBox.GetDistance(SvxBoxItemLine::LEFT));
+ aDistLR.SetRight(rBox.GetDistance(SvxBoxItemLine::RIGHT));
+ rSet.Put(aDistLR);
+
+ //add the paragraph border distance
+ SfxItemSetFixed<RES_BOX, RES_BOX> aCoreSet1( GetPool() );
+ rSh.GetCurAttr( aCoreSet1 );
+ const SvxBoxItem& rParaBox = aCoreSet1.Get(RES_BOX);
+ aDistLR.SetLeft(aDistLR.GetLeft() + rParaBox.GetDistance(SvxBoxItemLine::LEFT));
+ aDistLR.SetRight(aDistLR.GetRight() + rParaBox.GetDistance(SvxBoxItemLine::RIGHT));
+ }
+ m_nLeftBorderDistance = static_cast< sal_uInt16 >(aDistLR.GetLeft());
+ m_nRightBorderDistance = static_cast< sal_uInt16 >(aDistLR.GetRight());
+ }
+ else if ( IsTabColFromDoc() ||
+ ( rSh.GetTableFormat() && !bFrameSelection &&
+ !(nFrameType & FrameTypeFlags::COLSECT ) ) )
+ {
+ SvxBoxInfoItem aBoxInfo( SID_ATTR_BORDER_INNER );
+ aBoxInfo.SetTable(false);
+ aBoxInfo.SetDist(true);
+ aCoreSet2.Put(aBoxInfo);
+ rSh.GetTabBorders( aCoreSet2 );
+ const SvxBoxItem& rBox = aCoreSet2.Get(RES_BOX);
+ aDistLR.SetLeft(rBox.GetDistance(SvxBoxItemLine::LEFT));
+ aDistLR.SetRight(rBox.GetDistance(SvxBoxItemLine::RIGHT));
+ rSet.Put(aDistLR);
+
+ //add the border distance of the paragraph
+ SfxItemSetFixed<RES_BOX, RES_BOX> aCoreSet1( GetPool() );
+ rSh.GetCurAttr( aCoreSet1 );
+ const SvxBoxItem& rParaBox = aCoreSet1.Get(RES_BOX);
+ aDistLR.SetLeft(aDistLR.GetLeft() + rParaBox.GetDistance(SvxBoxItemLine::LEFT));
+ aDistLR.SetRight(aDistLR.GetRight() + rParaBox.GetDistance(SvxBoxItemLine::RIGHT));
+ m_nLeftBorderDistance = static_cast< sal_uInt16 >(aDistLR.GetLeft());
+ m_nRightBorderDistance = static_cast< sal_uInt16 >(aDistLR.GetRight());
+ }
+ else if ( !rSh.IsDirectlyInSection() )
+ {
+ //get the page/header/footer border distance
+ const SwFrameFormat& rMaster = rDesc.GetMaster();
+ const SvxBoxItem& rBox = rMaster.GetAttrSet().Get(RES_BOX);
+ aDistLR.SetLeft(rBox.GetDistance(SvxBoxItemLine::LEFT));
+ aDistLR.SetRight(rBox.GetDistance(SvxBoxItemLine::RIGHT));
+
+ const SvxBoxItem* pBox = nullptr;
+ if(nFrameType & FrameTypeFlags::HEADER)
+ {
+ rMaster.GetHeader();
+ const SwFormatHeader& rHeaderFormat = rMaster.GetHeader();
+ SwFrameFormat *pHeaderFormat = const_cast<SwFrameFormat*>(rHeaderFormat.GetHeaderFormat());
+ if( pHeaderFormat )// #i80890# if rDesc is not the one belonging to the current page is might crash
+ pBox = & pHeaderFormat->GetBox();
+ }
+ else if(nFrameType & FrameTypeFlags::FOOTER )
+ {
+ const SwFormatFooter& rFooterFormat = rMaster.GetFooter();
+ SwFrameFormat *pFooterFormat = const_cast<SwFrameFormat*>(rFooterFormat.GetFooterFormat());
+ if( pFooterFormat )// #i80890# if rDesc is not the one belonging to the current page is might crash
+ pBox = & pFooterFormat->GetBox();
+ }
+ if(pBox)
+ {
+ aDistLR.SetLeft(pBox->GetDistance(SvxBoxItemLine::LEFT));
+ aDistLR.SetRight(pBox->GetDistance(SvxBoxItemLine::RIGHT));
+ }
+ rSet.Put(aDistLR);
+
+ //add the border distance of the paragraph
+ rSh.GetCurAttr(aCoreSet2);
+ const SvxBoxItem& rParaBox = aCoreSet2.Get(RES_BOX);
+ aDistLR.SetLeft(aDistLR.GetLeft() + rParaBox.GetDistance(SvxBoxItemLine::LEFT));
+ aDistLR.SetRight(aDistLR.GetRight() + rParaBox.GetDistance(SvxBoxItemLine::RIGHT));
+ m_nLeftBorderDistance = static_cast< sal_uInt16 >(aDistLR.GetLeft());
+ m_nRightBorderDistance = static_cast< sal_uInt16 >(aDistLR.GetRight());
+ }
+ }
+ }
+ break;
+
+ case SID_RULER_TEXT_RIGHT_TO_LEFT:
+ {
+ if ( nSelType & SelectionType::Graphic ||
+ nSelType & SelectionType::Frame ||
+ nSelType & SelectionType::Ole ||
+ nFrameType == FrameTypeFlags::DRAWOBJ)
+ rSet.DisableItem(nWhich);
+ else
+ {
+ bool bFlag = rSh.IsInRightToLeftText();
+ rSet.Put(SfxBoolItem(nWhich, bFlag));
+ }
+ }
+ break;
+
+ case SID_RULER_BORDERS_VERTICAL:
+ case SID_RULER_BORDERS:
+ {
+ bool bFrameHasVerticalColumns(false);
+ {
+ bool bFrameRTL;
+ bool bFrameVertL2R;
+ bFrameHasVerticalColumns = rSh.IsFrameVertical(false, bFrameRTL, bFrameVertL2R) &&
+ bFrameSelection;
+ }
+ bool bHasTable = ( IsTabColFromDoc() ||
+ ( rSh.GetTableFormat() && !bFrameSelection &&
+ !(nFrameType & FrameTypeFlags::COLSECT ) ) );
+
+ bool bTableVertical = bHasTable && rSh.IsTableVertical();
+
+ if(((SID_RULER_BORDERS_VERTICAL == nWhich) &&
+ ((bHasTable && !bTableVertical) ||
+ (!bVerticalWriting && !bFrameSelection && !bHasTable ) ||
+ ( bFrameSelection && !bFrameHasVerticalColumns))) ||
+ ((SID_RULER_BORDERS == nWhich) &&
+ ((bHasTable && bTableVertical) ||
+ (bVerticalWriting && !bFrameSelection&& !bHasTable) || bFrameHasVerticalColumns)))
+ rSet.DisableItem(nWhich);
+ else if ( bHasTable )
+ {
+ SwTabCols aTabCols;
+ size_t nNum = 0;
+ m_bSetTabColFromDoc = IsTabColFromDoc();
+ if ( m_bSetTabColFromDoc )
+ {
+ rSh.GetMouseTabCols( aTabCols, m_aTabColFromDocPos );
+ nNum = rSh.GetCurMouseTabColNum( m_aTabColFromDocPos );
+ }
+ else
+ {
+ rSh.GetTabCols( aTabCols );
+ nNum = rSh.GetCurTabColNum();
+ if(rSh.IsTableRightToLeft())
+ nNum = aTabCols.Count() - nNum;
+ }
+
+ OSL_ENSURE(nNum <= aTabCols.Count(), "TabCol not found");
+ const int nLft = aTabCols.GetLeftMin() + aTabCols.GetLeft();
+ const int nRgt = (bTableVertical ? nPageHeight : nPageWidth) -
+ (aTabCols.GetLeftMin() + aTabCols.GetRight());
+
+ const sal_uInt16 nL = static_cast< sal_uInt16 >(std::max(nLft, 0));
+ const sal_uInt16 nR = static_cast< sal_uInt16 >(std::max(nRgt, 0));
+
+ SvxColumnItem aColItem(nNum, nL, nR);
+
+ tools::Long nStart = 0;
+ tools::Long nEnd = 0;
+
+ //columns in right-to-left tables need to be mirrored
+ bool bIsTableRTL =
+ IsTabColFromDoc() ?
+ rSh.IsMouseTableRightToLeft(m_aTabColFromDocPos)
+ : rSh.IsTableRightToLeft();
+ if(bIsTableRTL)
+ {
+ for ( size_t i = aTabCols.Count(); i; --i )
+ {
+ const SwTabColsEntry& rEntry = aTabCols.GetEntry( i - 1 );
+ nEnd = aTabCols.GetRight() - rEntry.nPos;
+ SvxColumnDescription aColDesc( nStart, nEnd,
+ aTabCols.GetRight() - rEntry.nMax,
+ aTabCols.GetRight() - rEntry.nMin,
+ !aTabCols.IsHidden(i - 1) );
+ aColItem.Append(aColDesc);
+ nStart = nEnd;
+ }
+ SvxColumnDescription aColDesc(nStart,
+ aTabCols.GetRight() - aTabCols.GetLeft(), true);
+ aColItem.Append(aColDesc);
+ }
+ else
+ {
+ for ( size_t i = 0; i < aTabCols.Count(); ++i )
+ {
+ const SwTabColsEntry& rEntry = aTabCols.GetEntry( i );
+ nEnd = rEntry.nPos - aTabCols.GetLeft();
+ SvxColumnDescription aColDesc( nStart, nEnd,
+ rEntry.nMin - aTabCols.GetLeft(), rEntry.nMax - aTabCols.GetLeft(),
+ !aTabCols.IsHidden(i) );
+ aColItem.Append(aColDesc);
+ nStart = nEnd;
+ }
+ SvxColumnDescription aColDesc(nStart, aTabCols.GetRight() - aTabCols.GetLeft(),
+ 0, 0, true);
+ aColItem.Append(aColDesc);
+ }
+ aColItem.SetWhich(nWhich);
+ rSet.Put(aColItem);
+ }
+ else if ( bFrameSelection || nFrameType & ( FrameTypeFlags::COLUMN | FrameTypeFlags::COLSECT ) )
+ {
+ // Out of frame or page?
+ sal_uInt16 nNum = 0;
+ if(bFrameSelection)
+ {
+ const SwFrameFormat* pFormat = rSh.GetFlyFrameFormat();
+ if(pFormat)
+ nNum = pFormat->GetCol().GetNumCols();
+ }
+ else
+ nNum = rSh.GetCurColNum();
+
+ if(
+ // For that matter FrameTypeFlags::COLSECT should not be included
+ // if the border is selected!
+ !bFrameSelection &&
+ nFrameType & FrameTypeFlags::COLSECT )
+ {
+ const SwSection *pSect = rSh.GetAnySection(false, pPt);
+ OSL_ENSURE( pSect, "Which section?");
+ if( pSect )
+ {
+ SwSectionFormat const *pFormat = pSect->GetFormat();
+ const SwFormatCol& rCol = pFormat->GetCol();
+ if (rSh.IsColRightToLeft())
+ nNum = rCol.GetColumns().size() - nNum;
+ else
+ --nNum;
+ SvxColumnItem aColItem(nNum);
+ SwRect aRect = rSh.GetAnyCurRect(CurRectType::SectionPrt, pPt);
+ const SwRect aTmpRect = rSh.GetAnyCurRect(CurRectType::Section, pPt);
+
+ ::lcl_FillSvxColumn(rCol, bVerticalWriting ? aRect.Height() : aRect.Width(), aColItem, 0);
+
+ if(bVerticalWriting)
+ {
+ aRect.Pos() += Point(aTmpRect.Left(), aTmpRect.Top());
+ aRect.Pos().AdjustY( -(rPageRect.Top()) );
+ aColItem.SetLeft(aRect.Top());
+ aColItem.SetRight(nPageHeight - aRect.Bottom());
+ }
+ else
+ {
+ aRect.Pos() += aTmpRect.Pos();
+
+ // make relative to page position:
+ aColItem.SetLeft (o3tl::narrowing<sal_uInt16>( aRect.Left() - rPageRect.Left() ));
+ aColItem.SetRight(o3tl::narrowing<sal_uInt16>( rPageRect.Right() - aRect.Right()));
+ }
+ aColItem.SetOrtho(aColItem.CalcOrtho());
+
+ aColItem.SetWhich(nWhich);
+ rSet.Put(aColItem);
+ }
+ }
+ else if( bFrameSelection || nFrameType & FrameTypeFlags::FLY_ANY )
+ {
+ // Columns in frame
+ if ( nNum )
+ {
+ const SwFrameFormat* pFormat = rSh.GetFlyFrameFormat() ;
+
+ const SwFormatCol& rCol = pFormat->GetCol();
+ if (rSh.IsColRightToLeft())
+ nNum = rCol.GetColumns().size() - nNum;
+ else
+ nNum--;
+ SvxColumnItem aColItem(nNum);
+ const SwRect &rSizeRect = rSh.GetAnyCurRect(CurRectType::FlyEmbeddedPrt, pPt);
+
+ bool bUseVertical = bFrameHasVerticalColumns || (!bFrameSelection && bVerticalWriting);
+ const tools::Long lWidth = bUseVertical ? rSizeRect.Height() : rSizeRect.Width();
+ const SwRect &rRect = rSh.GetAnyCurRect(CurRectType::FlyEmbedded, pPt);
+ tools::Long nDist2 = ((bUseVertical ? rRect.Height() : rRect.Width()) - lWidth) /2;
+ ::lcl_FillSvxColumn(rCol, lWidth, aColItem, nDist2);
+
+ if(bUseVertical)
+ {
+ aColItem.SetLeft(rRect.Top()- rPageRect.Top());
+ aColItem.SetRight(nPageHeight + rPageRect.Top() - rRect.Bottom());
+ }
+ else
+ {
+ aColItem.SetLeft(rRect.Left() - rPageRect.Left());
+ aColItem.SetRight(rPageRect.Right() - rRect.Right());
+ }
+
+ aColItem.SetOrtho(aColItem.CalcOrtho());
+
+ aColItem.SetWhich(nWhich);
+ rSet.Put(aColItem);
+ }
+ else
+ rSet.DisableItem(nWhich);
+ }
+ else
+ { // Columns on the page
+ const SwFrameFormat& rMaster = rDesc.GetMaster();
+ SwFormatCol aCol(rMaster.GetCol());
+ if(rFrameDir.GetValue() == SvxFrameDirection::Horizontal_RL_TB)
+ nNum = aCol.GetColumns().size() - nNum;
+ else
+ nNum--;
+
+ SvxColumnItem aColItem(nNum);
+ const SwRect aPrtRect = rSh.GetAnyCurRect(CurRectType::PagePrt, pPt);
+ const SvxBoxItem& rBox = rMaster.GetFormatAttr(RES_BOX);
+ tools::Long nDist = rBox.GetSmallestDistance();
+
+ lcl_FillSvxColumn(
+ aCol,
+ bVerticalWriting ? aPrtRect.Height() : aPrtRect.Width(),
+ aColItem, nDist);
+
+ if(bBrowse)
+ {
+ if (bVerticalWriting)
+ {
+ aColItem.SetLeft(o3tl::narrowing<sal_uInt16>(rPagePrtRect.Top()));
+ aColItem.SetRight(sal_uInt16(nPageHeight - rPagePrtRect.Bottom()));
+ }
+ else
+ {
+ aColItem.SetLeft(o3tl::narrowing<sal_uInt16>(rPagePrtRect.Left()));
+ aColItem.SetRight(sal_uInt16(nPageWidth - rPagePrtRect.Right()));
+ }
+ }
+ else
+ {
+ if (bVerticalWriting)
+ {
+ SvxULSpaceItem aUL( rDesc.GetMaster().GetULSpace() );
+ aColItem.SetLeft (aUL.GetUpper());
+ aColItem.SetRight(aUL.GetLower());
+ }
+ else
+ {
+ aColItem.SetLeft (aPageLRSpace.GetLeft());
+ aColItem.SetRight(aPageLRSpace.GetRight());
+ }
+ }
+ aColItem.SetOrtho(aColItem.CalcOrtho());
+
+ aColItem.SetWhich(nWhich);
+ rSet.Put(aColItem);
+ }
+ }
+ else
+ rSet.DisableItem(nWhich);
+ break;
+ }
+
+ case SID_RULER_ROWS :
+ case SID_RULER_ROWS_VERTICAL:
+ {
+ bool bFrameHasVerticalColumns(false);
+ {
+ bool bFrameRTL;
+ bool bFrameVertL2R;
+ bFrameHasVerticalColumns = rSh.IsFrameVertical(false, bFrameRTL, bFrameVertL2R) &&
+ bFrameSelection;
+ }
+
+ if(((SID_RULER_ROWS == nWhich) &&
+ ((!bVerticalWriting && !bFrameSelection) || (bFrameSelection && !bFrameHasVerticalColumns))) ||
+ ((SID_RULER_ROWS_VERTICAL == nWhich) &&
+ ((bVerticalWriting && !bFrameSelection) || bFrameHasVerticalColumns)))
+ rSet.DisableItem(nWhich);
+ else if ( IsTabRowFromDoc() ||
+ ( rSh.GetTableFormat() && !bFrameSelection &&
+ !(nFrameType & FrameTypeFlags::COLSECT ) ) )
+ {
+ SwTabCols aTabCols;
+ m_bSetTabRowFromDoc = IsTabRowFromDoc();
+ if ( m_bSetTabRowFromDoc )
+ {
+ rSh.GetMouseTabRows( aTabCols, m_aTabColFromDocPos );
+ }
+ else
+ {
+ rSh.GetTabRows( aTabCols );
+ }
+
+ const int nLft = aTabCols.GetLeftMin();
+ const int nRgt = (bVerticalWriting ? nPageWidth : nPageHeight) -
+ (aTabCols.GetLeftMin() + aTabCols.GetRight());
+
+ const sal_uInt16 nL = static_cast< sal_uInt16 >(std::max(nLft, 0));
+ const sal_uInt16 nR = static_cast< sal_uInt16 >(std::max(nRgt, 0));
+
+ SvxColumnItem aColItem(0, nL, nR);
+
+ tools::Long nStart = 0;
+ tools::Long nEnd = 0;
+
+ for ( size_t i = 0; i < aTabCols.Count(); ++i )
+ {
+ const SwTabColsEntry& rEntry = aTabCols.GetEntry( i );
+ if(bVerticalWriting)
+ {
+ nEnd = aTabCols.GetRight() - rEntry.nPos;
+ SvxColumnDescription aColDesc( nStart, nEnd,
+ std::max(tools::Long(0), aTabCols.GetRight() - rEntry.nMax),
+ std::max(tools::Long(0), aTabCols.GetRight() - rEntry.nMin),
+ !aTabCols.IsHidden(i) );
+ aColItem.Append(aColDesc);
+ }
+ else
+ {
+ nEnd = rEntry.nPos - aTabCols.GetLeft();
+ SvxColumnDescription aColDesc( nStart, nEnd,
+ rEntry.nMin - aTabCols.GetLeft(),
+ rEntry.nMax - aTabCols.GetLeft(),
+ !aTabCols.IsHidden(i) );
+ aColItem.Append(aColDesc);
+ }
+ nStart = nEnd;
+ }
+ if(bVerticalWriting)
+ nEnd = aTabCols.GetRight();
+ else
+ nEnd = aTabCols.GetLeft();
+
+ SvxColumnDescription aColDesc( nStart, nEnd,
+ aTabCols.GetRight(),
+ aTabCols.GetRight(),
+ false );
+ aColItem.Append(aColDesc);
+
+ aColItem.SetWhich(nWhich);
+ rSet.Put(aColItem);
+ }
+ else
+ rSet.DisableItem(nWhich);
+ }
+ break;
+
+ case SID_RULER_PAGE_POS:
+ {
+ SvxPagePosSizeItem aPagePosSize(
+ Point( rPageRect.Left(), rPageRect.Top()) , nPageWidth, nPageHeight);
+
+ rSet.Put(aPagePosSize);
+ break;
+ }
+
+ case SID_RULER_LR_MIN_MAX:
+ {
+ tools::Rectangle aRectangle;
+ if( ( nFrameType & FrameTypeFlags::COLSECT ) && !IsTabColFromDoc() &&
+ ( nFrameType & ( FrameTypeFlags::TABLE|FrameTypeFlags::COLUMN ) ) )
+ {
+ if( nFrameType & FrameTypeFlags::TABLE )
+ {
+ const size_t nNum = rSh.GetCurTabColNum();
+ SwTabCols aTabCols;
+ rSh.GetTabCols( aTabCols );
+
+ const int nLft = aTabCols.GetLeftMin() + aTabCols.GetLeft();
+ const int nRgt = nPageWidth -(aTabCols.GetLeftMin() + aTabCols.GetRight());
+
+ const sal_uInt16 nL = static_cast< sal_uInt16 >(std::max(nLft, 0));
+ const sal_uInt16 nR = static_cast< sal_uInt16 >(std::max(nRgt, 0));
+
+ aRectangle.SetLeft( nL );
+ if(nNum > 1)
+ aRectangle.AdjustLeft(aTabCols[nNum - 2] );
+ if(nNum)
+ aRectangle.AdjustLeft(MINLAY );
+ if(aTabCols.Count() <= nNum + 1 )
+ aRectangle.SetRight( nR );
+ else
+ aRectangle.SetRight( nPageWidth - (nL + aTabCols[nNum + 1]) );
+
+ if(nNum < aTabCols.Count())
+ aRectangle.AdjustRight(MINLAY );
+ }
+ else
+ {
+ const SwFrameFormat* pFormat = rSh.GetFlyFrameFormat();
+ const SwFormatCol* pCols = pFormat ? &pFormat->GetCol():
+ &rDesc.GetMaster().GetCol();
+ const SwColumns& rCols = pCols->GetColumns();
+ sal_uInt16 nNum = rSh.GetCurOutColNum();
+ const sal_uInt16 nCount = std::min(sal_uInt16(nNum + 1), sal_uInt16(rCols.size()));
+ const SwRect aRect( rSh.GetAnyCurRect( pFormat
+ ? CurRectType::FlyEmbeddedPrt
+ : CurRectType::PagePrt, pPt ));
+ const SwRect aAbsRect( rSh.GetAnyCurRect( pFormat
+ ? CurRectType::FlyEmbedded
+ : CurRectType::Page, pPt ));
+
+ // The width of the frame or within the page margins.
+ const sal_uInt16 nTotalWidth = o3tl::narrowing<sal_uInt16>(aRect.Width());
+ // The entire frame width - The difference is twice the distance to the edge.
+ const sal_uInt16 nOuterWidth = o3tl::narrowing<sal_uInt16>(aAbsRect.Width());
+ int nWidth = 0,
+ nEnd = 0;
+ aRectangle.SetLeft( 0 );
+ for ( sal_uInt16 i = 0; i < nCount; ++i )
+ {
+ const SwColumn* pCol = &rCols[i];
+ const int nStart = pCol->GetLeft() + nWidth;
+ if(i == nNum - 2)
+ aRectangle.SetLeft( nStart );
+ nWidth += pCols->CalcColWidth( i, nTotalWidth );
+ nEnd = nWidth - pCol->GetRight();
+ }
+ aRectangle.SetRight( rPageRect.Right() - nEnd );
+ aRectangle.AdjustLeft( -(rPageRect.Left()) );
+
+ if(nNum > 1)
+ {
+ aRectangle.AdjustLeft(MINLAY );
+ aRectangle.AdjustLeft(aRect.Left() );
+ }
+ if(pFormat) // Range in frame - here you may up to the edge
+ {
+ aRectangle.SetLeft(0);
+ aRectangle.SetRight(0);
+ }
+ else
+ {
+ // Move the rectangle to the correct absolute position.
+ aRectangle.AdjustLeft(aAbsRect.Left() );
+ aRectangle.AdjustRight( -(aAbsRect.Left()) );
+ // Include distance to the border.
+ aRectangle.AdjustRight( -((nOuterWidth - nTotalWidth) / 2) );
+ }
+
+ if(nNum < rCols.size())
+ {
+ aRectangle.AdjustRight(MINLAY );
+ }
+ else
+ // Right is only the margin now.
+ aRectangle.SetRight( 0 );
+
+ }
+ }
+ else if ( ((nFrameType & FrameTypeFlags::TABLE) || IsTabColFromDoc()) &&
+ !bFrameSelection )
+ {
+ bool bColumn;
+ if ( IsTabColFromDoc() )
+ bColumn = rSh.GetCurMouseColNum( m_aTabColFromDocPos ) != 0;
+ else
+ bColumn = bool(nFrameType & (FrameTypeFlags::COLUMN|FrameTypeFlags::FLY_ANY|FrameTypeFlags::COLSECTOUTTAB));
+
+ if ( !bColumn )
+ {
+ if( nFrameType & FrameTypeFlags::FLY_ANY && IsTabColFromDoc() )
+ {
+ SwRect aRect( rSh.GetAnyCurRect(
+ CurRectType::FlyEmbeddedPrt, pPt ) );
+ aRect.Pos() += rSh.GetAnyCurRect( CurRectType::FlyEmbedded,
+ pPt ).Pos();
+
+ aRectangle.SetLeft( aRect.Left() - rPageRect.Left() );
+ aRectangle.SetRight( rPageRect.Right() - aRect.Right() );
+ }
+ else if( bBrowse )
+ {
+ aRectangle.SetLeft( rPagePrtRect.Left() );
+ aRectangle.SetRight( nPageWidth - rPagePrtRect.Right() );
+ }
+ else
+ {
+ aRectangle.SetLeft( aPageLRSpace.GetLeft() );
+ aRectangle.SetRight( aPageLRSpace.GetRight() );
+ }
+ }
+ else
+ { // Here only for table in multi-column pages and borders.
+ bool bSectOutTable = bool(nFrameType & FrameTypeFlags::TABLE);
+ bool bFrame = bool(nFrameType & FrameTypeFlags::FLY_ANY);
+ bool bColSct = bool(nFrameType & ( bSectOutTable
+ ? FrameTypeFlags::COLSECTOUTTAB
+ : FrameTypeFlags::COLSECT )
+ );
+ //So you can also drag with the mouse, without being in the table.
+ CurRectType eRecType = CurRectType::PagePrt;
+ size_t nNum = IsTabColFromDoc() ?
+ rSh.GetCurMouseColNum( m_aTabColFromDocPos ):
+ rSh.GetCurOutColNum();
+ const SwFrameFormat* pFormat = nullptr;
+ if( bColSct )
+ {
+ eRecType = bSectOutTable ? CurRectType::SectionOutsideTable
+ : CurRectType::Section;
+ const SwSection *pSect = rSh.GetAnySection( bSectOutTable, pPt );
+ OSL_ENSURE( pSect, "Which section?");
+ pFormat = pSect->GetFormat();
+ }
+ else if( bFrame )
+ {
+ pFormat = rSh.GetFlyFrameFormat();
+ eRecType = CurRectType::FlyEmbeddedPrt;
+ }
+
+ const SwFormatCol* pCols = pFormat ? &pFormat->GetCol():
+ &rDesc.GetMaster().GetCol();
+ const SwColumns& rCols = pCols->GetColumns();
+ const sal_uInt16 nBorder = pFormat
+ ? pFormat->GetBox().GetSmallestDistance()
+ : rDesc.GetMaster().GetBox().GetSmallestDistance();
+
+ // RECT_FLY_PRT_EMBEDDED returns the relative position to RECT_FLY_EMBEDDED
+ // the absolute position must be added here
+
+ SwRect aRect( rSh.GetAnyCurRect( eRecType, pPt ) );
+ if(CurRectType::FlyEmbeddedPrt == eRecType)
+ aRect.Pos() += rSh.GetAnyCurRect( CurRectType::FlyEmbedded,
+ pPt ).Pos();
+
+ const sal_uInt16 nTotalWidth = o3tl::narrowing<sal_uInt16>(aRect.Width());
+ // Initialize nStart and nEnd for nNum == 0
+ int nWidth = 0,
+ nStart = 0,
+ nEnd = nTotalWidth;
+
+ if( nNum > rCols.size() )
+ {
+ OSL_ENSURE( false, "wrong FormatCol is being edited!" );
+ nNum = rCols.size();
+ }
+
+ for( size_t i = 0; i < nNum; ++i )
+ {
+ const SwColumn* pCol = &rCols[i];
+ nStart = pCol->GetLeft() + nWidth;
+ nWidth += pCols->CalcColWidth( o3tl::narrowing<sal_uInt16>(i), nTotalWidth );
+ nEnd = nWidth - pCol->GetRight();
+ }
+ if( bFrame || bColSct )
+ {
+ aRectangle.SetLeft( aRect.Left() - rPageRect.Left() + nStart );
+ aRectangle.SetRight( nPageWidth - aRectangle.Left() - nEnd + nStart );
+ }
+ else if(!bBrowse)
+ {
+ aRectangle.SetLeft( aPageLRSpace.GetLeft() + nStart );
+ aRectangle.SetRight( nPageWidth - nEnd - aPageLRSpace.GetLeft() );
+ }
+ else
+ {
+ tools::Long nLeft = rPagePrtRect.Left();
+ aRectangle.SetLeft( nStart + nLeft );
+ aRectangle.SetRight( nPageWidth - nEnd - nLeft );
+ }
+ if(!bFrame)
+ {
+ aRectangle.AdjustLeft(nBorder );
+ aRectangle.AdjustRight( -nBorder );
+ }
+ }
+ }
+ else if ( nFrameType & ( FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER ))
+ {
+ aRectangle.SetLeft( aPageLRSpace.GetLeft() );
+ aRectangle.SetRight( aPageLRSpace.GetRight() );
+ }
+ else
+ {
+ aRectangle.SetLeft(0);
+ aRectangle.SetRight(0);
+ }
+
+ SfxRectangleItem aLR( SID_RULER_LR_MIN_MAX , aRectangle);
+ rSet.Put(aLR);
+ }
+ break;
+
+ case SID_RULER_PROTECT:
+ {
+ if(bFrameSelection)
+ {
+ FlyProtectFlags nProtect = m_pWrtShell->IsSelObjProtected( FlyProtectFlags::Size|FlyProtectFlags::Pos|FlyProtectFlags::Content );
+
+ SvxProtectItem aProt(SID_RULER_PROTECT);
+ aProt.SetContentProtect(bool(nProtect & FlyProtectFlags::Content));
+ aProt.SetSizeProtect (bool(nProtect & FlyProtectFlags::Size));
+ aProt.SetPosProtect (bool(nProtect & FlyProtectFlags::Pos));
+ rSet.Put(aProt);
+ }
+ else
+ {
+ SvxProtectItem aProtect(SID_RULER_PROTECT);
+ if(bBrowse && !(nFrameType & (FrameTypeFlags::DRAWOBJ|FrameTypeFlags::COLUMN)) && !rSh.GetTableFormat())
+ {
+ aProtect.SetSizeProtect(true);
+ aProtect.SetPosProtect(true);
+ }
+ rSet.Put(aProtect);
+ }
+ }
+ break;
+
+ case SID_ATTR_PAGE_HEADER:
+ case SID_ATTR_PAGE_HEADER_LRMARGIN:
+ case SID_ATTR_PAGE_HEADER_SPACING:
+ case SID_ATTR_PAGE_HEADER_LAYOUT:
+ {
+ const SwFormatHeader& rHeader = rDesc.GetMaster().GetHeader();
+ bool bHeaderOn = rHeader.IsActive();
+ rSet.Put( SfxBoolItem(SID_ATTR_PAGE_HEADER, bHeaderOn ) );
+ if(bHeaderOn)
+ {
+ const SvxLRSpaceItem* pLR = rHeader.GetHeaderFormat()->GetAttrSet().GetItem(SID_ATTR_LRSPACE);
+ const SvxULSpaceItem* pUL = rHeader.GetHeaderFormat()->GetAttrSet().GetItem(SID_ATTR_ULSPACE);
+ if (pLR && pUL)
+ {
+ SvxLongLRSpaceItem aLR(pLR->GetLeft(), pLR->GetRight(), SID_ATTR_PAGE_HEADER_LRMARGIN);
+ rSet.Put(aLR);
+ SvxLongULSpaceItem aUL( pUL->GetUpper(), pUL->GetLower(), SID_ATTR_PAGE_HEADER_SPACING);
+ rSet.Put(aUL);
+ }
+
+ bool bShared = !rDesc.IsHeaderShared();
+ bool bFirst = !rDesc.IsFirstShared(); // FIXME control changes for both header footer - tdf#100287
+ sal_uInt16 nLayout = (static_cast<int>(bShared)<<1) + static_cast<int>(bFirst);
+ SfxInt16Item aLayoutItem(SID_ATTR_PAGE_HEADER_LAYOUT, nLayout);
+ rSet.Put(aLayoutItem);
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_FOOTER:
+ case SID_ATTR_PAGE_FOOTER_LRMARGIN:
+ case SID_ATTR_PAGE_FOOTER_SPACING:
+ case SID_ATTR_PAGE_FOOTER_LAYOUT:
+ {
+ const SwFormatFooter& rFooter = rDesc.GetMaster().GetFooter();
+ bool bFooterOn = rFooter.IsActive();
+ rSet.Put( SfxBoolItem(SID_ATTR_PAGE_FOOTER, bFooterOn ) );
+ if (bFooterOn)
+ {
+ if (const SvxLRSpaceItem* rLR = rFooter.GetFooterFormat()->GetAttrSet().GetItem<SvxLRSpaceItem>(SID_ATTR_LRSPACE))
+ {
+ SvxLongLRSpaceItem aLR(rLR->GetLeft(), rLR->GetRight(), SID_ATTR_PAGE_FOOTER_LRMARGIN);
+ rSet.Put(aLR);
+ }
+ if (const SvxULSpaceItem* rUL = rFooter.GetFooterFormat()->GetAttrSet().GetItem<SvxULSpaceItem>(SID_ATTR_ULSPACE))
+ {
+ SvxLongULSpaceItem aUL( rUL->GetUpper(), rUL->GetLower(), SID_ATTR_PAGE_FOOTER_SPACING);
+ rSet.Put(aUL);
+ }
+ bool bShared = !rDesc.IsFooterShared();
+ bool bFirst = !rDesc.IsFirstShared(); // FIXME control changes for both header footer - tdf#100287
+ sal_uInt16 nLayout = (static_cast<int>(bShared)<<1) + static_cast<int>(bFirst);
+ SfxInt16Item aLayoutItem(SID_ATTR_PAGE_FOOTER_LAYOUT, nLayout);
+ rSet.Put(aLayoutItem);
+ }
+ }
+ break;
+
+ case SID_ATTR_PAGE_COLOR:
+ case SID_ATTR_PAGE_FILLSTYLE:
+ case SID_ATTR_PAGE_GRADIENT:
+ case SID_ATTR_PAGE_HATCH:
+ case SID_ATTR_PAGE_BITMAP:
+ {
+ const SfxItemSet& rMasterSet = rDesc.GetMaster().GetAttrSet();
+ if (const auto pFillStyleItem = rMasterSet.GetItem(XATTR_FILLSTYLE))
+ {
+ drawing::FillStyle eXFS = pFillStyleItem->GetValue();
+ XFillStyleItem aFillStyleItem( eXFS );
+ aFillStyleItem.SetWhich( SID_ATTR_PAGE_FILLSTYLE );
+ rSet.Put(aFillStyleItem);
+
+ switch(eXFS)
+ {
+ case drawing::FillStyle_SOLID:
+ {
+ if (const auto pItem = rMasterSet.GetItem<XFillColorItem>(XATTR_FILLCOLOR, false))
+ {
+ Color aColor = pItem->GetColorValue();
+ XFillColorItem aFillColorItem( OUString(), aColor );
+ aFillColorItem.SetWhich( SID_ATTR_PAGE_COLOR );
+ rSet.Put( aFillColorItem );
+ }
+ break;
+ }
+
+ case drawing::FillStyle_GRADIENT:
+ {
+ const basegfx::BGradient& aBGradient = rMasterSet.GetItem<XFillGradientItem>( XATTR_FILLGRADIENT )->GetGradientValue();
+ XFillGradientItem aFillGradientItem( OUString(), aBGradient, SID_ATTR_PAGE_GRADIENT );
+ rSet.Put( aFillGradientItem );
+ }
+ break;
+
+ case drawing::FillStyle_HATCH:
+ {
+ const XFillHatchItem *pFillHatchItem( rMasterSet.GetItem<XFillHatchItem>( XATTR_FILLHATCH ) );
+ XFillHatchItem aFillHatchItem( pFillHatchItem->GetName(), pFillHatchItem->GetHatchValue());
+ aFillHatchItem.SetWhich( SID_ATTR_PAGE_HATCH );
+ rSet.Put( aFillHatchItem );
+ }
+ break;
+
+ case drawing::FillStyle_BITMAP:
+ {
+ const XFillBitmapItem *pFillBitmapItem = rMasterSet.GetItem<XFillBitmapItem>( XATTR_FILLBITMAP );
+ XFillBitmapItem aFillBitmapItem( pFillBitmapItem->GetName(), pFillBitmapItem->GetGraphicObject() );
+ aFillBitmapItem.SetWhich( SID_ATTR_PAGE_BITMAP );
+ rSet.Put( aFillBitmapItem );
+ }
+ break;
+ case drawing::FillStyle_NONE:
+ {
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+ }
+
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uno/SwXDocumentSettings.cxx b/sw/source/uibase/uno/SwXDocumentSettings.cxx
new file mode 100644
index 0000000000..3e40989828
--- /dev/null
+++ b/sw/source/uibase/uno/SwXDocumentSettings.cxx
@@ -0,0 +1,1709 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+#include <config_fuzzers.h>
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <utility>
+
+#include <o3tl/any.hxx>
+#include "SwXDocumentSettings.hxx"
+#include <comphelper/MasterPropertySetInfo.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/i18n/XForbiddenCharacters.hpp>
+#include <com/sun/star/document/PrinterIndependentLayout.hpp>
+#include <doc.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <docsh.hxx>
+#include <fldupde.hxx>
+#include <linkenum.hxx>
+#include <sfx2/printer.hxx>
+#include <editsh.hxx>
+#include <unotxdoc.hxx>
+#include <cmdid.h>
+#include <unomod.hxx>
+#include <vcl/svapp.hxx>
+#include <svl/asiancfg.hxx>
+#include <tools/stream.hxx>
+
+#include <cfgitems.hxx>
+#include <dbmgr.hxx>
+
+using namespace comphelper;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::i18n;
+
+namespace {
+
+enum SwDocumentSettingsPropertyHandles
+{
+ HANDLE_FORBIDDEN_CHARS,
+ HANDLE_LINK_UPDATE_MODE,
+ HANDLE_FIELD_AUTO_UPDATE,
+ HANDLE_CHART_AUTO_UPDATE,
+ HANDLE_ADD_PARA_TABLE_SPACING,
+ HANDLE_ADD_PARA_TABLE_SPACING_AT_START,
+ HANDLE_ALIGN_TAB_STOP_POSITION,
+ HANDLE_PRINTER_NAME,
+ HANDLE_PRINTER_SETUP,
+ HANDLE_PRINTER_PAPER,
+ HANDLE_IS_KERN_ASIAN_PUNCTUATION,
+ HANDLE_CHARACTER_COMPRESSION_TYPE,
+ HANDLE_APPLY_USER_DATA,
+ HANDLE_SAVE_THUMBNAIL,
+ HANDLE_SAVE_GLOBAL_DOCUMENT_LINKS,
+ HANDLE_CURRENT_DATABASE_DATA_SOURCE,
+ HANDLE_CURRENT_DATABASE_COMMAND,
+ HANDLE_CURRENT_DATABASE_COMMAND_TYPE,
+ HANDLE_EMBEDDED_DATABASE_NAME,
+ HANDLE_SAVE_VERSION_ON_CLOSE,
+ HANDLE_UPDATE_FROM_TEMPLATE,
+ HANDLE_PRINTER_INDEPENDENT_LAYOUT,
+ HANDLE_IS_LABEL_DOC,
+ HANDLE_IS_ADD_FLY_OFFSET,
+ HANDLE_IS_ADD_VERTICAL_FLY_OFFSET,
+ HANDLE_IS_ADD_EXTERNAL_LEADING,
+ HANDLE_OLD_NUMBERING,
+ HANDLE_OUTLINELEVEL_YIELDS_NUMBERING,
+ /* Stampit It disable the print cancel button of the shown progress dialog. */
+ HANDLE_ALLOW_PRINTJOB_CANCEL,
+ HANDLE_USE_FORMER_LINE_SPACING,
+ HANDLE_ADD_PARA_SPACING_TO_TABLE_CELLS,
+ HANDLE_ADD_PARA_LINE_SPACING_TO_TABLE_CELLS,
+ HANDLE_USE_FORMER_OBJECT_POSITIONING,
+ HANDLE_USE_FORMER_TEXT_WRAPPING,
+ HANDLE_CHANGES_PASSWORD,
+ HANDLE_CONSIDER_WRAP_ON_OBJPOS,
+ HANDLE_IGNORE_FIRST_LINE_INDENT_IN_NUMBERING,
+ HANDLE_DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK,
+ HANDLE_DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT,
+ HANDLE_TABLE_ROW_KEEP,
+ HANDLE_IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION,
+ HANDLE_LOAD_READONLY,
+ HANDLE_DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE,
+ HANDLE_CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAMES,
+ HANDLE_UNIX_FORCE_ZERO_EXT_LEADING,
+ HANDLE_USE_OLD_PRINTER_METRICS,
+ HANDLE_PROTECT_FORM,
+ HANDLE_MS_WORD_COMP_TRAILING_BLANKS,
+ HANDLE_MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY,
+ HANDLE_TABS_RELATIVE_TO_INDENT,
+ HANDLE_RSID,
+ HANDLE_RSID_ROOT,
+ HANDLE_TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST,
+ HANDLE_MODIFYPASSWORDINFO,
+ HANDLE_MATH_BASELINE_ALIGNMENT,
+ HANDLE_INVERT_BORDER_SPACING,
+ HANDLE_COLLAPSE_EMPTY_CELL_PARA,
+ HANDLE_SMALL_CAPS_PERCENTAGE_66,
+ HANDLE_TAB_OVERFLOW,
+ HANDLE_UNBREAKABLE_NUMBERINGS,
+ HANDLE_STYLES_NODEFAULT,
+ HANDLE_CLIPPED_PICTURES,
+ HANDLE_BACKGROUND_PARA_OVER_DRAWINGS,
+ HANDLE_EMBED_FONTS,
+ HANDLE_EMBED_USED_FONTS,
+ HANDLE_EMBED_LATIN_SCRIPT_FONTS,
+ HANDLE_EMBED_ASIAN_SCRIPT_FONTS,
+ HANDLE_EMBED_COMPLEX_SCRIPT_FONTS,
+ HANDLE_EMBED_SYSTEM_FONTS,
+ HANDLE_TAB_OVER_MARGIN,
+ HANDLE_TAB_OVER_SPACING,
+ HANDLE_TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK,
+ HANDLE_SURROUND_TEXT_WRAP_SMALL,
+ HANDLE_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING,
+ HANDLE_PROP_LINE_SPACING_SHRINKS_FIRST_LINE,
+ HANDLE_SUBTRACT_FLYS,
+ HANDLE_DISABLE_OFF_PAGE_POSITIONING,
+ HANDLE_EMPTY_DB_FIELD_HIDES_PARA,
+ HANDLE_CONTINUOUS_ENDNOTES,
+ HANDLE_PROTECT_BOOKMARKS,
+ HANDLE_PROTECT_FIELDS,
+ HANDLE_HEADER_SPACING_BELOW_LAST_PARA,
+ HANDLE_FRAME_AUTOWIDTH_WITH_MORE_PARA,
+ HANDLE_GUTTER_AT_TOP,
+ HANDLE_FOOTNOTE_IN_COLUMN_TO_PAGEEND,
+ HANDLE_IMAGE_PREFERRED_DPI,
+ HANDLE_AUTO_FIRST_LINE_INDENT_DISREGARD_LINE_SPACE,
+ HANDLE_HYPHENATE_URLS,
+ HANDLE_DO_NOT_BREAK_WRAPPED_TABLES,
+ HANDLE_ALLOW_TEXT_AFTER_FLOATING_TABLE_BREAK,
+ HANDLE_JUSTIFY_LINES_WITH_SHRINKING,
+ HANDLE_NO_NUMBERING_SHOW_FOLLOWBY,
+ HANDLE_DROP_CAP_PUNCTUATION,
+ HANDLE_USE_VARIABLE_WIDTH_NBSP,
+};
+
+}
+
+static rtl::Reference<MasterPropertySetInfo> lcl_createSettingsInfo()
+{
+ static PropertyInfo const aWriterSettingsInfoMap[] =
+ {
+ { OUString("ForbiddenCharacters"), HANDLE_FORBIDDEN_CHARS, cppu::UnoType<css::i18n::XForbiddenCharacters>::get(), 0},
+ { OUString("LinkUpdateMode"), HANDLE_LINK_UPDATE_MODE, cppu::UnoType<sal_Int16>::get(), 0},
+ { OUString("FieldAutoUpdate"), HANDLE_FIELD_AUTO_UPDATE, cppu::UnoType<bool>::get(), 0},
+ { OUString("ChartAutoUpdate"), HANDLE_CHART_AUTO_UPDATE, cppu::UnoType<bool>::get(), 0},
+ { OUString("AddParaTableSpacing"), HANDLE_ADD_PARA_TABLE_SPACING, cppu::UnoType<bool>::get(), 0},
+ { OUString("AddParaTableSpacingAtStart"), HANDLE_ADD_PARA_TABLE_SPACING_AT_START, cppu::UnoType<bool>::get(), 0},
+ { OUString("AlignTabStopPosition"), HANDLE_ALIGN_TAB_STOP_POSITION, cppu::UnoType<bool>::get(), 0},
+ { OUString("PrinterName"), HANDLE_PRINTER_NAME, cppu::UnoType<OUString>::get(), 0},
+ { OUString("PrinterSetup"), HANDLE_PRINTER_SETUP, cppu::UnoType< cppu::UnoSequenceType<sal_Int8> >::get(), 0},
+ { OUString("PrinterPaperFromSetup"), HANDLE_PRINTER_PAPER, cppu::UnoType<bool>::get(), 0},
+ { OUString("IsKernAsianPunctuation"), HANDLE_IS_KERN_ASIAN_PUNCTUATION, cppu::UnoType<bool>::get(), 0},
+ { OUString("CharacterCompressionType"), HANDLE_CHARACTER_COMPRESSION_TYPE, cppu::UnoType<sal_Int16>::get(), 0},
+ { OUString("ApplyUserData"), HANDLE_APPLY_USER_DATA, cppu::UnoType<bool>::get(), 0 },
+ { OUString("SaveThumbnail"), HANDLE_SAVE_THUMBNAIL, cppu::UnoType<bool>::get(), 0 },
+ { OUString("SaveGlobalDocumentLinks"), HANDLE_SAVE_GLOBAL_DOCUMENT_LINKS, cppu::UnoType<bool>::get(), 0},
+ { OUString("CurrentDatabaseDataSource"), HANDLE_CURRENT_DATABASE_DATA_SOURCE, cppu::UnoType<OUString>::get(), 0},
+ { OUString("CurrentDatabaseCommand"), HANDLE_CURRENT_DATABASE_COMMAND, cppu::UnoType<OUString>::get(), 0},
+ { OUString("CurrentDatabaseCommandType"), HANDLE_CURRENT_DATABASE_COMMAND_TYPE, cppu::UnoType<sal_Int32>::get(), 0},
+ { OUString("EmbeddedDatabaseName"), HANDLE_EMBEDDED_DATABASE_NAME, cppu::UnoType<OUString>::get(), 0},
+ { OUString("SaveVersionOnClose"), HANDLE_SAVE_VERSION_ON_CLOSE, cppu::UnoType<bool>::get(), 0},
+ { OUString("UpdateFromTemplate"), HANDLE_UPDATE_FROM_TEMPLATE, cppu::UnoType<bool>::get(), 0},
+
+ { OUString("PrinterIndependentLayout"), HANDLE_PRINTER_INDEPENDENT_LAYOUT, cppu::UnoType<sal_Int16>::get(), 0},
+ { OUString("IsLabelDocument"), HANDLE_IS_LABEL_DOC, cppu::UnoType<bool>::get(), 0},
+ { OUString("AddFrameOffsets"), HANDLE_IS_ADD_FLY_OFFSET, cppu::UnoType<bool>::get(), 0},
+ { OUString("AddVerticalFrameOffsets"), HANDLE_IS_ADD_VERTICAL_FLY_OFFSET, cppu::UnoType<bool>::get(), 0},
+ { OUString("AddExternalLeading"), HANDLE_IS_ADD_EXTERNAL_LEADING, cppu::UnoType<bool>::get(), 0},
+ { OUString("UseOldNumbering"), HANDLE_OLD_NUMBERING, cppu::UnoType<bool>::get(), 0},
+ { OUString("OutlineLevelYieldsNumbering"), HANDLE_OUTLINELEVEL_YIELDS_NUMBERING, cppu::UnoType<bool>::get(), 0},
+ /* Stampit It disable the print cancel button of the shown progress dialog. */
+ { OUString("AllowPrintJobCancel"), HANDLE_ALLOW_PRINTJOB_CANCEL, cppu::UnoType<bool>::get(), 0},
+ { OUString("UseFormerLineSpacing"), HANDLE_USE_FORMER_LINE_SPACING, cppu::UnoType<bool>::get(), 0},
+ { OUString("AddParaSpacingToTableCells"), HANDLE_ADD_PARA_SPACING_TO_TABLE_CELLS, cppu::UnoType<bool>::get(), 0},
+ { OUString("AddParaLineSpacingToTableCells"), HANDLE_ADD_PARA_LINE_SPACING_TO_TABLE_CELLS, cppu::UnoType<bool>::get(), 0},
+ { OUString("UseFormerObjectPositioning"), HANDLE_USE_FORMER_OBJECT_POSITIONING, cppu::UnoType<bool>::get(), 0},
+ { OUString("UseFormerTextWrapping"), HANDLE_USE_FORMER_TEXT_WRAPPING, cppu::UnoType<bool>::get(), 0},
+ { OUString("RedlineProtectionKey"), HANDLE_CHANGES_PASSWORD, cppu::UnoType< cppu::UnoSequenceType<sal_Int8> >::get(), 0},
+ { OUString("ConsiderTextWrapOnObjPos"), HANDLE_CONSIDER_WRAP_ON_OBJPOS, cppu::UnoType<bool>::get(), 0},
+ { OUString("IgnoreFirstLineIndentInNumbering"), HANDLE_IGNORE_FIRST_LINE_INDENT_IN_NUMBERING, cppu::UnoType<bool>::get(), 0},
+ { OUString("DoNotJustifyLinesWithManualBreak"), HANDLE_DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK, cppu::UnoType<bool>::get(), 0},
+ { OUString("DoNotResetParaAttrsForNumFont"), HANDLE_DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT, cppu::UnoType<bool>::get(), 0},
+ { OUString("TableRowKeep"), HANDLE_TABLE_ROW_KEEP, cppu::UnoType<bool>::get(), 0},
+ { OUString("IgnoreTabsAndBlanksForLineCalculation"), HANDLE_IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION, cppu::UnoType<bool>::get(), 0},
+ { OUString("LoadReadonly"), HANDLE_LOAD_READONLY, cppu::UnoType<bool>::get(), 0},
+ { OUString("DoNotCaptureDrawObjsOnPage"), HANDLE_DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE, cppu::UnoType<bool>::get(), 0},
+ { OUString("ClipAsCharacterAnchoredWriterFlyFrames"), HANDLE_CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAMES, cppu::UnoType<bool>::get(), 0},
+ { OUString("UnxForceZeroExtLeading"), HANDLE_UNIX_FORCE_ZERO_EXT_LEADING, cppu::UnoType<bool>::get(), 0},
+ { OUString("UseOldPrinterMetrics"), HANDLE_USE_OLD_PRINTER_METRICS, cppu::UnoType<bool>::get(), 0},
+ { OUString("TabsRelativeToIndent"), HANDLE_TABS_RELATIVE_TO_INDENT, cppu::UnoType<bool>::get(), 0},
+ { OUString("Rsid"), HANDLE_RSID, cppu::UnoType<sal_Int32>::get(), 0},
+ { OUString("RsidRoot"), HANDLE_RSID_ROOT, cppu::UnoType<sal_Int32>::get(), 0},
+ { OUString("ProtectForm"), HANDLE_PROTECT_FORM, cppu::UnoType<bool>::get(), 0},
+ { OUString("MsWordCompTrailingBlanks"), HANDLE_MS_WORD_COMP_TRAILING_BLANKS, cppu::UnoType<bool>::get(), 0 },
+ { OUString("MsWordCompMinLineHeightByFly"), HANDLE_MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY, cppu::UnoType<bool>::get(), 0 },
+ { OUString("TabAtLeftIndentForParagraphsInList"), HANDLE_TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST, cppu::UnoType<bool>::get(), 0},
+ { OUString("ModifyPasswordInfo"), HANDLE_MODIFYPASSWORDINFO, cppu::UnoType< cppu::UnoSequenceType<css::beans::PropertyValue> >::get(), 0},
+ { OUString("MathBaselineAlignment"), HANDLE_MATH_BASELINE_ALIGNMENT, cppu::UnoType<bool>::get(), 0},
+ { OUString("InvertBorderSpacing"), HANDLE_INVERT_BORDER_SPACING, cppu::UnoType<bool>::get(), 0},
+ { OUString("CollapseEmptyCellPara"), HANDLE_COLLAPSE_EMPTY_CELL_PARA, cppu::UnoType<bool>::get(), 0},
+ { OUString("SmallCapsPercentage66"), HANDLE_SMALL_CAPS_PERCENTAGE_66, cppu::UnoType<bool>::get(), 0},
+ { OUString("TabOverflow"), HANDLE_TAB_OVERFLOW, cppu::UnoType<bool>::get(), 0},
+ { OUString("UnbreakableNumberings"), HANDLE_UNBREAKABLE_NUMBERINGS, cppu::UnoType<bool>::get(), 0},
+ { OUString("StylesNoDefault"), HANDLE_STYLES_NODEFAULT, cppu::UnoType<bool>::get(), 0},
+ { OUString("ClippedPictures"), HANDLE_CLIPPED_PICTURES, cppu::UnoType<bool>::get(), 0},
+ { OUString("BackgroundParaOverDrawings"), HANDLE_BACKGROUND_PARA_OVER_DRAWINGS, cppu::UnoType<bool>::get(), 0},
+ { OUString("EmbedFonts"), HANDLE_EMBED_FONTS, cppu::UnoType<bool>::get(), 0},
+ { OUString("EmbedOnlyUsedFonts"), HANDLE_EMBED_USED_FONTS, cppu::UnoType<bool>::get(), 0},
+ { OUString("EmbedLatinScriptFonts"), HANDLE_EMBED_LATIN_SCRIPT_FONTS, cppu::UnoType<bool>::get(), 0},
+ { OUString("EmbedAsianScriptFonts"), HANDLE_EMBED_ASIAN_SCRIPT_FONTS, cppu::UnoType<bool>::get(), 0},
+ { OUString("EmbedComplexScriptFonts"), HANDLE_EMBED_COMPLEX_SCRIPT_FONTS, cppu::UnoType<bool>::get(), 0},
+ { OUString("EmbedSystemFonts"), HANDLE_EMBED_SYSTEM_FONTS, cppu::UnoType<bool>::get(), 0},
+ { OUString("TabOverMargin"), HANDLE_TAB_OVER_MARGIN, cppu::UnoType<bool>::get(), 0},
+ { OUString("TabOverSpacing"), HANDLE_TAB_OVER_SPACING, cppu::UnoType<bool>::get(), 0},
+ { OUString("TreatSingleColumnBreakAsPageBreak"), HANDLE_TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK, cppu::UnoType<bool>::get(), 0},
+ { OUString("SurroundTextWrapSmall"), HANDLE_SURROUND_TEXT_WRAP_SMALL, cppu::UnoType<bool>::get(), 0},
+ { OUString("ApplyParagraphMarkFormatToNumbering"), HANDLE_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING, cppu::UnoType<bool>::get(), 0},
+ { OUString("PropLineSpacingShrinksFirstLine"), HANDLE_PROP_LINE_SPACING_SHRINKS_FIRST_LINE, cppu::UnoType<bool>::get(), 0},
+ { OUString("SubtractFlysAnchoredAtFlys"), HANDLE_SUBTRACT_FLYS, cppu::UnoType<bool>::get(), 0},
+ { OUString("DisableOffPagePositioning"), HANDLE_DISABLE_OFF_PAGE_POSITIONING, cppu::UnoType<bool>::get(), 0},
+ { OUString("EmptyDbFieldHidesPara"), HANDLE_EMPTY_DB_FIELD_HIDES_PARA, cppu::UnoType<bool>::get(), 0 },
+ { OUString("ContinuousEndnotes"), HANDLE_CONTINUOUS_ENDNOTES, cppu::UnoType<bool>::get(), 0 },
+ { OUString("ProtectBookmarks"), HANDLE_PROTECT_BOOKMARKS, cppu::UnoType<bool>::get(), 0 },
+ { OUString("ProtectFields"), HANDLE_PROTECT_FIELDS, cppu::UnoType<bool>::get(), 0 },
+ { OUString("HeaderSpacingBelowLastPara"), HANDLE_HEADER_SPACING_BELOW_LAST_PARA, cppu::UnoType<bool>::get(), 0 },
+ { OUString("FrameAutowidthWithMorePara"), HANDLE_FRAME_AUTOWIDTH_WITH_MORE_PARA, cppu::UnoType<bool>::get(), 0 },
+ { OUString("GutterAtTop"), HANDLE_GUTTER_AT_TOP, cppu::UnoType<bool>::get(), 0 },
+ { OUString("FootnoteInColumnToPageEnd"), HANDLE_FOOTNOTE_IN_COLUMN_TO_PAGEEND, cppu::UnoType<bool>::get(), 0 },
+ { OUString("ImagePreferredDPI"), HANDLE_IMAGE_PREFERRED_DPI, cppu::UnoType<sal_Int32>::get(), 0 },
+ { OUString("AutoFirstLineIndentDisregardLineSpace"), HANDLE_AUTO_FIRST_LINE_INDENT_DISREGARD_LINE_SPACE, cppu::UnoType<bool>::get(), 0 },
+ { OUString("HyphenateURLs"), HANDLE_HYPHENATE_URLS, cppu::UnoType<bool>::get(), 0 },
+ { OUString("DoNotBreakWrappedTables"), HANDLE_DO_NOT_BREAK_WRAPPED_TABLES, cppu::UnoType<bool>::get(), 0 },
+ { OUString("AllowTextAfterFloatingTableBreak"), HANDLE_ALLOW_TEXT_AFTER_FLOATING_TABLE_BREAK, cppu::UnoType<bool>::get(), 0 },
+ { OUString("JustifyLinesWithShrinking"), HANDLE_JUSTIFY_LINES_WITH_SHRINKING, cppu::UnoType<bool>::get(), 0 },
+ { OUString("NoNumberingShowFollowBy"), HANDLE_NO_NUMBERING_SHOW_FOLLOWBY, cppu::UnoType<bool>::get(), 0 },
+ { OUString("DropCapPunctuation"), HANDLE_DROP_CAP_PUNCTUATION, cppu::UnoType<bool>::get(), 0 },
+ { OUString("UseVariableWidthNBSP"), HANDLE_USE_VARIABLE_WIDTH_NBSP, cppu::UnoType<bool>::get(), 0 },
+
+/*
+ * As OS said, we don't have a view when we need to set this, so I have to
+ * find another solution before adding them to this property set - MTG
+ { OUString("IsGridVisible"), HANDLE_IS_GRID_VISIBLE, cppu::UnoType<bool>::get(), 0, 0},
+ { OUString("IsSnapToGrid"), HANDLE_IS_SNAP_TO_GRID, cppu::UnoType<bool>::get(), 0, 0},
+ { OUString("IsSynchroniseAxes"), HANDLE_IS_SYNCHRONISE_AXES, cppu::UnoType<bool>::get(), 0, 0},
+ { OUString("HorizontalGridResolution"), HANDLE_HORIZONTAL_GRID_RESOLUTION, cppu::UnoType<sal_Int32>::get(), 0, 0},
+ { OUString("HorizontalGridSubdivision"), HANDLE_HORIZONTAL_GRID_SUBDIVISION, cppu::UnoType<sal_Int16>::get(), 0, 0},
+ { OUString("VerticalGridResolution"), HANDLE_VERTICAL_GRID_RESOLUTION, cppu::UnoType<sal_Int32>::get(), 0, 0},
+ { OUString("VerticalGridSubdivision"), HANDLE_VERTICAL_GRID_SUBDIVISION, cppu::UnoType<sal_Int16>::get(), 0, 0},
+
+ { OUString("ShowParagraphEnd"), HANDLE_SHOW_PARAGRAPH_END, cppu::UnoType<bool>::get(), 0, 0},
+ { OUString("ShowOptionalHyphens"), HANDLE_SHOW_OPTIONAL_HYPHENS, cppu::UnoType<bool>::get(), 0, 0},
+ { OUString("ShowSpaces"), HANDLE_SHOW_SPACES, cppu::UnoType<bool>::get(), 0, 0},
+ { OUString("ShowTabs"), HANDLE_SHOW_TABS, cppu::UnoType<bool>::get(), 0, 0},
+ { OUString("ShowBreaks"), HANDLE_SHOW_BREAKS, cppu::UnoType<bool>::get(), 0, 0},
+ { OUString("ShowHiddenText"), HANDLE_SHOW_HIDDEN_TEXT, cppu::UnoType<bool>::get(), 0, 0},
+ { OUString("ShowHiddenParagraphs"), HANDLE_SHOW_HIDDEN_PARAGRAPHS, cppu::UnoType<bool>::get(), 0, 0},
+
+ { OUString("ShowTextLimitGuide"), HANDLE_SHOW_TEXT_LIMIT_GUIDE, cppu::UnoType<bool>::get(), 0, 0},
+ { OUString("ShowTableLimitGuide"), HANDLE_SHOW_TABLE_LIMIT_GUIDE, cppu::UnoType<bool>::get(), 0, 0},
+ { OUString("ShowSectionLimitGuide"), HANDLE_SHOW_SECTION_LIMIT_GUIDE, cppu::UnoType<bool>::get(), 0, 0},
+ { OUString("ShowGuidesWhileMoving"), HANDLE_SHOW_GUIDES_WHILE_MOVING, cppu::UnoType<bool>::get(), 0, 0},
+*/
+ { OUString(), 0, css::uno::Type(), 0}
+ };
+ return new MasterPropertySetInfo ( aWriterSettingsInfoMap );
+}
+
+SwXDocumentSettings::SwXDocumentSettings ( SwXTextDocument * pModel )
+: MasterPropertySet ( lcl_createSettingsInfo().get(),
+ &Application::GetSolarMutex () )
+, mpModel ( pModel )
+, mpDocSh ( nullptr )
+, mpDoc ( nullptr )
+, mpPrinter( nullptr )
+, mbPreferPrinterPapersize( false )
+{
+ registerSlave ( new SwXPrintSettings ( SwXPrintSettingsType::Document, mpModel->GetDocShell()->GetDoc() ) );
+}
+
+SwXDocumentSettings::~SwXDocumentSettings()
+ noexcept
+{
+}
+
+Any SAL_CALL SwXDocumentSettings::queryInterface( const Type& rType )
+{
+ return ::cppu::queryInterface(rType,
+ // OWeakObject interfaces
+ static_cast<XInterface*>(static_cast<OWeakObject*>(this)),
+ static_cast<XWeak*>(this),
+ // my own interfaces
+ static_cast<XPropertySet*>(this),
+ static_cast<XPropertyState*>(this),
+ static_cast<XMultiPropertySet*>(this),
+ static_cast<XServiceInfo*>(this),
+ static_cast<XTypeProvider*>(this));
+}
+void SwXDocumentSettings::acquire ()
+ noexcept
+{
+ OWeakObject::acquire();
+}
+void SwXDocumentSettings::release ()
+ noexcept
+{
+ OWeakObject::release();
+}
+
+uno::Sequence< uno::Type > SAL_CALL SwXDocumentSettings::getTypes( )
+{
+ static const uno::Sequence< uno::Type > aTypes {
+ // from MasterPropertySet
+ cppu::UnoType<XPropertySet>::get(),
+ cppu::UnoType<XPropertyState>::get(),
+ cppu::UnoType<XMultiPropertySet>::get(),
+ cppu::UnoType<XServiceInfo>::get(),
+ cppu::UnoType<XTypeProvider>::get(),
+ };
+ return aTypes;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SwXDocumentSettings::getImplementationId( )
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+void SwXDocumentSettings::_preSetValues ()
+{
+ mpDocSh = mpModel->GetDocShell();
+ if (nullptr == mpDocSh)
+ throw UnknownPropertyException();
+
+ mpDoc = mpDocSh->GetDoc();
+ if (nullptr == mpDoc)
+ throw UnknownPropertyException();
+}
+
+void SwXDocumentSettings::_setSingleValue( const comphelper::PropertyInfo & rInfo, const uno::Any &rValue )
+{
+ if (rInfo.mnAttributes & PropertyAttribute::READONLY)
+ throw PropertyVetoException ("Property is read-only: " + rInfo.maName);
+
+ switch( rInfo.mnHandle )
+ {
+ case HANDLE_FORBIDDEN_CHARS:
+ break;
+ case HANDLE_LINK_UPDATE_MODE:
+ {
+ sal_Int16 nMode = 0;
+ rValue >>= nMode;
+ switch (nMode)
+ {
+ case NEVER:
+ case MANUAL:
+ case AUTOMATIC:
+ case GLOBALSETTING:
+ break;
+ default:
+ throw IllegalArgumentException();
+ }
+ mpDoc->getIDocumentSettingAccess().setLinkUpdateMode(nMode);
+ }
+ break;
+ case HANDLE_FIELD_AUTO_UPDATE:
+ {
+ bool bUpdateField = *o3tl::doAccess<bool>(rValue);
+ SwFieldUpdateFlags nFlag = mpDoc->getIDocumentSettingAccess().getFieldUpdateFlags(true);
+ mpDoc->getIDocumentSettingAccess().setFieldUpdateFlags( bUpdateField ?
+ nFlag == AUTOUPD_FIELD_AND_CHARTS ?
+ AUTOUPD_FIELD_AND_CHARTS :
+ AUTOUPD_FIELD_ONLY :
+ AUTOUPD_OFF );
+ }
+ break;
+ case HANDLE_CHART_AUTO_UPDATE:
+ {
+ bool bUpdateChart = *o3tl::doAccess<bool>(rValue);
+ SwFieldUpdateFlags nFlag = mpDoc->getIDocumentSettingAccess().getFieldUpdateFlags(true);
+ mpDoc->getIDocumentSettingAccess().setFieldUpdateFlags( (nFlag == AUTOUPD_FIELD_ONLY || nFlag == AUTOUPD_FIELD_AND_CHARTS ) ?
+ bUpdateChart ?
+ AUTOUPD_FIELD_AND_CHARTS :
+ AUTOUPD_FIELD_ONLY :
+ AUTOUPD_OFF );
+ }
+ break;
+ case HANDLE_ADD_PARA_TABLE_SPACING:
+ {
+ bool bParaSpace = false;
+ rValue >>= bParaSpace;
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::PARA_SPACE_MAX, bParaSpace );
+ }
+ break;
+ case HANDLE_ADD_PARA_TABLE_SPACING_AT_START:
+ {
+ bool bParaSpacePage = false;
+ rValue >>= bParaSpacePage;
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::PARA_SPACE_MAX_AT_PAGES, bParaSpacePage );
+ }
+ break;
+ case HANDLE_ALIGN_TAB_STOP_POSITION:
+ {
+ bool bAlignTab = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TAB_COMPAT, bAlignTab);
+ }
+ break;
+ case HANDLE_PRINTER_NAME:
+ {
+ //the printer must be created
+ OUString sPrinterName;
+ if( !(rValue >>= sPrinterName) )
+ throw IllegalArgumentException();
+
+ if( !mpPrinter && !sPrinterName.isEmpty() && mpDocSh->GetCreateMode() != SfxObjectCreateMode::EMBEDDED )
+ {
+ SfxPrinter* pPrinter = mpDoc->getIDocumentDeviceAccess().getPrinter( true );
+ if ( pPrinter->GetName() != sPrinterName )
+ {
+ VclPtrInstance<SfxPrinter> pNewPrinter( pPrinter->GetOptions().Clone(), sPrinterName );
+ assert (! pNewPrinter->isDisposed() );
+ if( pNewPrinter->IsKnown() )
+ {
+ // set printer only once; in _postSetValues
+ mpPrinter = pNewPrinter;
+ }
+ else
+ {
+ pNewPrinter.disposeAndClear();
+ }
+ }
+ }
+
+ }
+ break;
+ case HANDLE_PRINTER_SETUP:
+ {
+ Sequence < sal_Int8 > aSequence;
+ if ( !(rValue >>= aSequence) )
+ throw IllegalArgumentException();
+
+ sal_uInt32 nSize = aSequence.getLength();
+ if( nSize > 0 )
+ {
+ SvMemoryStream aStream (aSequence.getArray(), nSize,
+ StreamMode::READ );
+ aStream.Seek ( STREAM_SEEK_TO_BEGIN );
+ auto pItemSet = std::make_unique<SfxItemSetFixed<
+ SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
+ SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
+ SID_HTML_MODE, SID_HTML_MODE,
+ FN_PARAM_ADDPRINTER, FN_PARAM_ADDPRINTER>>( mpDoc->GetAttrPool() );
+ VclPtr<SfxPrinter> pPrinter = SfxPrinter::Create ( aStream, std::move(pItemSet) );
+ assert (! pPrinter->isDisposed() );
+ // set printer only once; in _postSetValues
+ mpPrinter.disposeAndClear();
+ mpPrinter = pPrinter;
+ }
+
+ }
+ break;
+ case HANDLE_PRINTER_PAPER:
+ {
+ bool bPreferPrinterPapersize = {}; // spurious -Werror=maybe-uninitialized
+ if(!(rValue >>= bPreferPrinterPapersize))
+ throw IllegalArgumentException();
+ mbPreferPrinterPapersize = bPreferPrinterPapersize;
+ }
+ break;
+ case HANDLE_IS_KERN_ASIAN_PUNCTUATION:
+ {
+ bool bIsKern = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::KERN_ASIAN_PUNCTUATION, bIsKern);
+ if (SwEditShell* pEditSh = mpDoc->GetEditShell())
+ pEditSh->ChgHyphenation();
+ }
+ break;
+ case HANDLE_CHARACTER_COMPRESSION_TYPE:
+ {
+ sal_Int16 nMode = 0;
+ rValue >>= nMode;
+ switch (static_cast<CharCompressType>(nMode))
+ {
+ case CharCompressType::NONE:
+ case CharCompressType::PunctuationOnly:
+ case CharCompressType::PunctuationAndKana:
+ break;
+ default:
+ throw IllegalArgumentException();
+ }
+ mpDoc->getIDocumentSettingAccess().setCharacterCompressionType(static_cast<CharCompressType>(nMode));
+ }
+ break;
+ case HANDLE_APPLY_USER_DATA:
+ {
+ mpDocSh->SetUseUserData(*o3tl::doAccess<bool>(rValue));
+ }
+ break;
+ case HANDLE_SAVE_THUMBNAIL:
+ {
+ mpDocSh->SetUseThumbnailSave(*o3tl::doAccess<bool>(rValue));
+ }
+ break;
+ case HANDLE_SAVE_GLOBAL_DOCUMENT_LINKS:
+ {
+ bool bSaveGlobal = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::GLOBAL_DOCUMENT_SAVE_LINKS, bSaveGlobal );
+ }
+ break;
+ case HANDLE_CURRENT_DATABASE_DATA_SOURCE:
+ {
+ SwDBData aData = mpDoc->GetDBData();
+ if ( rValue >>= aData.sDataSource )
+ mpDoc->ChgDBData( aData );
+ }
+ break;
+ case HANDLE_CURRENT_DATABASE_COMMAND:
+ {
+ SwDBData aData = mpDoc->GetDBData();
+
+ if ( rValue >>= aData.sCommand )
+ mpDoc->ChgDBData( aData );
+
+ SAL_WARN_IF( aData.sDataSource.isEmpty() && !aData.sCommand.isEmpty(), "sw.uno",
+ "\"CurrentDatabaseCommand\" property possibly set before \"CurrentDatabaseDataSource\"" );
+ }
+ break;
+ case HANDLE_CURRENT_DATABASE_COMMAND_TYPE:
+ {
+ SwDBData aData = mpDoc->GetDBData();
+ if ( rValue >>= aData.nCommandType )
+ mpDoc->ChgDBData( aData );
+ SAL_WARN_IF( aData.nCommandType && aData.sDataSource.isEmpty(), "sw.uno",
+ "\"CurrentDatabaseCommandType\" property possibly set before \"CurrentDatabaseDataSource\"" );
+ SAL_WARN_IF( aData.nCommandType && aData.sCommand.isEmpty(), "sw.uno",
+ "\"CurrentDatabaseCommandType\" property possibly set before \"CurrentDatabaseCommand\"" );
+ }
+ break;
+ case HANDLE_EMBEDDED_DATABASE_NAME:
+ {
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+ OUString sEmbeddedName;
+ if (rValue >>= sEmbeddedName)
+ mpDoc->GetDBManager()->setEmbeddedName(sEmbeddedName, *mpDocSh);
+#endif
+ }
+ break;
+ case HANDLE_SAVE_VERSION_ON_CLOSE:
+ {
+ mpDocSh->SetSaveVersionOnClose( *o3tl::doAccess<bool>(rValue) );
+ }
+ break;
+ case HANDLE_UPDATE_FROM_TEMPLATE:
+ {
+ mpDocSh->SetQueryLoadTemplate( *o3tl::doAccess<bool>(rValue) );
+ }
+ break;
+ case HANDLE_PRINTER_INDEPENDENT_LAYOUT:
+ {
+ sal_Int16 nTmp = 0;
+ rValue >>= nTmp;
+
+ bool bUseVirDev = true;
+ bool bHiResVirDev = true;
+ if( nTmp == document::PrinterIndependentLayout::DISABLED )
+ bUseVirDev = false;
+ else if ( nTmp == document::PrinterIndependentLayout::LOW_RESOLUTION )
+ bHiResVirDev = false;
+ else if ( nTmp != document::PrinterIndependentLayout::HIGH_RESOLUTION )
+ throw IllegalArgumentException();
+
+ mpDoc->getIDocumentDeviceAccess().setReferenceDeviceType( bUseVirDev, bHiResVirDev );
+ }
+ break;
+ case HANDLE_IS_LABEL_DOC :
+ {
+ bool bSet = false;
+ if(!(rValue >>= bSet))
+ throw IllegalArgumentException();
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::LABEL_DOCUMENT, bSet);
+ }
+ break;
+ case HANDLE_IS_ADD_FLY_OFFSET:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::ADD_FLY_OFFSETS, bTmp);
+ }
+ break;
+ case HANDLE_IS_ADD_VERTICAL_FLY_OFFSET:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS, bTmp);
+ }
+ break;
+ case HANDLE_IS_ADD_EXTERNAL_LEADING:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::ADD_EXT_LEADING, bTmp);
+ }
+ break;
+ case HANDLE_OLD_NUMBERING:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::OLD_NUMBERING, bTmp);
+ }
+ break;
+ case HANDLE_OUTLINELEVEL_YIELDS_NUMBERING:
+ {
+ // ignore - this is a dead property
+ }
+ break;
+ case HANDLE_ALLOW_PRINTJOB_CANCEL:
+ {
+ bool bState = false;
+ if (!(rValue >>= bState))
+ throw IllegalArgumentException();
+ mpDocSh->Stamp_SetPrintCancelState(bState);
+ }
+ break;
+ case HANDLE_USE_FORMER_LINE_SPACING:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::OLD_LINE_SPACING, bTmp);
+ }
+ break;
+ case HANDLE_ADD_PARA_SPACING_TO_TABLE_CELLS:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::ADD_PARA_SPACING_TO_TABLE_CELLS, bTmp);
+ }
+ break;
+ case HANDLE_ADD_PARA_LINE_SPACING_TO_TABLE_CELLS:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::ADD_PARA_LINE_SPACING_TO_TABLE_CELLS, bTmp);
+ }
+ break;
+ case HANDLE_USE_FORMER_OBJECT_POSITIONING:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::USE_FORMER_OBJECT_POS, bTmp);
+ }
+ break;
+ case HANDLE_USE_FORMER_TEXT_WRAPPING:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::USE_FORMER_TEXT_WRAPPING, bTmp);
+ }
+ break;
+ case HANDLE_CHANGES_PASSWORD:
+ {
+ Sequence <sal_Int8> aNew;
+ if(rValue >>= aNew)
+ {
+ mpDoc->getIDocumentRedlineAccess().SetRedlinePassword(aNew);
+ if(aNew.hasElements())
+ {
+ RedlineFlags eMode = mpDoc->getIDocumentRedlineAccess().GetRedlineFlags();
+ eMode |= RedlineFlags::On;
+ mpDoc->getIDocumentRedlineAccess().SetRedlineFlags( eMode );
+ }
+ }
+ }
+ break;
+ case HANDLE_CONSIDER_WRAP_ON_OBJPOS:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION, bTmp );
+ }
+ break;
+ case HANDLE_IGNORE_FIRST_LINE_INDENT_IN_NUMBERING:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING, bTmp);
+ }
+ break;
+ case HANDLE_DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK, bTmp);
+ }
+ break;
+ case HANDLE_DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT, bTmp);
+ }
+ break;
+ case HANDLE_TABLE_ROW_KEEP:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TABLE_ROW_KEEP, bTmp);
+ }
+ break;
+ case HANDLE_IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION, bTmp);
+ }
+ break;
+ case HANDLE_LOAD_READONLY:
+ {
+ mpDocSh->SetLoadReadonly( *o3tl::doAccess<bool>(rValue) );
+ }
+ break;
+ case HANDLE_DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE, bTmp);
+ }
+ break;
+ case HANDLE_CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAMES:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAME, bTmp);
+ }
+ break;
+ case HANDLE_UNIX_FORCE_ZERO_EXT_LEADING:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::UNIX_FORCE_ZERO_EXT_LEADING, bTmp);
+ }
+ break;
+ case HANDLE_USE_OLD_PRINTER_METRICS:
+ // ignore - this is a dead property
+ break;
+ case HANDLE_TABS_RELATIVE_TO_INDENT:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TABS_RELATIVE_TO_INDENT, bTmp);
+ }
+ break;
+ case HANDLE_RSID:
+ {
+ sal_uInt32 nTmp = 0;
+ rValue >>= nTmp;
+ mpDoc->setRsid( nTmp );
+ }
+ break;
+ case HANDLE_RSID_ROOT:
+ {
+ sal_uInt32 nTmp = 0;
+ rValue >>= nTmp;
+ mpDoc->setRsidRoot( nTmp );
+ }
+ break;
+ case HANDLE_PROTECT_FORM:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::PROTECT_FORM, bTmp);
+ }
+ break;
+ case HANDLE_MS_WORD_COMP_TRAILING_BLANKS:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS, bTmp);
+ }
+ break;
+ case HANDLE_MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY, bTmp);
+ }
+ break;
+ case HANDLE_TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST, bTmp);
+ }
+ break;
+ case HANDLE_MODIFYPASSWORDINFO:
+ {
+ uno::Sequence< beans::PropertyValue > aInfo;
+ if ( !( rValue >>= aInfo ) )
+ throw lang::IllegalArgumentException(
+ "Value of type Sequence<PropertyValue> expected!",
+ uno::Reference< uno::XInterface >(),
+ 2 );
+
+ if ( !mpDocSh->SetModifyPasswordInfo( aInfo ) )
+ throw beans::PropertyVetoException(
+ "The hash is not allowed to be changed now!",
+ uno::Reference< uno::XInterface >() );
+ }
+ break;
+ case HANDLE_MATH_BASELINE_ALIGNMENT:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set( DocumentSettingId::MATH_BASELINE_ALIGNMENT, bTmp );
+ }
+ break;
+ case HANDLE_INVERT_BORDER_SPACING:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::INVERT_BORDER_SPACING, bTmp);
+ }
+ break;
+ case HANDLE_COLLAPSE_EMPTY_CELL_PARA:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::COLLAPSE_EMPTY_CELL_PARA, bTmp);
+ }
+ break;
+ case HANDLE_SMALL_CAPS_PERCENTAGE_66:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::SMALL_CAPS_PERCENTAGE_66, bTmp);
+ }
+ break;
+ case HANDLE_TAB_OVERFLOW:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TAB_OVERFLOW, bTmp);
+ }
+ break;
+ case HANDLE_UNBREAKABLE_NUMBERINGS:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::UNBREAKABLE_NUMBERINGS, bTmp);
+ }
+ break;
+ case HANDLE_STYLES_NODEFAULT:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::STYLES_NODEFAULT, bTmp);
+ }
+ break;
+ case HANDLE_CLIPPED_PICTURES:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::CLIPPED_PICTURES, bTmp);
+ }
+ break;
+ case HANDLE_BACKGROUND_PARA_OVER_DRAWINGS:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::BACKGROUND_PARA_OVER_DRAWINGS, bTmp);
+ }
+ break;
+ case HANDLE_EMBED_FONTS:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_FONTS, bTmp);
+ }
+ break;
+ case HANDLE_EMBED_USED_FONTS:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_USED_FONTS, bTmp);
+ }
+ break;
+ case HANDLE_EMBED_LATIN_SCRIPT_FONTS:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_LATIN_SCRIPT_FONTS, bTmp);
+ }
+ break;
+ case HANDLE_EMBED_ASIAN_SCRIPT_FONTS:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_ASIAN_SCRIPT_FONTS, bTmp);
+ }
+ break;
+ case HANDLE_EMBED_COMPLEX_SCRIPT_FONTS:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_COMPLEX_SCRIPT_FONTS, bTmp);
+ }
+ break;
+ case HANDLE_EMBED_SYSTEM_FONTS:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_SYSTEM_FONTS, bTmp);
+ }
+ break;
+ case HANDLE_TAB_OVER_MARGIN:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TAB_OVER_MARGIN, bTmp);
+ }
+ break;
+ case HANDLE_TAB_OVER_SPACING:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TAB_OVER_SPACING, bTmp);
+ }
+ break;
+ case HANDLE_TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK, bTmp);
+ }
+ break;
+ case HANDLE_SURROUND_TEXT_WRAP_SMALL:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::SURROUND_TEXT_WRAP_SMALL, bTmp);
+ }
+ break;
+ case HANDLE_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING:
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue);
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING, bTmp);
+ }
+ break;
+ case HANDLE_PROP_LINE_SPACING_SHRINKS_FIRST_LINE:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ {
+ mpDoc->getIDocumentSettingAccess().set(
+ DocumentSettingId::PROP_LINE_SPACING_SHRINKS_FIRST_LINE, bTmp);
+ }
+ }
+ break;
+ case HANDLE_SUBTRACT_FLYS:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ {
+ mpDoc->getIDocumentSettingAccess().set(
+ DocumentSettingId::SUBTRACT_FLYS, bTmp);
+ }
+ }
+ break;
+ case HANDLE_DISABLE_OFF_PAGE_POSITIONING:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ {
+ mpDoc->getIDocumentSettingAccess().set(
+ DocumentSettingId::DISABLE_OFF_PAGE_POSITIONING, bTmp);
+ }
+ }
+ break;
+ case HANDLE_EMPTY_DB_FIELD_HIDES_PARA:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ {
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA,
+ bTmp);
+ }
+ }
+ break;
+ case HANDLE_CONTINUOUS_ENDNOTES:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ {
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::CONTINUOUS_ENDNOTES,
+ bTmp);
+ }
+ }
+ break;
+ case HANDLE_PROTECT_BOOKMARKS:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ {
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::PROTECT_BOOKMARKS,
+ bTmp);
+ }
+ }
+ break;
+ case HANDLE_PROTECT_FIELDS:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ {
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::PROTECT_FIELDS,
+ bTmp);
+ }
+ }
+ break;
+ case HANDLE_HEADER_SPACING_BELOW_LAST_PARA:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ {
+ mpDoc->getIDocumentSettingAccess().set(
+ DocumentSettingId::HEADER_SPACING_BELOW_LAST_PARA, bTmp);
+ }
+ }
+ break;
+ case HANDLE_FRAME_AUTOWIDTH_WITH_MORE_PARA:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ {
+ mpDoc->getIDocumentSettingAccess().set(
+ DocumentSettingId::FRAME_AUTOWIDTH_WITH_MORE_PARA, bTmp);
+ }
+ }
+ break;
+ case HANDLE_GUTTER_AT_TOP:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ {
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::GUTTER_AT_TOP, bTmp);
+ }
+ }
+ break;
+ case HANDLE_FOOTNOTE_IN_COLUMN_TO_PAGEEND:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ {
+ mpDoc->getIDocumentSettingAccess().set(
+ DocumentSettingId::FOOTNOTE_IN_COLUMN_TO_PAGEEND, bTmp);
+ }
+ }
+ break;
+ case HANDLE_IMAGE_PREFERRED_DPI:
+ {
+ sal_uInt32 nValue = 0;
+ if (rValue >>= nValue)
+ {
+ mpDoc->getIDocumentSettingAccess().setImagePreferredDPI(nValue);
+ }
+ }
+ break;
+ case HANDLE_AUTO_FIRST_LINE_INDENT_DISREGARD_LINE_SPACE:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ {
+ mpDoc->getIDocumentSettingAccess().set(
+ DocumentSettingId::AUTO_FIRST_LINE_INDENT_DISREGARD_LINE_SPACE, bTmp);
+ }
+ }
+ break;
+ case HANDLE_HYPHENATE_URLS:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ {
+ mpDoc->getIDocumentSettingAccess().set(
+ DocumentSettingId::HYPHENATE_URLS, bTmp);
+ }
+ }
+ break;
+ case HANDLE_DO_NOT_BREAK_WRAPPED_TABLES:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ {
+ mpDoc->getIDocumentSettingAccess().set(
+ DocumentSettingId::DO_NOT_BREAK_WRAPPED_TABLES, bTmp);
+ }
+ }
+ break;
+ case HANDLE_ALLOW_TEXT_AFTER_FLOATING_TABLE_BREAK:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ {
+ mpDoc->getIDocumentSettingAccess().set(
+ DocumentSettingId::ALLOW_TEXT_AFTER_FLOATING_TABLE_BREAK, bTmp);
+ }
+ }
+ break;
+ case HANDLE_JUSTIFY_LINES_WITH_SHRINKING:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ {
+ mpDoc->getIDocumentSettingAccess().set(
+ DocumentSettingId::JUSTIFY_LINES_WITH_SHRINKING, bTmp);
+ }
+ }
+ break;
+ case HANDLE_NO_NUMBERING_SHOW_FOLLOWBY:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ mpDoc->getIDocumentSettingAccess().set(
+ DocumentSettingId::NO_NUMBERING_SHOW_FOLLOWBY, bTmp);
+ }
+ break;
+ case HANDLE_DROP_CAP_PUNCTUATION:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ mpDoc->getIDocumentSettingAccess().set(
+ DocumentSettingId::DROP_CAP_PUNCTUATION, bTmp);
+ }
+ break;
+ case HANDLE_USE_VARIABLE_WIDTH_NBSP:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ mpDoc->getIDocumentSettingAccess().set(
+ DocumentSettingId::USE_VARIABLE_WIDTH_NBSP, bTmp);
+ }
+ break;
+ default:
+ throw UnknownPropertyException(OUString::number(rInfo.mnHandle));
+ }
+}
+
+void SwXDocumentSettings::_postSetValues ()
+{
+ // set printer only once, namely here!
+ if( mpPrinter != nullptr )
+ {
+ // #i86352# the printer is also used as container for options by sfx
+ // when setting a printer it should have decent default options
+ SfxItemSet aOptions( mpPrinter->GetOptions() );
+ SwPrintData aPrtData( mpDoc->getIDocumentDeviceAccess().getPrintData() );
+ SwAddPrinterItem aAddPrinterItem (aPrtData);
+ aOptions.Put(aAddPrinterItem);
+ mpPrinter->SetOptions( aOptions );
+ mpPrinter->SetPrinterSettingsPreferred( mbPreferPrinterPapersize );
+
+ mpDoc->getIDocumentDeviceAccess().setPrinter( mpPrinter, true, true );
+ }
+
+ mpPrinter = nullptr;
+ mpDocSh = nullptr;
+ mpDoc = nullptr;
+}
+
+void SwXDocumentSettings::_preGetValues ()
+{
+ mpDocSh = mpModel->GetDocShell();
+ if (nullptr == mpDocSh)
+ throw UnknownPropertyException();
+ mpDoc = mpDocSh->GetDoc();
+ if (nullptr == mpDoc)
+ throw UnknownPropertyException();
+}
+
+void SwXDocumentSettings::_getSingleValue( const comphelper::PropertyInfo & rInfo, uno::Any & rValue )
+{
+ switch( rInfo.mnHandle )
+ {
+ case HANDLE_FORBIDDEN_CHARS:
+ {
+ rValue <<= Reference<XForbiddenCharacters>(mpModel->GetPropertyHelper());
+ }
+ break;
+ case HANDLE_LINK_UPDATE_MODE:
+ {
+ rValue <<= static_cast < sal_Int16 > ( mpDoc->getIDocumentSettingAccess().getLinkUpdateMode(true) );
+ }
+ break;
+ case HANDLE_FIELD_AUTO_UPDATE:
+ {
+ SwFieldUpdateFlags nFlags = mpDoc->getIDocumentSettingAccess().getFieldUpdateFlags(true);
+ rValue <<= nFlags == AUTOUPD_FIELD_ONLY || nFlags == AUTOUPD_FIELD_AND_CHARTS;
+ }
+ break;
+ case HANDLE_CHART_AUTO_UPDATE:
+ {
+ SwFieldUpdateFlags nFlags = mpDoc->getIDocumentSettingAccess().getFieldUpdateFlags(true);
+ rValue <<= nFlags == AUTOUPD_FIELD_AND_CHARTS;
+ }
+ break;
+ case HANDLE_ADD_PARA_TABLE_SPACING:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::PARA_SPACE_MAX);
+ }
+ break;
+ case HANDLE_ADD_PARA_TABLE_SPACING_AT_START:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::PARA_SPACE_MAX_AT_PAGES);
+ }
+ break;
+ case HANDLE_ALIGN_TAB_STOP_POSITION:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::TAB_COMPAT);
+ }
+ break;
+ case HANDLE_PRINTER_NAME:
+ {
+ SfxPrinter *pPrinter = mpDoc->getIDocumentDeviceAccess().getPrinter( false );
+ rValue <<= pPrinter ? pPrinter->GetName() : OUString();
+ }
+ break;
+ case HANDLE_PRINTER_SETUP:
+ {
+ SfxPrinter *pPrinter = mpDoc->getIDocumentDeviceAccess().getPrinter( false );
+ if (pPrinter)
+ {
+ SvMemoryStream aStream;
+ pPrinter->Store( aStream );
+ sal_uInt32 nSize = aStream.TellEnd();
+ aStream.Seek ( STREAM_SEEK_TO_BEGIN );
+ Sequence < sal_Int8 > aSequence( nSize );
+ aStream.ReadBytes(aSequence.getArray(), nSize);
+ rValue <<= aSequence;
+ }
+ else
+ {
+ Sequence < sal_Int8 > aSequence ( 0 );
+ rValue <<= aSequence;
+ }
+ }
+ break;
+ case HANDLE_PRINTER_PAPER:
+ {
+ SfxPrinter *pTempPrinter = mpDoc->getIDocumentDeviceAccess().getPrinter( false );
+ rValue <<= pTempPrinter && pTempPrinter->GetPrinterSettingsPreferred();
+ }
+ break;
+ case HANDLE_IS_KERN_ASIAN_PUNCTUATION:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::KERN_ASIAN_PUNCTUATION);
+ }
+ break;
+ case HANDLE_APPLY_USER_DATA:
+ {
+ rValue <<= mpDocSh->IsUseUserData();
+ }
+ break;
+ case HANDLE_SAVE_THUMBNAIL:
+ {
+ rValue <<= mpDocSh->IsUseThumbnailSave();
+ }
+ break;
+ case HANDLE_CHARACTER_COMPRESSION_TYPE:
+ {
+ rValue <<= static_cast < sal_Int16 > (mpDoc->getIDocumentSettingAccess().getCharacterCompressionType());
+ }
+ break;
+ case HANDLE_SAVE_GLOBAL_DOCUMENT_LINKS:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT_SAVE_LINKS);
+ }
+ break;
+ case HANDLE_CURRENT_DATABASE_DATA_SOURCE:
+ {
+ const SwDBData& rData = mpDoc->GetDBData();
+ rValue <<= rData.sDataSource;
+ }
+ break;
+ case HANDLE_CURRENT_DATABASE_COMMAND:
+ {
+ const SwDBData& rData = mpDoc->GetDBData();
+ rValue <<= rData.sCommand;
+ }
+ break;
+ case HANDLE_CURRENT_DATABASE_COMMAND_TYPE:
+ {
+ const SwDBData& rData = mpDoc->GetDBData();
+ rValue <<= rData.nCommandType;
+ }
+ break;
+ case HANDLE_EMBEDDED_DATABASE_NAME:
+ {
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+ rValue <<= mpDoc->GetDBManager()->getEmbeddedName();
+#else
+ rValue = uno::Any();
+#endif
+ }
+ break;
+ case HANDLE_SAVE_VERSION_ON_CLOSE:
+ {
+ rValue <<= mpDocSh->IsSaveVersionOnClose();
+ }
+ break;
+ case HANDLE_UPDATE_FROM_TEMPLATE:
+ {
+ rValue <<= mpDocSh->IsQueryLoadTemplate();
+ }
+ break;
+ case HANDLE_PRINTER_INDEPENDENT_LAYOUT:
+ {
+ // returns short (see css.document.PrinterIndependentLayout)
+ sal_Int16 nVirDevType = mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::USE_VIRTUAL_DEVICE) ?
+ ( mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::USE_HIRES_VIRTUAL_DEVICE) ?
+ document::PrinterIndependentLayout::HIGH_RESOLUTION :
+ document::PrinterIndependentLayout::LOW_RESOLUTION ) :
+ document::PrinterIndependentLayout::DISABLED;
+ rValue <<= nVirDevType;
+ }
+ break;
+ case HANDLE_IS_LABEL_DOC:
+ {
+ bool bLabel = mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::LABEL_DOCUMENT);
+ rValue <<= bLabel;
+ }
+ break;
+ case HANDLE_IS_ADD_FLY_OFFSET:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::ADD_FLY_OFFSETS);
+ }
+ break;
+ case HANDLE_IS_ADD_VERTICAL_FLY_OFFSET:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS);
+ }
+ break;
+ case HANDLE_IS_ADD_EXTERNAL_LEADING:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::ADD_EXT_LEADING);
+ }
+ break;
+ case HANDLE_OLD_NUMBERING:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::OLD_NUMBERING);
+ }
+ break;
+ case HANDLE_OUTLINELEVEL_YIELDS_NUMBERING:
+ {
+ rValue <<= false;
+ }
+ break;
+ case HANDLE_ALLOW_PRINTJOB_CANCEL:
+ {
+ rValue <<= mpDocSh->Stamp_GetPrintCancelState();
+ }
+ break;
+ case HANDLE_USE_FORMER_LINE_SPACING:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::OLD_LINE_SPACING);
+ }
+ break;
+ case HANDLE_ADD_PARA_SPACING_TO_TABLE_CELLS:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::ADD_PARA_SPACING_TO_TABLE_CELLS);
+ }
+ break;
+ case HANDLE_ADD_PARA_LINE_SPACING_TO_TABLE_CELLS:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::ADD_PARA_LINE_SPACING_TO_TABLE_CELLS);
+ }
+ break;
+ case HANDLE_USE_FORMER_OBJECT_POSITIONING:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::USE_FORMER_OBJECT_POS);
+ }
+ break;
+ case HANDLE_USE_FORMER_TEXT_WRAPPING:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING);
+ }
+ break;
+ case HANDLE_CHANGES_PASSWORD:
+ {
+ rValue <<= mpDoc->getIDocumentRedlineAccess().GetRedlinePassword();
+ }
+ break;
+ case HANDLE_CONSIDER_WRAP_ON_OBJPOS:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION);
+ }
+ break;
+ case HANDLE_IGNORE_FIRST_LINE_INDENT_IN_NUMBERING:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING);
+ }
+ break;
+ case HANDLE_DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK);
+ }
+ break;
+ case HANDLE_DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT);
+ }
+ break;
+ case HANDLE_TABLE_ROW_KEEP :
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::TABLE_ROW_KEEP);
+ }
+ break;
+ case HANDLE_IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION);
+ }
+ break;
+ case HANDLE_LOAD_READONLY:
+ {
+ rValue <<= mpDocSh->IsLoadReadonly();
+ }
+ break;
+ case HANDLE_DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE);
+ }
+ break;
+ case HANDLE_CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAMES:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAME);
+ }
+ break;
+ case HANDLE_UNIX_FORCE_ZERO_EXT_LEADING:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::UNIX_FORCE_ZERO_EXT_LEADING);
+ }
+ break;
+ case HANDLE_USE_OLD_PRINTER_METRICS:
+ {
+ rValue <<= false;
+ }
+ break;
+ case HANDLE_TABS_RELATIVE_TO_INDENT:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::TABS_RELATIVE_TO_INDENT);
+ }
+ break;
+ case HANDLE_RSID:
+ {
+ rValue <<= static_cast < sal_Int32 > ( mpDoc->getRsid() );
+ }
+ break;
+ case HANDLE_RSID_ROOT:
+ {
+ rValue <<= static_cast < sal_Int32 > ( mpDoc->getRsidRoot() );
+ }
+ break;
+ case HANDLE_PROTECT_FORM:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_FORM);
+ }
+ break;
+ case HANDLE_MS_WORD_COMP_TRAILING_BLANKS:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS);
+ }
+ break;
+ case HANDLE_MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY);
+ }
+ break;
+ case HANDLE_TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST);
+ }
+ break;
+ case HANDLE_MODIFYPASSWORDINFO:
+ {
+ rValue <<= mpDocSh->GetModifyPasswordInfo();
+ }
+ break;
+ case HANDLE_MATH_BASELINE_ALIGNMENT:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT );
+ }
+ break;
+ case HANDLE_INVERT_BORDER_SPACING:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::INVERT_BORDER_SPACING);
+ }
+ break;
+ case HANDLE_COLLAPSE_EMPTY_CELL_PARA:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::COLLAPSE_EMPTY_CELL_PARA );
+ }
+ break;
+ case HANDLE_SMALL_CAPS_PERCENTAGE_66:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::SMALL_CAPS_PERCENTAGE_66 );
+ }
+ break;
+ case HANDLE_TAB_OVERFLOW:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::TAB_OVERFLOW );
+ }
+ break;
+ case HANDLE_UNBREAKABLE_NUMBERINGS:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::UNBREAKABLE_NUMBERINGS );
+ }
+ break;
+ case HANDLE_STYLES_NODEFAULT:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::STYLES_NODEFAULT );
+ }
+ break;
+ case HANDLE_CLIPPED_PICTURES:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::CLIPPED_PICTURES );
+ }
+ break;
+ case HANDLE_BACKGROUND_PARA_OVER_DRAWINGS:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::BACKGROUND_PARA_OVER_DRAWINGS );
+ }
+ break;
+ case HANDLE_EMBED_FONTS:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_FONTS );
+ }
+ break;
+ case HANDLE_EMBED_USED_FONTS:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_USED_FONTS );
+ }
+ break;
+ case HANDLE_EMBED_LATIN_SCRIPT_FONTS:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_LATIN_SCRIPT_FONTS );
+ }
+ break;
+ case HANDLE_EMBED_ASIAN_SCRIPT_FONTS:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_ASIAN_SCRIPT_FONTS );
+ }
+ break;
+ case HANDLE_EMBED_COMPLEX_SCRIPT_FONTS:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_COMPLEX_SCRIPT_FONTS );
+ }
+ break;
+ case HANDLE_EMBED_SYSTEM_FONTS:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_SYSTEM_FONTS );
+ }
+ break;
+ case HANDLE_TAB_OVER_MARGIN:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::TAB_OVER_MARGIN );
+ }
+ break;
+ case HANDLE_TAB_OVER_SPACING:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::TAB_OVER_SPACING);
+ }
+ break;
+ case HANDLE_TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK );
+ }
+ break;
+ case HANDLE_SURROUND_TEXT_WRAP_SMALL:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::SURROUND_TEXT_WRAP_SMALL );
+ }
+ break;
+ case HANDLE_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING );
+ }
+ break;
+ case HANDLE_PROP_LINE_SPACING_SHRINKS_FIRST_LINE:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::PROP_LINE_SPACING_SHRINKS_FIRST_LINE);
+ }
+ break;
+ case HANDLE_SUBTRACT_FLYS:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::SUBTRACT_FLYS);
+ }
+ break;
+ case HANDLE_DISABLE_OFF_PAGE_POSITIONING:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::DISABLE_OFF_PAGE_POSITIONING);
+ }
+ break;
+ case HANDLE_EMPTY_DB_FIELD_HIDES_PARA:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(
+ DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA);
+ }
+ break;
+ case HANDLE_CONTINUOUS_ENDNOTES:
+ {
+ rValue
+ <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::CONTINUOUS_ENDNOTES);
+ }
+ break;
+ case HANDLE_PROTECT_BOOKMARKS:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(
+ DocumentSettingId::PROTECT_BOOKMARKS);
+ }
+ break;
+ case HANDLE_PROTECT_FIELDS:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(
+ DocumentSettingId::PROTECT_FIELDS);
+ }
+ break;
+ case HANDLE_HEADER_SPACING_BELOW_LAST_PARA:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(
+ DocumentSettingId::HEADER_SPACING_BELOW_LAST_PARA);
+ }
+ break;
+ case HANDLE_FRAME_AUTOWIDTH_WITH_MORE_PARA:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(
+ DocumentSettingId::FRAME_AUTOWIDTH_WITH_MORE_PARA);
+ }
+ break;
+ case HANDLE_GUTTER_AT_TOP:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::GUTTER_AT_TOP);
+ }
+ break;
+ case HANDLE_FOOTNOTE_IN_COLUMN_TO_PAGEEND:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(
+ DocumentSettingId::FOOTNOTE_IN_COLUMN_TO_PAGEEND);
+ }
+ break;
+ case HANDLE_IMAGE_PREFERRED_DPI:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().getImagePreferredDPI();
+ }
+ break;
+ case HANDLE_AUTO_FIRST_LINE_INDENT_DISREGARD_LINE_SPACE:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(
+ DocumentSettingId::AUTO_FIRST_LINE_INDENT_DISREGARD_LINE_SPACE);
+ }
+ break;
+ case HANDLE_HYPHENATE_URLS:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(
+ DocumentSettingId::HYPHENATE_URLS);
+ }
+ break;
+ case HANDLE_DO_NOT_BREAK_WRAPPED_TABLES:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(
+ DocumentSettingId::DO_NOT_BREAK_WRAPPED_TABLES);
+ }
+ break;
+ case HANDLE_ALLOW_TEXT_AFTER_FLOATING_TABLE_BREAK:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(
+ DocumentSettingId::ALLOW_TEXT_AFTER_FLOATING_TABLE_BREAK);
+ }
+ break;
+ case HANDLE_JUSTIFY_LINES_WITH_SHRINKING:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(
+ DocumentSettingId::JUSTIFY_LINES_WITH_SHRINKING);
+ }
+ break;
+ case HANDLE_NO_NUMBERING_SHOW_FOLLOWBY:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(
+ DocumentSettingId::NO_NUMBERING_SHOW_FOLLOWBY);
+ }
+ break;
+ case HANDLE_DROP_CAP_PUNCTUATION:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(
+ DocumentSettingId::DROP_CAP_PUNCTUATION);
+ }
+ break;
+ case HANDLE_USE_VARIABLE_WIDTH_NBSP:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(
+ DocumentSettingId::USE_VARIABLE_WIDTH_NBSP);
+ }
+ break;
+ default:
+ throw UnknownPropertyException(OUString::number(rInfo.mnHandle));
+ }
+}
+
+void SwXDocumentSettings::_postGetValues ()
+{
+ mpDocSh = nullptr;
+ mpDoc = nullptr;
+}
+
+// XServiceInfo
+OUString SAL_CALL SwXDocumentSettings::getImplementationName( )
+{
+ return "SwXDocumentSettings";
+}
+
+sal_Bool SAL_CALL SwXDocumentSettings::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Sequence< OUString > SAL_CALL SwXDocumentSettings::getSupportedServiceNames( )
+{
+ return { "com.sun.star.document.Settings", "com.sun.star.text.DocumentSettings", "com.sun.star.text.PrintSettings" };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uno/SwXDocumentSettings.hxx b/sw/source/uibase/uno/SwXDocumentSettings.hxx
new file mode 100644
index 0000000000..3d722e40ba
--- /dev/null
+++ b/sw/source/uibase/uno/SwXDocumentSettings.hxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <comphelper/MasterPropertySet.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XTypeProvider.hpp>
+#include <cppuhelper/weak.hxx>
+#include <vcl/vclptr.hxx>
+
+class SwXTextDocument;
+class SwDocShell;
+class SwDoc;
+class SfxPrinter;
+
+class SwXDocumentSettings final :
+ public comphelper::MasterPropertySet,
+ public css::lang::XServiceInfo,
+ public css::lang::XTypeProvider,
+ public cppu::OWeakObject
+{
+ SwXTextDocument* mpModel;
+ SwDocShell* mpDocSh;
+ SwDoc* mpDoc;
+
+ /** the printer should be set only once; since there are several
+ * printer-related properties, remember the last printer and set it in
+ * _postSetValues */
+ VclPtr<SfxPrinter> mpPrinter;
+ bool mbPreferPrinterPapersize;
+
+ virtual void _preSetValues () override;
+ virtual void _setSingleValue( const comphelper::PropertyInfo & rInfo, const css::uno::Any &rValue ) override;
+ virtual void _postSetValues () override;
+
+ virtual void _preGetValues () override;
+ virtual void _getSingleValue( const comphelper::PropertyInfo & rInfo, css::uno::Any & rValue ) override;
+ virtual void _postGetValues () override;
+ virtual ~SwXDocumentSettings()
+ noexcept override;
+public:
+ SwXDocumentSettings( SwXTextDocument* pModel );
+
+ // XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
+ virtual void SAL_CALL acquire( )
+ noexcept override;
+ virtual void SAL_CALL release( )
+ noexcept override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uno/SwXFilterOptions.cxx b/sw/source/uibase/uno/SwXFilterOptions.cxx
new file mode 100644
index 0000000000..f73a4b0dd0
--- /dev/null
+++ b/sw/source/uibase/uno/SwXFilterOptions.cxx
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <SwXFilterOptions.hxx>
+#include <shellio.hxx>
+#include <swdll.hxx>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <unotxdoc.hxx>
+
+#include <swabstdlg.hxx>
+#include <memory>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::lang;
+
+constexpr OUString FILTER_OPTIONS_NAME = u"FilterOptions"_ustr;
+
+SwXFilterOptions::SwXFilterOptions()
+{
+}
+
+SwXFilterOptions::~SwXFilterOptions()
+{
+}
+
+uno::Sequence< beans::PropertyValue > SwXFilterOptions::getPropertyValues()
+{
+ return comphelper::InitPropertySequence({
+ { FILTER_OPTIONS_NAME, uno::Any(m_sFilterOptions) }
+ });
+}
+
+void SwXFilterOptions::setPropertyValues( const uno::Sequence<beans::PropertyValue >& aProps )
+{
+ for (const beans::PropertyValue& rProp : aProps)
+ {
+ OUString aPropName = rProp.Name;
+
+ if ( aPropName == FILTER_OPTIONS_NAME )
+ rProp.Value >>= m_sFilterOptions;
+ else if ( aPropName == "InputStream" )
+ rProp.Value >>= m_xInputStream;
+ }
+}
+
+void SwXFilterOptions::setTitle( const OUString& /*rTitle*/ )
+{
+}
+
+sal_Int16 SwXFilterOptions::execute()
+{
+ sal_Int16 nRet = ui::dialogs::ExecutableDialogResults::CANCEL;
+
+ std::unique_ptr<SvStream> pInStream;
+ if ( m_xInputStream.is() )
+ pInStream = utl::UcbStreamHelper::CreateStream( m_xInputStream );
+
+ SwDocShell* pDocShell = nullptr;
+ if (auto pXDoc = comphelper::getFromUnoTunnel<SwXTextDocument>(m_xModel); pXDoc)
+ pDocShell = pXDoc->GetDocShell();
+
+ if(pDocShell)
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractSwAsciiFilterDlg> pAsciiDlg(pFact->CreateSwAsciiFilterDlg(Application::GetFrameWeld(m_xDialogParent), *pDocShell,
+ pInStream.get()));
+ if(RET_OK == pAsciiDlg->Execute())
+ {
+ SwAsciiOptions aOptions;
+ pAsciiDlg->FillOptions( aOptions );
+ aOptions.WriteUserData(m_sFilterOptions);
+ nRet = ui::dialogs::ExecutableDialogResults::OK;
+ }
+ }
+
+ return nRet;
+}
+
+void SwXFilterOptions::setTargetDocument( const uno::Reference< XComponent >& xDoc )
+{
+ m_xModel = xDoc;
+}
+
+void SwXFilterOptions::setSourceDocument( const uno::Reference<XComponent >& xDoc )
+{
+ m_xModel = xDoc;
+}
+
+void SAL_CALL SwXFilterOptions::initialize(const uno::Sequence<uno::Any>& rArguments)
+{
+ ::comphelper::NamedValueCollection aProperties(rArguments);
+ if (aProperties.has("ParentWindow"))
+ aProperties.get("ParentWindow") >>= m_xDialogParent;
+}
+
+OUString SwXFilterOptions::getImplementationName()
+{
+ return "com.sun.star.comp.Writer.FilterOptionsDialog";
+}
+
+sal_Bool SwXFilterOptions::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SwXFilterOptions::getSupportedServiceNames()
+{
+ return { "com.sun.star.ui.dialogs.FilterOptionsDialog" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Writer_FilterOptionsDialog_get_implementation(css::uno::XComponentContext*,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ SolarMutexGuard aGuard;
+
+ //the module may not be loaded
+ SwGlobals::ensure();
+ return cppu::acquire(new SwXFilterOptions());
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uno/dlelstnr.cxx b/sw/source/uibase/uno/dlelstnr.cxx
new file mode 100644
index 0000000000..6cfe6f9719
--- /dev/null
+++ b/sw/source/uibase/uno/dlelstnr.cxx
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/linguistic2/LinguServiceManager.hpp>
+#include <com/sun/star/linguistic2/XLinguServiceEventBroadcaster.hpp>
+#include <com/sun/star/linguistic2/XProofreadingIterator.hpp>
+#include <com/sun/star/linguistic2/LinguServiceEventFlags.hpp>
+
+#include <unotools/lingucfg.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <com/sun/star/uno/Reference.h>
+#include <comphelper/processfactory.hxx>
+#include <vcl/svapp.hxx>
+#include <dlelstnr.hxx>
+#include <proofreadingiterator.hxx>
+#include <swmodule.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::linguistic2;
+using namespace ::com::sun::star::linguistic2::LinguServiceEventFlags;
+
+SwLinguServiceEventListener::SwLinguServiceEventListener()
+{
+ Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
+ try
+ {
+ m_xDesktop = frame::Desktop::create(xContext);
+ m_xDesktop->addTerminateListener( this );
+
+ m_xLngSvcMgr = LinguServiceManager::create(xContext);
+ m_xLngSvcMgr->addLinguServiceManagerListener( static_cast<XLinguServiceEventListener *>(this) );
+
+ if (SvtLinguConfig().HasGrammarChecker())
+ {
+ m_xGCIterator = sw::proofreadingiterator::get(xContext);
+ Reference< XLinguServiceEventBroadcaster > xBC( m_xGCIterator, UNO_QUERY );
+ if (xBC.is())
+ xBC->addLinguServiceEventListener( static_cast<XLinguServiceEventListener *>(this) );
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "sw", "SwLinguServiceEventListener c-tor" );
+ }
+}
+
+SwLinguServiceEventListener::~SwLinguServiceEventListener()
+{
+}
+
+void SAL_CALL SwLinguServiceEventListener::processLinguServiceEvent(
+ const LinguServiceEvent& rLngSvcEvent )
+{
+ SolarMutexGuard aGuard;
+
+ bool bIsSpellWrong = 0 != (rLngSvcEvent.nEvent & SPELL_WRONG_WORDS_AGAIN);
+ bool bIsSpellAll = 0 != (rLngSvcEvent.nEvent & SPELL_CORRECT_WORDS_AGAIN);
+ if (0 != (rLngSvcEvent.nEvent & PROOFREAD_AGAIN))
+ bIsSpellWrong = bIsSpellAll = true; // have all spelling and grammar checked...
+ if (bIsSpellWrong || bIsSpellAll)
+ {
+ SwModule::CheckSpellChanges( false, bIsSpellWrong, bIsSpellAll, false );
+ }
+ if (!(rLngSvcEvent.nEvent & HYPHENATE_AGAIN))
+ return;
+
+ SwView *pSwView = SwModule::GetFirstView();
+
+ //!! since this function may be called within the ctor of
+ //!! SwView (during formatting) where the WrtShell is not yet
+ //!! created, we have to check for the WrtShellPtr to see
+ //!! if it is already available
+ while (pSwView && pSwView->GetWrtShellPtr())
+ {
+ pSwView->GetWrtShell().ChgHyphenation();
+ pSwView = SwModule::GetNextView( pSwView );
+ }
+}
+
+void SAL_CALL SwLinguServiceEventListener::disposing(
+ const EventObject& rEventObj )
+{
+ SolarMutexGuard aGuard;
+
+ if (m_xLngSvcMgr.is() && rEventObj.Source == m_xLngSvcMgr)
+ m_xLngSvcMgr = nullptr;
+ if (m_xLngSvcMgr.is() && rEventObj.Source == m_xGCIterator)
+ m_xGCIterator = nullptr;
+}
+
+void SAL_CALL SwLinguServiceEventListener::queryTermination(
+ const EventObject& /*rEventObj*/ )
+{
+}
+
+void SAL_CALL SwLinguServiceEventListener::notifyTermination(
+ const EventObject& rEventObj )
+{
+ SolarMutexGuard aGuard;
+
+ if (m_xDesktop.is() && rEventObj.Source == m_xDesktop)
+ {
+ if (m_xLngSvcMgr.is())
+ m_xLngSvcMgr = nullptr;
+ if (m_xGCIterator.is())
+ m_xGCIterator = nullptr;
+ m_xDesktop = nullptr;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uno/loktxdoc.cxx b/sw/source/uibase/uno/loktxdoc.cxx
new file mode 100644
index 0000000000..4843af4cf4
--- /dev/null
+++ b/sw/source/uibase/uno/loktxdoc.cxx
@@ -0,0 +1,492 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <unotxdoc.hxx>
+
+#include <map>
+#include <utility>
+#include <vector>
+
+#include <com/sun/star/beans/XPropertyAccess.hpp>
+
+#include <comphelper/sequence.hxx>
+#include <o3tl/string_view.hxx>
+#include <tools/json_writer.hxx>
+#include <tools/urlobj.hxx>
+#include <xmloff/odffields.hxx>
+
+#include <IDocumentMarkAccess.hxx>
+#include <doc.hxx>
+#include <docsh.hxx>
+#include <fmtrfmrk.hxx>
+#include <wrtsh.hxx>
+#include <txtrfmrk.hxx>
+#include <ndtxt.hxx>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+/// Implements getCommandValues(".uno:TextFormFields").
+///
+/// Parameters:
+///
+/// - type: e.g. ODF_UNHANDLED
+/// - commandPrefix: field command prefix to not return all fieldmarks
+void GetTextFormFields(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
+ const std::map<OUString, OUString>& rArguments)
+{
+ OUString aType;
+ OUString aCommandPrefix;
+ {
+ auto it = rArguments.find("type");
+ if (it != rArguments.end())
+ {
+ aType = it->second;
+ }
+
+ it = rArguments.find("commandPrefix");
+ if (it != rArguments.end())
+ {
+ aCommandPrefix = it->second;
+ }
+ }
+
+ SwDoc* pDoc = pDocShell->GetDoc();
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+ tools::ScopedJsonWriterArray aFields = rJsonWriter.startArray("fields");
+ for (auto it = pMarkAccess->getFieldmarksBegin(); it != pMarkAccess->getFieldmarksEnd(); ++it)
+ {
+ auto pFieldmark = dynamic_cast<sw::mark::IFieldmark*>(*it);
+ assert(pFieldmark);
+ if (pFieldmark->GetFieldname() != aType)
+ {
+ continue;
+ }
+
+ auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM);
+ if (itParam == pFieldmark->GetParameters()->end())
+ {
+ continue;
+ }
+
+ OUString aCommand;
+ itParam->second >>= aCommand;
+ if (!aCommand.startsWith(aCommandPrefix))
+ {
+ continue;
+ }
+
+ tools::ScopedJsonWriterStruct aField = rJsonWriter.startStruct();
+ rJsonWriter.put("type", aType);
+ rJsonWriter.put("command", aCommand);
+ }
+}
+
+/// Implements getCommandValues(".uno:TextFormField").
+///
+/// Parameters:
+///
+/// - type: e.g. ODF_UNHANDLED
+/// - commandPrefix: field command prefix to not return all fieldmarks
+void GetTextFormField(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
+ const std::map<OUString, OUString>& rArguments)
+{
+ OUString aType;
+ OUString aCommandPrefix;
+ auto it = rArguments.find("type");
+ if (it != rArguments.end())
+ {
+ aType = it->second;
+ }
+
+ it = rArguments.find("commandPrefix");
+ if (it != rArguments.end())
+ {
+ aCommandPrefix = it->second;
+ }
+
+ IDocumentMarkAccess& rIDMA = *pDocShell->GetDoc()->getIDocumentMarkAccess();
+ SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+ SwPosition& rCursor = *pWrtShell->GetCursor()->GetPoint();
+ sw::mark::IFieldmark* pFieldmark = rIDMA.getInnerFieldmarkFor(rCursor);
+ auto typeNode = rJsonWriter.startNode("field");
+ if (!pFieldmark)
+ {
+ return;
+ }
+
+ if (pFieldmark->GetFieldname() != aType)
+ {
+ return;
+ }
+
+ auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM);
+ if (itParam == pFieldmark->GetParameters()->end())
+ {
+ return;
+ }
+
+ OUString aCommand;
+ itParam->second >>= aCommand;
+ if (!aCommand.startsWith(aCommandPrefix))
+ {
+ return;
+ }
+
+ rJsonWriter.put("type", aType);
+ rJsonWriter.put("command", aCommand);
+}
+
+/// Implements getCommandValues(".uno:SetDocumentProperties").
+///
+/// Parameters:
+///
+/// - namePrefix: field name prefix to not return all user-defined properties
+void GetDocumentProperties(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
+ const std::map<OUString, OUString>& rArguments)
+{
+ OUString aNamePrefix;
+ auto it = rArguments.find("namePrefix");
+ if (it != rArguments.end())
+ {
+ aNamePrefix = it->second;
+ }
+
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(pDocShell->GetModel(),
+ uno::UNO_QUERY);
+ uno::Reference<document::XDocumentProperties> xDP = xDPS->getDocumentProperties();
+ uno::Reference<beans::XPropertyAccess> xUDP(xDP->getUserDefinedProperties(), uno::UNO_QUERY);
+ auto aUDPs = comphelper::sequenceToContainer<std::vector<beans::PropertyValue>>(
+ xUDP->getPropertyValues());
+ tools::ScopedJsonWriterArray aProperties = rJsonWriter.startArray("userDefinedProperties");
+ for (const auto& rUDP : aUDPs)
+ {
+ if (!rUDP.Name.startsWith(aNamePrefix))
+ {
+ continue;
+ }
+
+ if (rUDP.Value.getValueTypeClass() != uno::TypeClass_STRING)
+ {
+ continue;
+ }
+
+ OUString aValue;
+ rUDP.Value >>= aValue;
+
+ tools::ScopedJsonWriterStruct aProperty = rJsonWriter.startStruct();
+ rJsonWriter.put("name", rUDP.Name);
+ rJsonWriter.put("type", "string");
+ rJsonWriter.put("value", aValue);
+ }
+}
+
+/// Implements getCommandValues(".uno:Bookmarks").
+///
+/// Parameters:
+///
+/// - namePrefix: bookmark name prefix to not return all bookmarks
+void GetBookmarks(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
+ const std::map<OUString, OUString>& rArguments)
+{
+ OUString aNamePrefix;
+ {
+ auto it = rArguments.find("namePrefix");
+ if (it != rArguments.end())
+ {
+ aNamePrefix = it->second;
+ }
+ }
+
+ IDocumentMarkAccess& rIDMA = *pDocShell->GetDoc()->getIDocumentMarkAccess();
+ tools::ScopedJsonWriterArray aBookmarks = rJsonWriter.startArray("bookmarks");
+ for (auto it = rIDMA.getBookmarksBegin(); it != rIDMA.getBookmarksEnd(); ++it)
+ {
+ sw::mark::IMark* pMark = *it;
+ if (!pMark->GetName().startsWith(aNamePrefix))
+ {
+ continue;
+ }
+
+ tools::ScopedJsonWriterStruct aProperty = rJsonWriter.startStruct();
+ rJsonWriter.put("name", pMark->GetName());
+ }
+}
+
+/// Implements getCommandValues(".uno:Bookmark").
+///
+/// Parameters:
+///
+/// - namePrefix: bookmark name prefix to not return all bookmarks
+void GetBookmark(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
+ const std::map<OUString, OUString>& rArguments)
+{
+ OUString aNamePrefix;
+ {
+ auto it = rArguments.find("namePrefix");
+ if (it != rArguments.end())
+ {
+ aNamePrefix = it->second;
+ }
+ }
+
+ IDocumentMarkAccess& rIDMA = *pDocShell->GetDoc()->getIDocumentMarkAccess();
+ SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+ SwPosition& rCursor = *pWrtShell->GetCursor()->GetPoint();
+ sw::mark::IMark* pBookmark = rIDMA.getOneInnermostBookmarkFor(rCursor);
+ tools::ScopedJsonWriterNode aBookmark = rJsonWriter.startNode("bookmark");
+ if (!pBookmark)
+ {
+ return;
+ }
+
+ if (!pBookmark->GetName().startsWith(aNamePrefix))
+ {
+ return;
+ }
+
+ rJsonWriter.put("name", pBookmark->GetName());
+}
+
+/// Implements getCommandValues(".uno:Fields").
+///
+/// Parameters:
+///
+/// - typeName: field type condition to not return all fields
+/// - namePrefix: field name prefix to not return all fields
+void GetFields(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
+ const std::map<OUString, OUString>& rArguments)
+{
+ OUString aTypeName;
+ {
+ auto it = rArguments.find("typeName");
+ if (it != rArguments.end())
+ {
+ aTypeName = it->second;
+ }
+ }
+ // See SwFieldTypeFromString().
+ if (aTypeName != "SetRef")
+ {
+ return;
+ }
+
+ OUString aNamePrefix;
+ {
+ auto it = rArguments.find("namePrefix");
+ if (it != rArguments.end())
+ {
+ aNamePrefix = it->second;
+ }
+ }
+
+ SwDoc* pDoc = pDocShell->GetDoc();
+ tools::ScopedJsonWriterArray aBookmarks = rJsonWriter.startArray("setRefs");
+ std::vector<const SwFormatRefMark*> aRefMarks;
+ for (sal_uInt16 i = 0; i < pDoc->GetRefMarks(); ++i)
+ {
+ aRefMarks.push_back(pDoc->GetRefMark(i));
+ }
+ // Sort the refmarks based on their start position.
+ std::sort(aRefMarks.begin(), aRefMarks.end(),
+ [](const SwFormatRefMark* pMark1, const SwFormatRefMark* pMark2) -> bool {
+ const SwTextRefMark* pTextRefMark1 = pMark1->GetTextRefMark();
+ const SwTextRefMark* pTextRefMark2 = pMark2->GetTextRefMark();
+ SwPosition aPos1(pTextRefMark1->GetTextNode(), pTextRefMark1->GetStart());
+ SwPosition aPos2(pTextRefMark2->GetTextNode(), pTextRefMark2->GetStart());
+ return aPos1 < aPos2;
+ });
+
+ for (const auto& pRefMark : aRefMarks)
+ {
+ if (!pRefMark->GetRefName().startsWith(aNamePrefix))
+ {
+ continue;
+ }
+
+ tools::ScopedJsonWriterStruct aProperty = rJsonWriter.startStruct();
+ rJsonWriter.put("name", pRefMark->GetRefName());
+ }
+}
+
+/// Implements getCommandValues(".uno:Field").
+///
+/// Parameters:
+///
+/// - typeName: field type condition to not return all fields
+/// - namePrefix: field name prefix to not return all fields
+void GetField(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
+ const std::map<OUString, OUString>& rArguments)
+{
+ OUString aTypeName;
+ {
+ auto it = rArguments.find("typeName");
+ if (it != rArguments.end())
+ {
+ aTypeName = it->second;
+ }
+ }
+ // See SwFieldTypeFromString().
+ if (aTypeName != "SetRef")
+ {
+ return;
+ }
+
+ OUString aNamePrefix;
+ {
+ auto it = rArguments.find("namePrefix");
+ if (it != rArguments.end())
+ {
+ aNamePrefix = it->second;
+ }
+ }
+
+ SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+ SwPosition& rCursor = *pWrtShell->GetCursor()->GetPoint();
+ SwTextNode* pTextNode = rCursor.GetNode().GetTextNode();
+ std::vector<SwTextAttr*> aAttrs
+ = pTextNode->GetTextAttrsAt(rCursor.GetContentIndex(), RES_TXTATR_REFMARK);
+ tools::ScopedJsonWriterNode aRefmark = rJsonWriter.startNode("setRef");
+ if (aAttrs.empty())
+ {
+ return;
+ }
+
+ const SwFormatRefMark& rRefmark = aAttrs[0]->GetRefMark();
+ if (!rRefmark.GetRefName().startsWith(aNamePrefix))
+ {
+ return;
+ }
+
+ rJsonWriter.put("name", rRefmark.GetRefName());
+}
+
+/// Implements getCommandValues(".uno:Sections").
+///
+/// Parameters:
+///
+/// - namePrefix: field name prefix to not return all sections
+void GetSections(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
+ const std::map<OUString, OUString>& rArguments)
+{
+ OUString aNamePrefix;
+ {
+ auto it = rArguments.find("namePrefix");
+ if (it != rArguments.end())
+ {
+ aNamePrefix = it->second;
+ }
+ }
+
+ SwDoc* pDoc = pDocShell->GetDoc();
+ tools::ScopedJsonWriterArray aBookmarks = rJsonWriter.startArray("sections");
+ for (const auto& pSection : pDoc->GetSections())
+ {
+ if (!pSection->GetName().startsWith(aNamePrefix))
+ {
+ continue;
+ }
+
+ tools::ScopedJsonWriterStruct aProperty = rJsonWriter.startStruct();
+ rJsonWriter.put("name", pSection->GetName());
+ }
+}
+}
+
+bool SwXTextDocument::supportsCommand(std::u16string_view rCommand)
+{
+ static const std::initializer_list<std::u16string_view> vForward
+ = { u"TextFormFields", u"TextFormField", u"SetDocumentProperties",
+ u"Bookmarks", u"Fields", u"Sections",
+ u"Bookmark", u"Field" };
+
+ return std::find(vForward.begin(), vForward.end(), rCommand) != vForward.end();
+}
+
+void SwXTextDocument::getCommandValues(tools::JsonWriter& rJsonWriter, std::string_view rCommand)
+{
+ std::map<OUString, OUString> aMap;
+
+ static constexpr OStringLiteral aTextFormFields(".uno:TextFormFields");
+ static constexpr OStringLiteral aTextFormField(".uno:TextFormField");
+ static constexpr OStringLiteral aSetDocumentProperties(".uno:SetDocumentProperties");
+ static constexpr OStringLiteral aBookmarks(".uno:Bookmarks");
+ static constexpr OStringLiteral aFields(".uno:Fields");
+ static constexpr OStringLiteral aSections(".uno:Sections");
+ static constexpr OStringLiteral aBookmark(".uno:Bookmark");
+ static constexpr OStringLiteral aField(".uno:Field");
+
+ INetURLObject aParser(OUString::fromUtf8(rCommand));
+ OUString aArguments = aParser.GetParam();
+ sal_Int32 nParamIndex = 0;
+ do
+ {
+ std::u16string_view aParam = o3tl::getToken(aArguments, 0, '&', nParamIndex);
+ sal_Int32 nIndex = 0;
+ OUString aKey;
+ OUString aValue;
+ do
+ {
+ std::u16string_view aToken = o3tl::getToken(aParam, 0, '=', nIndex);
+ if (aKey.isEmpty())
+ aKey = aToken;
+ else
+ aValue = aToken;
+ } while (nIndex >= 0);
+ OUString aDecodedValue
+ = INetURLObject::decode(aValue, INetURLObject::DecodeMechanism::WithCharset);
+ aMap[aKey] = aDecodedValue;
+ } while (nParamIndex >= 0);
+
+ if (o3tl::starts_with(rCommand, aTextFormFields))
+ {
+ GetTextFormFields(rJsonWriter, m_pDocShell, aMap);
+ }
+ if (o3tl::starts_with(rCommand, aTextFormField))
+ {
+ GetTextFormField(rJsonWriter, m_pDocShell, aMap);
+ }
+ else if (o3tl::starts_with(rCommand, aSetDocumentProperties))
+ {
+ GetDocumentProperties(rJsonWriter, m_pDocShell, aMap);
+ }
+ else if (o3tl::starts_with(rCommand, aBookmarks))
+ {
+ GetBookmarks(rJsonWriter, m_pDocShell, aMap);
+ }
+ else if (o3tl::starts_with(rCommand, aFields))
+ {
+ GetFields(rJsonWriter, m_pDocShell, aMap);
+ }
+ else if (o3tl::starts_with(rCommand, aSections))
+ {
+ GetSections(rJsonWriter, m_pDocShell, aMap);
+ }
+ else if (o3tl::starts_with(rCommand, aBookmark))
+ {
+ GetBookmark(rJsonWriter, m_pDocShell, aMap);
+ }
+ else if (o3tl::starts_with(rCommand, aField))
+ {
+ GetField(rJsonWriter, m_pDocShell, aMap);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uno/unoatxt.cxx b/sw/source/uibase/uno/unoatxt.cxx
new file mode 100644
index 0000000000..7ea3d9db4e
--- /dev/null
+++ b/sw/source/uibase/uno/unoatxt.cxx
@@ -0,0 +1,993 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/container/ElementExistException.hpp>
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+#include <rtl/character.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <svtools/unoevent.hxx>
+#include <sfx2/event.hxx>
+#include <glosdoc.hxx>
+#include <shellio.hxx>
+#include <initui.hxx>
+#include <gloslst.hxx>
+#include <unoatxt.hxx>
+#include <unomap.hxx>
+#include <unotextbodyhf.hxx>
+#include <unotextrange.hxx>
+#include <TextCursorHelper.hxx>
+#include <doc.hxx>
+#include <IDocumentContentOperations.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <IDocumentFieldsAccess.hxx>
+#include <IDocumentState.hxx>
+#include <docsh.hxx>
+#include <swdll.hxx>
+#include <svl/hint.hxx>
+#include <tools/urlobj.hxx>
+#include <svl/macitem.hxx>
+#include <editeng/acorrcfg.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+
+SwXAutoTextContainer::SwXAutoTextContainer()
+{
+ m_pGlossaries = ::GetGlossaries();
+
+}
+
+SwXAutoTextContainer::~SwXAutoTextContainer()
+{
+
+}
+
+sal_Int32 SwXAutoTextContainer::getCount()
+{
+ OSL_ENSURE(m_pGlossaries->GetGroupCnt() < o3tl::make_unsigned(SAL_MAX_INT32),
+ "SwXAutoTextContainer::getCount: too many items");
+ return static_cast<sal_Int32>(m_pGlossaries->GetGroupCnt());
+}
+
+uno::Any SwXAutoTextContainer::getByIndex(sal_Int32 nIndex)
+{
+ SolarMutexGuard aGuard;
+ const size_t nCount = m_pGlossaries->GetGroupCnt();
+ if ( nIndex < 0 || o3tl::make_unsigned(nIndex) >= nCount )
+ throw lang::IndexOutOfBoundsException();
+ return getByName(m_pGlossaries->GetGroupName( static_cast<size_t>(nIndex) ));
+}
+
+uno::Type SwXAutoTextContainer::getElementType()
+{
+ return cppu::UnoType<text::XAutoTextGroup>::get();
+
+}
+
+sal_Bool SwXAutoTextContainer::hasElements()
+{
+ // At least standard should always exists!
+ return true;
+}
+
+uno::Any SwXAutoTextContainer::getByName(const OUString& GroupName)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference< text::XAutoTextGroup > xGroup;
+ if ( m_pGlossaries && hasByName( GroupName ) ) // group name already known?
+ // true = create group if not already available
+ xGroup = m_pGlossaries->GetAutoTextGroup( GroupName );
+
+ if ( !xGroup.is() )
+ throw container::NoSuchElementException();
+
+ return css::uno::Any( xGroup );
+}
+
+uno::Sequence< OUString > SwXAutoTextContainer::getElementNames()
+{
+ SolarMutexGuard aGuard;
+ const size_t nCount = m_pGlossaries->GetGroupCnt();
+ OSL_ENSURE(nCount < o3tl::make_unsigned(SAL_MAX_INT32),
+ "SwXAutoTextContainer::getElementNames: too many groups");
+
+ uno::Sequence< OUString > aGroupNames(static_cast<sal_Int32>(nCount));
+ OUString *pArr = aGroupNames.getArray();
+
+ for ( size_t i = 0; i < nCount; ++i )
+ {
+ // The names will be passed without a path extension.
+ pArr[i] = m_pGlossaries->GetGroupName(i).getToken(0, GLOS_DELIM);
+ }
+ return aGroupNames;
+}
+// Finds group names with or without path index.
+sal_Bool SwXAutoTextContainer::hasByName(const OUString& Name)
+{
+ SolarMutexGuard aGuard;
+ OUString sGroupName( m_pGlossaries->GetCompleteGroupName( Name ) );
+ if(!sGroupName.isEmpty())
+ return true;
+ return false;
+}
+
+uno::Reference< text::XAutoTextGroup > SwXAutoTextContainer::insertNewByName(
+ const OUString& aGroupName)
+{
+ SolarMutexGuard aGuard;
+ if(hasByName(aGroupName))
+ throw container::ElementExistException();
+ //check for non-ASCII characters
+ if(aGroupName.isEmpty())
+ {
+ throw lang::IllegalArgumentException("group name must not be empty", nullptr, 0);
+ }
+ for(sal_Int32 nPos = 0; nPos < aGroupName.getLength(); nPos++)
+ {
+ sal_Unicode cChar = aGroupName[nPos];
+ if (rtl::isAsciiAlphanumeric(cChar) ||
+ (cChar == '_') ||
+ (cChar == 0x20) ||
+ (cChar == GLOS_DELIM) )
+ {
+ continue;
+ }
+ throw lang::IllegalArgumentException("group name must contain a-z, A-z, '_', ' ' only", nullptr, 0);
+ }
+ OUString sGroup(aGroupName);
+ if (sGroup.indexOf(GLOS_DELIM)<0)
+ {
+ sGroup += OUStringChar(GLOS_DELIM) + "0";
+ }
+ m_pGlossaries->NewGroupDoc(sGroup, sGroup.getToken(0, GLOS_DELIM));
+
+ uno::Reference< text::XAutoTextGroup > xGroup = m_pGlossaries->GetAutoTextGroup( sGroup );
+ OSL_ENSURE( xGroup.is(), "SwXAutoTextContainer::insertNewByName: no UNO object created? How this?" );
+ // We just inserted the group into the glossaries, so why doesn't it exist?
+
+ return xGroup;
+}
+
+void SwXAutoTextContainer::removeByName(const OUString& aGroupName)
+{
+ SolarMutexGuard aGuard;
+ // At first find the name with path extension
+ OUString sGroupName = m_pGlossaries->GetCompleteGroupName( aGroupName );
+ if(sGroupName.isEmpty())
+ throw container::NoSuchElementException();
+ m_pGlossaries->DelGroupDoc(sGroupName);
+}
+
+OUString SwXAutoTextContainer::getImplementationName()
+{
+ return "SwXAutoTextContainer";
+}
+
+sal_Bool SwXAutoTextContainer::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SwXAutoTextContainer::getSupportedServiceNames()
+{
+ return { "com.sun.star.text.AutoTextContainer" };
+}
+
+SwXAutoTextGroup::SwXAutoTextGroup(const OUString& rName,
+ SwGlossaries* pGlos) :
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_AUTO_TEXT_GROUP)),
+ m_pGlossaries(pGlos),
+ m_sName(rName),
+ m_sGroupName(rName)
+{
+ OSL_ENSURE( -1 != rName.indexOf( GLOS_DELIM ),
+ "SwXAutoTextGroup::SwXAutoTextGroup: to be constructed with a complete name only!" );
+}
+
+SwXAutoTextGroup::~SwXAutoTextGroup()
+{
+}
+
+uno::Sequence< OUString > SwXAutoTextGroup::getTitles()
+{
+ SolarMutexGuard aGuard;
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if (!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+ const sal_uInt16 nCount = pGlosGroup->GetCount();
+
+ uno::Sequence< OUString > aEntryTitles(nCount);
+ OUString *pArr = aEntryTitles.getArray();
+
+ for ( sal_uInt16 i = 0; i < nCount; i++ )
+ pArr[i] = pGlosGroup->GetLongName(i);
+ return aEntryTitles;
+}
+
+void SwXAutoTextGroup::renameByName(const OUString& aElementName,
+ const OUString& aNewElementName, const OUString& aNewElementTitle)
+{
+ SolarMutexGuard aGuard;
+ // throw exception only if the programmatic name is to be changed into an existing name
+ if(aNewElementName != aElementName && hasByName(aNewElementName))
+ throw container::ElementExistException();
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if(!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+
+ const sal_uInt16 nIdx = pGlosGroup->GetIndex( aElementName);
+ if(USHRT_MAX == nIdx)
+ throw lang::IllegalArgumentException();
+ OUString aNewShort(aNewElementName);
+ OUString aNewName(aNewElementTitle);
+ sal_uInt16 nOldLongIdx = pGlosGroup->GetLongIndex( aNewShort );
+ sal_uInt16 nOldIdx = pGlosGroup->GetIndex( aNewName );
+
+ if ((nOldLongIdx == USHRT_MAX || nOldLongIdx == nIdx)
+ && (nOldIdx == USHRT_MAX || nOldIdx == nIdx))
+ {
+ pGlosGroup->Rename( nIdx, &aNewShort, &aNewName );
+ if(pGlosGroup->GetError() != ERRCODE_NONE)
+ throw io::IOException();
+ }
+
+}
+
+static bool lcl_CopySelToDoc(SwDoc& rInsDoc, OTextCursorHelper* pxCursor, SwXTextRange* pxRange)
+{
+ SwNodes& rNds = rInsDoc.GetNodes();
+
+ SwNodeIndex aIdx( rNds.GetEndOfContent(), -1 );
+ SwContentNode * pNd = aIdx.GetNode().GetContentNode();
+ SwPosition aPos(aIdx, pNd, pNd ? pNd->Len() : 0);
+
+ bool bRet = false;
+ rInsDoc.getIDocumentFieldsAccess().LockExpFields();
+ {
+ SwDoc *const pDoc(pxCursor ? pxCursor->GetDoc() : &pxRange->GetDoc());
+ SwPaM aPam(pDoc->GetNodes());
+ SwPaM * pPam(nullptr);
+ if(pxCursor)
+ {
+ pPam = pxCursor->GetPaM();
+ }
+ else
+ {
+ if (pxRange->GetPositions(aPam))
+ {
+ pPam = & aPam;
+ }
+ }
+ if (!pPam) { return false; }
+ bRet = pDoc->getIDocumentContentOperations().CopyRange(*pPam, aPos, SwCopyFlags::CheckPosInFly)
+ || bRet;
+ }
+
+ rInsDoc.getIDocumentFieldsAccess().UnlockExpFields();
+ if( !rInsDoc.getIDocumentFieldsAccess().IsExpFieldsLocked() )
+ rInsDoc.getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
+
+ return bRet;
+}
+
+uno::Reference< text::XAutoTextEntry > SwXAutoTextGroup::insertNewByName(const OUString& aName,
+ const OUString& aTitle, const uno::Reference< text::XTextRange > & xTextRange)
+{
+ SolarMutexGuard aGuard;
+ if(hasByName(aName))
+ throw container::ElementExistException();
+ if(!xTextRange.is())
+ throw uno::RuntimeException();
+
+ std::unique_ptr<SwTextBlocks> pGlosGroup;
+ if (m_pGlossaries)
+ pGlosGroup = m_pGlossaries->GetGroupDoc(m_sGroupName);
+ const OUString& sShortName(aName);
+ const OUString& sLongName(aTitle);
+ if (pGlosGroup && !pGlosGroup->GetError())
+ {
+ SwXTextRange* pxRange = dynamic_cast<SwXTextRange*>(xTextRange.get());
+ OTextCursorHelper* pxCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get());
+
+ OUString sOnlyText;
+ OUString* pOnlyText = nullptr;
+ bool bNoAttr = !pxCursor && !pxRange;
+ if(bNoAttr)
+ {
+ sOnlyText = xTextRange->getString();
+ pOnlyText = &sOnlyText;
+ }
+
+ const SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get();
+
+ SwDoc* pGDoc = pGlosGroup->GetDoc();
+
+ // Until there is an option for that, delete base util::URL
+ if(rCfg.IsSaveRelFile())
+ {
+ INetURLObject aTemp(pGlosGroup->GetFileName());
+ pGlosGroup->SetBaseURL( aTemp.GetMainURL(INetURLObject::DecodeMechanism::NONE));
+ }
+ else
+ pGlosGroup->SetBaseURL( OUString() );
+
+ sal_uInt16 nRet = USHRT_MAX;
+ if( pOnlyText )
+ nRet = pGlosGroup->PutText( sShortName, sLongName, *pOnlyText );
+ else
+ {
+ pGlosGroup->ClearDoc();
+ if( pGlosGroup->BeginPutDoc( sShortName, sLongName ) )
+ {
+ pGDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines );
+ lcl_CopySelToDoc(*pGDoc, pxCursor, pxRange);
+ pGDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern(RedlineFlags::NONE);
+ nRet = pGlosGroup->PutDoc();
+ }
+ }
+
+ if (nRet == USHRT_MAX)
+ {
+ throw uno::RuntimeException();
+ }
+ }
+ pGlosGroup.reset();
+
+ uno::Reference< text::XAutoTextEntry > xEntry;
+
+ try
+ {
+ xEntry = m_pGlossaries ?
+ m_pGlossaries->GetAutoTextEntry( m_sGroupName, m_sName, sShortName ) :
+ uno::Reference< text::XAutoTextEntry >();
+ OSL_ENSURE( xEntry.is(), "SwXAutoTextGroup::insertNewByName: no UNO object created? How this?" );
+ // we just inserted the entry into the group, so why doesn't it exist?
+ }
+ catch (const container::ElementExistException&)
+ {
+ throw;
+ }
+ catch (const uno::RuntimeException&)
+ {
+ throw;
+ }
+ catch (const uno::Exception&)
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException(
+ "Error Getting AutoText!",
+ getXWeak(),
+ anyEx );
+ }
+
+ return xEntry;
+}
+
+void SwXAutoTextGroup::removeByName(const OUString& aEntryName)
+{
+ SolarMutexGuard aGuard;
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if(!pGlosGroup || pGlosGroup->GetError())
+ throw container::NoSuchElementException();
+
+ sal_uInt16 nIdx = pGlosGroup->GetIndex(aEntryName);
+ if ( nIdx == USHRT_MAX )
+ throw container::NoSuchElementException();
+
+ pGlosGroup->Delete(nIdx);
+}
+
+OUString SwXAutoTextGroup::getName()
+{
+ SolarMutexGuard aGuard;
+ return m_sName;
+}
+
+void SwXAutoTextGroup::setName(const OUString& rName)
+{
+ SolarMutexGuard aGuard;
+ if( !m_pGlossaries )
+ throw uno::RuntimeException();
+
+ sal_Int32 nNewDelimPos = rName.lastIndexOf( GLOS_DELIM );
+ sal_Int32 nOldDelimPos = m_sName.lastIndexOf( GLOS_DELIM );
+
+ OUString aNewSuffix;
+ if (nNewDelimPos > -1)
+ aNewSuffix = rName.copy( nNewDelimPos + 1 );
+ OUString aOldSuffix;
+ if (nOldDelimPos > -1)
+ aOldSuffix = m_sName.copy( nOldDelimPos + 1 );
+
+ sal_Int32 nNewNumeric = aNewSuffix.toInt32();
+ sal_Int32 nOldNumeric = aOldSuffix.toInt32();
+
+ OUString aNewPrefix( (nNewDelimPos > 1) ? rName.copy( 0, nNewDelimPos ) : rName );
+ OUString aOldPrefix( (nOldDelimPos > 1) ? m_sName.copy( 0, nOldDelimPos ) : m_sName );
+
+ if ( m_sName == rName ||
+ ( nNewNumeric == nOldNumeric && aNewPrefix == aOldPrefix ) )
+ return;
+ OUString sNewGroup(rName);
+ if (sNewGroup.indexOf(GLOS_DELIM)<0)
+ {
+ sNewGroup += OUStringChar(GLOS_DELIM) + "0";
+ }
+
+ //the name must be saved, the group may be invalidated while in RenameGroupDoc()
+ SwGlossaries* pTempGlossaries = m_pGlossaries;
+
+ OUString sPreserveTitle( m_pGlossaries->GetGroupTitle( m_sName ) );
+ if ( !m_pGlossaries->RenameGroupDoc( m_sName, sNewGroup, sPreserveTitle ) )
+ throw uno::RuntimeException();
+ m_sName = rName;
+ m_sGroupName = sNewGroup;
+ m_pGlossaries = pTempGlossaries;
+}
+
+sal_Int32 SwXAutoTextGroup::getCount()
+{
+ SolarMutexGuard aGuard;
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if (!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+ return static_cast<sal_Int32>(pGlosGroup->GetCount());
+}
+
+uno::Any SwXAutoTextGroup::getByIndex(sal_Int32 nIndex)
+{
+ SolarMutexGuard aGuard;
+ if (!m_pGlossaries)
+ throw uno::RuntimeException();
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries->GetGroupDoc(m_sGroupName));
+ if (!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+ const sal_uInt16 nCount = pGlosGroup->GetCount();
+ if (nIndex < 0 || o3tl::make_unsigned(nIndex) >= nCount)
+ throw lang::IndexOutOfBoundsException();
+ return getByName(pGlosGroup->GetShortName(o3tl::narrowing<sal_uInt16>(nIndex)));
+}
+
+uno::Type SwXAutoTextGroup::getElementType()
+{
+ return cppu::UnoType<text::XAutoTextEntry>::get();
+
+}
+
+sal_Bool SwXAutoTextGroup::hasElements()
+{
+ SolarMutexGuard aGuard;
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if (!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+ return pGlosGroup->GetCount() > 0;
+
+}
+
+uno::Any SwXAutoTextGroup::getByName(const OUString& _rName)
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XAutoTextEntry > xEntry = m_pGlossaries->GetAutoTextEntry( m_sGroupName, m_sName, _rName );
+ OSL_ENSURE( xEntry.is(), "SwXAutoTextGroup::getByName: GetAutoTextEntry is fractious!" );
+ // we told it to create the object, so why didn't it?
+ return css::uno::Any( xEntry );
+}
+
+uno::Sequence< OUString > SwXAutoTextGroup::getElementNames()
+{
+ SolarMutexGuard aGuard;
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if (!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+
+ const sal_uInt16 nCount = pGlosGroup->GetCount();
+ uno::Sequence< OUString > aEntryNames(nCount);
+ OUString *pArr = aEntryNames.getArray();
+
+ for ( sal_uInt16 i = 0; i < nCount; i++ )
+ pArr[i] = pGlosGroup->GetShortName(i);
+ return aEntryNames;
+}
+
+sal_Bool SwXAutoTextGroup::hasByName(const OUString& rName)
+{
+ SolarMutexGuard aGuard;
+ bool bRet = false;
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if (!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+
+ const sal_uInt16 nCount = pGlosGroup->GetCount();
+ for( sal_uInt16 i = 0; i < nCount; ++i )
+ {
+ OUString sCompare(pGlosGroup->GetShortName(i));
+ if(sCompare.equalsIgnoreAsciiCase(rName))
+ {
+ bRet = true;
+ break;
+ }
+ }
+ return bRet;
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXAutoTextGroup::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xRet = m_pPropSet->getPropertySetInfo();
+ return xRet;
+}
+
+void SwXAutoTextGroup::setPropertyValue(
+ const OUString& rPropertyName, const uno::Any& aValue)
+{
+ SolarMutexGuard aGuard;
+ const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
+
+ if(!pEntry)
+ throw beans::UnknownPropertyException(rPropertyName);
+
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if(!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+ switch(pEntry->nWID)
+ {
+ case WID_GROUP_TITLE:
+ {
+ OUString sNewTitle;
+ aValue >>= sNewTitle;
+ if(sNewTitle.isEmpty())
+ throw lang::IllegalArgumentException();
+ bool bChanged = sNewTitle != pGlosGroup->GetName();
+ pGlosGroup->SetName(sNewTitle);
+ if(bChanged && HasGlossaryList())
+ GetGlossaryList()->ClearGroups();
+ }
+ break;
+ }
+}
+
+uno::Any SwXAutoTextGroup::getPropertyValue(const OUString& rPropertyName)
+{
+ SolarMutexGuard aGuard;
+ const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName);
+
+ if(!pEntry)
+ throw beans::UnknownPropertyException(rPropertyName);
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if(!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+
+ uno::Any aAny;
+ switch(pEntry->nWID)
+ {
+ case WID_GROUP_PATH:
+ aAny <<= pGlosGroup->GetFileName();
+ break;
+ case WID_GROUP_TITLE:
+ aAny <<= pGlosGroup->GetName();
+ break;
+ }
+ return aAny;
+}
+
+void SwXAutoTextGroup::addPropertyChangeListener(
+ const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
+{
+}
+
+void SwXAutoTextGroup::removePropertyChangeListener(
+ const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
+{
+}
+
+void SwXAutoTextGroup::addVetoableChangeListener(
+ const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
+{
+}
+
+void SwXAutoTextGroup::removeVetoableChangeListener(
+ const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
+{
+}
+
+void SwXAutoTextGroup::Invalidate()
+{
+ m_pGlossaries = nullptr;
+ m_sName.clear();
+ m_sGroupName.clear();
+}
+
+OUString SwXAutoTextGroup::getImplementationName()
+{
+ return "SwXAutoTextGroup";
+}
+
+sal_Bool SwXAutoTextGroup::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SwXAutoTextGroup::getSupportedServiceNames()
+{
+ uno::Sequence<OUString> aRet { "com.sun.star.text.AutoTextGroup" };
+ return aRet;
+}
+
+SwXAutoTextEntry::SwXAutoTextEntry(SwGlossaries* pGlss, OUString aGroupName,
+ OUString aEntryName) :
+ m_pGlossaries(pGlss),
+ m_sGroupName(std::move(aGroupName)),
+ m_sEntryName(std::move(aEntryName))
+{
+}
+
+SwXAutoTextEntry::~SwXAutoTextEntry()
+{
+ SolarMutexGuard aGuard;
+
+ // ensure that any pending modifications are written
+ implFlushDocument( true );
+}
+
+void SwXAutoTextEntry::implFlushDocument( bool _bCloseDoc )
+{
+ if ( !m_xDocSh.is() )
+ return;
+
+ if ( m_xDocSh->GetDoc()->getIDocumentState().IsModified () )
+ m_xDocSh->Save();
+
+ if ( _bCloseDoc )
+ {
+ // stop listening at the document
+ EndListening( *m_xDocSh );
+
+ m_xDocSh->DoClose();
+ m_xDocSh.clear();
+ }
+}
+
+void SwXAutoTextEntry::Notify( SfxBroadcaster& _rBC, const SfxHint& _rHint )
+{
+ if ( &_rBC != m_xDocSh.get() )
+ return;
+
+// it's our document
+ if (_rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint)
+ {
+ const SfxEventHint& rEventHint = static_cast<const SfxEventHint&>(_rHint);
+ if (SfxEventHintId::PrepareCloseDoc == rEventHint.GetEventId())
+ {
+ implFlushDocument();
+ mxBodyText.clear();
+ EndListening( *m_xDocSh );
+ m_xDocSh.clear();
+ }
+ }
+ else
+ {
+ if ( SfxHintId::Deinitializing == _rHint.GetId() )
+ {
+ // our document is dying (possibly because we're shutting down, and the document was notified
+ // earlier than we are?)
+ // stop listening at the docu
+ EndListening( *m_xDocSh );
+ // and release our reference
+ m_xDocSh.clear();
+ }
+ }
+}
+
+void SwXAutoTextEntry::GetBodyText ()
+{
+ SolarMutexGuard aGuard;
+
+ m_xDocSh = m_pGlossaries->EditGroupDoc ( m_sGroupName, m_sEntryName, false );
+ OSL_ENSURE( m_xDocSh.is(), "SwXAutoTextEntry::GetBodyText: unexpected: no doc returned by EditGroupDoc!" );
+
+ // start listening at the document
+ StartListening( *m_xDocSh );
+
+ mxBodyText = new SwXBodyText ( m_xDocSh->GetDoc() );
+}
+
+void SwXAutoTextEntry::disposing(std::unique_lock<std::mutex>&)
+{
+ SolarMutexGuard g;
+ implFlushDocument(true);
+}
+
+uno::Reference< text::XTextCursor > SwXAutoTextEntry::createTextCursor()
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ return mxBodyText->createTextCursor();
+}
+
+uno::Reference< text::XTextCursor > SwXAutoTextEntry::createTextCursorByRange(
+ const uno::Reference< text::XTextRange > & aTextPosition)
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ return mxBodyText->createTextCursorByRange ( aTextPosition );
+}
+
+void SwXAutoTextEntry::insertString(const uno::Reference< text::XTextRange > & xRange, const OUString& aString, sal_Bool bAbsorb)
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ mxBodyText->insertString ( xRange, aString, bAbsorb );
+}
+
+void SwXAutoTextEntry::insertControlCharacter(const uno::Reference< text::XTextRange > & xRange,
+ sal_Int16 nControlCharacter, sal_Bool bAbsorb)
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ mxBodyText->insertControlCharacter ( xRange, nControlCharacter, bAbsorb );
+}
+
+void SwXAutoTextEntry::insertTextContent(
+ const uno::Reference< text::XTextRange > & xRange,
+ const uno::Reference< text::XTextContent > & xContent, sal_Bool bAbsorb)
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ mxBodyText->insertTextContent ( xRange, xContent, bAbsorb );
+}
+
+void SwXAutoTextEntry::removeTextContent(
+ const uno::Reference< text::XTextContent > & xContent)
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ mxBodyText->removeTextContent ( xContent );
+}
+
+uno::Reference< text::XText > SwXAutoTextEntry::getText()
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XText > xRet = static_cast<text::XText*>(this);
+ return xRet;
+}
+
+uno::Reference< text::XTextRange > SwXAutoTextEntry::getStart()
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ return mxBodyText->getStart();
+}
+
+uno::Reference< text::XTextRange > SwXAutoTextEntry::getEnd()
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ return mxBodyText->getEnd();
+}
+
+OUString SwXAutoTextEntry::getString()
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ return mxBodyText->getString();
+}
+
+void SwXAutoTextEntry::setString(const OUString& aString)
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ mxBodyText->setString( aString );
+}
+
+void SwXAutoTextEntry::applyTo(const uno::Reference< text::XTextRange > & xTextRange)
+{
+ SolarMutexGuard aGuard;
+
+ // ensure that any pending modifications are written
+ // reason is that we're holding the _copy_ of the auto text, while the real auto text
+ // is stored somewhere. And below, we're not working with our copy, but only tell the target
+ // TextRange to work with the stored version.
+ // #96380# - 2003-03-03 - fs@openoffice.org
+ implFlushDocument();
+ // TODO: think about if we should pass "true" here
+ // The difference would be that when the next modification is made to this instance here, then
+ // we would be forced to open the document again, instead of working on our current copy.
+ // This means that we would reflect any changes which were done to the AutoText by foreign instances
+ // in the meantime
+
+ // The reference to xKeepAlive is needed during the whole call, likely because it could be a
+ // different object, not xTextRange itself, and the reference guards it from preliminary death
+ auto xKeepAlive( xTextRange );
+ SwXTextRange* pRange = dynamic_cast<SwXTextRange*>(xTextRange.get());
+ OTextCursorHelper* pCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get());
+ SwXText *pText = dynamic_cast<SwXText*>(xTextRange.get());
+
+ SwDoc* pDoc = nullptr;
+ if (pRange)
+ pDoc = &pRange->GetDoc();
+ else if ( pCursor )
+ pDoc = pCursor->GetDoc();
+ else if ( pText && pText->GetDoc() )
+ {
+ xKeepAlive = pText->getStart();
+ pCursor = dynamic_cast<OTextCursorHelper*>(xKeepAlive.get());
+ if (pCursor)
+ pDoc = pText->GetDoc();
+ }
+
+ if(!pDoc)
+ throw uno::RuntimeException();
+
+ SwPaM InsertPaM(pDoc->GetNodes());
+ if (pRange)
+ {
+ if (!pRange->GetPositions(InsertPaM))
+ {
+ throw uno::RuntimeException();
+ }
+ }
+ else
+ {
+ InsertPaM = *pCursor->GetPaM();
+ }
+
+ std::unique_ptr<SwTextBlocks> pBlock(m_pGlossaries->GetGroupDoc(m_sGroupName));
+ const bool bResult = pBlock && !pBlock->GetError()
+ && pDoc->InsertGlossary( *pBlock, m_sEntryName, InsertPaM);
+
+ if(!bResult)
+ throw uno::RuntimeException();
+}
+
+OUString SwXAutoTextEntry::getImplementationName()
+{
+ return "SwXAutoTextEntry";
+}
+
+sal_Bool SwXAutoTextEntry::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SwXAutoTextEntry::getSupportedServiceNames()
+{
+ uno::Sequence<OUString> aRet { "com.sun.star.text.AutoTextEntry" };
+ return aRet;
+}
+
+uno::Reference< container::XNameReplace > SwXAutoTextEntry::getEvents()
+{
+ return new SwAutoTextEventDescriptor( *this );
+}
+
+const struct SvEventDescription aAutotextEvents[] =
+{
+ { SvMacroItemId::SwStartInsGlossary, "OnInsertStart" },
+ { SvMacroItemId::SwEndInsGlossary, "OnInsertDone" },
+ { SvMacroItemId::NONE, nullptr }
+};
+
+SwAutoTextEventDescriptor::SwAutoTextEventDescriptor(
+ SwXAutoTextEntry& rAutoText ) :
+ SvBaseEventDescriptor(aAutotextEvents),
+ m_rAutoTextEntry(rAutoText)
+{
+}
+
+SwAutoTextEventDescriptor::~SwAutoTextEventDescriptor()
+{
+}
+
+OUString SwAutoTextEventDescriptor::getImplementationName()
+{
+ return "SwAutoTextEventDescriptor";
+}
+
+void SwAutoTextEventDescriptor::replaceByName(
+ const SvMacroItemId nEvent,
+ const SvxMacro& rMacro)
+{
+ OSL_ENSURE( nullptr != m_rAutoTextEntry.GetGlossaries(),
+ "Strangely enough, the AutoText vanished!" );
+ OSL_ENSURE( (nEvent == SvMacroItemId::SwEndInsGlossary) ||
+ (nEvent == SvMacroItemId::SwStartInsGlossary) ,
+ "Unknown event ID" );
+
+ SwGlossaries *const pGlossaries =
+ const_cast<SwGlossaries*>(m_rAutoTextEntry.GetGlossaries());
+ std::unique_ptr<SwTextBlocks> pBlocks(
+ pGlossaries->GetGroupDoc( m_rAutoTextEntry.GetGroupName() ));
+ OSL_ENSURE( pBlocks,
+ "can't get autotext group; SwAutoTextEntry has illegal name?");
+
+ if( !pBlocks || pBlocks->GetError())
+ return;
+
+ sal_uInt16 nIndex = pBlocks->GetIndex( m_rAutoTextEntry.GetEntryName() );
+ if( nIndex != USHRT_MAX )
+ {
+ SvxMacroTableDtor aMacroTable;
+ if( pBlocks->GetMacroTable( nIndex, aMacroTable ) )
+ {
+ aMacroTable.Insert( nEvent, rMacro );
+ pBlocks->SetMacroTable( nIndex, aMacroTable );
+ }
+ }
+ // else: ignore
+}
+
+void SwAutoTextEventDescriptor::getByName(
+ SvxMacro& rMacro,
+ const SvMacroItemId nEvent )
+{
+ OSL_ENSURE( nullptr != m_rAutoTextEntry.GetGlossaries(), "no AutoText" );
+ OSL_ENSURE( (nEvent == SvMacroItemId::SwEndInsGlossary) ||
+ (nEvent == SvMacroItemId::SwStartInsGlossary) ,
+ "Unknown event ID" );
+
+ SwGlossaries *const pGlossaries =
+ const_cast<SwGlossaries*>(m_rAutoTextEntry.GetGlossaries());
+ std::unique_ptr<SwTextBlocks> pBlocks(
+ pGlossaries->GetGroupDoc( m_rAutoTextEntry.GetGroupName() ));
+ OSL_ENSURE( pBlocks,
+ "can't get autotext group; SwAutoTextEntry has illegal name?");
+
+ // return empty macro, unless macro is found
+ OUString sEmptyStr;
+ SvxMacro aEmptyMacro(sEmptyStr, sEmptyStr);
+ rMacro = aEmptyMacro;
+
+ if ( !pBlocks || pBlocks->GetError())
+ return;
+
+ sal_uInt16 nIndex = pBlocks->GetIndex( m_rAutoTextEntry.GetEntryName() );
+ if( nIndex != USHRT_MAX )
+ {
+ SvxMacroTableDtor aMacroTable;
+ if( pBlocks->GetMacroTable( nIndex, aMacroTable ) )
+ {
+ SvxMacro *pMacro = aMacroTable.Get( nEvent );
+ if( pMacro )
+ rMacro = *pMacro;
+ }
+ }
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+SwXAutoTextContainer_get_implementation(css::uno::XComponentContext*,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ //the module may not be loaded
+ SolarMutexGuard aGuard;
+ SwGlobals::ensure();
+ return cppu::acquire(new SwXAutoTextContainer());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uno/unodefaults.cxx b/sw/source/uibase/uno/unodefaults.cxx
new file mode 100644
index 0000000000..b12e804108
--- /dev/null
+++ b/sw/source/uibase/uno/unodefaults.cxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "unodefaults.hxx"
+#include <svx/unoprov.hxx>
+#include <drawdoc.hxx>
+#include <doc.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+
+SwSvxUnoDrawPool::SwSvxUnoDrawPool(SwDoc& rDoc)
+ : SvxUnoDrawPool(rDoc.getIDocumentDrawModelAccess().GetDrawModel(),
+ SvxPropertySetInfoPool::getWriterDrawingDefaults())
+ , m_rDoc(rDoc)
+{
+}
+
+SwSvxUnoDrawPool::~SwSvxUnoDrawPool() noexcept {}
+
+SfxItemPool* SwSvxUnoDrawPool::getModelPool(bool /*bReadOnly*/) noexcept
+{
+ // DVO, OD 01.10.2003 #i18732# - return item pool of writer document;
+ // it contains draw model item pool as secondary pool.
+ //SdrModel* pModel = m_rDoc.MakeDrawModel();
+ //return &pModel->GetItemPool();
+ // #i52858# - method name changed
+ m_rDoc.getIDocumentDrawModelAccess().GetOrCreateDrawModel();
+ return &(m_rDoc.GetAttrPool());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uno/unodefaults.hxx b/sw/source/uibase/uno/unodefaults.hxx
new file mode 100644
index 0000000000..3e01205950
--- /dev/null
+++ b/sw/source/uibase/uno/unodefaults.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <svx/unopool.hxx>
+
+class SwDoc;
+
+class SwSvxUnoDrawPool final : public SvxUnoDrawPool
+{
+ SwDoc& m_rDoc;
+
+public:
+ SwSvxUnoDrawPool(SwDoc& rDoc);
+ virtual ~SwSvxUnoDrawPool() noexcept override;
+
+ virtual SfxItemPool* getModelPool(bool bReadOnly) noexcept override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uno/unodispatch.cxx b/sw/source/uibase/uno/unodispatch.cxx
new file mode 100644
index 0000000000..a67afc31c1
--- /dev/null
+++ b/sw/source/uibase/uno/unodispatch.cxx
@@ -0,0 +1,374 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+#include <config_fuzzers.h>
+
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/dispatch.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <osl/diagnose.h>
+#include <unodispatch.hxx>
+#include <view.hxx>
+#include <cmdid.h>
+#include <wrtsh.hxx>
+#include <dbmgr.hxx>
+
+using namespace ::com::sun::star;
+
+const char cURLFormLetter[] = ".uno:DataSourceBrowser/FormLetter";
+const char cURLInsertContent[] = ".uno:DataSourceBrowser/InsertContent";//data into fields
+const char cURLInsertColumns[] = ".uno:DataSourceBrowser/InsertColumns";//data into text
+const char cURLDocumentDataSource[] = ".uno:DataSourceBrowser/DocumentDataSource";//current data source of the document
+const char cInternalDBChangeNotification[] = ".uno::Writer/DataSourceChanged";
+
+SwXDispatchProviderInterceptor::SwXDispatchProviderInterceptor(SwView& rVw) :
+ m_pView(&rVw)
+{
+ uno::Reference< frame::XFrame> xUnoFrame = m_pView->GetViewFrame().GetFrame().GetFrameInterface();
+ m_xIntercepted.set(xUnoFrame, uno::UNO_QUERY);
+ if(m_xIntercepted.is())
+ {
+ osl_atomic_increment(&m_refCount);
+ m_xIntercepted->registerDispatchProviderInterceptor(static_cast<frame::XDispatchProviderInterceptor*>(this));
+ // this should make us the top-level dispatch-provider for the component, via a call to our
+ // setDispatchProvider we should have got a fallback for requests we (i.e. our master) cannot fulfill
+ uno::Reference< lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY);
+ if (xInterceptedComponent.is())
+ xInterceptedComponent->addEventListener(static_cast<lang::XEventListener*>(this));
+ osl_atomic_decrement(&m_refCount);
+ }
+}
+
+SwXDispatchProviderInterceptor::~SwXDispatchProviderInterceptor()
+{
+}
+
+uno::Reference< frame::XDispatch > SwXDispatchProviderInterceptor::queryDispatch(
+ const util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags )
+{
+ DispatchMutexLock_Impl aLock;
+ uno::Reference< frame::XDispatch> xResult;
+ // create some dispatch ...
+ if(m_pView && aURL.Complete.startsWith(".uno:DataSourceBrowser/"))
+ {
+ if(aURL.Complete == cURLFormLetter ||
+ aURL.Complete == cURLInsertContent ||
+ aURL.Complete == cURLInsertColumns ||
+ aURL.Complete == cURLDocumentDataSource)
+ {
+ if(!m_xDispatch.is())
+ m_xDispatch = new SwXDispatch(*m_pView);
+ xResult = m_xDispatch;
+ }
+ }
+
+ // ask our slave provider
+ if (!xResult.is() && m_xSlaveDispatcher.is())
+ xResult = m_xSlaveDispatcher->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
+
+ return xResult;
+}
+
+uno::Sequence<OUString> SAL_CALL SwXDispatchProviderInterceptor::getInterceptedURLs()
+{
+ uno::Sequence<OUString> aRet =
+ {
+ OUString(".uno:DataSourceBrowser/*")
+ };
+
+ return aRet;
+}
+
+uno::Sequence< uno::Reference< frame::XDispatch > > SwXDispatchProviderInterceptor::queryDispatches(
+ const uno::Sequence< frame::DispatchDescriptor >& aDescripts )
+{
+ DispatchMutexLock_Impl aLock;
+ uno::Sequence< uno::Reference< frame::XDispatch> > aReturn(aDescripts.getLength());
+ std::transform(aDescripts.begin(), aDescripts.end(), aReturn.getArray(),
+ [this](const frame::DispatchDescriptor& rDescr) -> uno::Reference<frame::XDispatch> {
+ return queryDispatch(rDescr.FeatureURL, rDescr.FrameName, rDescr.SearchFlags); });
+ return aReturn;
+}
+
+uno::Reference< frame::XDispatchProvider > SwXDispatchProviderInterceptor::getSlaveDispatchProvider( )
+{
+ DispatchMutexLock_Impl aLock;
+ return m_xSlaveDispatcher;
+}
+
+void SwXDispatchProviderInterceptor::setSlaveDispatchProvider(
+ const uno::Reference< frame::XDispatchProvider >& xNewDispatchProvider )
+{
+ DispatchMutexLock_Impl aLock;
+ m_xSlaveDispatcher = xNewDispatchProvider;
+}
+
+uno::Reference< frame::XDispatchProvider > SwXDispatchProviderInterceptor::getMasterDispatchProvider( )
+{
+ DispatchMutexLock_Impl aLock;
+ return m_xMasterDispatcher;
+}
+
+void SwXDispatchProviderInterceptor::setMasterDispatchProvider(
+ const uno::Reference< frame::XDispatchProvider >& xNewSupplier )
+{
+ DispatchMutexLock_Impl aLock;
+ m_xMasterDispatcher = xNewSupplier;
+}
+
+void SwXDispatchProviderInterceptor::disposing( const lang::EventObject& )
+{
+ DispatchMutexLock_Impl aLock;
+ if (m_xIntercepted.is())
+ {
+ m_xIntercepted->releaseDispatchProviderInterceptor(static_cast<frame::XDispatchProviderInterceptor*>(this));
+ uno::Reference< lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY);
+ if (xInterceptedComponent.is())
+ xInterceptedComponent->removeEventListener(static_cast<lang::XEventListener*>(this));
+ m_xDispatch = nullptr;
+ }
+ m_xIntercepted = nullptr;
+}
+
+void SwXDispatchProviderInterceptor::Invalidate()
+{
+ DispatchMutexLock_Impl aLock;
+ if (m_xIntercepted.is())
+ {
+ m_xIntercepted->releaseDispatchProviderInterceptor(static_cast<frame::XDispatchProviderInterceptor*>(this));
+ uno::Reference< lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY);
+ if (xInterceptedComponent.is())
+ xInterceptedComponent->removeEventListener(static_cast<lang::XEventListener*>(this));
+ m_xDispatch = nullptr;
+ }
+ m_xIntercepted = nullptr;
+ m_pView = nullptr;
+}
+
+SwXDispatch::SwXDispatch(SwView& rVw) :
+ m_pView(&rVw),
+ m_bOldEnable(false),
+ m_bListenerAdded(false)
+{
+}
+
+SwXDispatch::~SwXDispatch()
+{
+ if(m_bListenerAdded && m_pView)
+ {
+ uno::Reference<view::XSelectionSupplier> xSupplier = m_pView->GetUNOObject();
+ uno::Reference<view::XSelectionChangeListener> xThis = this;
+ xSupplier->removeSelectionChangeListener(xThis);
+ }
+}
+
+void SwXDispatch::dispatch(const util::URL& aURL,
+ const uno::Sequence< beans::PropertyValue >& aArgs)
+{
+ if(!m_pView)
+ throw uno::RuntimeException();
+#if !HAVE_FEATURE_DBCONNECTIVITY || ENABLE_FUZZERS
+ (void) aArgs;
+ if (false)
+ {
+ }
+#else
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ SwDBManager* pDBManager = rSh.GetDBManager();
+ if(aURL.Complete == cURLInsertContent)
+ {
+ svx::ODataAccessDescriptor aDescriptor(aArgs);
+ SwMergeDescriptor aMergeDesc( DBMGR_MERGE, rSh, aDescriptor );
+ pDBManager->Merge(aMergeDesc);
+ }
+ else if(aURL.Complete == cURLInsertColumns)
+ {
+ SwDBManager::InsertText(rSh, aArgs);
+ }
+ else if(aURL.Complete == cURLFormLetter)
+ {
+ SfxUnoAnyItem aDBProperties(FN_PARAM_DATABASE_PROPERTIES, uno::Any(aArgs));
+ m_pView->GetViewFrame().GetDispatcher()->ExecuteList(
+ FN_MAILMERGE_WIZARD,
+ SfxCallMode::ASYNCHRON,
+ { &aDBProperties });
+ }
+#endif
+ else if(aURL.Complete == cURLDocumentDataSource)
+ {
+ OSL_FAIL("SwXDispatch::dispatch: this URL is not to be dispatched!");
+ }
+ else if(aURL.Complete == cInternalDBChangeNotification)
+ {
+ frame::FeatureStateEvent aEvent;
+ aEvent.Source = getXWeak();
+
+ const SwDBData& rData = m_pView->GetWrtShell().GetDBData();
+ svx::ODataAccessDescriptor aDescriptor;
+ aDescriptor.setDataSource(rData.sDataSource);
+ aDescriptor[svx::DataAccessDescriptorProperty::Command] <<= rData.sCommand;
+ aDescriptor[svx::DataAccessDescriptorProperty::CommandType] <<= rData.nCommandType;
+
+ aEvent.State <<= aDescriptor.createPropertyValueSequence();
+ aEvent.IsEnabled = !rData.sDataSource.isEmpty();
+
+ // calls to statusChanged may call addStatusListener or removeStatusListener
+ // so copy m_aStatusListenerVector on stack
+ auto copyStatusListenerVector = m_aStatusListenerVector;
+ for (auto & status : copyStatusListenerVector)
+ {
+ if(status.aURL.Complete == cURLDocumentDataSource)
+ {
+ aEvent.FeatureURL = status.aURL;
+ status.xListener->statusChanged( aEvent );
+ }
+ }
+ }
+ else
+ throw uno::RuntimeException();
+
+}
+
+void SwXDispatch::addStatusListener(
+ const uno::Reference< frame::XStatusListener >& xControl, const util::URL& aURL )
+{
+ if(!m_pView)
+ throw uno::RuntimeException();
+ ShellMode eMode = m_pView->GetShellMode();
+ bool bEnable = ShellMode::Text == eMode ||
+ ShellMode::ListText == eMode ||
+ ShellMode::TableText == eMode ||
+ ShellMode::TableListText == eMode;
+
+ m_bOldEnable = bEnable;
+ frame::FeatureStateEvent aEvent;
+ aEvent.IsEnabled = bEnable;
+ aEvent.Source = getXWeak();
+ aEvent.FeatureURL = aURL;
+
+ // one of the URLs requires a special state...
+ if (aURL.Complete == cURLDocumentDataSource)
+ {
+ const SwDBData& rData = m_pView->GetWrtShell().GetDBData();
+
+ svx::ODataAccessDescriptor aDescriptor;
+ aDescriptor.setDataSource(rData.sDataSource);
+ aDescriptor[svx::DataAccessDescriptorProperty::Command] <<= rData.sCommand;
+ aDescriptor[svx::DataAccessDescriptorProperty::CommandType] <<= rData.nCommandType;
+
+ aEvent.State <<= aDescriptor.createPropertyValueSequence();
+ aEvent.IsEnabled = !rData.sDataSource.isEmpty();
+ }
+
+ xControl->statusChanged( aEvent );
+
+ StatusStruct_Impl aStatus;
+ aStatus.xListener = xControl;
+ aStatus.aURL = aURL;
+ m_aStatusListenerVector.emplace_back(aStatus);
+
+ if(!m_bListenerAdded)
+ {
+ uno::Reference<view::XSelectionSupplier> xSupplier = m_pView->GetUNOObject();
+ uno::Reference<view::XSelectionChangeListener> xThis = this;
+ xSupplier->addSelectionChangeListener(xThis);
+ m_bListenerAdded = true;
+ }
+}
+
+void SwXDispatch::removeStatusListener(
+ const uno::Reference< frame::XStatusListener >& xControl, const util::URL& )
+{
+ std::erase_if(
+ m_aStatusListenerVector,
+ [&](const StatusStruct_Impl& status) { return status.xListener.get() == xControl.get(); });
+ if(m_aStatusListenerVector.empty() && m_pView)
+ {
+ uno::Reference<view::XSelectionSupplier> xSupplier = m_pView->GetUNOObject();
+ uno::Reference<view::XSelectionChangeListener> xThis = this;
+ xSupplier->removeSelectionChangeListener(xThis);
+ m_bListenerAdded = false;
+ }
+}
+
+void SwXDispatch::selectionChanged( const lang::EventObject& )
+{
+ ShellMode eMode = m_pView->GetShellMode();
+ bool bEnable = ShellMode::Text == eMode ||
+ ShellMode::ListText == eMode ||
+ ShellMode::TableText == eMode ||
+ ShellMode::TableListText == eMode;
+ if(bEnable == m_bOldEnable)
+ return;
+
+ m_bOldEnable = bEnable;
+ frame::FeatureStateEvent aEvent;
+ aEvent.IsEnabled = bEnable;
+ aEvent.Source = getXWeak();
+
+ // calls to statusChanged may call addStatusListener or removeStatusListener
+ // so copy m_aStatusListenerVector on stack
+ auto copyStatusListenerVector = m_aStatusListenerVector;
+ for (auto & status : copyStatusListenerVector)
+ {
+ aEvent.FeatureURL = status.aURL;
+ if (status.aURL.Complete != cURLDocumentDataSource)
+ // the document's data source does not depend on the selection, so it's state does not change here
+ status.xListener->statusChanged( aEvent );
+ }
+}
+
+void SwXDispatch::disposing( const lang::EventObject& rSource )
+{
+ uno::Reference<view::XSelectionSupplier> xSupplier(rSource.Source, uno::UNO_QUERY);
+ uno::Reference<view::XSelectionChangeListener> xThis = this;
+ xSupplier->removeSelectionChangeListener(xThis);
+ m_bListenerAdded = false;
+
+ lang::EventObject aObject;
+ aObject.Source = getXWeak();
+ // calls to statusChanged may call addStatusListener or removeStatusListener
+ // so copy m_aStatusListenerVector on stack
+ auto copyStatusListenerVector = m_aStatusListenerVector;
+ for (auto & status : copyStatusListenerVector)
+ {
+ status.xListener->disposing(aObject);
+ }
+ m_pView = nullptr;
+}
+
+const char* SwXDispatch::GetDBChangeURL()
+{
+ return cInternalDBChangeNotification;
+}
+
+SwXDispatchProviderInterceptor::DispatchMutexLock_Impl::DispatchMutexLock_Impl()
+{
+}
+
+SwXDispatchProviderInterceptor::DispatchMutexLock_Impl::~DispatchMutexLock_Impl()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uno/unodoc.cxx b/sw/source/uibase/uno/unodoc.cxx
new file mode 100644
index 0000000000..b525d2e366
--- /dev/null
+++ b/sw/source/uibase/uno/unodoc.cxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+#include <config_features.h>
+#include <config_fuzzers.h>
+
+#include <sfx2/sfxmodelfactory.hxx>
+#include <swdll.hxx>
+#include <docsh.hxx>
+#include <globdoc.hxx>
+#include <wdocsh.hxx>
+#include <vcl/svapp.hxx>
+#include <unomailmerge.hxx>
+
+using namespace ::com::sun::star;
+
+// com.sun.star.comp.Writer.TextDocument
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+Writer_SwTextDocument_get_implementation(
+ css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const& args)
+{
+ SolarMutexGuard aGuard;
+ SwGlobals::ensure();
+ css::uno::Reference<css::uno::XInterface> xInterface = sfx2::createSfxModelInstance(args,
+ [](SfxModelFlags _nCreationFlags)
+ {
+ SfxObjectShell* pShell = new SwDocShell( _nCreationFlags );
+ return pShell->GetModel();
+ });
+ xInterface->acquire();
+ return xInterface.get();
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Writer_WebDocument_get_implementation(css::uno::XComponentContext*,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ SolarMutexGuard aGuard;
+ SwGlobals::ensure();
+ SfxObjectShell* pShell = new SwWebDocShell;
+ uno::Reference< uno::XInterface > model( pShell->GetModel() );
+ model->acquire();
+ return model.get();
+}
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Writer_GlobalDocument_get_implementation(css::uno::XComponentContext*,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ SolarMutexGuard aGuard;
+ SwGlobals::ensure();
+ SfxObjectShell* pShell = new SwGlobalDocShell( SfxObjectCreateMode::STANDARD );
+ uno::Reference< uno::XInterface > model( pShell->GetModel() );
+ model->acquire();
+ return model.get();
+}
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+SwXMailMerge_get_implementation(css::uno::XComponentContext*,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+ SolarMutexGuard aGuard;
+
+ //the module may not be loaded
+ SwGlobals::ensure();
+ return cppu::acquire(new SwXMailMerge());
+#else
+ return nullptr;
+#endif
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uno/unomailmerge.cxx b/sw/source/uibase/uno/unomailmerge.cxx
new file mode 100644
index 0000000000..2b5fecf21b
--- /dev/null
+++ b/sw/source/uibase/uno/unomailmerge.cxx
@@ -0,0 +1,1168 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <comphelper/servicehelper.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <osl/mutex.hxx>
+#include <svl/itemprop.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#include <unotools/tempfile.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/docfilt.hxx>
+#include <tools/urlobj.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/string.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <vcl/timer.hxx>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/text/MailMergeType.hpp>
+#include <com/sun/star/text/MailMergeEvent.hpp>
+#include <com/sun/star/text/XMailMergeListener.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XRowSet.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/util/CloseVetoException.hpp>
+#include <com/sun/star/sdbcx/XRowLocate.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/mail/XSmtpService.hpp>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/event.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <printdata.hxx>
+#include <swevent.hxx>
+#include <unomailmerge.hxx>
+#include <unoprnms.hxx>
+#include <unomap.hxx>
+#include <swunohelper.hxx>
+#include <docsh.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <view.hxx>
+#include <dbmgr.hxx>
+#include <unotxdoc.hxx>
+#include <wrtsh.hxx>
+#include <mmconfigitem.hxx>
+#include <mailmergehelper.hxx>
+
+#include <iodetect.hxx>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::text;
+using namespace SWUnoHelper;
+
+typedef ::utl::SharedUNOComponent< XInterface > SharedComponent;
+
+static osl::Mutex & GetMailMergeMutex()
+{
+ static osl::Mutex aMutex;
+ return aMutex;
+}
+
+namespace {
+
+enum CloseResult
+{
+ eSuccess, // successfully closed
+ eVetoed, // vetoed, ownership transferred to the vetoing instance
+ eFailed // failed for some unknown reason
+};
+
+}
+
+static CloseResult CloseModelAndDocSh(
+ Reference< frame::XModel > const &rxModel,
+ SfxObjectShellRef &rxDocSh )
+{
+ CloseResult eResult = eSuccess;
+
+ rxDocSh = nullptr;
+
+ //! models/documents should never be disposed (they may still be
+ //! used for printing which is called asynchronously for example)
+ //! instead call close
+ Reference< util::XCloseable > xClose( rxModel, UNO_QUERY );
+ if (xClose.is())
+ {
+ try
+ {
+ //! 'sal_True' -> transfer ownership to vetoing object if vetoed!
+ //! I.e. now that object is responsible for closing the model and doc shell.
+ xClose->close( true );
+ }
+ catch (const util::CloseVetoException&)
+ {
+ //! here we have the problem that the temporary file that is
+ //! currently being printed will never be deleted. :-(
+ eResult = eVetoed;
+ }
+ catch (const uno::RuntimeException&)
+ {
+ eResult = eFailed;
+ }
+ }
+ return eResult;
+}
+
+/// @throws RuntimeException
+static bool LoadFromURL_impl(
+ Reference< frame::XModel > &rxModel,
+ SfxObjectShellRef &rxDocSh,
+ const OUString &rURL,
+ bool bClose )
+{
+ // try to open the document readonly and hidden
+ Reference< frame::XModel > xTmpModel;
+ Sequence < PropertyValue > aArgs{ comphelper::makePropertyValue("Hidden", true) };
+ try
+ {
+ Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
+ xTmpModel.set( xDesktop->loadComponentFromURL( rURL, "_blank", 0, aArgs ), UNO_QUERY );
+ }
+ catch (const Exception&)
+ {
+ return false;
+ }
+
+ // try to get the DocShell
+ SwDocShell *pTmpDocShell = nullptr;
+ if (auto pTextDoc = comphelper::getFromUnoTunnel<SwXTextDocument>(xTmpModel); pTextDoc)
+ pTmpDocShell = pTextDoc->GetDocShell();
+
+ bool bRes = false;
+ if (xTmpModel.is() && pTmpDocShell) // everything available?
+ {
+ if (bClose)
+ CloseModelAndDocSh( rxModel, rxDocSh );
+ // set new stuff
+ rxModel = xTmpModel;
+ rxDocSh = pTmpDocShell;
+ bRes = true;
+ }
+ else
+ {
+ // SfxObjectShellRef is ok here, since the document will be explicitly closed
+ SfxObjectShellRef xTmpDocSh = pTmpDocShell;
+ CloseModelAndDocSh( xTmpModel, xTmpDocSh );
+ }
+
+ return bRes;
+}
+
+namespace
+{
+ class DelayedFileDeletion : public ::cppu::WeakImplHelper<util::XCloseListener>
+ {
+ protected:
+ ::osl::Mutex m_aMutex;
+ Reference< util::XCloseable > m_xDocument;
+ Timer m_aDeleteTimer;
+ OUString m_sTemporaryFile;
+ sal_Int32 m_nPendingDeleteAttempts;
+
+ DelayedFileDeletion(DelayedFileDeletion const&) = delete;
+ DelayedFileDeletion& operator=(DelayedFileDeletion const&) = delete;
+
+ public:
+ DelayedFileDeletion( const Reference< XModel >& _rxModel,
+ OUString _aTemporaryFile );
+
+ protected:
+ virtual ~DelayedFileDeletion( ) override;
+
+ // XCloseListener
+ virtual void SAL_CALL queryClosing( const EventObject& _rSource, sal_Bool _bGetsOwnership ) override;
+ virtual void SAL_CALL notifyClosing( const EventObject& _rSource ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const EventObject& Source ) override;
+
+ private:
+ void implTakeOwnership( );
+ DECL_LINK( OnTryDeleteFile, Timer*, void );
+ };
+
+ DelayedFileDeletion::DelayedFileDeletion( const Reference< XModel >& _rxModel, OUString _aTemporaryFile )
+ :
+ m_xDocument( _rxModel, UNO_QUERY )
+ ,m_aDeleteTimer("sw DelayedFileDeletion m_aDeleteTimer")
+ ,m_sTemporaryFile(std::move( _aTemporaryFile ))
+ ,m_nPendingDeleteAttempts( 0 )
+ {
+ osl_atomic_increment( &m_refCount );
+ try
+ {
+ if ( m_xDocument.is() )
+ {
+ m_xDocument->addCloseListener( this );
+ // successfully added -> keep ourself alive
+ acquire();
+ }
+ else {
+ OSL_FAIL("DelayedFileDeletion::DelayedFileDeletion: model is no component!" );
+ }
+ }
+ catch (const Exception&)
+ {
+ OSL_FAIL("DelayedFileDeletion::DelayedFileDeletion: could not register as event listener at the model!" );
+ }
+ osl_atomic_decrement( &m_refCount );
+ }
+
+ IMPL_LINK_NOARG(DelayedFileDeletion, OnTryDeleteFile, Timer *, void)
+ {
+ ::osl::ClearableMutexGuard aGuard( m_aMutex );
+
+ bool bSuccess = false;
+ try
+ {
+ bool bDeliverOwnership = ( 0 == m_nPendingDeleteAttempts );
+ // if this is our last attempt, then anybody which vetoes this has to take the consequences
+ // (means take the ownership)
+ m_xDocument->close( bDeliverOwnership );
+ bSuccess = true;
+ }
+ catch (const util::CloseVetoException&)
+ {
+ // somebody vetoed -> next try
+ if ( m_nPendingDeleteAttempts )
+ {
+ // next attempt
+ --m_nPendingDeleteAttempts;
+ m_aDeleteTimer.Start();
+ }
+ else
+ bSuccess = true; // can't do anything here ...
+ }
+ catch (const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "sw", "DelayedFileDeletion::OnTryDeleteFile: caught a strange exception!" );
+ bSuccess = true;
+ // can't do anything here ...
+ }
+
+ if ( bSuccess )
+ {
+ SWUnoHelper::UCB_DeleteFile( m_sTemporaryFile );
+ aGuard.clear();
+ release(); // this should be our last reference, we should be dead after this
+ }
+ }
+
+ void DelayedFileDeletion::implTakeOwnership( )
+ {
+ // revoke ourself as listener
+ try
+ {
+ m_xDocument->removeCloseListener( this );
+ }
+ catch (const Exception&)
+ {
+ OSL_FAIL("DelayedFileDeletion::implTakeOwnership: could not revoke the listener!" );
+ }
+
+ m_aDeleteTimer.SetTimeout( 3000 ); // 3 seconds
+ m_aDeleteTimer.SetInvokeHandler( LINK( this, DelayedFileDeletion, OnTryDeleteFile ) );
+ m_nPendingDeleteAttempts = 3; // try 3 times at most
+ m_aDeleteTimer.Start( );
+ }
+
+ void SAL_CALL DelayedFileDeletion::queryClosing( const EventObject& , sal_Bool _bGetsOwnership )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( _bGetsOwnership )
+ implTakeOwnership( );
+
+ // always veto: We want to take the ownership ourself, as this is the only chance to delete
+ // the temporary file which the model is based on
+ throw util::CloseVetoException( );
+ }
+
+ void SAL_CALL DelayedFileDeletion::notifyClosing( const EventObject& )
+ {
+ OSL_FAIL("DelayedFileDeletion::notifyClosing: how this?" );
+ // this should not happen:
+ // Either, a foreign instance closes the document, then we should veto this, and take the ownership
+ // Or, we ourself close the document, then we should not be a listener anymore
+ }
+
+ void SAL_CALL DelayedFileDeletion::disposing( const EventObject& )
+ {
+ OSL_FAIL("DelayedFileDeletion::disposing: how this?" );
+ // this should not happen:
+ // Either, a foreign instance closes the document, then we should veto this, and take the ownership
+ // Or, we ourself close the document, then we should not be a listener anymore
+ }
+
+ DelayedFileDeletion::~DelayedFileDeletion( )
+ {
+ }
+}
+
+static bool DeleteTmpFile_Impl(
+ Reference< frame::XModel > &rxModel,
+ SfxObjectShellRef &rxDocSh,
+ const OUString &rTmpFileURL )
+{
+ bool bRes = false;
+ if (!rTmpFileURL.isEmpty())
+ {
+ bool bDelete = true;
+ if ( eVetoed == CloseModelAndDocSh( rxModel, rxDocSh ) )
+ {
+ // somebody vetoed the closing, and took the ownership of the document
+ // -> ensure that the temporary file is deleted later on
+ new DelayedFileDeletion( rxModel, rTmpFileURL );
+ // note: as soon as #106931# is fixed, the whole DelayedFileDeletion is to be superseded by
+ // a better solution
+ bDelete = false;
+ }
+
+ rxModel = nullptr;
+ rxDocSh = nullptr; // destroy doc shell
+
+ if ( bDelete )
+ {
+ if ( !SWUnoHelper::UCB_DeleteFile( rTmpFileURL ) )
+ {
+ new DelayedFileDeletion( rxModel, rTmpFileURL );
+ // same not as above: as soon as #106931#, ...
+ }
+ }
+ else
+ bRes = true; // file will be deleted delayed
+ }
+ return bRes;
+}
+
+SwXMailMerge::SwXMailMerge() :
+ m_aEvtListeners ( GetMailMergeMutex() ),
+ m_aMergeListeners ( GetMailMergeMutex() ),
+ m_aPropListeners ( GetMailMergeMutex() ),
+ m_pPropSet( aSwMapProvider.GetPropertySet( PROPERTY_MAP_MAILMERGE ) ),
+ m_nDataCommandType(sdb::CommandType::TABLE),
+ m_nOutputType(MailMergeType::PRINTER),
+ m_bEscapeProcessing(true), //!! allow to process properties like "Filter", "Order", ...
+ m_bSinglePrintJobs(false),
+ m_bFileNameFromColumn(false),
+ m_bSendAsHTML(false),
+ m_bSendAsAttachment(false),
+ m_bSaveAsSingleFile(false),
+ m_bDisposing(false),
+ m_pMgr(nullptr)
+{
+ // create empty document
+ // like in: SwModule::InsertEnv (appenv.cxx)
+ m_xDocSh = new SwDocShell( SfxObjectCreateMode::STANDARD );
+ m_xDocSh->DoInitNew();
+ SfxViewFrame *pFrame = SfxViewFrame::LoadHiddenDocument( *m_xDocSh, SFX_INTERFACE_NONE );
+ SwView *pView = static_cast<SwView*>( pFrame->GetViewShell() );
+ pView->AttrChangedNotify(nullptr); //So that SelectShell is called.
+ m_xModel = m_xDocSh->GetModel();
+}
+
+SwXMailMerge::~SwXMailMerge()
+{
+ if (!m_aTmpFileName.isEmpty())
+ DeleteTmpFile_Impl( m_xModel, m_xDocSh, m_aTmpFileName );
+ else // there was no temporary file in use
+ {
+ //! we still need to close the model and doc shell manually
+ //! because there is no automatism that will do that later.
+ //! #120086#
+ if ( eVetoed == CloseModelAndDocSh( m_xModel, m_xDocSh ) )
+ OSL_FAIL("ownership transferred to vetoing object!" );
+
+ m_xModel = nullptr;
+ m_xDocSh = nullptr; // destroy doc shell
+ }
+}
+
+// Guarantee object consistence in case of an exception
+class MailMergeExecuteFinalizer
+{
+public:
+ explicit MailMergeExecuteFinalizer(SwXMailMerge *mailmerge)
+ : m_pMailMerge(mailmerge)
+ {
+ assert(m_pMailMerge); //mailmerge object missing
+ }
+ ~MailMergeExecuteFinalizer()
+ {
+ osl::MutexGuard aMgrGuard( GetMailMergeMutex() );
+ m_pMailMerge->m_pMgr = nullptr;
+ }
+
+private:
+ MailMergeExecuteFinalizer(MailMergeExecuteFinalizer const&) = delete;
+ MailMergeExecuteFinalizer& operator=(MailMergeExecuteFinalizer const&) = delete;
+
+ SwXMailMerge *m_pMailMerge;
+};
+
+uno::Any SAL_CALL SwXMailMerge::execute(
+ const uno::Sequence< beans::NamedValue >& rArguments )
+{
+ SolarMutexGuard aGuard;
+ MailMergeExecuteFinalizer aFinalizer(this);
+
+ // get property values to be used
+ // (use values from the service as default and override them with
+ // the values that are provided as arguments)
+
+ uno::Sequence< uno::Any > aCurSelection = m_aSelection;
+ uno::Reference< sdbc::XResultSet > xCurResultSet = m_xResultSet;
+ uno::Reference< sdbc::XConnection > xCurConnection = m_xConnection;
+ uno::Reference< frame::XModel > xCurModel = m_xModel;
+ OUString aCurDataSourceName = m_aDataSourceName;
+ OUString aCurDataCommand = m_aDataCommand;
+ OUString aCurFilter = m_aFilter;
+ OUString aCurDocumentURL = m_aDocumentURL;
+ OUString aCurOutputURL = m_aOutputURL;
+ OUString aCurFileNamePrefix = m_aFileNamePrefix;
+ sal_Int32 nCurDataCommandType = m_nDataCommandType;
+ sal_Int16 nCurOutputType = m_nOutputType;
+ bool bCurEscapeProcessing = m_bEscapeProcessing;
+ bool bCurSinglePrintJobs = m_bSinglePrintJobs;
+ bool bCurFileNameFromColumn = m_bFileNameFromColumn;
+
+ SfxObjectShellRef xCurDocSh = m_xDocSh; // the document
+
+ for (const beans::NamedValue& rArgument : rArguments)
+ {
+ const OUString &rName = rArgument.Name;
+ const Any &rValue = rArgument.Value;
+
+ bool bOK = true;
+ if (rName == UNO_NAME_SELECTION)
+ bOK = rValue >>= aCurSelection;
+ else if (rName == UNO_NAME_RESULT_SET)
+ bOK = rValue >>= xCurResultSet;
+ else if (rName == UNO_NAME_CONNECTION)
+ bOK = rValue >>= xCurConnection;
+ else if (rName == UNO_NAME_MODEL)
+ throw PropertyVetoException("Property is read-only: " + rName, getXWeak() );
+ else if (rName == UNO_NAME_DATA_SOURCE_NAME)
+ bOK = rValue >>= aCurDataSourceName;
+ else if (rName == UNO_NAME_DAD_COMMAND)
+ bOK = rValue >>= aCurDataCommand;
+ else if (rName == UNO_NAME_FILTER)
+ bOK = rValue >>= aCurFilter;
+ else if (rName == UNO_NAME_DOCUMENT_URL)
+ {
+ bOK = rValue >>= aCurDocumentURL;
+ if (!aCurDocumentURL.isEmpty()
+ && !LoadFromURL_impl( xCurModel, xCurDocSh, aCurDocumentURL, false ))
+ throw RuntimeException("Failed to create document from URL: " + aCurDocumentURL, getXWeak() );
+ }
+ else if (rName == UNO_NAME_OUTPUT_URL)
+ {
+ bOK = rValue >>= aCurOutputURL;
+ if (!aCurOutputURL.isEmpty())
+ {
+ if (!UCB_IsDirectory(aCurOutputURL))
+ throw IllegalArgumentException("URL does not point to a directory: " + aCurOutputURL, getXWeak(), 0 );
+ if (UCB_IsReadOnlyFileName(aCurOutputURL))
+ throw IllegalArgumentException("URL is read-only: " + aCurOutputURL, getXWeak(), 0 );
+ }
+ }
+ else if (rName == UNO_NAME_FILE_NAME_PREFIX)
+ bOK = rValue >>= aCurFileNamePrefix;
+ else if (rName == UNO_NAME_DAD_COMMAND_TYPE)
+ bOK = rValue >>= nCurDataCommandType;
+ else if (rName == UNO_NAME_OUTPUT_TYPE)
+ bOK = rValue >>= nCurOutputType;
+ else if (rName == UNO_NAME_ESCAPE_PROCESSING)
+ bOK = rValue >>= bCurEscapeProcessing;
+ else if (rName == UNO_NAME_SINGLE_PRINT_JOBS)
+ bOK = rValue >>= bCurSinglePrintJobs;
+ else if (rName == UNO_NAME_FILE_NAME_FROM_COLUMN)
+ bOK = rValue >>= bCurFileNameFromColumn;
+ else if (rName == UNO_NAME_SUBJECT)
+ bOK = rValue >>= m_sSubject;
+ else if (rName == UNO_NAME_ADDRESS_FROM_COLUMN)
+ bOK = rValue >>= m_sAddressFromColumn;
+ else if (rName == UNO_NAME_SEND_AS_HTML)
+ bOK = rValue >>= m_bSendAsHTML;
+ else if (rName == UNO_NAME_MAIL_BODY)
+ bOK = rValue >>= m_sMailBody;
+ else if (rName == UNO_NAME_ATTACHMENT_NAME)
+ bOK = rValue >>= m_sAttachmentName;
+ else if (rName == UNO_NAME_ATTACHMENT_FILTER)
+ bOK = rValue >>= m_sAttachmentFilter;
+ else if (rName == UNO_NAME_COPIES_TO)
+ bOK = rValue >>= m_aCopiesTo;
+ else if (rName == UNO_NAME_BLIND_COPIES_TO)
+ bOK = rValue >>= m_aBlindCopiesTo;
+ else if (rName == UNO_NAME_SEND_AS_ATTACHMENT)
+ bOK = rValue >>= m_bSendAsAttachment;
+ else if (rName == UNO_NAME_PRINT_OPTIONS)
+ bOK = rValue >>= m_aPrintSettings;
+ else if (rName == UNO_NAME_SAVE_AS_SINGLE_FILE)
+ bOK = rValue >>= m_bSaveAsSingleFile;
+ else if (rName == UNO_NAME_SAVE_FILTER)
+ bOK = rValue >>= m_sSaveFilter;
+ else if (rName == UNO_NAME_SAVE_FILTER_OPTIONS)
+ bOK = rValue >>= m_sSaveFilterOptions;
+ else if (rName == UNO_NAME_SAVE_FILTER_DATA)
+ bOK = rValue >>= m_aSaveFilterData;
+ else if (rName == UNO_NAME_IN_SERVER_PASSWORD)
+ bOK = rValue >>= m_sInServerPassword;
+ else if (rName == UNO_NAME_OUT_SERVER_PASSWORD)
+ bOK = rValue >>= m_sOutServerPassword;
+ else
+ throw UnknownPropertyException( "Property is unknown: " + rName, getXWeak() );
+
+ if (!bOK)
+ throw IllegalArgumentException("Property type mismatch or property not set: " + rName, getXWeak(), 0 );
+ }
+
+ // need to translate the selection: the API here requires a sequence of bookmarks, but the Merge
+ // method we will call below requires a sequence of indices.
+ if ( aCurSelection.hasElements() )
+ {
+ Sequence< Any > aTranslated( aCurSelection.getLength() );
+
+ bool bValid = false;
+ Reference< sdbcx::XRowLocate > xRowLocate( xCurResultSet, UNO_QUERY );
+ if ( xRowLocate.is() )
+ {
+ Any* pTranslated = aTranslated.getArray();
+
+ try
+ {
+ bool bEverythingsFine = true;
+ for ( const Any& rBookmark : std::as_const(aCurSelection) )
+ {
+ bEverythingsFine = xRowLocate->moveToBookmark( rBookmark );
+ if ( !bEverythingsFine )
+ break;
+ *pTranslated <<= xCurResultSet->getRow();
+ ++pTranslated;
+ }
+ if ( bEverythingsFine )
+ bValid = true;
+ }
+ catch (const Exception&)
+ {
+ bValid = false;
+ }
+ }
+
+ if ( !bValid )
+ {
+ throw IllegalArgumentException(
+ "The current 'Selection' does not describe a valid array of bookmarks, relative to the current 'ResultSet'.",
+ getXWeak(),
+ 0
+ );
+ }
+
+ aCurSelection = aTranslated;
+ }
+
+ SfxViewFrame* pFrame = SfxViewFrame::GetFirst( xCurDocSh.get(), false);
+ SwView *pView = pFrame ? dynamic_cast<SwView*>( pFrame->GetViewShell() ) : nullptr;
+ if (!pView)
+ throw RuntimeException();
+
+ // avoid assertion in 'Update' from Sfx by supplying a shell
+ // and thus avoiding the SelectShell call in Writers GetState function
+ // while still in Update of Sfx.
+ // (GetSelection in Update is not allowed)
+ if (!aCurDocumentURL.isEmpty())
+ pView->AttrChangedNotify(nullptr);//So that SelectShell is called.
+
+ SharedComponent aRowSetDisposeHelper;
+ if (!xCurResultSet.is())
+ {
+ if (aCurDataSourceName.isEmpty() || aCurDataCommand.isEmpty() )
+ {
+ OSL_FAIL("PropertyValues missing or unset");
+ throw IllegalArgumentException("Either the ResultSet or DataSourceName and DataCommand must be set.", getXWeak(), 0 );
+ }
+
+ // build ResultSet from DataSourceName, DataCommand and DataCommandType
+
+ Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
+ if (xMgr.is())
+ {
+ Reference< XInterface > xInstance = xMgr->createInstance( "com.sun.star.sdb.RowSet" );
+ aRowSetDisposeHelper.reset( xInstance, SharedComponent::TakeOwnership );
+ Reference< XPropertySet > xRowSetPropSet( xInstance, UNO_QUERY );
+ OSL_ENSURE( xRowSetPropSet.is(), "failed to get XPropertySet interface from RowSet" );
+ if (xRowSetPropSet.is())
+ {
+ if (xCurConnection.is())
+ xRowSetPropSet->setPropertyValue( "ActiveConnection", Any( xCurConnection ) );
+ xRowSetPropSet->setPropertyValue( "DataSourceName", Any( aCurDataSourceName ) );
+ xRowSetPropSet->setPropertyValue( "Command", Any( aCurDataCommand ) );
+ xRowSetPropSet->setPropertyValue( "CommandType", Any( nCurDataCommandType ) );
+ xRowSetPropSet->setPropertyValue( "EscapeProcessing", Any( bCurEscapeProcessing ) );
+ xRowSetPropSet->setPropertyValue( "ApplyFilter", Any( true ) );
+ xRowSetPropSet->setPropertyValue( "Filter", Any( aCurFilter ) );
+
+ Reference< sdbc::XRowSet > xRowSet( xInstance, UNO_QUERY );
+ if (xRowSet.is())
+ xRowSet->execute(); // build ResultSet from properties
+ if( !xCurConnection.is() )
+ xCurConnection.set( xRowSetPropSet->getPropertyValue( "ActiveConnection" ), UNO_QUERY );
+ xCurResultSet = xRowSet;
+ OSL_ENSURE( xCurResultSet.is(), "failed to build ResultSet" );
+ }
+ }
+ }
+
+ svx::ODataAccessDescriptor aDescriptor;
+ aDescriptor.setDataSource(aCurDataSourceName);
+ aDescriptor[ svx::DataAccessDescriptorProperty::Connection ] <<= xCurConnection;
+ aDescriptor[ svx::DataAccessDescriptorProperty::Command ] <<= aCurDataCommand;
+ aDescriptor[ svx::DataAccessDescriptorProperty::CommandType ] <<= nCurDataCommandType;
+ aDescriptor[ svx::DataAccessDescriptorProperty::EscapeProcessing ] <<= bCurEscapeProcessing;
+ aDescriptor[ svx::DataAccessDescriptorProperty::Cursor ] <<= xCurResultSet;
+ // aDescriptor[ svx::DataAccessDescriptorProperty::ColumnName ] not used
+ // aDescriptor[ svx::DataAccessDescriptorProperty::ColumnObject ] not used
+ aDescriptor[ svx::DataAccessDescriptorProperty::Selection ] <<= aCurSelection;
+
+ DBManagerOptions nMergeType;
+ switch (nCurOutputType)
+ {
+ case MailMergeType::PRINTER : nMergeType = DBMGR_MERGE_PRINTER; break;
+ case MailMergeType::FILE : nMergeType = DBMGR_MERGE_FILE; break;
+ case MailMergeType::MAIL : nMergeType = DBMGR_MERGE_EMAIL; break;
+ case MailMergeType::SHELL : nMergeType = DBMGR_MERGE_SHELL; break;
+ default:
+ throw IllegalArgumentException("Invalid value of property: OutputType", getXWeak(), 0 );
+ }
+
+ SwWrtShell &rSh = pView->GetWrtShell();
+ SwDBManager* pMgr = rSh.GetDBManager();
+ //force layout creation
+ rSh.CalcLayout();
+ OSL_ENSURE( pMgr, "database manager missing" );
+ m_pMgr = pMgr;
+
+ SwMergeDescriptor aMergeDesc( nMergeType, rSh, aDescriptor );
+
+ std::unique_ptr< SwMailMergeConfigItem > pMMConfigItem;
+ uno::Reference< mail::XMailService > xInService;
+ switch (nCurOutputType)
+ {
+ case MailMergeType::PRINTER:
+ {
+ IDocumentDeviceAccess& rIDDA = rSh.getIDocumentDeviceAccess();
+ SwPrintData aPrtData( rIDDA.getPrintData() );
+ aPrtData.SetPrintSingleJobs( bCurSinglePrintJobs );
+ rIDDA.setPrintData( aPrtData );
+ // #i25686# printing should not be done asynchronously to prevent dangling offices
+ // when mail merge is called as command line macro
+ aMergeDesc.aPrintOptions = m_aPrintSettings;
+ aMergeDesc.bCreateSingleFile = true;
+ }
+ break;
+ case MailMergeType::SHELL:
+ aMergeDesc.bCreateSingleFile = true;
+ pMMConfigItem.reset(new SwMailMergeConfigItem);
+ aMergeDesc.pMailMergeConfigItem = pMMConfigItem.get();
+ break;
+ case MailMergeType::FILE:
+ {
+ INetURLObject aURLObj;
+ aURLObj.SetSmartProtocol( INetProtocol::File );
+
+ if (!aCurDocumentURL.isEmpty())
+ {
+ // if OutputURL or FileNamePrefix are missing get
+ // them from DocumentURL
+ aURLObj.SetSmartURL( aCurDocumentURL );
+ if (aCurFileNamePrefix.isEmpty())
+ aCurFileNamePrefix = aURLObj.GetBase(); // filename without extension
+ if (aCurOutputURL.isEmpty())
+ {
+ aURLObj.removeSegment();
+ aCurOutputURL = aURLObj.GetMainURL( INetURLObject::DecodeMechanism::ToIUri );
+ }
+ }
+ else // default empty document without URL
+ {
+ if (aCurOutputURL.isEmpty())
+ throw RuntimeException("OutputURL is not set and can not be obtained.", getXWeak() );
+ }
+
+ aURLObj.SetSmartURL( aCurOutputURL );
+ OUString aPath = aURLObj.GetMainURL( INetURLObject::DecodeMechanism::ToIUri );
+
+ static constexpr OUString aDelim( u"/"_ustr );
+ if (!aPath.isEmpty() && !aPath.endsWith(aDelim))
+ aPath += aDelim;
+ if (bCurFileNameFromColumn)
+ aMergeDesc.sDBcolumn = aCurFileNamePrefix;
+ else
+ {
+ aPath += aCurFileNamePrefix;
+ }
+
+ aMergeDesc.sPrefix = aPath;
+ aMergeDesc.sSaveToFilter = m_sSaveFilter;
+ aMergeDesc.sSaveToFilterOptions = m_sSaveFilterOptions;
+ aMergeDesc.aSaveToFilterData = m_aSaveFilterData;
+ aMergeDesc.bCreateSingleFile = m_bSaveAsSingleFile;
+ }
+ break;
+ case MailMergeType::MAIL:
+ {
+ aMergeDesc.sDBcolumn = m_sAddressFromColumn;
+ if(m_sAddressFromColumn.isEmpty())
+ throw RuntimeException("Mail address column not set.", getXWeak() );
+ aMergeDesc.sSaveToFilter = m_sAttachmentFilter;
+ aMergeDesc.sSubject = m_sSubject;
+ aMergeDesc.sMailBody = m_sMailBody;
+ aMergeDesc.sAttachmentName = m_sAttachmentName;
+ aMergeDesc.aCopiesTo = m_aCopiesTo;
+ aMergeDesc.aBlindCopiesTo = m_aBlindCopiesTo;
+ aMergeDesc.bSendAsHTML = m_bSendAsHTML;
+ aMergeDesc.bSendAsAttachment = m_bSendAsAttachment;
+
+ aMergeDesc.bCreateSingleFile = false;
+ pMMConfigItem.reset(new SwMailMergeConfigItem);
+ aMergeDesc.pMailMergeConfigItem = pMMConfigItem.get();
+ aMergeDesc.xSmtpServer = SwMailMergeHelper::ConnectToSmtpServer(
+ *pMMConfigItem,
+ xInService,
+ m_sInServerPassword, m_sOutServerPassword );
+ if( !aMergeDesc.xSmtpServer.is() || !aMergeDesc.xSmtpServer->isConnected())
+ throw RuntimeException("Failed to connect to mail server.", getXWeak() );
+ }
+ break;
+ }
+
+ // save document with temporary filename
+ std::shared_ptr<const SfxFilter> pSfxFlt = SwIoSystem::GetFilterOfFormat(
+ FILTER_XML,
+ SwDocShell::Factory().GetFilterContainer() );
+ OUString aExtension(comphelper::string::stripStart(pSfxFlt->GetDefaultExtension(), '*'));
+ m_aTmpFileName = utl::CreateTempURL( u"SwMM", true, aExtension );
+
+ Reference< XStorable > xStorable( xCurModel, UNO_QUERY );
+ bool bStoredAsTemporary = false;
+ if ( xStorable.is() )
+ {
+ try
+ {
+ xStorable->storeAsURL( m_aTmpFileName, Sequence< PropertyValue >() );
+ bStoredAsTemporary = true;
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+ if ( !bStoredAsTemporary )
+ throw RuntimeException("Failed to save temporary file.", getXWeak() );
+
+ pMgr->SetMergeSilent( true ); // suppress dialogs, message boxes, etc.
+ const SwXMailMerge *pOldSrc = pMgr->GetMailMergeEvtSrc();
+ OSL_ENSURE( !pOldSrc || pOldSrc == this, "Ooops... different event source already set." );
+ pMgr->SetMailMergeEvtSrc( this ); // launch events for listeners
+
+ SfxGetpApp()->NotifyEvent(SfxEventHint(SfxEventHintId::SwMailMerge, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE), xCurDocSh.get()));
+ bool bSucc = pMgr->Merge( aMergeDesc );
+ SfxGetpApp()->NotifyEvent(SfxEventHint(SfxEventHintId::SwMailMergeEnd, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE_END), xCurDocSh.get()));
+
+ pMgr->SetMailMergeEvtSrc( pOldSrc );
+
+ if ( xCurModel.get() != m_xModel.get() )
+ { // in case it was a temporary model -> close it, and delete the file
+ DeleteTmpFile_Impl( xCurModel, xCurDocSh, m_aTmpFileName );
+ m_aTmpFileName.clear();
+ }
+ // (in case it wasn't a temporary model, it will be closed in the dtor, at the latest)
+
+ if (!bSucc)
+ throw Exception("Mail merge failed. Sorry, no further information available.", getXWeak() );
+
+ //de-initialize services
+ if(xInService.is() && xInService->isConnected())
+ xInService->disconnect();
+ if(aMergeDesc.xSmtpServer.is() && aMergeDesc.xSmtpServer->isConnected())
+ aMergeDesc.xSmtpServer->disconnect();
+
+ if (DBMGR_MERGE_SHELL == nMergeType)
+ {
+ return Any( aMergeDesc.pMailMergeConfigItem->GetTargetView()->GetDocShell()->GetBaseModel() );
+ }
+ else
+ return Any( true );
+}
+
+void SAL_CALL SwXMailMerge::cancel()
+{
+ // Cancel may be called from a second thread, so this protects from m_pMgr
+ /// cleanup in the execute function.
+ osl::MutexGuard aMgrGuard( GetMailMergeMutex() );
+ if (m_pMgr)
+ m_pMgr->MergeCancel();
+}
+
+void SwXMailMerge::LaunchMailMergeEvent( const MailMergeEvent &rEvt ) const
+{
+ comphelper::OInterfaceIteratorHelper2 aIt( const_cast<SwXMailMerge *>(this)->m_aMergeListeners );
+ while (aIt.hasMoreElements())
+ {
+ static_cast< XMailMergeListener* >( aIt.next() )->notifyMailMergeEvent( rEvt );
+ }
+}
+
+void SwXMailMerge::launchEvent( const PropertyChangeEvent &rEvt ) const
+{
+ comphelper::OInterfaceContainerHelper3<XPropertyChangeListener> *pContainer =
+ m_aPropListeners.getContainer( rEvt.PropertyHandle );
+ if (pContainer)
+ {
+ pContainer->notifyEach( &XPropertyChangeListener::propertyChange, rEvt );
+ }
+}
+
+uno::Reference< beans::XPropertySetInfo > SAL_CALL SwXMailMerge::getPropertySetInfo( )
+{
+ SolarMutexGuard aGuard;
+ static Reference< XPropertySetInfo > aRef = m_pPropSet->getPropertySetInfo();
+ return aRef;
+}
+
+void SAL_CALL SwXMailMerge::setPropertyValue(
+ const OUString& rPropertyName, const uno::Any& rValue )
+{
+ SolarMutexGuard aGuard;
+
+ const SfxItemPropertyMapEntry* pCur = m_pPropSet->getPropertyMap().getByName( rPropertyName );
+ if (!pCur)
+ throw UnknownPropertyException(rPropertyName);
+ else if (pCur->nFlags & PropertyAttribute::READONLY)
+ throw PropertyVetoException();
+ else
+ {
+ void *pData = nullptr;
+ switch (pCur->nWID)
+ {
+ case WID_SELECTION : pData = &m_aSelection; break;
+ case WID_RESULT_SET : pData = &m_xResultSet; break;
+ case WID_CONNECTION : pData = &m_xConnection; break;
+ case WID_MODEL : pData = &m_xModel; break;
+ case WID_DATA_SOURCE_NAME : pData = &m_aDataSourceName; break;
+ case WID_DATA_COMMAND : pData = &m_aDataCommand; break;
+ case WID_FILTER : pData = &m_aFilter; break;
+ case WID_DOCUMENT_URL : pData = &m_aDocumentURL; break;
+ case WID_OUTPUT_URL : pData = &m_aOutputURL; break;
+ case WID_DATA_COMMAND_TYPE : pData = &m_nDataCommandType; break;
+ case WID_OUTPUT_TYPE : pData = &m_nOutputType; break;
+ case WID_ESCAPE_PROCESSING : pData = &m_bEscapeProcessing; break;
+ case WID_SINGLE_PRINT_JOBS : pData = &m_bSinglePrintJobs; break;
+ case WID_FILE_NAME_FROM_COLUMN : pData = &m_bFileNameFromColumn; break;
+ case WID_FILE_NAME_PREFIX : pData = &m_aFileNamePrefix; break;
+ case WID_MAIL_SUBJECT: pData = &m_sSubject; break;
+ case WID_ADDRESS_FROM_COLUMN: pData = &m_sAddressFromColumn; break;
+ case WID_SEND_AS_HTML: pData = &m_bSendAsHTML; break;
+ case WID_SEND_AS_ATTACHMENT: pData = &m_bSendAsAttachment; break;
+ case WID_MAIL_BODY: pData = &m_sMailBody; break;
+ case WID_ATTACHMENT_NAME: pData = &m_sAttachmentName; break;
+ case WID_ATTACHMENT_FILTER: pData = &m_sAttachmentFilter;break;
+ case WID_PRINT_OPTIONS: pData = &m_aPrintSettings; break;
+ case WID_SAVE_AS_SINGLE_FILE: pData = &m_bSaveAsSingleFile; break;
+ case WID_SAVE_FILTER: pData = &m_sSaveFilter; break;
+ case WID_SAVE_FILTER_OPTIONS: pData = &m_sSaveFilterOptions; break;
+ case WID_SAVE_FILTER_DATA: pData = &m_aSaveFilterData; break;
+ case WID_COPIES_TO: pData = &m_aCopiesTo; break;
+ case WID_BLIND_COPIES_TO: pData = &m_aBlindCopiesTo;break;
+ case WID_IN_SERVER_PASSWORD: pData = &m_sInServerPassword; break;
+ case WID_OUT_SERVER_PASSWORD: pData = &m_sOutServerPassword; break;
+ default :
+ OSL_FAIL("unknown WID");
+ }
+ Any aOld( pData, pCur->aType );
+
+ bool bChanged = false;
+ bool bOK = true;
+ if (aOld != rValue)
+ {
+ if (pData == &m_aSelection)
+ bOK = rValue >>= m_aSelection;
+ else if (pData == &m_xResultSet)
+ bOK = rValue >>= m_xResultSet;
+ else if (pData == &m_xConnection)
+ bOK = rValue >>= m_xConnection;
+ else if (pData == &m_xModel)
+ bOK = rValue >>= m_xModel;
+ else if (pData == &m_aDataSourceName)
+ bOK = rValue >>= m_aDataSourceName;
+ else if (pData == &m_aDataCommand)
+ bOK = rValue >>= m_aDataCommand;
+ else if (pData == &m_aFilter)
+ bOK = rValue >>= m_aFilter;
+ else if (pData == &m_aDocumentURL)
+ {
+ OUString aText;
+ bOK = rValue >>= aText;
+ if (!aText.isEmpty()
+ && !LoadFromURL_impl( m_xModel, m_xDocSh, aText, true ))
+ throw RuntimeException("Failed to create document from URL: " + aText, getXWeak() );
+ m_aDocumentURL = aText;
+ }
+ else if (pData == &m_aOutputURL)
+ {
+ OUString aText;
+ bOK = rValue >>= aText;
+ if (!aText.isEmpty())
+ {
+ if (!UCB_IsDirectory(aText))
+ throw IllegalArgumentException("URL does not point to a directory: " + aText, getXWeak(), 0 );
+ if (UCB_IsReadOnlyFileName(aText))
+ throw IllegalArgumentException("URL is read-only: " + aText, getXWeak(), 0 );
+ }
+ m_aOutputURL = aText;
+ }
+ else if (pData == &m_nDataCommandType)
+ bOK = rValue >>= m_nDataCommandType;
+ else if (pData == &m_nOutputType)
+ bOK = rValue >>= m_nOutputType;
+ else if (pData == &m_bEscapeProcessing)
+ bOK = rValue >>= m_bEscapeProcessing;
+ else if (pData == &m_bSinglePrintJobs)
+ bOK = rValue >>= m_bSinglePrintJobs;
+ else if (pData == &m_bFileNameFromColumn)
+ bOK = rValue >>= m_bFileNameFromColumn;
+ else if (pData == &m_aFileNamePrefix)
+ bOK = rValue >>= m_aFileNamePrefix;
+ else if (pData == &m_sSubject)
+ bOK = rValue >>= m_sSubject;
+ else if (pData == &m_sAddressFromColumn)
+ bOK = rValue >>= m_sAddressFromColumn;
+ else if (pData == &m_bSendAsHTML)
+ bOK = rValue >>= m_bSendAsHTML;
+ else if (pData == &m_bSendAsAttachment)
+ bOK = rValue >>= m_bSendAsAttachment;
+ else if (pData == &m_sMailBody)
+ bOK = rValue >>= m_sMailBody;
+ else if (pData == &m_sAttachmentName)
+ bOK = rValue >>= m_sAttachmentName;
+ else if (pData == &m_sAttachmentFilter)
+ bOK = rValue >>= m_sAttachmentFilter;
+ else if (pData == &m_aPrintSettings)
+ bOK = rValue >>= m_aPrintSettings;
+ else if (pData == &m_bSaveAsSingleFile)
+ bOK = rValue >>= m_bSaveAsSingleFile;
+ else if (pData == &m_sSaveFilter)
+ bOK = rValue >>= m_sSaveFilter;
+ else if (pData == &m_sSaveFilterOptions)
+ bOK = rValue >>= m_sSaveFilterOptions;
+ else if (pData == &m_aSaveFilterData)
+ bOK = rValue >>= m_aSaveFilterData;
+ else if (pData == &m_aCopiesTo)
+ bOK = rValue >>= m_aCopiesTo;
+ else if (pData == &m_aBlindCopiesTo)
+ bOK = rValue >>= m_aBlindCopiesTo;
+ else if(pData == &m_sInServerPassword)
+ bOK = rValue >>= m_sInServerPassword;
+ else if(pData == &m_sOutServerPassword)
+ bOK = rValue >>= m_sOutServerPassword;
+ else {
+ OSL_FAIL("invalid pointer" );
+ }
+ OSL_ENSURE( bOK, "set value failed" );
+ bChanged = true;
+ }
+ if (!bOK)
+ throw IllegalArgumentException("Property type mismatch or property not set: " + rPropertyName, getXWeak(), 0 );
+
+ if (bChanged)
+ {
+ PropertyChangeEvent aChgEvt( static_cast<XPropertySet *>(this), rPropertyName,
+ false, pCur->nWID, aOld, rValue );
+ launchEvent( aChgEvt );
+ }
+ }
+}
+
+uno::Any SAL_CALL SwXMailMerge::getPropertyValue(
+ const OUString& rPropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ Any aRet;
+
+ const SfxItemPropertyMapEntry* pCur = m_pPropSet->getPropertyMap().getByName( rPropertyName );
+ if (!pCur)
+ throw UnknownPropertyException(rPropertyName);
+
+ switch (pCur->nWID)
+ {
+ case WID_SELECTION : aRet <<= m_aSelection; break;
+ case WID_RESULT_SET : aRet <<= m_xResultSet; break;
+ case WID_CONNECTION : aRet <<= m_xConnection; break;
+ case WID_MODEL : aRet <<= m_xModel; break;
+ case WID_DATA_SOURCE_NAME : aRet <<= m_aDataSourceName; break;
+ case WID_DATA_COMMAND : aRet <<= m_aDataCommand; break;
+ case WID_FILTER : aRet <<= m_aFilter; break;
+ case WID_DOCUMENT_URL : aRet <<= m_aDocumentURL; break;
+ case WID_OUTPUT_URL : aRet <<= m_aOutputURL; break;
+ case WID_DATA_COMMAND_TYPE : aRet <<= m_nDataCommandType; break;
+ case WID_OUTPUT_TYPE : aRet <<= m_nOutputType; break;
+ case WID_ESCAPE_PROCESSING : aRet <<= m_bEscapeProcessing; break;
+ case WID_SINGLE_PRINT_JOBS : aRet <<= m_bSinglePrintJobs; break;
+ case WID_FILE_NAME_FROM_COLUMN : aRet <<= m_bFileNameFromColumn; break;
+ case WID_FILE_NAME_PREFIX : aRet <<= m_aFileNamePrefix; break;
+ case WID_MAIL_SUBJECT: aRet <<= m_sSubject; break;
+ case WID_ADDRESS_FROM_COLUMN: aRet <<= m_sAddressFromColumn; break;
+ case WID_SEND_AS_HTML: aRet <<= m_bSendAsHTML; break;
+ case WID_SEND_AS_ATTACHMENT: aRet <<= m_bSendAsAttachment; break;
+ case WID_MAIL_BODY: aRet <<= m_sMailBody; break;
+ case WID_ATTACHMENT_NAME: aRet <<= m_sAttachmentName; break;
+ case WID_ATTACHMENT_FILTER: aRet <<= m_sAttachmentFilter;break;
+ case WID_PRINT_OPTIONS: aRet <<= m_aPrintSettings; break;
+ case WID_SAVE_AS_SINGLE_FILE: aRet <<= m_bSaveAsSingleFile; break;
+ case WID_SAVE_FILTER: aRet <<= m_sSaveFilter; break;
+ case WID_SAVE_FILTER_OPTIONS: aRet <<= m_sSaveFilterOptions; break;
+ case WID_SAVE_FILTER_DATA: aRet <<= m_aSaveFilterData; break;
+ case WID_COPIES_TO: aRet <<= m_aCopiesTo; break;
+ case WID_BLIND_COPIES_TO: aRet <<= m_aBlindCopiesTo;break;
+ case WID_IN_SERVER_PASSWORD: aRet <<= m_sInServerPassword; break;
+ case WID_OUT_SERVER_PASSWORD: aRet <<= m_sOutServerPassword; break;
+ default :
+ OSL_FAIL("unknown WID");
+ }
+
+ return aRet;
+}
+
+void SAL_CALL SwXMailMerge::addPropertyChangeListener(
+ const OUString& rPropertyName,
+ const uno::Reference< beans::XPropertyChangeListener >& rListener )
+{
+ SolarMutexGuard aGuard;
+ if (!m_bDisposing && rListener.is())
+ {
+ const SfxItemPropertyMapEntry* pCur = m_pPropSet->getPropertyMap().getByName( rPropertyName );
+ if (!pCur)
+ throw UnknownPropertyException(rPropertyName);
+ m_aPropListeners.addInterface( pCur->nWID, rListener );
+ }
+}
+
+void SAL_CALL SwXMailMerge::removePropertyChangeListener(
+ const OUString& rPropertyName,
+ const uno::Reference< beans::XPropertyChangeListener >& rListener )
+{
+ SolarMutexGuard aGuard;
+ if (!m_bDisposing && rListener.is())
+ {
+ const SfxItemPropertyMapEntry* pCur = m_pPropSet->getPropertyMap().getByName( rPropertyName );
+ if (!pCur)
+ throw UnknownPropertyException(rPropertyName);
+ m_aPropListeners.removeInterface( pCur->nWID, rListener );
+ }
+}
+
+void SAL_CALL SwXMailMerge::addVetoableChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*rListener*/ )
+{
+ // no vetoable property, thus no support for vetoable change listeners
+ OSL_FAIL("not implemented");
+}
+
+void SAL_CALL SwXMailMerge::removeVetoableChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*rListener*/ )
+{
+ // no vetoable property, thus no support for vetoable change listeners
+ OSL_FAIL("not implemented");
+}
+
+void SAL_CALL SwXMailMerge::dispose()
+{
+ SolarMutexGuard aGuard;
+
+ if (!m_bDisposing)
+ {
+ m_bDisposing = true;
+
+ EventObject aEvtObj( static_cast<XPropertySet *>(this) );
+ m_aEvtListeners.disposeAndClear( aEvtObj );
+ m_aMergeListeners.disposeAndClear( aEvtObj );
+ m_aPropListeners.disposeAndClear( aEvtObj );
+ }
+}
+
+void SAL_CALL SwXMailMerge::addEventListener(
+ const Reference< XEventListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+ if (!m_bDisposing && rxListener.is())
+ m_aEvtListeners.addInterface( rxListener );
+}
+
+void SAL_CALL SwXMailMerge::removeEventListener(
+ const Reference< XEventListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+ if (!m_bDisposing && rxListener.is())
+ m_aEvtListeners.removeInterface( rxListener );
+}
+
+void SAL_CALL SwXMailMerge::addMailMergeEventListener(
+ const uno::Reference< XMailMergeListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+ if (!m_bDisposing && rxListener.is())
+ m_aMergeListeners.addInterface( rxListener );
+}
+
+void SAL_CALL SwXMailMerge::removeMailMergeEventListener(
+ const uno::Reference< XMailMergeListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+ if (!m_bDisposing && rxListener.is())
+ m_aMergeListeners.removeInterface( rxListener );
+}
+
+OUString SAL_CALL SwXMailMerge::getImplementationName()
+{
+ return "SwXMailMerge";
+}
+
+sal_Bool SAL_CALL SwXMailMerge::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL SwXMailMerge::getSupportedServiceNames()
+{
+ return { "com.sun.star.text.MailMerge", "com.sun.star.sdb.DataAccessDescriptor" };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uno/unomod.cxx b/sw/source/uibase/uno/unomod.cxx
new file mode 100644
index 0000000000..63250ede85
--- /dev/null
+++ b/sw/source/uibase/uno/unomod.cxx
@@ -0,0 +1,976 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/view/DocumentZoomType.hpp>
+#include <comphelper/ChainablePropertySetInfo.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <o3tl/any.hxx>
+#include <osl/diagnose.h>
+#include <svl/itemprop.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/UnitConversion.hxx>
+#include <vcl/svapp.hxx>
+
+#include <unomod.hxx>
+#include <usrpref.hxx>
+#include <prtopt.hxx>
+#include <swmodule.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <wrtsh.hxx>
+#include <viewopt.hxx>
+#include <doc.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <edtwin.hxx>
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::comphelper;
+
+namespace {
+
+enum SwViewSettingsPropertyHandles
+{
+ HANDLE_VIEWSET_ANNOTATIONS,
+ HANDLE_VIEWSET_BREAKS,
+ HANDLE_VIEWSET_DRAWINGS,
+ HANDLE_VIEWSET_FIELD_COMMANDS,
+ HANDLE_VIEWSET_FOOTNOTE_BACKGROUND,
+ HANDLE_VIEWSET_GRAPHICS,
+ HANDLE_VIEWSET_HIDDEN_CHARACTERS,
+ HANDLE_VIEWSET_HIDDEN_PARAGRAPHS,
+ HANDLE_VIEWSET_HIDDEN_TEXT,
+ HANDLE_VIEWSET_HRULER,
+ HANDLE_VIEWSET_HSCROLL,
+ HANDLE_VIEWSET_INDEX_MARK_BACKGROUND,
+ HANDLE_VIEWSET_NONPRINTING_CHARACTERS,
+ HANDLE_VIEWSET_ONLINE_LAYOUT,
+ HANDLE_VIEWSET_PARA_BREAKS,
+ HANDLE_VIEWSET_PROTECTED_SPACES,
+ HANDLE_VIEWSET_SOFT_HYPHENS,
+ HANDLE_VIEWSET_SPACES,
+ HANDLE_VIEWSET_TABLE_BOUNDARIES,
+ HANDLE_VIEWSET_TABLES,
+ HANDLE_VIEWSET_TABSTOPS,
+ HANDLE_VIEWSET_TEXT_BOUNDARIES,
+ HANDLE_VIEWSET_TEXT_FIELD_BACKGROUND,
+ HANDLE_VIEWSET_VRULER,
+ HANDLE_VIEWSET_VSCROLL,
+ HANDLE_VIEWSET_SMOOTH_SCROLLING,
+ HANDLE_VIEWSET_ZOOM_TYPE,
+ HANDLE_VIEWSET_ZOOM,
+ HANDLE_VIEWSET_SHOW_CONTENT_TIPS,
+ HANDLE_VIEWSET_HELP_URL,
+ HANDLE_VIEWSET_VRULER_RIGHT,
+ HANDLE_VIEWSET_SHOW_RULER,
+ HANDLE_VIEWSET_IS_RASTER_VISIBLE,
+ HANDLE_VIEWSET_IS_SNAP_TO_RASTER,
+ HANDLE_VIEWSET_RASTER_RESOLUTION_X,
+ HANDLE_VIEWSET_RASTER_RESOLUTION_Y,
+ HANDLE_VIEWSET_RASTER_SUBDIVISION_X,
+ HANDLE_VIEWSET_RASTER_SUBDIVISION_Y,
+ HANDLE_VIEWSET_HORI_RULER_METRIC,
+ HANDLE_VIEWSET_VERT_RULER_METRIC,
+ HANDLE_VIEWSET_SCROLLBAR_TIPS,
+ HANDLE_VIEWSET_INLINECHANGES_TIPS,
+ HANDLE_VIEWSET_HIDE_WHITESPACE,
+ HANDLE_VIEWSET_USE_HEADERFOOTERMENU,
+ HANDLE_VIEWSET_BOOKMARKS,
+ HANDLE_VIEWSET_SHOW_OUTLINECONTENTVISIBILITYBUTTON,
+ HANDLE_VIEWSET_TREAT_SUB_OUTLINE_LEVELS_AS_CONTENT,
+ HANDLE_VIEWSET_CHANGES_IN_MARGIN
+};
+
+enum SwPrintSettingsPropertyHandles
+{
+ HANDLE_PRINTSET_ANNOTATION_MODE,
+ HANDLE_PRINTSET_BLACK_FONTS,
+ HANDLE_PRINTSET_CONTROLS,
+ HANDLE_PRINTSET_DRAWINGS,
+ HANDLE_PRINTSET_GRAPHICS,
+ HANDLE_PRINTSET_LEFT_PAGES,
+ HANDLE_PRINTSET_PAGE_BACKGROUND,
+ HANDLE_PRINTSET_PROSPECT,
+ HANDLE_PRINTSET_REVERSED,
+ HANDLE_PRINTSET_RIGHT_PAGES,
+ HANDLE_PRINTSET_FAX_NAME,
+ HANDLE_PRINTSET_PAPER_FROM_SETUP,
+ HANDLE_PRINTSET_TABLES,
+ HANDLE_PRINTSET_SINGLE_JOBS,
+ HANDLE_PRINTSET_EMPTY_PAGES,
+ HANDLE_PRINTSET_PROSPECT_RTL,
+ HANDLE_PRINTSET_PLACEHOLDER,
+ HANDLE_PRINTSET_HIDDEN_TEXT
+};
+
+}
+
+static rtl::Reference<ChainablePropertySetInfo> lcl_createViewSettingsInfo()
+{
+ static PropertyInfo const aViewSettingsMap_Impl[] =
+ {
+ { OUString( "HelpURL" ), HANDLE_VIEWSET_HELP_URL , cppu::UnoType<OUString>::get(), PROPERTY_NONE},
+ { OUString( "HorizontalRulerMetric"),HANDLE_VIEWSET_HORI_RULER_METRIC , cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE},
+ { OUString( "IsRasterVisible"), HANDLE_VIEWSET_IS_RASTER_VISIBLE, cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "IsSnapToRaster"), HANDLE_VIEWSET_IS_SNAP_TO_RASTER, cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "IsVertRulerRightAligned"),HANDLE_VIEWSET_VRULER_RIGHT , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowContentTips" ), HANDLE_VIEWSET_SHOW_CONTENT_TIPS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowInlineTooltips" ), HANDLE_VIEWSET_INLINECHANGES_TIPS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "UseHeaderFooterMenu" ), HANDLE_VIEWSET_USE_HEADERFOOTERMENU , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowOutlineContentVisibilityButton" ), HANDLE_VIEWSET_SHOW_OUTLINECONTENTVISIBILITYBUTTON , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "TreatSubOutlineLevelsAsContent" ), HANDLE_VIEWSET_TREAT_SUB_OUTLINE_LEVELS_AS_CONTENT , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowChangesInMargin" ), HANDLE_VIEWSET_CHANGES_IN_MARGIN, cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "RasterResolutionX"), HANDLE_VIEWSET_RASTER_RESOLUTION_X, cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE},
+ { OUString( "RasterResolutionY"), HANDLE_VIEWSET_RASTER_RESOLUTION_Y, cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE},
+ { OUString( "RasterSubdivisionX"), HANDLE_VIEWSET_RASTER_SUBDIVISION_X, cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE},
+ { OUString( "RasterSubdivisionY"), HANDLE_VIEWSET_RASTER_SUBDIVISION_Y, cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE},
+ { OUString( "ShowAnnotations" ), HANDLE_VIEWSET_ANNOTATIONS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowBookmarks" ), HANDLE_VIEWSET_BOOKMARKS, cppu::UnoType<bool>::get(), PROPERTY_NONE },
+ { OUString( "ShowBreaks"), HANDLE_VIEWSET_BREAKS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowDrawings"), HANDLE_VIEWSET_DRAWINGS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowFieldCommands"), HANDLE_VIEWSET_FIELD_COMMANDS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowFootnoteBackground"),HANDLE_VIEWSET_FOOTNOTE_BACKGROUND , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowGraphics"), HANDLE_VIEWSET_GRAPHICS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowHiddenCharacters"), HANDLE_VIEWSET_HIDDEN_CHARACTERS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "HideWhitespace"), HANDLE_VIEWSET_HIDE_WHITESPACE , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowHiddenParagraphs"), HANDLE_VIEWSET_HIDDEN_PARAGRAPHS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowHiddenText"), HANDLE_VIEWSET_HIDDEN_TEXT , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowHoriRuler"), HANDLE_VIEWSET_HRULER , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowHoriScrollBar"), HANDLE_VIEWSET_HSCROLL , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowIndexMarkBackground"),HANDLE_VIEWSET_INDEX_MARK_BACKGROUND, cppu::UnoType<bool>::get(),PROPERTY_NONE},
+ { OUString( "ShowNonprintingCharacters"),HANDLE_VIEWSET_NONPRINTING_CHARACTERS, cppu::UnoType<bool>::get(),PROPERTY_NONE},
+ { OUString( "ShowOnlineLayout"), HANDLE_VIEWSET_ONLINE_LAYOUT , cppu::UnoType<bool>::get(), PropertyAttribute::MAYBEVOID},
+ { OUString( "ShowParaBreaks"), HANDLE_VIEWSET_PARA_BREAKS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowProtectedSpaces"), HANDLE_VIEWSET_PROTECTED_SPACES , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowRulers"), HANDLE_VIEWSET_SHOW_RULER , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowScrollBarTips"), HANDLE_VIEWSET_SCROLLBAR_TIPS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowSoftHyphens"), HANDLE_VIEWSET_SOFT_HYPHENS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowSpaces"), HANDLE_VIEWSET_SPACES , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowTableBoundaries"), HANDLE_VIEWSET_TABLE_BOUNDARIES , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowTables"), HANDLE_VIEWSET_TABLES , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowTabstops"), HANDLE_VIEWSET_TABSTOPS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowTextBoundaries"), HANDLE_VIEWSET_TEXT_BOUNDARIES , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowTextFieldBackground"),HANDLE_VIEWSET_TEXT_FIELD_BACKGROUND, cppu::UnoType<bool>::get(),PROPERTY_NONE},
+ { OUString( "ShowVertRuler"), HANDLE_VIEWSET_VRULER , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "ShowVertScrollBar"), HANDLE_VIEWSET_VSCROLL , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "SmoothScrolling"), HANDLE_VIEWSET_SMOOTH_SCROLLING , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "VerticalRulerMetric"), HANDLE_VIEWSET_VERT_RULER_METRIC , cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE},
+ { OUString( "ZoomType"), HANDLE_VIEWSET_ZOOM_TYPE , cppu::UnoType<sal_Int16>::get(), PROPERTY_NONE},
+ { OUString( "ZoomValue"), HANDLE_VIEWSET_ZOOM , cppu::UnoType<sal_Int16>::get(), PROPERTY_NONE},
+ { OUString(), 0, css::uno::Type(), 0 }
+ };
+ return new ChainablePropertySetInfo ( aViewSettingsMap_Impl );
+}
+
+static rtl::Reference<ChainablePropertySetInfo> lcl_createPrintSettingsInfo()
+{
+ static PropertyInfo const aPrintSettingsMap_Impl[] =
+ {
+ { OUString( "PrintAnnotationMode" ), HANDLE_PRINTSET_ANNOTATION_MODE , cppu::UnoType<sal_Int16>::get(), PROPERTY_NONE},
+ { OUString( "PrintBlackFonts" ), HANDLE_PRINTSET_BLACK_FONTS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "PrintControls" ), HANDLE_PRINTSET_CONTROLS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "PrintDrawings" ), HANDLE_PRINTSET_DRAWINGS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "PrintGraphics" ), HANDLE_PRINTSET_GRAPHICS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "PrintHiddenText"), HANDLE_PRINTSET_HIDDEN_TEXT , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "PrintLeftPages" ), HANDLE_PRINTSET_LEFT_PAGES , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "PrintPageBackground" ), HANDLE_PRINTSET_PAGE_BACKGROUND , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "PrintProspect" ), HANDLE_PRINTSET_PROSPECT , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "PrintProspectRTL" ), HANDLE_PRINTSET_PROSPECT_RTL , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "PrintReversed" ), HANDLE_PRINTSET_REVERSED , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "PrintRightPages" ), HANDLE_PRINTSET_RIGHT_PAGES , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "PrintFaxName" ), HANDLE_PRINTSET_FAX_NAME , cppu::UnoType<OUString>::get(), PROPERTY_NONE},
+ { OUString( "PrintPaperFromSetup" ), HANDLE_PRINTSET_PAPER_FROM_SETUP , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "PrintTables" ), HANDLE_PRINTSET_TABLES , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "PrintTextPlaceholder"), HANDLE_PRINTSET_PLACEHOLDER , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "PrintSingleJobs" ), HANDLE_PRINTSET_SINGLE_JOBS , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString( "PrintEmptyPages" ), HANDLE_PRINTSET_EMPTY_PAGES , cppu::UnoType<bool>::get(), PROPERTY_NONE},
+ { OUString(), 0, css::uno::Type(), 0}
+ };
+ return new ChainablePropertySetInfo ( aPrintSettingsMap_Impl );
+}
+
+SwXModule::SwXModule()
+{
+}
+
+SwXModule::~SwXModule()
+{
+}
+
+Reference< XPropertySet > SwXModule::getViewSettings()
+{
+ SolarMutexGuard aGuard;
+ if(!mxViewSettings.is())
+ {
+ OSL_FAIL("Web or Text?");
+ mxViewSettings = new SwXViewSettings( nullptr );
+ }
+ return mxViewSettings;
+}
+
+Reference< XPropertySet > SwXModule::getPrintSettings()
+{
+ SolarMutexGuard aGuard;
+ if(!mxPrintSettings.is())
+ {
+ OSL_FAIL("Web or Text?");
+ mxPrintSettings = new SwXPrintSettings( SwXPrintSettingsType::Module );
+ }
+ return mxPrintSettings;
+}
+
+OUString SwXModule::getImplementationName()
+{
+ return "SwXModule";
+}
+
+sal_Bool SwXModule::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence< OUString > SwXModule::getSupportedServiceNames()
+{
+ return { "com.sun.star.text.GlobalSettings" };
+}
+
+SwXPrintSettings::SwXPrintSettings(SwXPrintSettingsType eType, SwDoc* pDoc)
+: ChainablePropertySet ( lcl_createPrintSettingsInfo().get(), &Application::GetSolarMutex() )
+, meType(eType)
+, mpPrtOpt ( nullptr )
+, mpDoc ( pDoc )
+{
+}
+
+SwXPrintSettings::~SwXPrintSettings()
+ noexcept
+{
+}
+
+void SwXPrintSettings::_preSetValues ()
+{
+ switch (meType)
+ {
+ case SwXPrintSettingsType::Module:
+ mpPrtOpt = SW_MOD()->GetPrtOptions( false );
+ break;
+ case SwXPrintSettingsType::Document:
+ {
+ if (!mpDoc)
+ throw IllegalArgumentException ();
+ mpPrtOpt = const_cast< SwPrintData * >(&mpDoc->getIDocumentDeviceAccess().getPrintData());
+ }
+ break;
+ }
+}
+
+namespace
+{
+ bool tryBoolAccess(std::u16string_view rName, const uno::Any &rValue)
+ {
+ const std::optional<const bool> xPrSet = o3tl::tryAccess<bool>(rValue);
+ if (!xPrSet.has_value())
+ throw lang::IllegalArgumentException(OUString(OUString::Concat(rName) + " no value"), nullptr, 0);
+ return *xPrSet;
+ }
+}
+
+void SwXPrintSettings::_setSingleValue( const comphelper::PropertyInfo & rInfo, const uno::Any &rValue )
+{
+ switch( rInfo.mnHandle )
+ {
+ case HANDLE_PRINTSET_LEFT_PAGES:
+ {
+ mpPrtOpt->SetPrintLeftPage(tryBoolAccess(rInfo.maName, rValue));
+ }
+ break;
+ case HANDLE_PRINTSET_RIGHT_PAGES:
+ {
+ mpPrtOpt->SetPrintRightPage(tryBoolAccess(rInfo.maName, rValue));
+ }
+ break;
+ case HANDLE_PRINTSET_REVERSED:
+ {
+ mpPrtOpt->SetPrintReverse(tryBoolAccess(rInfo.maName, rValue));
+ }
+ break;
+ case HANDLE_PRINTSET_PROSPECT:
+ {
+ mpPrtOpt->SetPrintProspect(tryBoolAccess(rInfo.maName, rValue));
+ }
+ break;
+ case HANDLE_PRINTSET_GRAPHICS:
+ {
+ mpPrtOpt->SetPrintGraphic(tryBoolAccess(rInfo.maName, rValue));
+ }
+ break;
+ case HANDLE_PRINTSET_TABLES:
+ {
+ mpPrtOpt->SetPrintTable(tryBoolAccess(rInfo.maName, rValue));
+ }
+ break;
+ case HANDLE_PRINTSET_DRAWINGS:
+ {
+ mpPrtOpt->SetPrintDraw(tryBoolAccess(rInfo.maName, rValue));
+ }
+ break;
+ case HANDLE_PRINTSET_CONTROLS:
+ {
+ mpPrtOpt->SetPrintControl(tryBoolAccess(rInfo.maName, rValue));
+ }
+ break;
+ case HANDLE_PRINTSET_PAGE_BACKGROUND:
+ {
+ mpPrtOpt->SetPrintPageBackground(tryBoolAccess(rInfo.maName, rValue));
+ }
+ break;
+ case HANDLE_PRINTSET_BLACK_FONTS:
+ {
+ mpPrtOpt->SetPrintBlackFont(tryBoolAccess(rInfo.maName, rValue));
+ }
+ break;
+ case HANDLE_PRINTSET_SINGLE_JOBS:
+ {
+ mpPrtOpt->SetPrintSingleJobs(tryBoolAccess(rInfo.maName, rValue));
+ }
+ break;
+ case HANDLE_PRINTSET_PAPER_FROM_SETUP:
+ {
+ mpPrtOpt->SetPaperFromSetup(tryBoolAccess(rInfo.maName, rValue));
+ }
+ break;
+ case HANDLE_PRINTSET_ANNOTATION_MODE:
+ {
+ sal_Int16 nTmp = 0;
+ rValue >>= nTmp;
+ SwPostItMode nVal = static_cast<SwPostItMode>(nTmp);
+ if(nVal > SwPostItMode::EndPage)
+ throw lang::IllegalArgumentException(OUString::number(nTmp) + " > SwPostItMode::EndPage", nullptr, 0);
+
+ mpPrtOpt->SetPrintPostIts(nVal);
+ }
+ break;
+ case HANDLE_PRINTSET_EMPTY_PAGES:
+ {
+ mpPrtOpt->SetPrintEmptyPages(tryBoolAccess(rInfo.maName, rValue));
+ }
+ break;
+ case HANDLE_PRINTSET_FAX_NAME:
+ {
+ OUString sString;
+ if ( !(rValue >>= sString))
+ throw lang::IllegalArgumentException();
+
+ mpPrtOpt->SetFaxName(sString);
+ }
+ break;
+ case HANDLE_PRINTSET_PROSPECT_RTL:
+ {
+ mpPrtOpt->SetPrintProspect_RTL(tryBoolAccess(rInfo.maName, rValue));
+ }
+ break;
+ case HANDLE_PRINTSET_PLACEHOLDER:
+ {
+ mpPrtOpt->SetPrintTextPlaceholder(tryBoolAccess(rInfo.maName, rValue));
+ }
+ break;
+ case HANDLE_PRINTSET_HIDDEN_TEXT:
+ {
+ mpPrtOpt->SetPrintHiddenText(tryBoolAccess(rInfo.maName, rValue));
+ }
+ break;
+ default:
+ throw UnknownPropertyException(OUString::number(rInfo.mnHandle));
+ }
+}
+
+void SwXPrintSettings::_postSetValues()
+{
+ mpPrtOpt = nullptr;
+}
+
+void SwXPrintSettings::_preGetValues()
+{
+ switch (meType)
+ {
+ case SwXPrintSettingsType::Module:
+ mpPrtOpt = SW_MOD()->GetPrtOptions( false );
+ break;
+ case SwXPrintSettingsType::Document:
+ {
+ if (!mpDoc)
+ throw IllegalArgumentException ();
+ mpPrtOpt = const_cast< SwPrintData * >(&mpDoc->getIDocumentDeviceAccess().getPrintData());
+ }
+ break;
+ }
+}
+
+void SwXPrintSettings::_getSingleValue( const comphelper::PropertyInfo & rInfo, uno::Any & rValue )
+{
+ switch( rInfo.mnHandle )
+ {
+ case HANDLE_PRINTSET_LEFT_PAGES:
+ rValue <<= mpPrtOpt->IsPrintLeftPage();
+ break;
+ case HANDLE_PRINTSET_RIGHT_PAGES:
+ rValue <<= mpPrtOpt->IsPrintRightPage();
+ break;
+ case HANDLE_PRINTSET_REVERSED:
+ rValue <<= mpPrtOpt->IsPrintReverse();
+ break;
+ case HANDLE_PRINTSET_PROSPECT:
+ rValue <<= mpPrtOpt->IsPrintProspect();
+ break;
+ case HANDLE_PRINTSET_GRAPHICS:
+ rValue <<= mpPrtOpt->IsPrintGraphic();
+ break;
+ case HANDLE_PRINTSET_TABLES:
+ rValue <<= mpPrtOpt->IsPrintTable();
+ break;
+ case HANDLE_PRINTSET_DRAWINGS:
+ rValue <<= mpPrtOpt->IsPrintDraw();
+ break;
+ case HANDLE_PRINTSET_CONTROLS:
+ rValue <<= mpPrtOpt->IsPrintControl();
+ break;
+ case HANDLE_PRINTSET_PAGE_BACKGROUND:
+ rValue <<= mpPrtOpt->IsPrintPageBackground();
+ break;
+ case HANDLE_PRINTSET_BLACK_FONTS:
+ rValue <<= mpPrtOpt->IsPrintBlackFont();
+ break;
+ case HANDLE_PRINTSET_SINGLE_JOBS:
+ rValue <<= mpPrtOpt->IsPrintSingleJobs();
+ break;
+ case HANDLE_PRINTSET_EMPTY_PAGES:
+ rValue <<= mpPrtOpt->IsPrintEmptyPages();
+ break;
+ case HANDLE_PRINTSET_PAPER_FROM_SETUP:
+ rValue <<= mpPrtOpt->IsPaperFromSetup();
+ break;
+ case HANDLE_PRINTSET_ANNOTATION_MODE:
+ {
+ rValue <<= static_cast < sal_Int16 > ( mpPrtOpt->GetPrintPostIts() );
+ }
+ break;
+ case HANDLE_PRINTSET_FAX_NAME :
+ {
+ rValue <<= mpPrtOpt->GetFaxName();
+ }
+ break;
+ case HANDLE_PRINTSET_PROSPECT_RTL:
+ {
+ rValue <<= mpPrtOpt->IsPrintProspectRTL();
+ }
+ break;
+ case HANDLE_PRINTSET_PLACEHOLDER:
+ {
+ rValue <<= mpPrtOpt->IsPrintTextPlaceholder();
+ }
+ break;
+ case HANDLE_PRINTSET_HIDDEN_TEXT:
+ {
+ rValue <<= mpPrtOpt->IsPrintHiddenText();
+ }
+ break;
+ default:
+ throw UnknownPropertyException(OUString::number(rInfo.mnHandle));
+ }
+}
+
+void SwXPrintSettings::_postGetValues ()
+{
+ mpPrtOpt = nullptr;
+}
+
+OUString SwXPrintSettings::getImplementationName()
+{
+ return "SwXPrintSettings";
+}
+
+sal_Bool SwXPrintSettings::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence< OUString > SwXPrintSettings::getSupportedServiceNames()
+{
+ Sequence<OUString> aRet { "com.sun.star.text.PrintSettings" };
+ return aRet;
+}
+
+SwXViewSettings::SwXViewSettings(SwView* pVw)
+ : ChainablePropertySet( lcl_createViewSettingsInfo().get(), &Application::GetSolarMutex() )
+ , m_pView(pVw)
+ , mpConstViewOption(nullptr)
+ , m_bObjectValid(true)
+ , mbApplyZoom(false)
+ , m_eHRulerUnit(FieldUnit::CM)
+ , mbApplyHRulerMetric(false)
+ , m_eVRulerUnit(FieldUnit::CM)
+ , mbApplyVRulerMetric(false)
+{
+ // This property only exists if we have a view (ie, not at the module )
+ if ( !m_pView )
+ mxInfo->remove ( "HelpURL" );
+
+}
+
+SwXViewSettings::~SwXViewSettings()
+ noexcept
+{
+
+}
+
+void SwXViewSettings::_preSetValues ()
+{
+ const SwViewOption* pVOpt = nullptr;
+ if(m_pView)
+ {
+ if(!IsValid())
+ return;
+ pVOpt = m_pView->GetWrtShell().GetViewOptions();
+ }
+ else
+ pVOpt = SW_MOD()->GetViewOption(false);
+
+ mpViewOption.reset( new SwViewOption (*pVOpt) );
+ mbApplyZoom = false;
+ if(m_pView)
+ mpViewOption->SetStarOneSetting(true);
+}
+
+void SwXViewSettings::_setSingleValue( const comphelper::PropertyInfo & rInfo, const uno::Any &rValue )
+{
+ // the API flag should not be set to the application's view settings
+ switch( rInfo.mnHandle )
+ {
+ case HANDLE_VIEWSET_SHOW_RULER : mpViewOption->SetViewAnyRuler(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_HRULER : mpViewOption->SetViewHRuler(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_VRULER : mpViewOption->SetViewVRuler(*o3tl::doAccess<bool>(rValue));break;
+ case HANDLE_VIEWSET_VRULER_RIGHT : mpViewOption->SetVRulerRight(*o3tl::doAccess<bool>(rValue));break;
+ case HANDLE_VIEWSET_HSCROLL : mpViewOption->SetViewHScrollBar(*o3tl::doAccess<bool>(rValue));break;
+ case HANDLE_VIEWSET_VSCROLL : mpViewOption->SetViewVScrollBar(*o3tl::doAccess<bool>(rValue));break;
+ case HANDLE_VIEWSET_GRAPHICS : mpViewOption->SetGraphic(*o3tl::doAccess<bool>(rValue));break;
+ case HANDLE_VIEWSET_TABLES : mpViewOption->SetTable(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_DRAWINGS : mpViewOption->SetDraw(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_FIELD_COMMANDS : mpViewOption->SetFieldName(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_ANNOTATIONS : mpViewOption->SetPostIts(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_INDEX_MARK_BACKGROUND : mpViewOption->SetAppearanceFlag(ViewOptFlags::FieldShadings, *o3tl::doAccess<bool>(rValue), true); break;
+ case HANDLE_VIEWSET_NONPRINTING_CHARACTERS: mpViewOption->SetViewMetaChars( *o3tl::doAccess<bool>(rValue) ); break;
+ case HANDLE_VIEWSET_FOOTNOTE_BACKGROUND : mpViewOption->SetAppearanceFlag(ViewOptFlags::FieldShadings, *o3tl::doAccess<bool>(rValue), true); break;
+ case HANDLE_VIEWSET_TEXT_FIELD_BACKGROUND : mpViewOption->SetAppearanceFlag(ViewOptFlags::FieldShadings, *o3tl::doAccess<bool>(rValue), true); break;
+ case HANDLE_VIEWSET_PARA_BREAKS : mpViewOption->SetParagraph(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_SOFT_HYPHENS : mpViewOption->SetSoftHyph(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_SPACES : mpViewOption->SetBlank(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_PROTECTED_SPACES : mpViewOption->SetHardBlank(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_TABSTOPS : mpViewOption->SetTab(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_BREAKS : mpViewOption->SetLineBreak(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_BOOKMARKS : mpViewOption->SetShowBookmarks(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_HIDDEN_TEXT : mpViewOption->SetShowHiddenField(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_HIDDEN_CHARACTERS : mpViewOption->SetShowHiddenChar(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_HIDDEN_PARAGRAPHS : mpViewOption->SetShowHiddenPara(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_TABLE_BOUNDARIES : mpViewOption->SetAppearanceFlag(ViewOptFlags::TableBoundaries, *o3tl::doAccess<bool>(rValue), true); break;
+ case HANDLE_VIEWSET_TEXT_BOUNDARIES : mpViewOption->SetDocBoundaries(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_SMOOTH_SCROLLING : mpViewOption->SetSmoothScroll(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_SHOW_CONTENT_TIPS : mpViewOption->SetShowContentTips(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_IS_RASTER_VISIBLE : mpViewOption->SetGridVisible(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_IS_SNAP_TO_RASTER : mpViewOption->SetSnap(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_SCROLLBAR_TIPS : mpViewOption->SetShowScrollBarTips(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_INLINECHANGES_TIPS : mpViewOption->SetShowInlineTooltips(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_USE_HEADERFOOTERMENU : mpViewOption->SetUseHeaderFooterMenu(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_SHOW_OUTLINECONTENTVISIBILITYBUTTON : mpViewOption->SetShowOutlineContentVisibilityButton(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_TREAT_SUB_OUTLINE_LEVELS_AS_CONTENT : mpViewOption->SetTreatSubOutlineLevelsAsContent(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_CHANGES_IN_MARGIN : mpViewOption->SetShowChangesInMargin(*o3tl::doAccess<bool>(rValue)); break;
+ case HANDLE_VIEWSET_RASTER_RESOLUTION_X :
+ {
+ sal_Int32 nTmp = 0;
+ if(!(rValue >>= nTmp) || nTmp < 10)
+ throw IllegalArgumentException();
+ Size aSize( mpViewOption->GetSnapSize() );
+ aSize.setWidth( o3tl::toTwips(nTmp, o3tl::Length::mm100) );
+ mpViewOption->SetSnapSize( aSize );
+ }
+ break;
+ case HANDLE_VIEWSET_RASTER_RESOLUTION_Y :
+ {
+ sal_Int32 nTmp = 0;
+ if(!(rValue >>= nTmp) || nTmp < 10)
+ throw IllegalArgumentException();
+ Size aSize( mpViewOption->GetSnapSize() );
+ aSize.setHeight( o3tl::toTwips(nTmp, o3tl::Length::mm100) );
+ mpViewOption->SetSnapSize( aSize );
+ }
+ break;
+ case HANDLE_VIEWSET_RASTER_SUBDIVISION_X :
+ {
+ sal_Int32 nTmp = 0;
+ if(!(rValue >>= nTmp) || (0 > nTmp || nTmp >= 100))
+ throw IllegalArgumentException();
+ mpViewOption->SetDivisionX( static_cast<short>(nTmp) );
+ }
+ break;
+ case HANDLE_VIEWSET_RASTER_SUBDIVISION_Y :
+ {
+ sal_Int32 nTmp = 0;
+ if(!(rValue >>= nTmp) || (0 > nTmp || nTmp >= 100))
+ throw IllegalArgumentException();
+ mpViewOption->SetDivisionY( static_cast<short>(nTmp) );
+ }
+ break;
+ case HANDLE_VIEWSET_ZOOM :
+ {
+ sal_Int16 nZoom = 0;
+ if(!(rValue >>= nZoom) || nZoom > MAXZOOM || nZoom < MINZOOM)
+ throw lang::IllegalArgumentException();
+ mpViewOption->SetZoom(o3tl::narrowing<sal_uInt16>(nZoom));
+ mbApplyZoom = true;
+ }
+ break;
+ case HANDLE_VIEWSET_ZOOM_TYPE:
+ {
+ sal_Int16 nZoom = 0;
+ if(!(rValue >>= nZoom))
+ throw IllegalArgumentException();
+ SvxZoomType eZoom;
+ switch (nZoom)
+ {
+ case view::DocumentZoomType::OPTIMAL:
+ eZoom = SvxZoomType::OPTIMAL;
+ break;
+ case view::DocumentZoomType::PAGE_WIDTH:
+ eZoom = SvxZoomType::PAGEWIDTH;
+ break;
+ case view::DocumentZoomType::ENTIRE_PAGE:
+ eZoom = SvxZoomType::WHOLEPAGE;
+ break;
+ case view::DocumentZoomType::BY_VALUE:
+ eZoom = SvxZoomType::PERCENT;
+ break;
+ case view::DocumentZoomType::PAGE_WIDTH_EXACT:
+ eZoom = SvxZoomType::PAGEWIDTH_NOBORDER;
+ break;
+ default:
+ throw IllegalArgumentException(
+ "SwXViewSettings: invalid zoom type", nullptr, 0);
+ }
+ mpViewOption->SetZoomType( eZoom );
+ mbApplyZoom = true;
+ }
+ break;
+ case HANDLE_VIEWSET_ONLINE_LAYOUT :
+ {
+ if ( m_pView )
+ {
+ bool bVal = *o3tl::doAccess<bool>(rValue);
+ SwViewOption aOpt(*m_pView->GetWrtShell().GetViewOptions());
+ if (!bVal != !aOpt.getBrowseMode())
+ {
+ aOpt.setBrowseMode( bVal );
+ m_pView->GetWrtShell().ApplyViewOptions( aOpt );
+
+ // must be set in mpViewOption as this will overwrite settings in _post!
+ if(mpViewOption)
+ mpViewOption->setBrowseMode(bVal);
+
+ m_pView->GetDocShell()->ToggleLayoutMode(m_pView);
+ }
+ }
+ }
+ break;
+ case HANDLE_VIEWSET_HIDE_WHITESPACE:
+ {
+ if ( m_pView )
+ {
+ bool bVal = *o3tl::doAccess<bool>(rValue);
+ SwViewOption aOpt(*m_pView->GetWrtShell().GetViewOptions());
+ if (!bVal != !aOpt.IsHideWhitespaceMode())
+ {
+ aOpt.SetHideWhitespaceMode( bVal );
+ m_pView->GetWrtShell().ApplyViewOptions( aOpt );
+
+ // must be set in mpViewOption as this will overwrite settings in _post!
+ if(mpViewOption)
+ mpViewOption->SetHideWhitespaceMode(bVal);
+ }
+ }
+ }
+ break;
+ case HANDLE_VIEWSET_HELP_URL:
+ {
+ if ( !m_pView )
+ throw UnknownPropertyException();
+
+ OUString sHelpURL;
+ if ( ! ( rValue >>= sHelpURL ) )
+ throw IllegalArgumentException();
+
+ INetURLObject aHID( sHelpURL );
+ if ( aHID.GetProtocol() != INetProtocol::Hid )
+ throw IllegalArgumentException ();
+
+ m_pView->GetEditWin().SetHelpId( aHID.GetURLPath() );
+ }
+ break;
+ case HANDLE_VIEWSET_HORI_RULER_METRIC:
+ case HANDLE_VIEWSET_VERT_RULER_METRIC:
+ {
+ sal_uInt16 nUnit;
+ if( rValue >>= nUnit )
+ switch (static_cast<FieldUnit>(nUnit))
+ {
+ case FieldUnit::MM:
+ case FieldUnit::CM:
+ case FieldUnit::POINT:
+ case FieldUnit::PICA:
+ case FieldUnit::INCH:
+ if( rInfo.mnHandle == HANDLE_VIEWSET_HORI_RULER_METRIC )
+ {
+ m_eHRulerUnit = static_cast<FieldUnit>(nUnit);
+ mbApplyHRulerMetric = true;
+ }
+ else
+ {
+ m_eVRulerUnit = static_cast<FieldUnit>(nUnit);
+ mbApplyVRulerMetric = true;
+ }
+ break;
+ default:
+ throw IllegalArgumentException();
+ }
+ }
+ break;
+ default:
+ throw UnknownPropertyException(OUString::number(rInfo.mnHandle));
+ }
+}
+
+void SwXViewSettings::_postSetValues()
+{
+ if( m_pView )
+ {
+ if(mbApplyZoom )
+ m_pView->SetZoom( mpViewOption->GetZoomType(),
+ mpViewOption->GetZoom(), true );
+ if(mbApplyHRulerMetric)
+ m_pView->ChangeTabMetric(m_eHRulerUnit);
+ if(mbApplyVRulerMetric)
+ m_pView->ChangeVRulerMetric(m_eVRulerUnit);
+
+ }
+ else
+ {
+ if(mbApplyHRulerMetric)
+ SW_MOD()->ApplyRulerMetric( m_eHRulerUnit, true, false );
+ if(mbApplyVRulerMetric)
+ SW_MOD()->ApplyRulerMetric( m_eVRulerUnit, false, false );
+ }
+
+ SW_MOD()->ApplyUsrPref( *mpViewOption, m_pView, m_pView ? SvViewOpt::DestViewOnly
+ : SvViewOpt::DestText );
+
+ mpViewOption.reset();
+}
+
+void SwXViewSettings::_preGetValues ()
+{
+ if(m_pView)
+ {
+ if(!IsValid())
+ return;
+ mpConstViewOption = m_pView->GetWrtShell().GetViewOptions();
+ }
+ else
+ mpConstViewOption = SW_MOD()->GetViewOption(false);
+}
+
+void SwXViewSettings::_getSingleValue( const comphelper::PropertyInfo & rInfo, uno::Any & rValue )
+{
+ bool bBool = true;
+ bool bBoolVal = false;
+ switch( rInfo.mnHandle )
+ {
+ case HANDLE_VIEWSET_SHOW_RULER: bBoolVal = mpConstViewOption->IsViewAnyRuler(); break;
+ case HANDLE_VIEWSET_HRULER : bBoolVal = mpConstViewOption->IsViewHRuler(true); break;
+ case HANDLE_VIEWSET_VRULER : bBoolVal = mpConstViewOption->IsViewVRuler(true);break;
+ case HANDLE_VIEWSET_VRULER_RIGHT : bBoolVal = mpConstViewOption->IsVRulerRight();break;
+ case HANDLE_VIEWSET_HSCROLL: bBoolVal = mpConstViewOption->IsViewHScrollBar();break;
+ case HANDLE_VIEWSET_VSCROLL: bBoolVal = mpConstViewOption->IsViewVScrollBar();break;
+ case HANDLE_VIEWSET_GRAPHICS : bBoolVal = mpConstViewOption->IsGraphic();break;
+ case HANDLE_VIEWSET_TABLES : bBoolVal = mpConstViewOption->IsTable(); break;
+ case HANDLE_VIEWSET_DRAWINGS : bBoolVal = mpConstViewOption->IsDraw(); break;
+ case HANDLE_VIEWSET_FIELD_COMMANDS : bBoolVal = mpConstViewOption->IsFieldName(); break;
+ case HANDLE_VIEWSET_ANNOTATIONS : bBoolVal = mpConstViewOption->IsPostIts(); break;
+ case HANDLE_VIEWSET_INDEX_MARK_BACKGROUND : bBoolVal = mpConstViewOption->IsFieldShadings(); break;
+ case HANDLE_VIEWSET_NONPRINTING_CHARACTERS: bBoolVal = mpConstViewOption->IsViewMetaChars(); break;
+ case HANDLE_VIEWSET_FOOTNOTE_BACKGROUND : bBoolVal = mpConstViewOption->IsFieldShadings(); break;
+ case HANDLE_VIEWSET_TEXT_FIELD_BACKGROUND : bBoolVal = mpConstViewOption->IsFieldShadings(); break;
+ case HANDLE_VIEWSET_PARA_BREAKS : bBoolVal = mpConstViewOption->IsParagraph(true); break;
+ case HANDLE_VIEWSET_SOFT_HYPHENS : bBoolVal = mpConstViewOption->IsSoftHyph(); break;
+ case HANDLE_VIEWSET_SPACES : bBoolVal = mpConstViewOption->IsBlank(true); break;
+ case HANDLE_VIEWSET_PROTECTED_SPACES : bBoolVal = mpConstViewOption->IsHardBlank(); break;
+ case HANDLE_VIEWSET_TABSTOPS : bBoolVal = mpConstViewOption->IsTab(true); break;
+ case HANDLE_VIEWSET_BREAKS : bBoolVal = mpConstViewOption->IsLineBreak(true); break;
+ case HANDLE_VIEWSET_BOOKMARKS : bBoolVal = mpConstViewOption->IsShowBookmarks(true); break;
+ case HANDLE_VIEWSET_HIDDEN_TEXT : bBoolVal = mpConstViewOption->IsShowHiddenField(); break;
+ case HANDLE_VIEWSET_HIDDEN_CHARACTERS : bBoolVal = mpConstViewOption->IsShowHiddenChar(true); break;
+ case HANDLE_VIEWSET_HIDE_WHITESPACE : bBoolVal = mpConstViewOption->IsHideWhitespaceMode(); break;
+ case HANDLE_VIEWSET_HIDDEN_PARAGRAPHS : bBoolVal = mpConstViewOption->IsShowHiddenPara(); break;
+ case HANDLE_VIEWSET_TABLE_BOUNDARIES : bBoolVal = mpConstViewOption->IsTableBoundaries(); break;
+ case HANDLE_VIEWSET_TEXT_BOUNDARIES : bBoolVal = mpConstViewOption->IsDocBoundaries(); break;
+ case HANDLE_VIEWSET_SMOOTH_SCROLLING : bBoolVal = mpConstViewOption->IsSmoothScroll(); break;
+ case HANDLE_VIEWSET_SHOW_CONTENT_TIPS : bBoolVal = mpConstViewOption->IsShowContentTips(); break;
+ case HANDLE_VIEWSET_INLINECHANGES_TIPS : bBoolVal = mpConstViewOption->IsShowInlineTooltips(); break;
+ case HANDLE_VIEWSET_CHANGES_IN_MARGIN : bBoolVal = mpConstViewOption->IsShowChangesInMargin(); break;
+ case HANDLE_VIEWSET_IS_RASTER_VISIBLE : bBoolVal = mpConstViewOption->IsGridVisible(); break;
+ case HANDLE_VIEWSET_IS_SNAP_TO_RASTER : bBoolVal = mpConstViewOption->IsSnap(); break;
+ case HANDLE_VIEWSET_SCROLLBAR_TIPS : bBoolVal = mpConstViewOption->IsShowScrollBarTips(); break;
+ case HANDLE_VIEWSET_RASTER_RESOLUTION_X :
+ bBool = false;
+ rValue <<= static_cast<sal_Int32>(convertTwipToMm100(mpConstViewOption->GetSnapSize().Width()));
+ break;
+ case HANDLE_VIEWSET_RASTER_RESOLUTION_Y :
+ bBool = false;
+ rValue <<= static_cast<sal_Int32>(convertTwipToMm100(mpConstViewOption->GetSnapSize().Height()));
+ break;
+ case HANDLE_VIEWSET_RASTER_SUBDIVISION_X :
+ bBool = false;
+ rValue <<= static_cast<sal_Int32>(mpConstViewOption->GetDivisionX());
+ break;
+ case HANDLE_VIEWSET_RASTER_SUBDIVISION_Y :
+ bBool = false;
+ rValue <<= static_cast<sal_Int32>(mpConstViewOption->GetDivisionY());
+ break;
+ case HANDLE_VIEWSET_ZOOM :
+ bBool = false;
+ rValue <<= static_cast<sal_Int16>(mpConstViewOption->GetZoom());
+ break;
+ case HANDLE_VIEWSET_ZOOM_TYPE:
+ {
+ bBool = false;
+ sal_Int16 nRet(0);
+ switch (mpConstViewOption->GetZoomType())
+ {
+ case SvxZoomType::OPTIMAL:
+ nRet = view::DocumentZoomType::OPTIMAL;
+ break;
+ case SvxZoomType::PAGEWIDTH:
+ nRet = view::DocumentZoomType::PAGE_WIDTH;
+ break;
+ case SvxZoomType::WHOLEPAGE:
+ nRet = view::DocumentZoomType::ENTIRE_PAGE;
+ break;
+ case SvxZoomType::PERCENT:
+ nRet = view::DocumentZoomType::BY_VALUE;
+ break;
+ case SvxZoomType::PAGEWIDTH_NOBORDER:
+ nRet = view::DocumentZoomType::PAGE_WIDTH_EXACT;
+ break;
+ default:
+ OSL_FAIL("SwXViewSettings: invalid zoom type");
+ break;
+ }
+ rValue <<= nRet;
+ }
+ break;
+ case HANDLE_VIEWSET_ONLINE_LAYOUT:
+ if(m_pView)
+ bBoolVal = m_pView->GetWrtShell().GetViewOptions()->getBrowseMode();
+ break;
+ case HANDLE_VIEWSET_HELP_URL :
+ {
+ if ( !m_pView )
+ throw UnknownPropertyException();
+
+ bBool = false;
+ SwEditWin &rEditWin = m_pView->GetEditWin();
+ OUString sHelpURL = INET_HID_SCHEME + rEditWin.GetHelpId();
+ rValue <<= sHelpURL;
+ }
+ break;
+ case HANDLE_VIEWSET_HORI_RULER_METRIC:
+ {
+ if ( m_pView )
+ {
+ FieldUnit eUnit;
+ m_pView->GetHRulerMetric( eUnit );
+ rValue <<= static_cast<sal_Int32>(eUnit);
+ }
+ else
+ {
+ const SwMasterUsrPref* pUsrPref = SW_MOD()->GetUsrPref( false );
+ rValue <<= static_cast<sal_Int32>(pUsrPref->GetHScrollMetric());
+ }
+ bBool = false;
+ }
+ break;
+ case HANDLE_VIEWSET_VERT_RULER_METRIC:
+ {
+ if ( m_pView )
+ {
+ FieldUnit eUnit;
+ m_pView->GetVRulerMetric( eUnit );
+ rValue <<= static_cast<sal_Int32>(eUnit);
+ }
+ else
+ {
+ const SwMasterUsrPref* pUsrPref = SW_MOD()->GetUsrPref( false );
+ rValue <<= static_cast<sal_Int32>(pUsrPref->GetVScrollMetric());
+ }
+ bBool = false;
+ }
+ break;
+ default: OSL_FAIL("there is no such ID!");
+ }
+ if( bBool )
+ rValue <<= bBoolVal;
+}
+
+void SwXViewSettings::_postGetValues ()
+{
+ mpConstViewOption = nullptr;
+}
+
+OUString SwXViewSettings::getImplementationName()
+{
+ return "SwXViewSettings";
+}
+
+sal_Bool SwXViewSettings::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence< OUString > SwXViewSettings::getSupportedServiceNames()
+{
+ Sequence<OUString> aRet { "com.sun.star.text.ViewSettings" };
+ return aRet;
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+SwXModule_get_implementation(css::uno::XComponentContext*,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new SwXModule());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uno/unomodule.cxx b/sw/source/uibase/uno/unomodule.cxx
new file mode 100644
index 0000000000..478502c4fe
--- /dev/null
+++ b/sw/source/uibase/uno/unomodule.cxx
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/frame/DispatchResultState.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+
+#include <swmodule.hxx>
+#include <swdll.hxx>
+#include "unomodule.hxx"
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/processfactory.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <sfx2/frame.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace css;
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_comp_Writer_WriterModule_get_implementation(uno::XComponentContext* /*pCtx*/,
+ uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ SolarMutexGuard aGuard;
+ return cppu::acquire(new SwUnoModule);
+}
+
+ // XNotifyingDispatch
+void SAL_CALL SwUnoModule::dispatchWithNotification( const util::URL& aURL, const uno::Sequence< beans::PropertyValue >& aArgs, const uno::Reference< frame::XDispatchResultListener >& xListener )
+{
+ // there is no guarantee, that we are holded alive during this method!
+ // May the outside dispatch container will be updated by a CONTEXT_CHANGED
+ // asynchronous ...
+ uno::Reference< uno::XInterface > xThis(static_cast< frame::XNotifyingDispatch* >(this));
+
+ SolarMutexGuard aGuard;
+ SwGlobals::ensure();
+ const SfxSlot* pSlot = SW_MOD()->GetInterface()->GetSlot( aURL.Complete );
+
+ sal_Int16 aState = frame::DispatchResultState::DONTKNOW;
+ if ( !pSlot )
+ aState = frame::DispatchResultState::FAILURE;
+ else
+ {
+ SfxRequest aReq( pSlot, aArgs, SfxCallMode::SYNCHRON, SW_MOD()->GetPool() );
+ SfxAllItemSet aInternalSet( SfxGetpApp()->GetPool() );
+
+ css::uno::Reference<css::frame::XDesktop2> xDesktop = css::frame::Desktop::create(::comphelper::getProcessComponentContext());
+ css::uno::Reference<css::frame::XFrame> xCurrentFrame = xDesktop->getCurrentFrame();
+ if (xCurrentFrame.is()) // an empty set is no problem ... but an empty frame reference can be a problem !
+ aInternalSet.Put(SfxUnoFrameItem(SID_FILLFRAME, xCurrentFrame));
+
+ aReq.SetInternalArgs_Impl(aInternalSet);
+ const SfxPoolItemHolder& rResult(SW_MOD()->ExecuteSlot(aReq));
+ if (nullptr != rResult.getItem())
+ aState = frame::DispatchResultState::SUCCESS;
+ else
+ aState = frame::DispatchResultState::FAILURE;
+ }
+
+ if ( xListener.is() )
+ {
+ xListener->dispatchFinished(
+ frame::DispatchResultEvent(
+ xThis, aState, uno::Any()));
+ }
+}
+
+ // XDispatch
+void SAL_CALL SwUnoModule::dispatch( const util::URL& aURL, const uno::Sequence< beans::PropertyValue >& aArgs )
+{
+ dispatchWithNotification(aURL, aArgs, uno::Reference< frame::XDispatchResultListener >());
+}
+
+void SAL_CALL SwUnoModule::addStatusListener(
+ const uno::Reference< frame::XStatusListener > & /*xControl*/,
+ const util::URL& /*aURL*/)
+{
+}
+
+void SAL_CALL SwUnoModule::removeStatusListener(
+ const uno::Reference< frame::XStatusListener > & /*xControl*/,
+ const util::URL& /*aURL*/)
+{
+}
+
+uno::Sequence< uno::Reference< frame::XDispatch > > SAL_CALL SwUnoModule::queryDispatches(
+ const uno::Sequence< frame::DispatchDescriptor >& seqDescripts )
+{
+ sal_Int32 nCount = seqDescripts.getLength();
+ uno::Sequence< uno::Reference< frame::XDispatch > > lDispatcher( nCount );
+
+ std::transform(seqDescripts.begin(), seqDescripts.end(), lDispatcher.getArray(),
+ [this](const frame::DispatchDescriptor& rDescr) -> uno::Reference< frame::XDispatch > {
+ return queryDispatch( rDescr.FeatureURL, rDescr.FrameName, rDescr.SearchFlags ); });
+
+ return lDispatcher;
+}
+
+// XDispatchProvider
+uno::Reference< frame::XDispatch > SAL_CALL SwUnoModule::queryDispatch(
+ const util::URL& aURL, const OUString& /*sTargetFrameName*/,
+ sal_Int32 /*eSearchFlags*/ )
+{
+ uno::Reference< frame::XDispatch > xReturn;
+
+ SolarMutexGuard aGuard;
+ SwGlobals::ensure();
+ const SfxSlot* pSlot = SW_MOD()->GetInterface()->GetSlot( aURL.Complete );
+ if ( pSlot )
+ xReturn = this;
+
+ return xReturn;
+}
+
+// XServiceInfo
+OUString SAL_CALL SwUnoModule::getImplementationName( )
+{
+ return "com.sun.star.comp.Writer.WriterModule";
+}
+
+sal_Bool SAL_CALL SwUnoModule::supportsService( const OUString& sServiceName )
+{
+ return cppu::supportsService(this, sServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL SwUnoModule::getSupportedServiceNames( )
+{
+ uno::Sequence<OUString> aSeq { "com.sun.star.text.ModuleDispatcher" };
+ return aSeq;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uno/unomodule.hxx b/sw/source/uibase/uno/unomodule.hxx
new file mode 100644
index 0000000000..fa85f11d74
--- /dev/null
+++ b/sw/source/uibase/uno/unomodule.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/frame/XNotifyingDispatch.hpp>
+#include <com/sun/star/frame/DispatchDescriptor.hpp>
+#include <com/sun/star/uno/Reference.h>
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+namespace com
+{
+ namespace sun
+ {
+ namespace star
+ {
+ namespace lang
+ {
+ class XMultiServiceFactory;
+ }
+ namespace beans
+ {
+ struct PropertyValue;
+ }
+ }
+ }
+}
+
+class SwUnoModule : public ::cppu::WeakImplHelper< css::frame::XDispatchProvider, css::frame::XNotifyingDispatch, css::lang::XServiceInfo >
+{
+public:
+ SwUnoModule() {}
+
+ // XNotifyingDispatch
+ virtual void SAL_CALL dispatchWithNotification( const css::util::URL& aURL, const css::uno::Sequence< css::beans::PropertyValue >& aArgs, const css::uno::Reference< css::frame::XDispatchResultListener >& xListener ) override;
+
+ // XDispatch
+ virtual void SAL_CALL dispatch( const css::util::URL& aURL, const css::uno::Sequence< css::beans::PropertyValue >& aArgs ) override;
+ virtual void SAL_CALL addStatusListener(const css::uno::Reference< css::frame::XStatusListener > & xControl, const css::util::URL& aURL) override;
+ virtual void SAL_CALL removeStatusListener(const css::uno::Reference< css::frame::XStatusListener > & xControl, const css::util::URL& aURL) override;
+
+ // XDispatchProvider
+ virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& seqDescriptor ) override ;
+ virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch( const css::util::URL & aURL ,
+ const OUString & sTargetFrameName,
+ sal_Int32 eSearchFlags ) override ;
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
new file mode 100644
index 0000000000..f5e0904fa8
--- /dev/null
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -0,0 +1,4816 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+#include <officecfg/Office/Common.hxx>
+#include <comphelper/string.hxx>
+#include <AnnotationWin.hxx>
+#include <o3tl/any.hxx>
+#include <utility>
+#include <vcl/virdev.hxx>
+#include <vcl/sysdata.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/print.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/lokhelper.hxx>
+#include <sfx2/LokControlHandler.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/printer.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <toolkit/awt/vclxdevice.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <sfx2/lokcomponenthelpers.hxx>
+#include <sfx2/ipclient.hxx>
+#include <editeng/svxacorr.hxx>
+#include <editeng/acorrcfg.hxx>
+#include <cmdid.h>
+#include <swtypes.hxx>
+#include <wdocsh.hxx>
+#include <wrtsh.hxx>
+#include <pview.hxx>
+#include <viewsh.hxx>
+#include <pvprtdat.hxx>
+#include <printdata.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <svl/stritem.hxx>
+#include <unotxdoc.hxx>
+#include <svl/numformat.hxx>
+#include <svl/numuno.hxx>
+#include <fldbas.hxx>
+#include <unomap.hxx>
+#include <unotextbodyhf.hxx>
+#include <unotextrange.hxx>
+#include <unotextcursor.hxx>
+#include <unosett.hxx>
+#include <unocoll.hxx>
+#include <unoredlines.hxx>
+#include <unosrch.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/objsh.hxx>
+#include <unoprnms.hxx>
+#include <unostyle.hxx>
+#include <unodraw.hxx>
+#include <svl/eitem.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/datetime.hxx>
+#include <unocrsr.hxx>
+#include <unofieldcoll.hxx>
+#include <unoidxcoll.hxx>
+#include <unocrsrhelper.hxx>
+#include <globdoc.hxx>
+#include <viewopt.hxx>
+#include <unochart.hxx>
+#include <charatr.hxx>
+#include <svx/xmleohlp.hxx>
+#include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+#include <com/sun/star/lang/NotInitializedException.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/XFastPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyAccess.hpp>
+#include <com/sun/star/document/RedlineDisplayType.hpp>
+#include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/script/XInvocation.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <sfx2/linkmgr.hxx>
+#include <svx/unofill.hxx>
+#include <swmodule.hxx>
+#include <docstat.hxx>
+#include <modcfg.hxx>
+#include <ndtxt.hxx>
+#include <strings.hrc>
+#include <bitmaps.hlst>
+#include "unodefaults.hxx"
+#include "SwXDocumentSettings.hxx"
+#include <doc.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentChartDataProviderAccess.hxx>
+#include <IDocumentLinksAdministration.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <IDocumentFieldsAccess.hxx>
+#include <IDocumentStatistics.hxx>
+#include <IDocumentStylePoolAccess.hxx>
+#include <IDocumentState.hxx>
+#include <drawdoc.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <osl/file.hxx>
+#include <comphelper/lok.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <sfx2/dispatch.hxx>
+#include <swruler.hxx>
+#include <docufld.hxx>
+
+#include <EnhancedPDFExportHelper.hxx>
+#include <numrule.hxx>
+
+#include <editeng/langitem.hxx>
+#include <docary.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <i18nutil/searchopt.hxx>
+
+#include <charfmt.hxx>
+#include <fmtcol.hxx>
+#include <istyleaccess.hxx>
+
+#include <swatrset.hxx>
+#include <view.hxx>
+#include <viscrs.hxx>
+#include <srcview.hxx>
+#include <edtwin.hxx>
+#include <swdtflvr.hxx>
+#include <PostItMgr.hxx>
+
+#include <svtools/langtab.hxx>
+#include <map>
+#include <set>
+#include <vector>
+
+#include <editeng/eeitem.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/editview.hxx>
+#include <svx/svdoutl.hxx>
+#include <svx/svdview.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <memory>
+#include <redline.hxx>
+#include <DocumentRedlineManager.hxx>
+#include <xmloff/odffields.hxx>
+#include <tools/json_writer.hxx>
+#include <tools/UnitConversion.hxx>
+
+#include <svx/svdpage.hxx>
+#include <o3tl/string_view.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+
+#include <IDocumentOutlineNodes.hxx>
+#include <SearchResultLocator.hxx>
+#include <textcontentcontrol.hxx>
+#include <unocontentcontrol.hxx>
+#include <unoport.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::document;
+using ::osl::FileBase;
+
+static std::unique_ptr<SwPrintUIOptions> lcl_GetPrintUIOptions(
+ SwDocShell * pDocShell,
+ const SfxViewShell * pView )
+{
+ if (!pDocShell)
+ return nullptr;
+
+ const bool bWebDoc = nullptr != dynamic_cast< const SwWebDocShell * >(pDocShell);
+ const bool bSwSrcView = nullptr != dynamic_cast< const SwSrcView * >(pView);
+ const SwView * pSwView = dynamic_cast< const SwView * >(pView);
+ const bool bHasSelection = pSwView && pSwView->HasSelection( false ); // check for any selection, not just text selection
+ const bool bHasPostIts = sw_GetPostIts(pDocShell->GetDoc()->getIDocumentFieldsAccess(), nullptr);
+
+ // get default values to use in dialog from documents SwPrintData
+ const SwPrintData &rPrintData = pDocShell->GetDoc()->getIDocumentDeviceAccess().getPrintData();
+
+ // Get current page number
+ sal_uInt16 nCurrentPage = 1;
+ const SwWrtShell* pSh = pDocShell->GetWrtShell();
+ const SwRootFrame *pFrame = nullptr;
+ if (pSh)
+ {
+ SwPaM* pShellCursor = pSh->GetCursor();
+ nCurrentPage = pShellCursor->GetPageNum();
+ pFrame = pSh->GetLayout();
+ }
+ else if (!bSwSrcView)
+ {
+ const SwPagePreview* pPreview = dynamic_cast< const SwPagePreview* >(pView);
+ OSL_ENSURE(pPreview, "Unexpected type of the view shell");
+ if (pPreview)
+ {
+ nCurrentPage = pPreview->GetSelectedPage();
+ pFrame = pPreview->GetViewShell()->GetLayout();
+ }
+ }
+
+ // If blanks are skipped, account for them in initial page range value
+ if (pFrame && !rPrintData.IsPrintEmptyPages())
+ {
+ sal_uInt16 nMax = nCurrentPage;
+ const SwPageFrame *pPage = dynamic_cast<const SwPageFrame*>(pFrame->Lower());
+ while (pPage && nMax-- > 0)
+ {
+ if (pPage->getFrameArea().Height() == 0)
+ nCurrentPage--;
+ pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
+ }
+ }
+ return std::make_unique<SwPrintUIOptions>( nCurrentPage, bWebDoc, bSwSrcView, bHasSelection, bHasPostIts, rPrintData );
+}
+
+static SwTextFormatColl *lcl_GetParaStyle(const OUString& rCollName, SwDoc& rDoc)
+{
+ SwTextFormatColl* pColl = rDoc.FindTextFormatCollByName( rCollName );
+ if( !pColl )
+ {
+ const sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(
+ rCollName, SwGetPoolIdFromName::TxtColl );
+ if( USHRT_MAX != nId )
+ pColl = rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool( nId );
+ }
+ return pColl;
+}
+
+static void lcl_DisposeView( SfxViewFrame* pToClose, SwDocShell const * pDocShell )
+{
+ // check if the view frame still exists
+ SfxViewFrame* pFound = SfxViewFrame::GetFirst( pDocShell, false );
+ while(pFound)
+ {
+ if( pFound == pToClose)
+ {
+ pToClose->DoClose();
+ break;
+ }
+ pFound = SfxViewFrame::GetNext( *pFound, pDocShell, false );
+ }
+}
+
+class SwXTextDocument::Impl
+{
+public:
+ std::mutex m_Mutex; // just for OInterfaceContainerHelper4
+ ::comphelper::OInterfaceContainerHelper4<css::util::XRefreshListener> m_RefreshListeners;
+};
+
+const Sequence< sal_Int8 > & SwXTextDocument::getUnoTunnelId()
+{
+ static const comphelper::UnoIdInit theSwXTextDocumentUnoTunnelId;
+ return theSwXTextDocumentUnoTunnelId.getSeq();
+}
+
+sal_Int64 SAL_CALL SwXTextDocument::getSomething( const Sequence< sal_Int8 >& rId )
+{
+ if( comphelper::isUnoTunnelId<SwXTextDocument>(rId) )
+ {
+ return comphelper::getSomething_cast(this);
+ }
+ if( comphelper::isUnoTunnelId<SfxObjectShell>(rId) )
+ {
+ return comphelper::getSomething_cast(m_pDocShell);
+ }
+
+ sal_Int64 nRet = SfxBaseModel::getSomething( rId );
+ if (nRet)
+ return nRet;
+
+ GetNumberFormatter();
+ if (!m_xNumFormatAgg.is()) // may happen if not valid or no SwDoc
+ return 0;
+ Any aNumTunnel = m_xNumFormatAgg->queryAggregation(cppu::UnoType<XUnoTunnel>::get());
+ Reference<XUnoTunnel> xNumTunnel;
+ aNumTunnel >>= xNumTunnel;
+ return (xNumTunnel.is()) ? xNumTunnel->getSomething(rId) : 0;
+}
+
+Any SAL_CALL SwXTextDocument::queryInterface( const uno::Type& rType )
+{
+ Any aRet = SwXTextDocumentBaseClass::queryInterface(rType);
+ if ( !aRet.hasValue() )
+ aRet = SfxBaseModel::queryInterface(rType);
+ if ( !aRet.hasValue() &&
+ rType == cppu::UnoType<lang::XMultiServiceFactory>::get())
+ {
+ Reference<lang::XMultiServiceFactory> xTmp = this;
+ aRet <<= xTmp;
+ }
+ if ( !aRet.hasValue() &&
+ rType == cppu::UnoType<tiledrendering::XTiledRenderable>::get())
+ {
+ Reference<tiledrendering::XTiledRenderable> xTmp = this;
+ aRet <<= xTmp;
+ }
+
+ if ( !aRet.hasValue()
+ && rType != cppu::UnoType<css::document::XDocumentEventBroadcaster>::get()
+ && rType != cppu::UnoType<css::frame::XController>::get()
+ && rType != cppu::UnoType<css::frame::XFrame>::get()
+ && rType != cppu::UnoType<css::script::XInvocation>::get()
+ && rType != cppu::UnoType<css::beans::XFastPropertySet>::get()
+ && rType != cppu::UnoType<css::awt::XWindow>::get())
+ {
+ GetNumberFormatter();
+ if(m_xNumFormatAgg.is())
+ aRet = m_xNumFormatAgg->queryAggregation(rType);
+ }
+ return aRet;
+}
+
+void SAL_CALL SwXTextDocument::acquire()noexcept
+{
+ SfxBaseModel::acquire();
+}
+
+void SAL_CALL SwXTextDocument::release()noexcept
+{
+ SfxBaseModel::release();
+}
+
+Sequence< uno::Type > SAL_CALL SwXTextDocument::getTypes()
+{
+ Sequence< uno::Type > aNumTypes;
+ GetNumberFormatter();
+ if(m_xNumFormatAgg.is())
+ {
+ const uno::Type& rProvType = cppu::UnoType<XTypeProvider>::get();
+ Any aNumProv = m_xNumFormatAgg->queryAggregation(rProvType);
+ Reference<XTypeProvider> xNumProv;
+ if(aNumProv >>= xNumProv)
+ {
+ aNumTypes = xNumProv->getTypes();
+ }
+ }
+ return comphelper::concatSequences(
+ SfxBaseModel::getTypes(),
+ SwXTextDocumentBaseClass::getTypes(),
+ aNumTypes,
+ Sequence {
+ cppu::UnoType<lang::XMultiServiceFactory>::get(),
+ cppu::UnoType<tiledrendering::XTiledRenderable>::get()});
+}
+
+SwXTextDocument::SwXTextDocument(SwDocShell* pShell)
+ : SwXTextDocumentBaseClass(pShell)
+ , m_pImpl(new Impl)
+ ,
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_DOCUMENT)),
+ m_pDocShell(pShell),
+ m_bObjectValid(pShell != nullptr),
+ m_pHiddenViewFrame(nullptr),
+ // #i117783#
+ m_bApplyPagePrintSettingsFromXPagePrintable( false )
+{
+}
+
+SwDoc& SwXTextDocument::GetDocOrThrow() const
+{
+ if (SwDoc* pDoc = m_pDocShell->GetDoc())
+ return *pDoc;
+ throw css::lang::NotInitializedException(
+ u"Document not initialized by a call to attachResource() or load()"_ustr,
+ const_cast<SwXTextDocument*>(this)->getXWeak());
+}
+
+SdrModel& SwXTextDocument::getSdrModelFromUnoModel() const
+{
+ assert(GetDocOrThrow().getIDocumentDrawModelAccess().GetOrCreateDrawModel());
+ return *GetDocOrThrow().getIDocumentDrawModelAccess().GetDrawModel();
+}
+
+SwXTextDocument::~SwXTextDocument()
+{
+ InitNewDoc();
+ if(m_xNumFormatAgg.is())
+ {
+ Reference< XInterface > x0;
+ m_xNumFormatAgg->setDelegator(x0);
+ m_xNumFormatAgg = nullptr;
+ }
+ m_pPrintUIOptions.reset();
+ if (m_pRenderData && m_pRenderData->IsViewOptionAdjust())
+ { // rhbz#827695: this can happen if the last page is not printed
+ // the SwViewShell has been deleted already by SwView::~SwView
+ // FIXME: replace this awful implementation of XRenderable with
+ // something less insane that has its own view
+ m_pRenderData->ViewOptionAdjustCrashPreventionKludge();
+ }
+ m_pRenderData.reset();
+}
+
+SwXDocumentPropertyHelper * SwXTextDocument::GetPropertyHelper ()
+{
+ if(!mxPropertyHelper.is())
+ {
+ mxPropertyHelper = new SwXDocumentPropertyHelper(GetDocOrThrow());
+ }
+ return mxPropertyHelper.get();
+}
+
+void SwXTextDocument::GetNumberFormatter()
+{
+ if(!IsValid())
+ return;
+
+ if(!m_xNumFormatAgg.is())
+ {
+ if ( m_pDocShell->GetDoc() )
+ {
+ rtl::Reference<SvNumberFormatsSupplierObj> pNumFormat = new SvNumberFormatsSupplierObj(
+ m_pDocShell->GetDoc()->GetNumberFormatter());
+ m_xNumFormatAgg = pNumFormat;
+ }
+ if(m_xNumFormatAgg.is())
+ m_xNumFormatAgg->setDelegator(getXWeak());
+ }
+ else
+ {
+ const uno::Type& rTunnelType = cppu::UnoType<XUnoTunnel>::get();
+ Any aNumTunnel = m_xNumFormatAgg->queryAggregation(rTunnelType);
+ Reference< XUnoTunnel > xNumTunnel;
+ aNumTunnel >>= xNumTunnel;
+ SvNumberFormatsSupplierObj* pNumFormat
+ = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(xNumTunnel);
+ OSL_ENSURE(pNumFormat, "No number formatter available");
+ if (pNumFormat && !pNumFormat->GetNumberFormatter())
+ pNumFormat->SetNumberFormatter(GetDocOrThrow().GetNumberFormatter());
+ }
+}
+
+Reference< XText > SwXTextDocument::getText()
+{
+ return getBodyText();
+}
+
+rtl::Reference< SwXBodyText > SwXTextDocument::getBodyText()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!m_xBodyText.is())
+ {
+ m_xBodyText = new SwXBodyText(m_pDocShell->GetDoc());
+ }
+ return m_xBodyText;
+}
+
+void SwXTextDocument::reformat()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+}
+
+void SwXTextDocument::lockControllers()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+
+ maActionArr.emplace_front(new UnoActionContext(m_pDocShell->GetDoc()));
+}
+
+void SwXTextDocument::unlockControllers()
+{
+ SolarMutexGuard aGuard;
+ if(maActionArr.empty())
+ throw RuntimeException("Nothing to unlock");
+
+ maActionArr.pop_front();
+}
+
+sal_Bool SwXTextDocument::hasControllersLocked()
+{
+ SolarMutexGuard aGuard;
+ return !maActionArr.empty();
+}
+
+Reference< frame::XController > SwXTextDocument::getCurrentController()
+{
+ return SfxBaseModel::getCurrentController();
+}
+
+void SwXTextDocument::setCurrentController(const Reference< frame::XController > & xController)
+{
+ SfxBaseModel::setCurrentController(xController);
+}
+
+Reference< XInterface > SwXTextDocument::getCurrentSelection()
+{
+ SolarMutexGuard aGuard;
+ Reference< XInterface > xRef;
+ if(IsValid())
+ {
+ SwView* pView = static_cast<SwView*>(SfxViewShell::GetFirst(true, checkSfxViewShell<SwView>));
+ while(pView && pView->GetObjectShell() != m_pDocShell)
+ {
+ pView = static_cast<SwView*>(SfxViewShell::GetNext(*pView, true, checkSfxViewShell<SwView>));
+ }
+ if(pView)
+ {
+ Any aRef = pView->GetUNOObject()->getSelection();
+ aRef >>= xRef;
+ }
+ }
+ return xRef;
+}
+
+sal_Bool SwXTextDocument::attachResource(const OUString& aURL, const Sequence< beans::PropertyValue >& aArgs)
+{
+ return SfxBaseModel::attachResource(aURL, aArgs);
+}
+
+OUString SwXTextDocument::getURL()
+{
+ return SfxBaseModel::getURL();
+}
+
+Sequence< beans::PropertyValue > SwXTextDocument::getArgs()
+{
+ return SfxBaseModel::getArgs();
+}
+
+void SwXTextDocument::connectController(const Reference< frame::XController > & xController)
+{
+ SfxBaseModel::connectController(xController);
+}
+
+void SwXTextDocument::disconnectController(const Reference< frame::XController > & xController)
+{
+ SfxBaseModel::disconnectController(xController);
+}
+
+void SwXTextDocument::dispose()
+{
+ // Delete UnoActionContexts before deleting the SwDoc, as the first has unowned pointers to the
+ // second.
+ maActionArr.clear();
+
+ SfxBaseModel::dispose();
+}
+
+void SwXTextDocument::close( sal_Bool bDeliverOwnership )
+{
+ if(m_pDocShell)
+ {
+ uno::Sequence< uno::Any > aArgs;
+ m_pDocShell->CallAutomationDocumentEventSinks( "Close", aArgs );
+ }
+ SolarMutexGuard aGuard;
+ if(IsValid() && m_pHiddenViewFrame)
+ lcl_DisposeView( m_pHiddenViewFrame, m_pDocShell);
+ SfxBaseModel::close(bDeliverOwnership);
+}
+
+void SwXTextDocument::addEventListener(const Reference< lang::XEventListener > & aListener)
+{
+ SfxBaseModel::addEventListener(aListener);
+}
+
+void SwXTextDocument::removeEventListener(const Reference< lang::XEventListener > & aListener)
+{
+ SfxBaseModel::removeEventListener(aListener);
+}
+
+Reference< XPropertySet > SwXTextDocument::getLineNumberingProperties()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+
+ if(!mxXLineNumberingProperties.is())
+ {
+ mxXLineNumberingProperties = new SwXLineNumberingProperties(m_pDocShell->GetDoc());
+ }
+ return mxXLineNumberingProperties;
+}
+
+Reference< XIndexReplace > SwXTextDocument::getChapterNumberingRules()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXChapterNumbering.is())
+ {
+ mxXChapterNumbering = new SwXChapterNumbering(*m_pDocShell);
+ }
+ return mxXChapterNumbering;
+}
+
+Reference< XIndexAccess > SwXTextDocument::getNumberingRules()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXNumberingRules.is() )
+ {
+ mxXNumberingRules = new SwXNumberingRulesCollection( m_pDocShell->GetDoc() );
+ }
+ return mxXNumberingRules;
+}
+
+Reference< XIndexAccess > SwXTextDocument::getFootnotes()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXFootnotes.is())
+ {
+ mxXFootnotes = new SwXFootnotes(false, m_pDocShell->GetDoc());
+ }
+ return mxXFootnotes;
+}
+
+Reference< XPropertySet > SAL_CALL
+ SwXTextDocument::getFootnoteSettings()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXFootnoteSettings.is())
+ {
+ mxXFootnoteSettings = new SwXFootnoteProperties(m_pDocShell->GetDoc());
+ }
+ return mxXFootnoteSettings;
+}
+
+Reference< XIndexAccess > SwXTextDocument::getEndnotes()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXEndnotes.is())
+ {
+ mxXEndnotes = new SwXFootnotes(true, m_pDocShell->GetDoc());
+ }
+ return mxXEndnotes;
+}
+
+Reference< XPropertySet > SwXTextDocument::getEndnoteSettings()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXEndnoteSettings.is())
+ {
+ mxXEndnoteSettings = new SwXEndnoteProperties(m_pDocShell->GetDoc());
+ }
+ return mxXEndnoteSettings;
+}
+
+Reference< XIndexAccess > SwXTextDocument::getContentControls()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXContentControls.is())
+ {
+ mxXContentControls = new SwXContentControls(m_pDocShell->GetDoc());
+ }
+ return mxXContentControls;
+}
+
+Reference< util::XReplaceDescriptor > SwXTextDocument::createReplaceDescriptor()
+{
+ return new SwXTextSearch;
+}
+
+SwUnoCursor* SwXTextDocument::CreateCursorForSearch(Reference< XTextCursor > & xCursor)
+{
+ getText();
+ XText *const pText = m_xBodyText.get();
+ SwXBodyText* pBText = static_cast<SwXBodyText*>(pText);
+ rtl::Reference<SwXTextCursor> pXTextCursor = pBText->CreateTextCursor(true);
+ xCursor.set( static_cast<text::XWordCursor*>(pXTextCursor.get()) );
+
+ auto& rUnoCursor(pXTextCursor->GetCursor());
+ rUnoCursor.SetRemainInSection(false);
+ return &rUnoCursor;
+}
+
+sal_Int32 SwXTextDocument::replaceAll(const Reference< util::XSearchDescriptor > & xDesc)
+{
+ SolarMutexGuard aGuard;
+ SwXTextSearch* pSearch;
+ if (!IsValid() || !(pSearch = dynamic_cast<SwXTextSearch*>(xDesc.get())))
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+
+ Reference< XTextCursor > xCursor;
+ auto pUnoCursor(CreateCursorForSearch(xCursor));
+ int eRanges(FindRanges::InBody|FindRanges::InSelAll);
+
+ i18nutil::SearchOptions2 aSearchOpt;
+ pSearch->FillSearchOptions( aSearchOpt );
+
+ SwDocPositions eStart = pSearch->m_bBack ? SwDocPositions::End : SwDocPositions::Start;
+ SwDocPositions eEnd = pSearch->m_bBack ? SwDocPositions::Start : SwDocPositions::End;
+
+ // Search should take place anywhere
+ pUnoCursor->SetRemainInSection(false);
+ sal_Int32 nResult;
+ UnoActionContext aContext(m_pDocShell->GetDoc());
+ //try attribute search first
+ if(pSearch->HasSearchAttributes()||pSearch->HasReplaceAttributes())
+ {
+ auto& pool = GetDocOrThrow().GetAttrPool();
+ SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_PARATR_BEGIN, RES_PARATR_END-1,
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1> aSearch(pool);
+ SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_PARATR_BEGIN, RES_PARATR_END-1,
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1> aReplace(pool);
+ pSearch->FillSearchItemSet(aSearch);
+ pSearch->FillReplaceItemSet(aReplace);
+ bool bCancel;
+ nResult = pUnoCursor->FindAttrs(aSearch, !pSearch->m_bStyles,
+ eStart, eEnd, bCancel,
+ static_cast<FindRanges>(eRanges),
+ !pSearch->m_sSearchText.isEmpty() ? &aSearchOpt : nullptr,
+ &aReplace );
+ }
+ else if(pSearch->m_bStyles)
+ {
+ SwTextFormatColl *pSearchColl = lcl_GetParaStyle(pSearch->m_sSearchText, pUnoCursor->GetDoc());
+ SwTextFormatColl *pReplaceColl = lcl_GetParaStyle(pSearch->m_sReplaceText, pUnoCursor->GetDoc());
+
+ bool bCancel;
+ nResult = pUnoCursor->FindFormat(*pSearchColl,
+ eStart, eEnd, bCancel,
+ static_cast<FindRanges>(eRanges), pReplaceColl );
+
+ }
+ else
+ {
+ //todo/mba: assuming that notes should be omitted
+ bool bCancel;
+ nResult = pUnoCursor->Find_Text(aSearchOpt, false/*bSearchInNotes*/,
+ eStart, eEnd, bCancel,
+ static_cast<FindRanges>(eRanges),
+ true );
+ }
+ return nResult;
+
+}
+
+Reference< util::XSearchDescriptor > SwXTextDocument::createSearchDescriptor()
+{
+ return new SwXTextSearch;
+}
+
+// Used for findAll/First/Next
+
+SwUnoCursor* SwXTextDocument::FindAny(const Reference< util::XSearchDescriptor > & xDesc,
+ Reference< XTextCursor > & xCursor,
+ bool bAll,
+ sal_Int32& nResult,
+ Reference< XInterface > const & xLastResult)
+{
+ const auto pSearch = dynamic_cast<SwXTextSearch*>(xDesc.get());
+ if(!IsValid() || !pSearch)
+ return nullptr;
+
+ auto pUnoCursor(CreateCursorForSearch(xCursor));
+
+ bool bParentInExtra = false;
+ if(xLastResult.is())
+ {
+ OTextCursorHelper* pPosCursor = dynamic_cast<OTextCursorHelper*>(xLastResult.get());
+ SwPaM* pCursor = pPosCursor ? pPosCursor->GetPaM() : nullptr;
+ if(pCursor)
+ {
+ *pUnoCursor->GetPoint() = *pCursor->End();
+ pUnoCursor->DeleteMark();
+ }
+ else
+ {
+ SwXTextRange* pRange = dynamic_cast<SwXTextRange*>(xLastResult.get());
+ if(!pRange)
+ return nullptr;
+ pRange->GetPositions(*pUnoCursor);
+ if(pUnoCursor->HasMark())
+ {
+ if(*pUnoCursor->GetPoint() < *pUnoCursor->GetMark())
+ pUnoCursor->Exchange();
+ pUnoCursor->DeleteMark();
+ }
+ }
+ const SwNode& rRangeNode = pUnoCursor->GetPointNode();
+ bParentInExtra = rRangeNode.FindFlyStartNode() ||
+ rRangeNode.FindFootnoteStartNode() ||
+ rRangeNode.FindHeaderStartNode() ||
+ rRangeNode.FindFooterStartNode() ;
+ }
+
+ i18nutil::SearchOptions2 aSearchOpt;
+ pSearch->FillSearchOptions( aSearchOpt );
+
+/**
+ * The following combinations are allowed:
+ * - Search in the body: -> FindRanges::InBody
+ * - Search all in the body: -> FindRanges::InBodyOnly | FindRanges::InSelAll
+ * - Search in selections: one / all -> FindRanges::InSel [ | FindRanges::InSelAll ]
+ * - Search outside the body: one / all -> FindRanges::InOther [ | FindRanges::InSelAll ]
+ * - Search everywhere all: -> FindRanges::InSelAll
+ */
+ FindRanges eRanges(FindRanges::InBody);
+ if(bParentInExtra)
+ eRanges = FindRanges::InOther;
+ if(bAll) //always - everywhere?
+ eRanges = FindRanges::InSelAll;
+ SwDocPositions eStart = !bAll ? SwDocPositions::Curr : pSearch->m_bBack ? SwDocPositions::End : SwDocPositions::Start;
+ SwDocPositions eEnd = pSearch->m_bBack ? SwDocPositions::Start : SwDocPositions::End;
+
+ nResult = 0;
+ for (int nSearchProc = 0; nSearchProc < 2; ++nSearchProc)
+ {
+ //try attribute search first
+ if(pSearch->HasSearchAttributes())
+ {
+ SfxItemSetFixed<
+ RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
+ RES_TXTATR_INETFMT, RES_TXTATR_CHARFMT,
+ RES_PARATR_BEGIN, RES_PARATR_END - 1,
+ RES_FRMATR_BEGIN, RES_FRMATR_END - 1>
+ aSearch( GetDocOrThrow().GetAttrPool() );
+ pSearch->FillSearchItemSet(aSearch);
+ bool bCancel;
+ nResult = pUnoCursor->FindAttrs(aSearch, !pSearch->m_bStyles,
+ eStart, eEnd, bCancel,
+ eRanges,
+ !pSearch->m_sSearchText.isEmpty() ? &aSearchOpt : nullptr );
+ }
+ else if(pSearch->m_bStyles)
+ {
+ SwTextFormatColl *pSearchColl = lcl_GetParaStyle(pSearch->m_sSearchText, pUnoCursor->GetDoc());
+ //pSearch->sReplaceText
+ SwTextFormatColl *pReplaceColl = nullptr;
+ bool bCancel;
+ nResult = pUnoCursor->FindFormat(*pSearchColl,
+ eStart, eEnd, bCancel,
+ eRanges, pReplaceColl );
+ }
+ else
+ {
+ //todo/mba: assuming that notes should be omitted
+ bool bCancel;
+ nResult = pUnoCursor->Find_Text(aSearchOpt, false/*bSearchInNotes*/,
+ eStart, eEnd, bCancel,
+ eRanges );
+ }
+ if(nResult || (eRanges&(FindRanges::InSelAll|FindRanges::InOther)))
+ break;
+ //second step - find in other
+ eRanges = FindRanges::InOther;
+ }
+ return pUnoCursor;
+}
+
+Reference< XIndexAccess >
+ SwXTextDocument::findAll(const Reference< util::XSearchDescriptor > & xDesc)
+{
+ SolarMutexGuard aGuard;
+ Reference< XInterface > xTmp;
+ sal_Int32 nResult = 0;
+ Reference< XTextCursor > xCursor;
+ auto pResultCursor(FindAny(xDesc, xCursor, true, nResult, xTmp));
+ if(!pResultCursor)
+ throw RuntimeException("No result cursor");
+ Reference< XIndexAccess > xRet = SwXTextRanges::Create( nResult ? &(*pResultCursor) : nullptr );
+ return xRet;
+}
+
+Reference< XInterface > SwXTextDocument::findFirst(const Reference< util::XSearchDescriptor > & xDesc)
+{
+ SolarMutexGuard aGuard;
+ Reference< XInterface > xTmp;
+ sal_Int32 nResult = 0;
+ Reference< XTextCursor > xCursor;
+ auto pResultCursor(FindAny(xDesc, xCursor, false, nResult, xTmp));
+ if(!pResultCursor)
+ throw RuntimeException("No result cursor");
+ Reference< XInterface > xRet;
+ if(nResult)
+ {
+ const uno::Reference< text::XText > xParent =
+ ::sw::CreateParentXText(GetDocOrThrow(),
+ *pResultCursor->GetPoint());
+ xRet = *new SwXTextCursor(xParent, *pResultCursor);
+ }
+ return xRet;
+}
+
+Reference< XInterface > SwXTextDocument::findNext(const Reference< XInterface > & xStartAt,
+ const Reference< util::XSearchDescriptor > & xDesc)
+{
+ SolarMutexGuard aGuard;
+ sal_Int32 nResult = 0;
+ Reference< XTextCursor > xCursor;
+ if(!xStartAt.is())
+ throw RuntimeException("xStartAt missing");
+ auto pResultCursor(FindAny(xDesc, xCursor, false, nResult, xStartAt));
+ if(!pResultCursor)
+ throw RuntimeException("No result cursor");
+ Reference< XInterface > xRet;
+ if(nResult)
+ {
+ const uno::Reference< text::XText > xParent =
+ ::sw::CreateParentXText(GetDocOrThrow(),
+ *pResultCursor->GetPoint());
+
+ xRet = *new SwXTextCursor(xParent, *pResultCursor);
+ }
+ return xRet;
+}
+
+Sequence< beans::PropertyValue > SwXTextDocument::getPagePrintSettings()
+{
+ SolarMutexGuard aGuard;
+ Sequence< beans::PropertyValue > aSeq(9);
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+
+ beans::PropertyValue* pArray = aSeq.getArray();
+ SwPagePreviewPrtData aData;
+ const SwPagePreviewPrtData* pData = GetDocOrThrow().GetPreviewPrtData();
+ if(pData)
+ aData = *pData;
+ Any aVal;
+ aVal <<= aData.GetRow();
+ pArray[0] = beans::PropertyValue("PageRows", -1, aVal, PropertyState_DIRECT_VALUE);
+ aVal <<= aData.GetCol();
+ pArray[1] = beans::PropertyValue("PageColumns", -1, aVal, PropertyState_DIRECT_VALUE);
+ aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetLeftSpace()));
+ pArray[2] = beans::PropertyValue("LeftMargin", -1, aVal, PropertyState_DIRECT_VALUE);
+ aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetRightSpace()));
+ pArray[3] = beans::PropertyValue("RightMargin", -1, aVal, PropertyState_DIRECT_VALUE);
+ aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetTopSpace()));
+ pArray[4] = beans::PropertyValue("TopMargin", -1, aVal, PropertyState_DIRECT_VALUE);
+ aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetBottomSpace()));
+ pArray[5] = beans::PropertyValue("BottomMargin", -1, aVal, PropertyState_DIRECT_VALUE);
+ aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetHorzSpace()));
+ pArray[6] = beans::PropertyValue("HoriMargin", -1, aVal, PropertyState_DIRECT_VALUE);
+ aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetVertSpace()));
+ pArray[7] = beans::PropertyValue("VertMargin", -1, aVal, PropertyState_DIRECT_VALUE);
+ aVal <<= aData.GetLandscape();
+ pArray[8] = beans::PropertyValue("IsLandscape", -1, aVal, PropertyState_DIRECT_VALUE);
+
+ return aSeq;
+}
+
+static sal_uInt32 lcl_Any_To_ULONG(const Any& rValue, bool& bException)
+{
+ bException = false;
+ TypeClass eType = rValue.getValueType().getTypeClass();
+
+ sal_uInt32 nRet = 0;
+ if( eType == TypeClass_UNSIGNED_LONG )
+ rValue >>= nRet;
+ else
+ {
+ sal_Int32 nVal=0;
+ bException = !(rValue >>= nVal);
+ if( !bException )
+ nRet = static_cast<sal_uInt32>(nVal);
+ }
+
+ return nRet;
+}
+
+static OUString lcl_CreateOutlineString(const size_t nIndex, const SwDoc* pDoc)
+{
+ OUStringBuffer sEntry;
+ const SwOutlineNodes& rOutlineNodes = pDoc->GetNodes().GetOutLineNds();
+ const SwNumRule* pOutlRule = pDoc->GetOutlineNumRule();
+ const SwTextNode * pTextNd = rOutlineNodes[ nIndex ]->GetTextNode();
+ SwNumberTree::tNumberVector aNumVector = pTextNd->GetNumberVector();
+ if( pOutlRule && pTextNd->GetNumRule())
+ for( int nLevel = 0;
+ nLevel <= pTextNd->GetActualListLevel();
+ nLevel++ )
+ {
+ tools::Long nVal = aNumVector[nLevel];
+ nVal ++;
+ nVal -= pOutlRule->Get(nLevel).GetStart();
+ sEntry.append( OUString::number(nVal) + ".");
+ }
+ OUString sOutlineText = pDoc->getIDocumentOutlineNodes().getOutlineText(
+ nIndex, pDoc->GetDocShell()->GetWrtShell()->GetLayout(), false);
+ sEntry.append(sOutlineText);
+ return sEntry.makeStringAndClear();
+}
+
+void SwXTextDocument::setPagePrintSettings(const Sequence< beans::PropertyValue >& aSettings)
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+
+ SwPagePreviewPrtData aData;
+ SwDoc& rDoc = GetDocOrThrow();
+ //if only a few properties are coming, then use the current settings
+ const SwPagePreviewPrtData* pData = rDoc.GetPreviewPrtData();
+ if(pData)
+ aData = *pData;
+ for(const beans::PropertyValue& rProperty : aSettings)
+ {
+ OUString sName = rProperty.Name;
+ const Any& rVal = rProperty.Value;
+ bool bException;
+ sal_uInt32 nVal = lcl_Any_To_ULONG(rVal, bException);
+ if( sName == "PageRows" )
+ {
+ if(!nVal || nVal > 0xff)
+ throw RuntimeException("Invalid value");
+ aData.SetRow(nVal);
+ }
+ else if(sName == "PageColumns")
+ {
+ if(!nVal || nVal > 0xff)
+ throw RuntimeException("Invalid value");
+ aData.SetCol(nVal);
+ }
+ else if(sName == "LeftMargin")
+ {
+ aData.SetLeftSpace(o3tl::toTwips(nVal, o3tl::Length::mm100));
+ }
+ else if(sName == "RightMargin")
+ {
+ aData.SetRightSpace(o3tl::toTwips(nVal, o3tl::Length::mm100));
+ }
+ else if(sName == "TopMargin")
+ {
+ aData.SetTopSpace(o3tl::toTwips(nVal, o3tl::Length::mm100));
+ }
+ else if(sName == "BottomMargin")
+ {
+ aData.SetBottomSpace(o3tl::toTwips(nVal, o3tl::Length::mm100));
+ }
+ else if(sName == "HoriMargin")
+ {
+ aData.SetHorzSpace(o3tl::toTwips(nVal, o3tl::Length::mm100));
+ }
+ else if(sName == "VertMargin")
+ {
+ aData.SetVertSpace(o3tl::toTwips(nVal, o3tl::Length::mm100));
+ }
+ else if(sName == "IsLandscape")
+ {
+ std::optional<const bool> b = o3tl::tryAccess<bool>(rVal);
+ bException = !b.has_value();
+ if (b)
+ {
+ aData.SetLandscape(*b);
+ }
+ }
+ else
+ bException = true;
+ if(bException)
+ throw RuntimeException();
+ }
+ rDoc.SetPreviewPrtData(&aData);
+
+}
+
+void SwXTextDocument::printPages(const Sequence< beans::PropertyValue >& xOptions)
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+
+ SfxViewFrame* pFrame = SfxViewFrame::LoadHiddenDocument( *m_pDocShell, SfxInterfaceId(7) );
+ SfxRequest aReq(FN_PRINT_PAGEPREVIEW, SfxCallMode::SYNCHRON,
+ GetDocOrThrow().GetAttrPool());
+ aReq.AppendItem(SfxBoolItem(FN_PRINT_PAGEPREVIEW, true));
+
+ for ( const beans::PropertyValue &rProp : xOptions )
+ {
+ // get Property-Value from options
+ Any aValue( rProp.Value );
+
+ // FileName-Property?
+ if ( rProp.Name == UNO_NAME_FILE_NAME )
+ {
+ OUString sFileURL;
+ if ( rProp.Value >>= sFileURL )
+ {
+ // Convert the File URL into a system dependent path, as the SalPrinter expects
+ OUString sSystemPath;
+ FileBase::getSystemPathFromFileURL ( sFileURL, sSystemPath );
+ aReq.AppendItem(SfxStringItem( SID_FILE_NAME, sSystemPath ) );
+ }
+ else if ( rProp.Value.getValueType() != cppu::UnoType<void>::get() )
+ throw IllegalArgumentException();
+ }
+
+ // CopyCount-Property
+ else if ( rProp.Name == UNO_NAME_COPY_COUNT )
+ {
+ sal_Int32 nCopies = 0;
+ aValue >>= nCopies;
+ aReq.AppendItem(SfxInt16Item( SID_PRINT_COPIES, static_cast<sal_Int16>(nCopies) ) );
+ }
+
+ // Collate-Property
+ else if ( rProp.Name == UNO_NAME_COLLATE )
+ {
+ std::optional<const bool> b = o3tl::tryAccess<bool>(rProp.Value);
+ if ( !b.has_value() )
+ throw IllegalArgumentException();
+ aReq.AppendItem(SfxBoolItem( SID_PRINT_COLLATE, *b ) );
+
+ }
+
+ // Sort-Property
+ else if ( rProp.Name == UNO_NAME_SORT )
+ {
+ std::optional<const bool> b = o3tl::tryAccess<bool>(rProp.Value);
+ if ( !b.has_value() )
+ throw IllegalArgumentException();
+
+ aReq.AppendItem(SfxBoolItem( SID_PRINT_SORT, *b ) );
+ }
+
+ // Pages-Property
+ else if ( rProp.Name == UNO_NAME_PAGES )
+ {
+ OUString sTmp;
+ if ( !(rProp.Value >>= sTmp) )
+ throw IllegalArgumentException();
+
+ aReq.AppendItem( SfxStringItem( SID_PRINT_PAGES, sTmp ) );
+
+ }
+ }
+
+ // #i117783#
+ m_bApplyPagePrintSettingsFromXPagePrintable = true;
+ pFrame->GetViewShell()->ExecuteSlot(aReq);
+ // Frame close
+ pFrame->DoClose();
+
+}
+
+Reference< XNameAccess > SwXTextDocument::getReferenceMarks()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXReferenceMarks.is())
+ {
+ mxXReferenceMarks = new SwXReferenceMarks(m_pDocShell->GetDoc());
+ }
+ return mxXReferenceMarks;
+}
+
+Reference< XEnumerationAccess > SwXTextDocument::getTextFields()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXTextFieldTypes.is())
+ {
+ mxXTextFieldTypes = new SwXTextFieldTypes(m_pDocShell->GetDoc());
+ }
+ return mxXTextFieldTypes;
+}
+
+Reference< XNameAccess > SwXTextDocument::getTextFieldMasters()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXTextFieldMasters.is())
+ {
+ mxXTextFieldMasters = new SwXTextFieldMasters(m_pDocShell->GetDoc());
+ }
+ return mxXTextFieldMasters;
+}
+
+Reference< XNameAccess > SwXTextDocument::getEmbeddedObjects()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXEmbeddedObjects.is())
+ {
+ mxXEmbeddedObjects = new SwXTextEmbeddedObjects(m_pDocShell->GetDoc());
+ }
+ return mxXEmbeddedObjects;
+}
+
+Reference< XNameAccess > SwXTextDocument::getBookmarks()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXBookmarks.is())
+ {
+ mxXBookmarks = new SwXBookmarks(m_pDocShell->GetDoc());
+ }
+ return mxXBookmarks;
+}
+
+Reference< XNameAccess > SwXTextDocument::getTextSections()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXTextSections.is())
+ {
+ mxXTextSections = new SwXTextSections(m_pDocShell->GetDoc());
+ }
+ return mxXTextSections;
+}
+
+Reference< XNameAccess > SwXTextDocument::getTextTables()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXTextTables.is())
+ {
+ mxXTextTables = new SwXTextTables(m_pDocShell->GetDoc());
+ }
+ return mxXTextTables;
+}
+
+Reference< XNameAccess > SwXTextDocument::getGraphicObjects()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXGraphicObjects.is())
+ {
+ mxXGraphicObjects = new SwXTextGraphicObjects(m_pDocShell->GetDoc());
+ }
+ return mxXGraphicObjects;
+}
+
+Reference< XNameAccess > SwXTextDocument::getTextFrames()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXTextFrames.is())
+ {
+ mxXTextFrames = new SwXTextFrames(m_pDocShell->GetDoc());
+ }
+ return mxXTextFrames;
+}
+
+Reference< XNameAccess > SwXTextDocument::getStyleFamilies()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXStyleFamilies.is())
+ {
+ mxXStyleFamilies = new SwXStyleFamilies(*m_pDocShell);
+ }
+ return mxXStyleFamilies;
+}
+
+uno::Reference< style::XAutoStyles > SwXTextDocument::getAutoStyles( )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!mxXAutoStyles.is())
+ {
+ mxXAutoStyles = new SwXAutoStyles(*m_pDocShell);
+ }
+ return mxXAutoStyles;
+
+}
+
+Reference< drawing::XDrawPage > SwXTextDocument::getDrawPage()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ if(!m_xDrawPage.is())
+ {
+ SwDoc& rDoc = GetDocOrThrow();
+ // #i52858#
+ SwDrawModel* pModel = rDoc.getIDocumentDrawModelAccess().GetOrCreateDrawModel();
+ SdrPage* pPage = pModel->GetPage( 0 );
+ m_xDrawPage = new SwFmDrawPage(&rDoc, pPage);
+ }
+ return m_xDrawPage;
+}
+
+namespace {
+
+class SwDrawPagesObj : public cppu::WeakImplHelper<
+ css::drawing::XDrawPages,
+ css::lang::XServiceInfo>
+{
+private:
+ css::uno::Reference< css::drawing::XDrawPageSupplier > m_xDoc;
+public:
+ SwDrawPagesObj(css::uno::Reference< css::drawing::XDrawPageSupplier > xDoc) : m_xDoc(std::move(xDoc)) {}
+
+ // XDrawPages
+ virtual css::uno::Reference< css::drawing::XDrawPage > SAL_CALL
+ insertNewByIndex(sal_Int32 /*nIndex*/) override { throw css::lang::NoSupportException(); }
+
+ virtual void SAL_CALL remove(const css::uno::Reference< css::drawing::XDrawPage >& /*xPage*/) override
+ {
+ throw css::lang::NoSupportException();
+ }
+
+ // XIndexAccess
+ virtual sal_Int32 SAL_CALL getCount() override { return 1; }
+
+ virtual css::uno::Any SAL_CALL getByIndex(sal_Int32 Index) override
+ {
+ if (Index != 0)
+ throw css::lang::IndexOutOfBoundsException("Writer documents have only one DrawPage!");
+ return css::uno::Any(m_xDoc->getDrawPage());
+ }
+
+ // XElementAccess
+ virtual css::uno::Type SAL_CALL getElementType() override
+ {
+ return cppu::UnoType<drawing::XDrawPage>::get();
+ }
+
+ virtual sal_Bool SAL_CALL hasElements() override { return true; }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override
+ {
+ return "SwDrawPagesObj";
+ }
+
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override
+ {
+ return cppu::supportsService(this, ServiceName);
+ }
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
+ {
+ return { "com.sun.star.drawing.DrawPages" };
+ }
+};
+
+}
+
+// XDrawPagesSupplier
+
+uno::Reference<drawing::XDrawPages> SAL_CALL SwXTextDocument::getDrawPages()
+{
+ SolarMutexGuard aGuard;
+ return new SwDrawPagesObj(this);
+}
+
+void SwXTextDocument::Invalidate()
+{
+ m_bObjectValid = false;
+ if(m_xNumFormatAgg.is())
+ {
+ const uno::Type& rTunnelType = cppu::UnoType<XUnoTunnel>::get();
+ Any aNumTunnel = m_xNumFormatAgg->queryAggregation(rTunnelType);
+ Reference< XUnoTunnel > xNumTunnel;
+ aNumTunnel >>= xNumTunnel;
+ SvNumberFormatsSupplierObj* pNumFormat
+ = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(xNumTunnel);
+ OSL_ENSURE(pNumFormat, "No number formatter available");
+ if (pNumFormat)
+ pNumFormat->SetNumberFormatter(nullptr);
+ OSL_ENSURE(pNumFormat, "No number formatter available");
+ }
+ InitNewDoc();
+ m_pDocShell = nullptr;
+ lang::EventObject const ev(static_cast<SwXTextDocumentBaseClass &>(*this));
+ std::unique_lock aGuard(m_pImpl->m_Mutex);
+ m_pImpl->m_RefreshListeners.disposeAndClear(aGuard, ev);
+}
+
+void SwXTextDocument::Reactivate(SwDocShell* pNewDocShell)
+{
+ if(m_pDocShell && m_pDocShell != pNewDocShell)
+ Invalidate();
+ m_pDocShell = pNewDocShell;
+ m_bObjectValid = true;
+}
+
+void SwXTextDocument::InitNewDoc()
+{
+ // first invalidate all collections, then delete references and Set to zero
+ if(mxXTextTables.is())
+ {
+ XNameAccess* pTables = mxXTextTables.get();
+ static_cast<SwXTextTables*>(pTables)->Invalidate();
+ mxXTextTables.clear();
+ }
+
+ if(mxXTextFrames.is())
+ {
+ XNameAccess* pFrames = mxXTextFrames.get();
+ static_cast<SwXTextFrames*>(pFrames)->Invalidate();
+ mxXTextFrames.clear();
+ }
+
+ if(mxXGraphicObjects.is())
+ {
+ XNameAccess* pFrames = mxXGraphicObjects.get();
+ static_cast<SwXTextGraphicObjects*>(pFrames)->Invalidate();
+ mxXGraphicObjects.clear();
+ }
+
+ if(mxXEmbeddedObjects.is())
+ {
+ XNameAccess* pOLE = mxXEmbeddedObjects.get();
+ static_cast<SwXTextEmbeddedObjects*>(pOLE)->Invalidate();
+ mxXEmbeddedObjects.clear();
+ }
+
+ m_xBodyText = nullptr;
+
+ if(m_xNumFormatAgg.is())
+ {
+ const uno::Type& rTunnelType = cppu::UnoType<XUnoTunnel>::get();
+ Any aNumTunnel = m_xNumFormatAgg->queryAggregation(rTunnelType);
+ Reference< XUnoTunnel > xNumTunnel;
+ aNumTunnel >>= xNumTunnel;
+ SvNumberFormatsSupplierObj* pNumFormat
+ = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(xNumTunnel);
+ OSL_ENSURE(pNumFormat, "No number formatter available");
+ if (pNumFormat)
+ pNumFormat->SetNumberFormatter(nullptr);
+ }
+
+ if(mxXTextFieldTypes.is())
+ {
+ XEnumerationAccess* pT = mxXTextFieldTypes.get();
+ static_cast<SwXTextFieldTypes*>(pT)->Invalidate();
+ mxXTextFieldTypes.clear();
+ }
+
+ if(mxXTextFieldMasters.is())
+ {
+ XNameAccess* pT = mxXTextFieldMasters.get();
+ static_cast<SwXTextFieldMasters*>(pT)->Invalidate();
+ mxXTextFieldMasters.clear();
+ }
+
+ if(mxXTextSections.is())
+ {
+ XNameAccess* pSect = mxXTextSections.get();
+ static_cast<SwXTextSections*>(pSect)->Invalidate();
+ mxXTextSections.clear();
+ }
+
+ if(m_xDrawPage.is())
+ {
+ // #i91798#, #i91895#
+ // dispose XDrawPage here. We are the owner and know that it is no longer in a valid condition.
+ m_xDrawPage->dispose();
+ m_xDrawPage->InvalidateSwDoc();
+ m_xDrawPage.clear();
+ }
+
+ if ( mxXNumberingRules.is() )
+ {
+ XIndexAccess* pNum = mxXNumberingRules.get();
+ static_cast<SwXNumberingRulesCollection*>(pNum)->Invalidate();
+ mxXNumberingRules.clear();
+ }
+
+ if(mxXFootnotes.is())
+ {
+ XIndexAccess* pFootnote = mxXFootnotes.get();
+ static_cast<SwXFootnotes*>(pFootnote)->Invalidate();
+ mxXFootnotes.clear();
+ }
+
+ if(mxXEndnotes.is())
+ {
+ XIndexAccess* pFootnote = mxXEndnotes.get();
+ static_cast<SwXFootnotes*>(pFootnote)->Invalidate();
+ mxXEndnotes.clear();
+ }
+
+ if(mxXContentControls.is())
+ {
+ XIndexAccess* pContentControls = mxXContentControls.get();
+ static_cast<SwXContentControls*>(pContentControls)->Invalidate();
+ mxXContentControls.clear();
+ }
+
+ if(mxXDocumentIndexes.is())
+ {
+ XIndexAccess* pIdxs = mxXDocumentIndexes.get();
+ static_cast<SwXDocumentIndexes*>(pIdxs)->Invalidate();
+ mxXDocumentIndexes.clear();
+ }
+
+ if(mxXStyleFamilies.is())
+ {
+ XNameAccess* pStyles = mxXStyleFamilies.get();
+ static_cast<SwXStyleFamilies*>(pStyles)->Invalidate();
+ mxXStyleFamilies.clear();
+ }
+ if(mxXAutoStyles.is())
+ {
+ XNameAccess* pStyles = mxXAutoStyles.get();
+ static_cast<SwXAutoStyles*>(pStyles)->Invalidate();
+ mxXAutoStyles.clear();
+ }
+
+ if(mxXBookmarks.is())
+ {
+ XNameAccess* pBm = mxXBookmarks.get();
+ static_cast<SwXBookmarks*>(pBm)->Invalidate();
+ mxXBookmarks.clear();
+ }
+
+ if(mxXChapterNumbering.is())
+ {
+ XIndexReplace* pCh = mxXChapterNumbering.get();
+ static_cast<SwXChapterNumbering*>(pCh)->Invalidate();
+ mxXChapterNumbering.clear();
+ }
+
+ if(mxXFootnoteSettings.is())
+ {
+ XPropertySet* pFntSet = mxXFootnoteSettings.get();
+ static_cast<SwXFootnoteProperties*>(pFntSet)->Invalidate();
+ mxXFootnoteSettings.clear();
+ }
+
+ if(mxXEndnoteSettings.is())
+ {
+ XPropertySet* pEndSet = mxXEndnoteSettings.get();
+ static_cast<SwXEndnoteProperties*>(pEndSet)->Invalidate();
+ mxXEndnoteSettings.clear();
+ }
+
+ if(mxXLineNumberingProperties.is())
+ {
+ XPropertySet* pLine = mxXLineNumberingProperties.get();
+ static_cast<SwXLineNumberingProperties*>(pLine)->Invalidate();
+ mxXLineNumberingProperties.clear();
+ }
+ if(mxXReferenceMarks.is())
+ {
+ XNameAccess* pMarks = mxXReferenceMarks.get();
+ static_cast<SwXReferenceMarks*>(pMarks)->Invalidate();
+ mxXReferenceMarks.clear();
+ }
+ if(mxLinkTargetSupplier.is())
+ {
+ XNameAccess* pAccess = mxLinkTargetSupplier.get();
+ static_cast<SwXLinkTargetSupplier*>(pAccess)->Invalidate();
+ mxLinkTargetSupplier.clear();
+ }
+ if(mxXRedlines.is())
+ {
+ XEnumerationAccess* pMarks = mxXRedlines.get();
+ static_cast<SwXRedlines*>(pMarks)->Invalidate();
+ mxXRedlines.clear();
+ }
+ if(mxPropertyHelper.is())
+ {
+ mxPropertyHelper->Invalidate();
+ mxPropertyHelper.clear();
+ }
+}
+
+css::uno::Reference<css::uno::XInterface> SwXTextDocument::create(
+ OUString const & rServiceName,
+ css::uno::Sequence<css::uno::Any> const * arguments)
+{
+ SolarMutexGuard aGuard;
+ if (!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+
+ const SwServiceType nType = SwXServiceProvider::GetProviderType(rServiceName);
+ if (nType != SwServiceType::Invalid)
+ {
+ return SwXServiceProvider::MakeInstance(nType, GetDocOrThrow());
+ }
+ if (rServiceName == "com.sun.star.drawing.DashTable")
+ {
+ return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Dash);
+ }
+ if (rServiceName == "com.sun.star.drawing.GradientTable")
+ {
+ return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Gradient);
+ }
+ if (rServiceName == "com.sun.star.drawing.HatchTable")
+ {
+ return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Hatch);
+ }
+ if (rServiceName == "com.sun.star.drawing.BitmapTable")
+ {
+ return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Bitmap);
+ }
+ if (rServiceName == "com.sun.star.drawing.TransparencyGradientTable")
+ {
+ return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::TransGradient);
+ }
+ if (rServiceName == "com.sun.star.drawing.MarkerTable")
+ {
+ return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Marker);
+ }
+ if (rServiceName == "com.sun.star.drawing.Defaults")
+ {
+ return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Defaults);
+ }
+ if (rServiceName == "com.sun.star.document.Settings")
+ {
+ return Reference<XInterface>(*new SwXDocumentSettings(this));
+ }
+ if (rServiceName == "com.sun.star.document.ImportEmbeddedObjectResolver")
+ {
+ return cppu::getXWeak(
+ new SvXMLEmbeddedObjectHelper(
+ *m_pDocShell, SvXMLEmbeddedObjectHelperMode::Read));
+ }
+ if (rServiceName == "com.sun.star.text.DocumentSettings")
+ {
+ return Reference<XInterface>(*new SwXDocumentSettings(this));
+ }
+ if (rServiceName == "com.sun.star.chart2.data.DataProvider")
+ {
+ return Reference<XInterface>(
+ static_cast<chart2::data::XDataProvider *>(
+ m_pDocShell->getIDocumentChartDataProviderAccess().
+ GetChartDataProvider()));
+ }
+ if (!rServiceName.startsWith("com.sun.star.")
+ || rServiceName.endsWith(".OLE2Shape"))
+ {
+ // We do not want to insert OLE2 Shapes (e.g.,
+ // "com.sun.star.drawing.OLE2Shape", ...) like this (by creating them
+ // with the documents factory and adding the shapes to the draw page);
+ // for inserting OLE objects the proper way is to use
+ // "com.sun.star.text.TextEmbeddedObject":
+ throw ServiceNotRegisteredException();
+ }
+ // The XML import is allowed to create instances of
+ // "com.sun.star.drawing.OLE2Shape"; thus, a temporary service name is
+ // introduced to make this possible:
+ OUString aTmpServiceName(rServiceName);
+ if (rServiceName == "com.sun.star.drawing.temporaryForXMLImportOLE2Shape")
+ {
+ aTmpServiceName = "com.sun.star.drawing.OLE2Shape";
+ }
+ Reference<XInterface> xTmp(
+ arguments == nullptr
+ ? SvxFmMSFactory::createInstance(aTmpServiceName)
+ : SvxFmMSFactory::createInstanceWithArguments(
+ aTmpServiceName, *arguments));
+ if (rServiceName == "com.sun.star.drawing.GroupShape"
+ || rServiceName == "com.sun.star.drawing.Shape3DSceneObject")
+ {
+ return *new SwXGroupShape(xTmp, m_pDocShell->GetDoc());
+ }
+ if (rServiceName.startsWith("com.sun.star.drawing."))
+ {
+ return *new SwXShape(xTmp, m_pDocShell->GetDoc());
+ }
+ return xTmp;
+}
+
+Reference< XInterface > SwXTextDocument::createInstance(const OUString& rServiceName)
+{
+ return create(rServiceName, nullptr);
+}
+
+Reference< XInterface > SwXTextDocument::createInstanceWithArguments(
+ const OUString& ServiceSpecifier,
+ const Sequence< Any >& Arguments)
+{
+ return create(ServiceSpecifier, &Arguments);
+}
+
+Sequence< OUString > SwXTextDocument::getAvailableServiceNames()
+{
+ static Sequence< OUString > aServices;
+ if ( !aServices.hasElements() )
+ {
+ Sequence< OUString > aRet = SvxFmMSFactory::getAvailableServiceNames();
+ auto i = comphelper::findValue(aRet, "com.sun.star.drawing.OLE2Shape");
+ if (i != -1)
+ {
+ auto nLength = aRet.getLength();
+ aRet.getArray()[i] = aRet[nLength - 1];
+ aRet.realloc( nLength - 1 );
+ }
+ Sequence< OUString > aOwn = SwXServiceProvider::GetAllServiceNames();
+ aServices = comphelper::concatSequences(aRet, aOwn);
+ }
+
+ return aServices;
+}
+
+OUString SwXTextDocument::getImplementationName()
+{
+ return "SwXTextDocument";
+ /* // Matching the .component information:
+ return dynamic_cast<SwGlobalDocShell*>( pDocShell ) != nullptr
+ ? OUString("com.sun.star.comp.Writer.GlobalDocument")
+ : dynamic_cast<SwWebDocShell*>( pDocShell ) != nullptr
+ ? OUString("com.sun.star.comp.Writer.WebDocument")
+ : OUString("com.sun.star.comp.Writer.TextDocument");
+ */
+}
+
+sal_Bool SwXTextDocument::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence< OUString > SwXTextDocument::getSupportedServiceNames()
+{
+ bool bWebDoc = (dynamic_cast<SwWebDocShell*>( m_pDocShell) != nullptr );
+ bool bGlobalDoc = (dynamic_cast<SwGlobalDocShell*>( m_pDocShell) != nullptr );
+ bool bTextDoc = (!bWebDoc && !bGlobalDoc);
+
+ Sequence< OUString > aRet (3);
+ OUString* pArray = aRet.getArray();
+
+ pArray[0] = "com.sun.star.document.OfficeDocument";
+ pArray[1] = "com.sun.star.text.GenericTextDocument";
+
+ if (bTextDoc)
+ pArray[2] = "com.sun.star.text.TextDocument";
+ else if (bWebDoc)
+ pArray[2] = "com.sun.star.text.WebDocument";
+ else if (bGlobalDoc)
+ pArray[2] = "com.sun.star.text.GlobalDocument";
+
+ return aRet;
+}
+
+Reference< XIndexAccess > SwXTextDocument::getDocumentIndexes()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+
+ if(!mxXDocumentIndexes.is())
+ {
+ mxXDocumentIndexes = new SwXDocumentIndexes(m_pDocShell->GetDoc());
+ }
+ return mxXDocumentIndexes;
+}
+
+Reference< XPropertySetInfo > SwXTextDocument::getPropertySetInfo()
+{
+ static Reference< XPropertySetInfo > xRet = m_pPropSet->getPropertySetInfo();
+ return xRet;
+}
+
+void SwXTextDocument::setPropertyValue(const OUString& rPropertyName, const Any& aValue)
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+
+ const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName);
+
+ if(!pEntry)
+ throw UnknownPropertyException(rPropertyName);
+ if(pEntry->nFlags & PropertyAttribute::READONLY)
+ throw PropertyVetoException();
+ switch(pEntry->nWID)
+ {
+ case WID_DOC_CHAR_COUNT :
+ case WID_DOC_PARA_COUNT :
+ case WID_DOC_WORD_COUNT :
+ throw RuntimeException(
+ "bad WID",
+ getXWeak());
+ case WID_DOC_WORD_SEPARATOR :
+ {
+ OUString sDelim;
+ aValue >>= sDelim;
+ SW_MOD()->GetModuleConfig()->SetWordDelimiter(sDelim);
+ }
+ break;
+ case WID_DOC_CHANGES_RECORD:
+ case WID_DOC_CHANGES_SHOW:
+ {
+ SwDoc& rDoc = GetDocOrThrow();
+ sw::DocumentRedlineManager& rRedlineManager = rDoc.GetDocumentRedlineManager();
+ bool bSet = *o3tl::doAccess<bool>(aValue);
+ RedlineFlags eMode = rRedlineManager.GetRedlineFlags();
+ if(WID_DOC_CHANGES_SHOW == pEntry->nWID)
+ {
+ eMode |= RedlineFlags(RedlineFlags::ShowInsert | RedlineFlags::ShowDelete);
+ if( !bSet )
+ rRedlineManager.SetHideRedlines(true);
+ }
+ else if(WID_DOC_CHANGES_RECORD == pEntry->nWID)
+ {
+ eMode = bSet ? eMode|RedlineFlags::On : eMode&~RedlineFlags::On;
+ }
+ rRedlineManager.SetRedlineFlags(eMode);
+ }
+ break;
+ case WID_DOC_CHANGES_PASSWORD:
+ {
+ Sequence <sal_Int8> aNew;
+ if(aValue >>= aNew)
+ {
+ auto& rRedlineAccess = GetDocOrThrow().getIDocumentRedlineAccess();
+ rRedlineAccess.SetRedlinePassword(aNew);
+ if(aNew.hasElements())
+ {
+ RedlineFlags eMode = rRedlineAccess.GetRedlineFlags();
+ eMode |= RedlineFlags::On;
+ rRedlineAccess.SetRedlineFlags(eMode);
+ }
+ }
+ }
+ break;
+ case WID_DOC_AUTO_MARK_URL :
+ {
+ OUString sURL;
+ aValue >>= sURL;
+ GetDocOrThrow().SetTOIAutoMarkURL(sURL);
+ }
+ break;
+ case WID_DOC_HIDE_TIPS :
+ SW_MOD()->GetModuleConfig()->SetHideFieldTips(*o3tl::doAccess<bool>(aValue));
+ break;
+ case WID_DOC_REDLINE_DISPLAY:
+ {
+ auto& rRedlineAccess = GetDocOrThrow().getIDocumentRedlineAccess();
+ RedlineFlags eRedMode = rRedlineAccess.GetRedlineFlags();
+ eRedMode = eRedMode & (~RedlineFlags::ShowMask);
+ sal_Int16 nSet = 0;
+ aValue >>= nSet;
+ switch(nSet)
+ {
+ case RedlineDisplayType::NONE: break;
+ case RedlineDisplayType::INSERTED: eRedMode |= RedlineFlags::ShowInsert; break;
+ case RedlineDisplayType::REMOVED: eRedMode |= RedlineFlags::ShowDelete; break;
+ case RedlineDisplayType::
+ INSERTED_AND_REMOVED: eRedMode |= RedlineFlags::ShowInsert|RedlineFlags::ShowDelete;
+ break;
+ default: throw IllegalArgumentException();
+ }
+ rRedlineAccess.SetRedlineFlags(eRedMode);
+ }
+ break;
+ case WID_DOC_TWO_DIGIT_YEAR:
+ {
+ sal_Int16 nYear = 0;
+ aValue >>= nYear;
+ SfxRequest aRequest ( SID_ATTR_YEAR2000, SfxCallMode::SLOT, GetDocOrThrow().GetAttrPool());
+ aRequest.AppendItem(SfxUInt16Item( SID_ATTR_YEAR2000, static_cast < sal_uInt16 > ( nYear ) ) );
+ m_pDocShell->Execute ( aRequest );
+ }
+ break;
+ case WID_DOC_AUTOMATIC_CONTROL_FOCUS:
+ {
+ auto& rDrawModelAccess = GetDocOrThrow().getIDocumentDrawModelAccess();
+ bool bAuto = *o3tl::doAccess<bool>(aValue);
+ // if setting to true, and we don't have an
+ // SdrModel, then we are changing the default and
+ // must thus create an SdrModel, if we don't have an
+ // SdrModel and we are leaving the default at false,
+ // we don't need to make an SdrModel and can do nothing
+ // #i52858# - method name changed
+ SwDrawModel* pDrawDoc
+ = bAuto ? rDrawModelAccess.GetOrCreateDrawModel() : rDrawModelAccess.GetDrawModel();
+
+ if ( nullptr != pDrawDoc )
+ pDrawDoc->SetAutoControlFocus( bAuto );
+ }
+ break;
+ case WID_DOC_APPLY_FORM_DESIGN_MODE:
+ {
+ auto& rDrawModelAccess = GetDocOrThrow().getIDocumentDrawModelAccess();
+ bool bMode = *o3tl::doAccess<bool>(aValue);
+ // if setting to false, and we don't have an
+ // SdrModel, then we are changing the default and
+ // must thus create an SdrModel, if we don't have an
+ // SdrModel and we are leaving the default at true,
+ // we don't need to make an SdrModel and can do
+ // nothing
+ // #i52858# - method name changed
+ SwDrawModel* pDrawDoc
+ = bMode ? rDrawModelAccess.GetDrawModel() : rDrawModelAccess.GetOrCreateDrawModel();
+
+ if ( nullptr != pDrawDoc )
+ pDrawDoc->SetOpenInDesignMode( bMode );
+ }
+ break;
+ // #i42634# New property to set the bInReading
+ // flag at the document, used during binary import
+ case WID_DOC_LOCK_UPDATES :
+ {
+ bool bBool (false);
+ if( aValue >>= bBool )
+ {
+ GetDocOrThrow().SetInReading( bBool );
+ }
+ }
+ break;
+ case WID_DOC_WRITERFILTER:
+ {
+ SwDoc& rDoc = GetDocOrThrow();
+ bool bBool = {};
+ if (aValue >>= bBool)
+ { // HACK: writerfilter has to use API to set this :(
+ bool bOld = rDoc.IsInWriterfilterImport();
+ rDoc.SetInWriterfilterImport(bBool);
+ if (bOld && !bBool)
+ {
+ rDoc.getIDocumentFieldsAccess().SetFieldsDirty(false, nullptr, SwNodeOffset(0));
+ }
+ }
+ }
+ break;
+ case WID_DOC_BUILDID:
+ aValue >>= maBuildId;
+ break;
+
+ case WID_DOC_DEFAULT_PAGE_MODE:
+ {
+ bool bDefaultPageMode( false );
+ aValue >>= bDefaultPageMode;
+ GetDocOrThrow().SetDefaultPageMode( bDefaultPageMode );
+ }
+ break;
+ case WID_DOC_INTEROP_GRAB_BAG:
+ setGrabBagItem(aValue);
+ break;
+
+ default:
+ {
+ SwDoc& rDoc = GetDocOrThrow();
+ const SfxPoolItem& rItem = rDoc.GetDefault(pEntry->nWID);
+ std::unique_ptr<SfxPoolItem> pNewItem(rItem.Clone());
+ pNewItem->PutValue(aValue, pEntry->nMemberId);
+ rDoc.SetDefault(*pNewItem);
+ }
+ }
+}
+
+Any SwXTextDocument::getPropertyValue(const OUString& rPropertyName)
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+
+ if (rPropertyName == "ODFExport_ListNodes")
+ {
+ // A hack to avoid writing random list ids to ODF when they are not referred later
+ // see XMLTextParagraphExport::DocumentListNodes ctor
+
+ // Sequence of nodes, each of them represented by three-element sequence:
+ // [ index, styleIntPtr, list_id ]
+ std::vector<css::uno::Sequence<css::uno::Any>> nodes;
+
+ const SwDoc& rDoc = GetDocOrThrow();
+ for (const SwNumRule* pNumRule : rDoc.GetNumRuleTable())
+ {
+ SwNumRule::tTextNodeList textNodes;
+ pNumRule->GetTextNodeList(textNodes);
+ css::uno::Any styleIntPtr(reinterpret_cast<sal_uInt64>(pNumRule));
+
+ for (const SwTextNode* pTextNode : textNodes)
+ {
+ css::uno::Any index(pTextNode->GetIndex().get());
+ css::uno::Any list_id(pTextNode->GetListId());
+
+ nodes.push_back({ index, styleIntPtr, list_id });
+ }
+ }
+ return css::uno::Any(comphelper::containerToSequence(nodes));
+ }
+
+ const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName);
+
+ if(!pEntry)
+ throw UnknownPropertyException(rPropertyName);
+ Any aAny;
+ switch(pEntry->nWID)
+ {
+ case WID_DOC_ISTEMPLATEID :
+ aAny <<= m_pDocShell->IsTemplate();
+ break;
+ case WID_DOC_CHAR_COUNT :
+ case WID_DOC_PARA_COUNT :
+ case WID_DOC_WORD_COUNT :
+ {
+ const SwDocStat& rStat(GetDocOrThrow().getIDocumentStatistics().GetUpdatedDocStat( false, true ));
+ sal_Int32 nValue;
+ switch(pEntry->nWID)
+ {
+ case WID_DOC_CHAR_COUNT :nValue = rStat.nChar;break;
+ case WID_DOC_PARA_COUNT :nValue = rStat.nPara;break;
+ case WID_DOC_WORD_COUNT :nValue = rStat.nWord;break;
+ }
+ aAny <<= nValue;
+ }
+ break;
+ case WID_DOC_WORD_SEPARATOR :
+ {
+ aAny <<= SW_MOD()->GetDocStatWordDelim();
+ }
+ break;
+ case WID_DOC_CHANGES_RECORD:
+ case WID_DOC_CHANGES_SHOW:
+ {
+ const RedlineFlags eMode = GetDocOrThrow().getIDocumentRedlineAccess().GetRedlineFlags();
+ bool bSet = false;
+ if(WID_DOC_CHANGES_SHOW == pEntry->nWID)
+ {
+ bSet = IDocumentRedlineAccess::IsShowChanges(eMode);
+ }
+ else if(WID_DOC_CHANGES_RECORD == pEntry->nWID)
+ {
+ bSet = bool(eMode & RedlineFlags::On);
+ }
+ aAny <<= bSet;
+ }
+ break;
+ case WID_DOC_CHANGES_PASSWORD:
+ aAny <<= GetDocOrThrow().getIDocumentRedlineAccess().GetRedlinePassword();
+ break;
+ case WID_DOC_AUTO_MARK_URL :
+ aAny <<= GetDocOrThrow().GetTOIAutoMarkURL();
+ break;
+ case WID_DOC_HIDE_TIPS :
+ aAny <<= SW_MOD()->GetModuleConfig()->IsHideFieldTips();
+ break;
+ case WID_DOC_REDLINE_DISPLAY:
+ {
+ RedlineFlags eRedMode = GetDocOrThrow().getIDocumentRedlineAccess().GetRedlineFlags();
+ eRedMode = eRedMode & RedlineFlags::ShowMask;
+ sal_Int16 nRet = RedlineDisplayType::NONE;
+ if(RedlineFlags::ShowInsert == eRedMode)
+ nRet = RedlineDisplayType::INSERTED;
+ else if(RedlineFlags::ShowDelete == eRedMode)
+ nRet = RedlineDisplayType::REMOVED;
+ else if(RedlineFlags::ShowMask == eRedMode)
+ nRet = RedlineDisplayType::INSERTED_AND_REMOVED;
+ aAny <<= nRet;
+ }
+ break;
+ case WID_DOC_FORBIDDEN_CHARS:
+ {
+ GetPropertyHelper();
+ Reference<XForbiddenCharacters> xRet = mxPropertyHelper;
+ aAny <<= xRet;
+ }
+ break;
+ case WID_DOC_TWO_DIGIT_YEAR:
+ {
+ aAny <<= static_cast < sal_Int16 > (GetDocOrThrow().GetNumberFormatter ()->GetYear2000());
+ }
+ break;
+ case WID_DOC_AUTOMATIC_CONTROL_FOCUS:
+ {
+ SwDrawModel * pDrawDoc = GetDocOrThrow().getIDocumentDrawModelAccess().GetDrawModel();
+ bool bAuto;
+ if ( nullptr != pDrawDoc )
+ bAuto = pDrawDoc->GetAutoControlFocus();
+ else
+ bAuto = false;
+ aAny <<= bAuto;
+ }
+ break;
+ case WID_DOC_APPLY_FORM_DESIGN_MODE:
+ {
+ SwDrawModel * pDrawDoc = GetDocOrThrow().getIDocumentDrawModelAccess().GetDrawModel();
+ bool bMode;
+ if ( nullptr != pDrawDoc )
+ bMode = pDrawDoc->GetOpenInDesignMode();
+ else
+ bMode = true;
+ aAny <<= bMode;
+ }
+ break;
+ case WID_DOC_BASIC_LIBRARIES:
+ aAny <<= m_pDocShell->GetBasicContainer();
+ break;
+ case WID_DOC_DIALOG_LIBRARIES:
+ aAny <<= m_pDocShell->GetDialogContainer();
+ break;
+ case WID_DOC_VBA_DOCOBJ:
+ {
+ /* #i111553# This property provides the name of the constant that
+ will be used to store this model in the global Basic manager.
+ That constant will be equivalent to 'ThisComponent' but for
+ each application, so e.g. a 'ThisExcelDoc' and a 'ThisWordDoc'
+ constant can co-exist, as required by VBA. */
+ aAny <<= OUString( "ThisWordDoc" );
+ }
+ break;
+ case WID_DOC_RUNTIME_UID:
+ aAny <<= getRuntimeUID();
+ break;
+ case WID_DOC_LOCK_UPDATES :
+ aAny <<= GetDocOrThrow().IsInReading();
+ break;
+ case WID_DOC_BUILDID:
+ aAny <<= maBuildId;
+ break;
+ case WID_DOC_HAS_VALID_SIGNATURES:
+ aAny <<= hasValidSignatures();
+ break;
+ case WID_DOC_INTEROP_GRAB_BAG:
+ getGrabBagItem(aAny);
+ break;
+
+ default:
+ {
+ const SfxPoolItem& rItem = GetDocOrThrow().GetDefault(pEntry->nWID);
+ rItem.QueryValue(aAny, pEntry->nMemberId);
+ }
+ }
+ return aAny;
+}
+
+void SwXTextDocument::addPropertyChangeListener(const OUString& /*PropertyName*/,
+ const Reference< XPropertyChangeListener > & /*aListener*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+void SwXTextDocument::removePropertyChangeListener(const OUString& /*PropertyName*/,
+ const Reference< XPropertyChangeListener > & /*aListener*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+void SwXTextDocument::addVetoableChangeListener(const OUString& /*PropertyName*/,
+ const Reference< XVetoableChangeListener > & /*aListener*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+void SwXTextDocument::removeVetoableChangeListener(const OUString& /*PropertyName*/,
+ const Reference< XVetoableChangeListener > & /*aListener*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+Reference< XNameAccess > SwXTextDocument::getLinks()
+{
+ if(!mxLinkTargetSupplier.is())
+ {
+ mxLinkTargetSupplier = new SwXLinkTargetSupplier(*this);
+ }
+ return mxLinkTargetSupplier;
+}
+
+Reference< XEnumerationAccess > SwXTextDocument::getRedlines( )
+{
+ if(!mxXRedlines.is())
+ {
+ mxXRedlines = new SwXRedlines(m_pDocShell->GetDoc());
+ }
+ return mxXRedlines;
+}
+
+void SwXTextDocument::NotifyRefreshListeners()
+{
+ // why does SwBaseShell not just call refresh? maybe because it's rSh is
+ // (sometimes) a different shell than GetWrtShell()?
+ lang::EventObject const ev(static_cast<SwXTextDocumentBaseClass &>(*this));
+ std::unique_lock aGuard(m_pImpl->m_Mutex);
+ m_pImpl->m_RefreshListeners.notifyEach(aGuard,
+ & util::XRefreshListener::refreshed, ev);
+}
+
+void SwXTextDocument::refresh()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+
+ SwViewShell *pViewShell = m_pDocShell->GetWrtShell();
+ NotifyRefreshListeners();
+ if(pViewShell)
+ pViewShell->Reformat();
+}
+
+void SAL_CALL SwXTextDocument::addRefreshListener(
+ const Reference<util::XRefreshListener> & xListener)
+{
+ if (xListener)
+ {
+ std::unique_lock aGuard(m_pImpl->m_Mutex);
+ m_pImpl->m_RefreshListeners.addInterface(aGuard, xListener);
+ }
+}
+
+void SAL_CALL SwXTextDocument::removeRefreshListener(
+ const Reference<util::XRefreshListener> & xListener)
+{
+ if (xListener)
+ {
+ std::unique_lock aGuard(m_pImpl->m_Mutex);
+ m_pImpl->m_RefreshListeners.removeInterface(aGuard, xListener);
+ }
+}
+
+void SwXTextDocument::updateLinks( )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+
+ SwDoc& rDoc = GetDocOrThrow();
+ sfx2::LinkManager& rLnkMan = rDoc.getIDocumentLinksAdministration().GetLinkManager();
+ if( !rLnkMan.GetLinks().empty() )
+ {
+ UnoActionContext aAction(&rDoc);
+ rLnkMan.UpdateAllLinks( false, true, nullptr );
+ }
+}
+
+//XPropertyState
+PropertyState SAL_CALL SwXTextDocument::getPropertyState( const OUString& rPropertyName )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+
+ const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName);
+ if(!pEntry)
+ throw UnknownPropertyException(rPropertyName);
+ return PropertyState_DIRECT_VALUE;
+}
+
+Sequence< PropertyState > SAL_CALL SwXTextDocument::getPropertyStates( const Sequence< OUString >& rPropertyNames )
+{
+ const sal_Int32 nCount = rPropertyNames.getLength();
+ Sequence < PropertyState > aRet ( nCount );
+
+ std::transform(rPropertyNames.begin(), rPropertyNames.end(), aRet.getArray(),
+ [this](const OUString& rName) -> PropertyState { return getPropertyState(rName); });
+
+ return aRet;
+}
+
+void SAL_CALL SwXTextDocument::setPropertyToDefault( const OUString& rPropertyName )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+
+ const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName);
+ if(!pEntry)
+ throw UnknownPropertyException(rPropertyName);
+ switch(pEntry->nWID)
+ {
+ case 0:default:break;
+ }
+}
+
+Any SAL_CALL SwXTextDocument::getPropertyDefault( const OUString& rPropertyName )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+
+ const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName);
+ if(!pEntry)
+ throw UnknownPropertyException(rPropertyName);
+ Any aAny;
+ switch(pEntry->nWID)
+ {
+ case 0:default:break;
+ }
+ return aAny;
+}
+
+static VclPtr< OutputDevice > lcl_GetOutputDevice( const SwPrintUIOptions &rPrintUIOptions )
+{
+ VclPtr< OutputDevice > pOut;
+
+ uno::Any aAny( rPrintUIOptions.getValue( "RenderDevice" ));
+ uno::Reference< awt::XDevice > xRenderDevice;
+ aAny >>= xRenderDevice;
+ if (xRenderDevice.is())
+ {
+ VCLXDevice* pDevice = dynamic_cast<VCLXDevice*>( xRenderDevice.get() );
+ pOut = pDevice ? pDevice->GetOutputDevice() : VclPtr< OutputDevice >();
+ }
+
+ return pOut;
+}
+
+static bool lcl_SeqHasProperty(
+ const uno::Sequence< beans::PropertyValue >& rOptions,
+ const char *pPropName )
+{
+ return std::any_of(rOptions.begin(), rOptions.end(),
+ [&pPropName](const beans::PropertyValue& rProp) {
+ return rProp.Name.equalsAscii( pPropName ); });
+}
+
+static bool lcl_GetBoolProperty(
+ const uno::Sequence< beans::PropertyValue >& rOptions,
+ const char *pPropName )
+{
+ bool bRes = false;
+ auto pOption = std::find_if(rOptions.begin(), rOptions.end(),
+ [&pPropName](const beans::PropertyValue& rProp) {
+ return rProp.Name.equalsAscii( pPropName ); });
+ if (pOption != rOptions.end())
+ pOption->Value >>= bRes;
+ return bRes;
+}
+
+SfxViewShell * SwXTextDocument::GetRenderView(
+ bool &rbIsSwSrcView,
+ const uno::Sequence< beans::PropertyValue >& rOptions,
+ bool bIsPDFExport )
+{
+ // get view shell to use
+ SfxViewShell *pView = nullptr;
+ if (bIsPDFExport)
+ pView = GuessViewShell( rbIsSwSrcView );
+ else
+ {
+ uno::Any aTmp;
+ auto pOption = std::find_if(rOptions.begin(), rOptions.end(),
+ [](const beans::PropertyValue& rProp) { return rProp.Name == "View"; });
+ if (pOption != rOptions.end())
+ aTmp = pOption->Value;
+
+ uno::Reference< frame::XController > xController;
+ if (aTmp >>= xController)
+ {
+ OSL_ENSURE( xController.is(), "controller is empty!" );
+ pView = GuessViewShell( rbIsSwSrcView, xController );
+ }
+ }
+ return pView;
+}
+
+/*
+ * GetRenderDoc:
+ * returns the document to be rendered, usually this will be the 'regular'
+ * document but in case of PDF export of (multi-)selection it will
+ * be a temporary document that gets created if not already done.
+ * The rpView variable will be set (if not already done) to the used
+ * SfxViewShell.
+*/
+SwDoc * SwXTextDocument::GetRenderDoc(
+ SfxViewShell *&rpView,
+ const uno::Any& rSelection,
+ bool bIsPDFExport )
+{
+ SwDoc *pDoc = nullptr;
+
+ uno::Reference< frame::XModel > xModel;
+ rSelection >>= xModel;
+ if (xModel == m_pDocShell->GetModel())
+ pDoc = m_pDocShell->GetDoc();
+ else
+ {
+ OSL_ENSURE( !xModel.is(), "unexpected model found" );
+
+ if (rSelection.hasValue()) // is anything selected ?
+ {
+ // this part should only be called when a temporary document needs to be created,
+ // for example for PDF export or printing of (multi-)selection only.
+
+ if (!rpView)
+ {
+ bool bIsSwSrcView = false;
+ // aside from maybe PDF export the view should always have been provided!
+ OSL_ENSURE( bIsPDFExport, "view is missing, guessing one..." );
+
+ rpView = GuessViewShell( bIsSwSrcView );
+ }
+ OSL_ENSURE( rpView, "SwViewShell missing" );
+ // the view shell should be SwView for documents PDF export.
+ // for the page preview no selection should be possible
+ // (the export dialog does not allow for this option)
+ if (auto pSwView = dynamic_cast<SwView *>( rpView ))
+ {
+ if (!m_pRenderData)
+ {
+ OSL_FAIL("GetRenderDoc: no renderdata");
+ return nullptr;
+ }
+ SfxObjectShellLock xDocSh(m_pRenderData->GetTempDocShell());
+ if (!xDocSh.Is())
+ {
+ xDocSh = pSwView->CreateTmpSelectionDoc();
+ m_pRenderData->SetTempDocShell(xDocSh);
+ }
+ if (xDocSh.Is())
+ {
+ pDoc = static_cast<SwDocShell*>(&xDocSh)->GetDoc();
+ rpView = pDoc->GetDocShell()->GetView();
+ }
+ }
+ else
+ {
+ OSL_FAIL("unexpected SwViewShell" );
+ }
+ }
+ }
+ return pDoc;
+}
+
+static void lcl_SavePrintUIOptionsToDocumentPrintData(
+ SwDoc &rDoc,
+ const SwPrintUIOptions &rPrintUIOptions,
+ bool bIsPDFEXport )
+{
+ SwPrintData aDocPrintData( rDoc.getIDocumentDeviceAccess().getPrintData() );
+
+ aDocPrintData.SetPrintGraphic( rPrintUIOptions.IsPrintGraphics() );
+ aDocPrintData.SetPrintTable( true ); // for now it was decided that tables should always be printed
+ aDocPrintData.SetPrintDraw( rPrintUIOptions.IsPrintDrawings() );
+ aDocPrintData.SetPrintControl( rPrintUIOptions.IsPrintFormControls() );
+ aDocPrintData.SetPrintLeftPage( rPrintUIOptions.IsPrintLeftPages() );
+ aDocPrintData.SetPrintRightPage( rPrintUIOptions.IsPrintRightPages() );
+ aDocPrintData.SetPrintReverse( false ); /*handled by print dialog now*/
+ aDocPrintData.SetPaperFromSetup( rPrintUIOptions.IsPaperFromSetup() );
+ aDocPrintData.SetPrintEmptyPages( rPrintUIOptions.IsPrintEmptyPages( bIsPDFEXport ) );
+ aDocPrintData.SetPrintPostIts( rPrintUIOptions.GetPrintPostItsType() );
+ aDocPrintData.SetPrintProspect( rPrintUIOptions.IsPrintProspect() );
+ aDocPrintData.SetPrintProspect_RTL( rPrintUIOptions.IsPrintProspectRTL() );
+ aDocPrintData.SetPrintPageBackground( rPrintUIOptions.IsPrintPageBackground() );
+ aDocPrintData.SetPrintBlackFont( rPrintUIOptions.IsPrintWithBlackTextColor() );
+ // aDocPrintData.SetPrintSingleJobs( b ); handled by File/Print dialog itself
+ // arDocPrintData.SetFaxName( s ); n/a in File/Print dialog
+ aDocPrintData.SetPrintHiddenText( rPrintUIOptions.IsPrintHiddenText() );
+ aDocPrintData.SetPrintTextPlaceholder( rPrintUIOptions.IsPrintTextPlaceholders() );
+
+ rDoc.getIDocumentDeviceAccess().setPrintData( aDocPrintData );
+}
+
+sal_Int32 SAL_CALL SwXTextDocument::getRendererCount(
+ const uno::Any& rSelection,
+ const uno::Sequence< beans::PropertyValue >& rxOptions )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ {
+ throw DisposedException( OUString(),
+ static_cast< XTextDocument* >(this) );
+ }
+
+ const bool bIsPDFExport = !lcl_SeqHasProperty( rxOptions, "IsPrinter" );
+ bool bIsSwSrcView = false;
+ SfxViewShell *pView = GetRenderView( bIsSwSrcView, rxOptions, bIsPDFExport );
+
+ if (!bIsSwSrcView && !m_pRenderData)
+ m_pRenderData.reset(new SwRenderData);
+ if (!m_pPrintUIOptions)
+ m_pPrintUIOptions = lcl_GetPrintUIOptions( m_pDocShell, pView );
+ bool bFormat = m_pPrintUIOptions->processPropertiesAndCheckFormat( rxOptions );
+
+ SwDoc *pDoc = GetRenderDoc( pView, rSelection, bIsPDFExport );
+ OSL_ENSURE( pDoc && pView, "doc or view shell missing!" );
+ if (!pDoc || !pView)
+ return 0;
+
+ // save current UI options from the print dialog for the next call to that dialog
+ lcl_SavePrintUIOptionsToDocumentPrintData( *pDoc, *m_pPrintUIOptions, bIsPDFExport );
+
+ sal_Int32 nRet = 0;
+ if (bIsSwSrcView)
+ {
+ SwSrcView& rSwSrcView = dynamic_cast<SwSrcView&>(*pView);
+ VclPtr< OutputDevice> pOutDev = lcl_GetOutputDevice( *m_pPrintUIOptions );
+ nRet = rSwSrcView.PrintSource( pOutDev, 1 /* dummy */, true /* get page count only */ );
+ }
+ else
+ {
+ SwDocShell *pRenderDocShell = pDoc->GetDocShell();
+
+ // TODO/mba: we really need a generic way to get the SwViewShell!
+ SwViewShell* pViewShell = nullptr;
+ SwView* pSwView = dynamic_cast<SwView*>( pView );
+ if ( pSwView )
+ {
+ pViewShell = pSwView->GetWrtShellPtr();
+ }
+ else
+ {
+ if ( bIsPDFExport && bFormat )
+ {
+ //create a hidden view to be able to export as PDF also in print preview
+ //pView and pSwView are not changed intentionally!
+ m_pHiddenViewFrame = SfxViewFrame::LoadHiddenDocument( *pRenderDocShell, SFX_INTERFACE_SFXDOCSH );
+ pViewShell = static_cast<SwView*>(m_pHiddenViewFrame->GetViewShell())->GetWrtShellPtr();
+ }
+ else
+ pViewShell = static_cast<SwPagePreview*>(pView)->GetViewShell();
+ }
+
+ if (!pViewShell || !pViewShell->GetLayout())
+ return 0;
+
+ if (bFormat)
+ {
+ // #i38289
+ if( pViewShell->GetViewOptions()->getBrowseMode() ||
+ pViewShell->GetViewOptions()->IsWhitespaceHidden() )
+ {
+ SwViewOption aOpt( *pViewShell->GetViewOptions() );
+ aOpt.setBrowseMode( false );
+ aOpt.SetHideWhitespaceMode( false );
+ pViewShell->ApplyViewOptions( aOpt );
+ if (pSwView)
+ {
+ pSwView->RecheckBrowseMode();
+ }
+ }
+
+ // reformatting the document for printing will show the changes in the view
+ // which is likely to produce many unwanted and not nice to view actions.
+ // We don't want that! Thus we disable updating of the view.
+ pViewShell->StartAction();
+
+ if (pSwView)
+ {
+ if (m_pRenderData && m_pRenderData->NeedNewViewOptionAdjust( *pViewShell ) )
+ m_pRenderData->ViewOptionAdjustStop();
+ if (m_pRenderData && !m_pRenderData->IsViewOptionAdjust())
+ {
+ m_pRenderData->ViewOptionAdjustStart(
+ *pViewShell, *pViewShell->GetViewOptions() );
+ }
+ }
+
+ m_pRenderData->MakeSwPrtOptions( pRenderDocShell,
+ m_pPrintUIOptions.get(), bIsPDFExport );
+
+ if (pSwView)
+ {
+ // PDF export should not make use of the SwPrtOptions
+ const SwPrintData *pPrtOptions = bIsPDFExport
+ ? nullptr : m_pRenderData->GetSwPrtOptions();
+ bool setShowPlaceHoldersInPDF = false;
+ if(bIsPDFExport)
+ setShowPlaceHoldersInPDF = lcl_GetBoolProperty( rxOptions, "ExportPlaceholders" );
+ m_pRenderData->ViewOptionAdjust( pPrtOptions, setShowPlaceHoldersInPDF );
+ }
+
+ // since printing now also use the API for PDF export this option
+ // should be set for printing as well ...
+ pViewShell->SetPDFExportOption( true );
+
+ // there is some redundancy between those two function calls, but right now
+ // there is no time to sort this out.
+ //TODO: check what exactly needs to be done and make just one function for that
+ pViewShell->CalcLayout();
+
+ // #122919# Force field update before PDF export, but after layout init (tdf#121962)
+ bool bStateChanged = false;
+ // check configuration: shall update of printing information in DocInfo set the document to "modified"?
+ if (pRenderDocShell->IsEnableSetModified() && !utl::ConfigManager::IsFuzzing() && !officecfg::Office::Common::Print::PrintingModifiesDocument::get())
+ {
+ pRenderDocShell->EnableSetModified( false );
+ bStateChanged = true;
+ }
+ pViewShell->SwViewShell::UpdateFields(true);
+ if( bStateChanged )
+ pRenderDocShell->EnableSetModified();
+
+ pViewShell->CalcPagesForPrint( pViewShell->GetPageCount() );
+
+ pViewShell->SetPDFExportOption( false );
+
+ // enable view again
+ pViewShell->EndAction();
+ }
+
+ const sal_Int32 nPageCount = pViewShell->GetPageCount();
+
+ // get number of pages to be rendered
+
+ const bool bPrintProspect = m_pPrintUIOptions->getBoolValue( "PrintProspect" );
+ if (bPrintProspect)
+ {
+ SwDoc::CalculatePagePairsForProspectPrinting( *pViewShell->GetLayout(), *m_pRenderData, *m_pPrintUIOptions, nPageCount );
+ nRet = m_pRenderData->GetPagePairsForProspectPrinting().size();
+ }
+ else
+ {
+ const SwPostItMode nPostItMode = static_cast<SwPostItMode>( m_pPrintUIOptions->getIntValue( "PrintAnnotationMode", 0 ) );
+ if (nPostItMode != SwPostItMode::NONE)
+ {
+ VclPtr< OutputDevice > pOutDev = lcl_GetOutputDevice( *m_pPrintUIOptions );
+ m_pRenderData->CreatePostItData(*pDoc, pViewShell->GetViewOptions(), pOutDev);
+ }
+
+ // get set of valid document pages (according to the current settings)
+ // and their start frames
+ SwDoc::CalculatePagesForPrinting( *pViewShell->GetLayout(), *m_pRenderData, *m_pPrintUIOptions, bIsPDFExport, nPageCount );
+
+ if (nPostItMode != SwPostItMode::NONE)
+ {
+ SwDoc::UpdatePagesForPrintingWithPostItData( *m_pRenderData,
+ *m_pPrintUIOptions, nPageCount );
+ }
+
+ nRet = m_pRenderData->GetPagesToPrint().size();
+ }
+ }
+ OSL_ENSURE( nRet >= 0, "negative number of pages???" );
+ // tdf#144989 the layout is complete now - prevent DoIdleJobs() from
+ // messing it up, particulary SwDocUpdateField::MakeFieldList_() unhiding
+ // sections
+ pDoc->getIDocumentTimerAccess().BlockIdling();
+
+ return nRet;
+}
+
+uno::Sequence< beans::PropertyValue > SAL_CALL SwXTextDocument::getRenderer(
+ sal_Int32 nRenderer,
+ const uno::Any& rSelection,
+ const uno::Sequence< beans::PropertyValue >& rxOptions )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ {
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+ }
+
+ const bool bIsPDFExport = !lcl_SeqHasProperty( rxOptions, "IsPrinter" );
+ bool bIsSwSrcView = false;
+ SfxViewShell *pView = GetRenderView( bIsSwSrcView, rxOptions, bIsPDFExport );
+
+ // m_pRenderData should NOT be created here!
+ // That should only be done in getRendererCount. If this function is called before
+ // getRendererCount was called then the caller will probably just retrieve the extra UI options
+ // and is not interested in getting valid information about the other data that would
+ // otherwise be provided here!
+// if( ! m_pRenderData )
+// m_pRenderData = new SwRenderData;
+ if (!m_pPrintUIOptions)
+ m_pPrintUIOptions = lcl_GetPrintUIOptions( m_pDocShell, pView );
+ m_pPrintUIOptions->processProperties( rxOptions );
+ const bool bPrintProspect = m_pPrintUIOptions->getBoolValue( "PrintProspect" );
+ const bool bIsSkipEmptyPages = !m_pPrintUIOptions->IsPrintEmptyPages( bIsPDFExport );
+ const bool bPrintPaperFromSetup = m_pPrintUIOptions->getBoolValue( "PrintPaperFromSetup" );
+
+ SwDoc *pDoc = GetRenderDoc( pView, rSelection, bIsPDFExport );
+ OSL_ENSURE( pDoc && pView, "doc or view shell missing!" );
+ if (!pDoc || !pView)
+ return uno::Sequence< beans::PropertyValue >();
+
+ // due to #110067# (document page count changes sometimes during
+ // PDF export/printing) we can not check for the upper bound properly.
+ // Thus instead of throwing the exception we silently return.
+ if (0 > nRenderer)
+ throw IllegalArgumentException();
+
+ sal_Int32 nMaxRenderer = 0;
+ if (!bIsSwSrcView && m_pRenderData)
+ {
+ OSL_ENSURE( m_pRenderData, "m_pRenderData missing!!" );
+ nMaxRenderer = bPrintProspect?
+ m_pRenderData->GetPagePairsForProspectPrinting().size() - 1 :
+ m_pRenderData->GetPagesToPrint().size() - 1;
+ }
+ // since SwSrcView::PrintSource is a poor implementation to get the number of pages to print
+ // we obmit checking of the upper bound in this case.
+ if (!bIsSwSrcView && m_pRenderData && nRenderer > nMaxRenderer)
+ return uno::Sequence< beans::PropertyValue >();
+
+ uno::Sequence< beans::PropertyValue > aRenderer;
+ if (m_pRenderData)
+ {
+ // #i114210#
+ // determine the correct page number from the renderer index
+ // #i114875
+ // consider brochure print
+ const sal_Int32 nPage = bPrintProspect
+ ? nRenderer + 1
+ : m_pRenderData->GetPagesToPrint()[ nRenderer ];
+
+ // get paper tray to use ...
+ sal_Int32 nPrinterPaperTray = -1;
+ if (! bPrintPaperFromSetup)
+ {
+ // ... from individual page style (see the page tab in Format/Page dialog)
+ const std::map< sal_Int32, sal_Int32 > &rPaperTrays = m_pRenderData->GetPrinterPaperTrays();
+ std::map< sal_Int32, sal_Int32 >::const_iterator aIt( rPaperTrays.find( nPage ) );
+ if (aIt != rPaperTrays.end())
+ nPrinterPaperTray = aIt->second;
+ }
+
+ awt::Size aPageSize;
+ awt::Point aPagePos;
+ awt::Size aPreferredPageSize;
+ Size aTmpSize;
+ if (bIsSwSrcView || bPrintProspect)
+ {
+ // for printing of HTML source code and prospect printing we should use
+ // the printers paper size since
+ // a) HTML source view has no page size
+ // b) prospect printing has a different page size from the documents page
+ // since two document pages will get rendered on one printer page
+
+ // since PageIncludesNonprintableArea will be set to true we can return the
+ // printers paper size here.
+ // Sometimes 'getRenderer' is only called to get "ExtraPrintUIOptions", in this
+ // case we won't get an OutputDevice here, but then the caller also has no need
+ // for the correct PageSize right now...
+ VclPtr< Printer > pPrinter = dynamic_cast< Printer * >(lcl_GetOutputDevice( *m_pPrintUIOptions ).get());
+ if (pPrinter)
+ {
+ // HTML source view and prospect adapt to the printer's paper size
+ aTmpSize = pPrinter->GetPaperSize();
+ aTmpSize = OutputDevice::LogicToLogic( aTmpSize,
+ pPrinter->GetMapMode(), MapMode( MapUnit::Map100thMM ));
+ aPageSize = awt::Size( aTmpSize.Width(), aTmpSize.Height() );
+ #if 0
+ // #i115048# it seems users didn't like getting double the formatted page size
+ // revert to "old" behavior scaling to the current paper size of the printer
+ if (bPrintProspect)
+ {
+ // we just state what output size we would need
+ // which may cause vcl to set that page size on the printer
+ // (if available and not overridden by the user)
+ aTmpSize = pVwSh->GetPageSize( nPage, bIsSkipEmptyPages );
+ aPreferredPageSize = awt::Size ( convertTwipToMm100( 2 * aTmpSize.Width() ),
+ convertTwipToMm100( aTmpSize.Height() ));
+ }
+ #else
+ if( bPrintProspect )
+ {
+ // just switch to an appropriate portrait/landscape format
+ // FIXME: brochure printing with landscape pages puts the
+ // pages next to each other, so landscape is currently always
+ // the better choice
+ if( aPageSize.Width < aPageSize.Height )
+ {
+ aPreferredPageSize.Width = aPageSize.Height;
+ aPreferredPageSize.Height = aPageSize.Width;
+ }
+ }
+ #endif
+ }
+ }
+ else
+ {
+ // TODO/mba: we really need a generic way to get the SwViewShell!
+ SwViewShell* pVwSh = nullptr;
+ SwView* pSwView = dynamic_cast<SwView*>( pView );
+ if ( pSwView )
+ pVwSh = pSwView->GetWrtShellPtr();
+ else
+ pVwSh = static_cast<SwPagePreview*>(pView)->GetViewShell();
+
+ if (pVwSh)
+ {
+ aTmpSize = pVwSh->GetPageSize( nPage, bIsSkipEmptyPages );
+ aPageSize = awt::Size ( convertTwipToMm100( aTmpSize.Width() ),
+ convertTwipToMm100( aTmpSize.Height() ));
+ Point aPoint = pVwSh->GetPagePos(nPage);
+ aPagePos = awt::Point(convertTwipToMm100(aPoint.X()), convertTwipToMm100(aPoint.Y()));
+ }
+ }
+
+ sal_Int32 nLen = 3;
+ aRenderer = { comphelper::makePropertyValue("PageSize", aPageSize),
+ comphelper::makePropertyValue("PageIncludesNonprintableArea", true),
+ comphelper::makePropertyValue("PagePos", aPagePos) };
+ if (aPreferredPageSize.Width && aPreferredPageSize.Height)
+ {
+ ++nLen;
+ aRenderer.realloc( nLen );
+ auto pRenderer = aRenderer.getArray();
+ pRenderer[ nLen - 1 ].Name = "PreferredPageSize";
+ pRenderer[ nLen - 1 ].Value <<= aPreferredPageSize;
+ }
+ if (nPrinterPaperTray >= 0)
+ {
+ ++nLen;
+ aRenderer.realloc( nLen );
+ auto pRenderer = aRenderer.getArray();
+ pRenderer[ nLen - 1 ].Name = "PrinterPaperTray";
+ pRenderer[ nLen - 1 ].Value <<= nPrinterPaperTray;
+ }
+ }
+
+ // #i117783#
+ if ( m_bApplyPagePrintSettingsFromXPagePrintable )
+ {
+ SwDoc& rDoc = GetDocOrThrow();
+ const SwPagePreviewPrtData* pPagePrintSettings = rDoc.GetPreviewPrtData();
+ if ( pPagePrintSettings &&
+ ( pPagePrintSettings->GetRow() > 1 ||
+ pPagePrintSettings->GetCol() > 1 ) )
+ {
+ // extend render data by page print settings attributes
+ sal_Int32 nLen = aRenderer.getLength();
+ const sal_Int32 nRenderDataIdxStart = nLen;
+ nLen += 9;
+ aRenderer.realloc( nLen );
+ auto pRenderer = aRenderer.getArray();
+ // put page print settings attribute into render data
+ const sal_Int32 nRow = pPagePrintSettings->GetRow();
+ pRenderer[ nRenderDataIdxStart + 0 ].Name = "NUpRows";
+ pRenderer[ nRenderDataIdxStart + 0 ].Value <<= std::max<sal_Int32>( nRow, 1);
+ const sal_Int32 nCol = pPagePrintSettings->GetCol();
+ pRenderer[ nRenderDataIdxStart + 1 ].Name = "NUpColumns";
+ pRenderer[ nRenderDataIdxStart + 1 ].Value <<= std::max<sal_Int32>( nCol, 1);
+ pRenderer[ nRenderDataIdxStart + 2 ].Name = "NUpPageMarginLeft";
+ pRenderer[ nRenderDataIdxStart + 2 ].Value <<= pPagePrintSettings->GetLeftSpace();
+ pRenderer[ nRenderDataIdxStart + 3 ].Name = "NUpPageMarginRight";
+ pRenderer[ nRenderDataIdxStart + 3 ].Value <<= pPagePrintSettings->GetRightSpace();
+ pRenderer[ nRenderDataIdxStart + 4 ].Name = "NUpPageMarginTop";
+ pRenderer[ nRenderDataIdxStart + 4 ].Value <<= pPagePrintSettings->GetTopSpace();
+ pRenderer[ nRenderDataIdxStart + 5 ].Name = "NUpPageMarginBottom";
+ pRenderer[ nRenderDataIdxStart + 5 ].Value <<= pPagePrintSettings->GetBottomSpace();
+ pRenderer[ nRenderDataIdxStart + 6 ].Name = "NUpHorizontalSpacing";
+ pRenderer[ nRenderDataIdxStart + 6 ].Value <<= pPagePrintSettings->GetHorzSpace();
+ pRenderer[ nRenderDataIdxStart + 7 ].Name = "NUpVerticalSpacing";
+ pRenderer[ nRenderDataIdxStart + 7 ].Value <<= pPagePrintSettings->GetVertSpace();
+ if (Printer* pPrinter = rDoc.getIDocumentDeviceAccess().getPrinter(false))
+ {
+ awt::Size aNewPageSize;
+ const Size aPageSize = pPrinter->PixelToLogic( pPrinter->GetPaperSizePixel(), MapMode( MapUnit::Map100thMM ) );
+ aNewPageSize = awt::Size( aPageSize.Width(), aPageSize.Height() );
+ if ( ( pPagePrintSettings->GetLandscape() &&
+ aPageSize.Width() < aPageSize.Height() ) ||
+ ( !pPagePrintSettings->GetLandscape() &&
+ aPageSize.Width() > aPageSize.Height() ) )
+ {
+ aNewPageSize = awt::Size( aPageSize.Height(), aPageSize.Width() );
+ }
+ pRenderer[ nRenderDataIdxStart + 8 ].Name = "NUpPaperSize";
+ pRenderer[ nRenderDataIdxStart + 8 ].Value <<= aNewPageSize;
+ }
+ }
+
+ m_bApplyPagePrintSettingsFromXPagePrintable = false;
+ }
+
+ m_pPrintUIOptions->appendPrintUIOptions( aRenderer );
+
+ return aRenderer;
+}
+
+SfxViewShell * SwXTextDocument::GuessViewShell(
+ /* out */ bool &rbIsSwSrcView,
+ const uno::Reference< css::frame::XController >& rController )
+{
+ // #130810# SfxViewShell::Current() / SfxViewShell::GetObjectShell()
+ // must not be used (see comment from MBA)
+
+ SfxViewShell *pView = nullptr;
+ SwView *pSwView = nullptr;
+ SwPagePreview *pSwPagePreview = nullptr;
+ SwSrcView *pSwSrcView = nullptr;
+ SfxViewFrame *pFrame = SfxViewFrame::GetFirst( m_pDocShell, false );
+
+ // look for the view shell with the same controller in use,
+ // otherwise look for a suitable view, preferably a SwView,
+ // if that one is not found use a SwPagePreview if found.
+ while (pFrame)
+ {
+ pView = pFrame->GetViewShell();
+ pSwView = dynamic_cast< SwView * >(pView);
+ pSwSrcView = dynamic_cast< SwSrcView * >(pView);
+ if (!pSwPagePreview)
+ pSwPagePreview = dynamic_cast< SwPagePreview * >(pView);
+ if (rController.is())
+ {
+ if (pView && pView->GetController() == rController)
+ break;
+ }
+ else if (pSwView || pSwSrcView)
+ break;
+ pFrame = SfxViewFrame::GetNext( *pFrame, m_pDocShell, false );
+ }
+
+ OSL_ENSURE( pSwView || pSwPagePreview || pSwSrcView, "failed to get view shell" );
+ if (pView)
+ rbIsSwSrcView = pSwSrcView != nullptr;
+ return pView;
+}
+
+void SAL_CALL SwXTextDocument::render(
+ sal_Int32 nRenderer,
+ const uno::Any& rSelection,
+ const uno::Sequence< beans::PropertyValue >& rxOptions )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ {
+ throw DisposedException( OUString(),
+ static_cast< XTextDocument* >(this) );
+ }
+
+ // due to #110067# (document page count changes sometimes during
+ // PDF export/printing) we can not check for the upper bound properly.
+ // Thus instead of throwing the exception we silently return.
+ if (0 > nRenderer)
+ throw IllegalArgumentException();
+
+ // tdf#135244: prevent jumping to cursor at any temporary modification
+ auto aLock = m_pDocShell->LockAllViews();
+
+ const bool bHasPDFExtOutDevData = lcl_SeqHasProperty( rxOptions, "HasPDFExtOutDevData" );
+ const bool bIsPDFExport = !lcl_SeqHasProperty( rxOptions, "IsPrinter" ) || bHasPDFExtOutDevData;
+ bool bIsSwSrcView = false;
+ SfxViewShell *pView = GetRenderView( bIsSwSrcView, rxOptions, bIsPDFExport );
+
+ OSL_ENSURE( m_pRenderData, "data should have been created already in getRendererCount..." );
+ OSL_ENSURE( m_pPrintUIOptions, "data should have been created already in getRendererCount..." );
+ if (!bIsSwSrcView && !m_pRenderData)
+ m_pRenderData.reset(new SwRenderData);
+ if (!m_pPrintUIOptions)
+ m_pPrintUIOptions = lcl_GetPrintUIOptions( m_pDocShell, pView );
+ m_pPrintUIOptions->processProperties( rxOptions );
+ const bool bPrintProspect = m_pPrintUIOptions->getBoolValue( "PrintProspect" );
+ const bool bLastPage = m_pPrintUIOptions->getBoolValue( "IsLastPage" );
+
+ SwDoc *pDoc = GetRenderDoc( pView, rSelection, bIsPDFExport );
+ OSL_ENSURE( pDoc && pView, "doc or view shell missing!" );
+ if (pDoc && pView)
+ {
+ sal_Int32 nMaxRenderer = 0;
+ if (!bIsSwSrcView)
+ {
+ OSL_ENSURE( m_pRenderData, "m_pRenderData missing!!" );
+ nMaxRenderer = bPrintProspect?
+ m_pRenderData->GetPagePairsForProspectPrinting().size() - 1 :
+ m_pRenderData->GetPagesToPrint().size() - 1;
+ }
+ // since SwSrcView::PrintSource is a poor implementation to get the number of pages to print
+ // we obmit checking of the upper bound in this case.
+ if (bIsSwSrcView || nRenderer <= nMaxRenderer)
+ {
+ if (bIsSwSrcView)
+ {
+ SwSrcView& rSwSrcView = dynamic_cast<SwSrcView&>(*pView);
+ VclPtr< OutputDevice > pOutDev = lcl_GetOutputDevice( *m_pPrintUIOptions );
+ rSwSrcView.PrintSource(pOutDev, nRenderer + 1, false);
+ }
+ else
+ {
+ // the view shell should be SwView for documents PDF export
+ // or SwPagePreview for PDF export of the page preview
+ SwViewShell* pVwSh = nullptr;
+ // TODO/mba: we really need a generic way to get the SwViewShell!
+ const SwView* pSwView = dynamic_cast<const SwView*>(pView);
+ if (pSwView)
+ pVwSh = pSwView->GetWrtShellPtr();
+ else
+ pVwSh = static_cast<SwPagePreview*>(pView)->GetViewShell();
+
+ // get output device to use
+ VclPtr< OutputDevice > pOut = lcl_GetOutputDevice( *m_pPrintUIOptions );
+
+ if(pVwSh && pOut && m_pRenderData->HasSwPrtOptions())
+ {
+ const OUString aPageRange = m_pPrintUIOptions->getStringValue( "PageRange" );
+ const bool bFirstPage = m_pPrintUIOptions->getBoolValue( "IsFirstPage" );
+ bool bIsSkipEmptyPages = !m_pPrintUIOptions->IsPrintEmptyPages( bIsPDFExport );
+
+ OSL_ENSURE((pSwView && m_pRenderData->IsViewOptionAdjust())
+ || (!pSwView && !m_pRenderData->IsViewOptionAdjust()),
+ "SwView / SwViewOptionAdjust_Impl availability mismatch" );
+
+ // since printing now also use the API for PDF export this option
+ // should be set for printing as well ...
+ pVwSh->SetPDFExportOption( true );
+
+ // #i12836# enhanced pdf export
+
+ // First, we have to export hyperlinks, notes, and outline to pdf.
+ // During this process, additional information required for tagging
+ // the pdf file are collected, which are evaluated during painting.
+
+ SwWrtShell* pWrtShell = pSwView ? pSwView->GetWrtShellPtr() : nullptr;
+
+ SwPrintData rSwPrtOptions = *m_pRenderData->GetSwPrtOptions();
+ if (bIsPDFExport)
+ {
+ rSwPrtOptions.SetPrintPostIts(
+ lcl_GetBoolProperty(rxOptions, "ExportNotesInMargin")
+ ? SwPostItMode::InMargins
+ : SwPostItMode::NONE);
+ }
+
+ if (bIsPDFExport && (bFirstPage || bHasPDFExtOutDevData) && pWrtShell)
+ {
+ SwEnhancedPDFExportHelper aHelper( *pWrtShell, *pOut, aPageRange, bIsSkipEmptyPages, false, rSwPrtOptions );
+ }
+
+ if (bPrintProspect)
+ pVwSh->PrintProspect( pOut, rSwPrtOptions, nRenderer );
+ else // normal printing and PDF export
+ pVwSh->PrintOrPDFExport( pOut, rSwPrtOptions, nRenderer, bIsPDFExport );
+
+ // #i35176#
+
+ // After printing the last page, we take care for the links coming
+ // from the EditEngine. The links are generated during the painting
+ // process, but the destinations are still missing.
+
+ if (bIsPDFExport && bLastPage && pWrtShell)
+ {
+ SwEnhancedPDFExportHelper aHelper( *pWrtShell, *pOut, aPageRange, bIsSkipEmptyPages, true, rSwPrtOptions );
+ }
+
+ pVwSh->SetPDFExportOption( false );
+
+ // last page to be rendered? (not necessarily the last page of the document)
+ // -> do clean-up of data
+ if (bLastPage)
+ {
+ // #i96167# haggai: delete ViewOptionsAdjust here because it makes use
+ // of the shell, which might get destroyed in lcl_DisposeView!
+ if (m_pRenderData->IsViewOptionAdjust())
+ m_pRenderData->ViewOptionAdjustStop();
+
+ if (m_pRenderData->HasPostItData())
+ m_pRenderData->DeletePostItData();
+ if (m_pHiddenViewFrame)
+ {
+ lcl_DisposeView( m_pHiddenViewFrame, m_pDocShell );
+ m_pHiddenViewFrame = nullptr;
+
+ // prevent crash described in #i108805
+ SwDocShell *pRenderDocShell = pDoc->GetDocShell();
+ pRenderDocShell->GetMedium()->GetItemSet().Put( SfxBoolItem( SID_HIDDEN, false ) );
+
+ }
+ }
+ }
+ }
+ }
+ }
+ if( bLastPage )
+ {
+ // tdf#144989 enable DoIdleJobs() again after last page
+ pDoc->getIDocumentTimerAccess().UnblockIdling();
+ m_pRenderData.reset();
+ m_pPrintUIOptions.reset();
+ }
+}
+
+// xforms::XFormsSupplier
+Reference<XNameContainer> SAL_CALL SwXTextDocument::getXForms()
+{
+ SolarMutexGuard aGuard;
+ if ( !m_pDocShell )
+ throw DisposedException( OUString(), static_cast< XTextDocument* >( this ) );
+ return GetDocOrThrow().getXForms();
+}
+
+uno::Reference< text::XFlatParagraphIterator > SAL_CALL SwXTextDocument::getFlatParagraphIterator(::sal_Int32 nTextMarkupType, sal_Bool bAutomatic)
+{
+ SolarMutexGuard aGuard;
+ if (!IsValid())
+ {
+ throw DisposedException("SwXTextDocument not valid",
+ static_cast<XTextDocument*>(this));
+ }
+
+ return SwUnoCursorHelper::CreateFlatParagraphIterator(
+ GetDocOrThrow(), nTextMarkupType, bAutomatic);
+}
+
+uno::Reference< util::XCloneable > SwXTextDocument::createClone( )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw DisposedException("", static_cast< XTextDocument* >(this));
+
+ // create a new document - hidden - copy the storage and return it
+ // SfxObjectShellRef is used here, since the model should control object lifetime after creation
+ // and thus SfxObjectShellLock is not allowed here
+ // the model holds reference to the shell, so the shell will not destructed at the end of method
+ SfxObjectShellRef pShell = GetDocOrThrow().CreateCopy(false, false);
+ uno::Reference< frame::XModel > xNewModel = pShell->GetModel();
+ uno::Reference< embed::XStorage > xNewStorage = ::comphelper::OStorageHelper::GetTemporaryStorage( );
+ uno::Sequence< beans::PropertyValue > aTempMediaDescriptor;
+ storeToStorage( xNewStorage, aTempMediaDescriptor );
+ uno::Reference< document::XStorageBasedDocument > xStorageDoc( xNewModel, uno::UNO_QUERY );
+ xStorageDoc->loadFromStorage( xNewStorage, aTempMediaDescriptor );
+ return uno::Reference< util::XCloneable >( xNewModel, UNO_QUERY );
+}
+
+void SwXTextDocument::addPasteEventListener(const uno::Reference<text::XPasteListener>& xListener)
+{
+ SolarMutexGuard aGuard;
+
+ if (IsValid() && xListener.is())
+ m_pDocShell->GetWrtShell()->GetPasteListeners().addInterface(xListener);
+}
+
+void SwXTextDocument::removePasteEventListener(
+ const uno::Reference<text::XPasteListener>& xListener)
+{
+ SolarMutexGuard aGuard;
+
+ if (IsValid() && xListener.is())
+ m_pDocShell->GetWrtShell()->GetPasteListeners().removeInterface(xListener);
+}
+
+void SwXTextDocument::paintTile( VirtualDevice &rDevice,
+ int nOutputWidth, int nOutputHeight,
+ int nTilePosX, int nTilePosY,
+ tools::Long nTileWidth, tools::Long nTileHeight )
+{
+ SwViewShell* pViewShell = m_pDocShell->GetWrtShell();
+ pViewShell->PaintTile(rDevice, nOutputWidth, nOutputHeight,
+ nTilePosX, nTilePosY, nTileWidth, nTileHeight);
+
+ LokChartHelper::PaintAllChartsOnTile(rDevice, nOutputWidth, nOutputHeight,
+ nTilePosX, nTilePosY, nTileWidth, nTileHeight);
+
+ // Draw Form controls
+ comphelper::LibreOfficeKit::setTiledPainting(true);
+ SwDrawModel* pDrawLayer = GetDocOrThrow().getIDocumentDrawModelAccess().GetDrawModel();
+ SdrPage* pPage = pDrawLayer->GetPage(sal_uInt16(0));
+ SdrView* pDrawView = pViewShell->GetDrawView();
+ SwEditWin& rEditWin = m_pDocShell->GetView()->GetEditWin();
+ tools::Rectangle aTileRect(Point(nTilePosX, nTilePosY), Size(nTileWidth, nTileHeight));
+ Size aOutputSize(nOutputWidth, nOutputHeight);
+ LokControlHandler::paintControlTile(pPage, pDrawView, rEditWin, rDevice, aOutputSize, aTileRect);
+ comphelper::LibreOfficeKit::setTiledPainting(false);
+}
+
+Size SwXTextDocument::getDocumentSize()
+{
+ SwViewShell* pViewShell = m_pDocShell->GetWrtShell();
+ Size aDocSize = pViewShell->GetDocSize();
+
+ return Size(aDocSize.Width() + 2 * DOCUMENTBORDER,
+ aDocSize.Height() + 2 * DOCUMENTBORDER);
+}
+
+void SwXTextDocument::setPart(int nPart, bool /*bAllowChangeFocus*/)
+{
+ SolarMutexGuard aGuard;
+
+ SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
+ if (!pWrtShell)
+ return;
+
+ pWrtShell->GotoPage(nPart + 1, true);
+}
+
+int SwXTextDocument::getParts()
+{
+ SolarMutexGuard aGuard;
+
+ SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
+ if (!pWrtShell)
+ return 0;
+
+ return pWrtShell->GetPageCnt();
+}
+
+OUString SwXTextDocument::getPartPageRectangles()
+{
+ SolarMutexGuard aGuard;
+
+ SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
+ if (!pWrtShell)
+ return OUString();
+
+ return pWrtShell->getPageRectangles();
+}
+
+void SwXTextDocument::setClipboard(const uno::Reference<datatransfer::clipboard::XClipboard>& xClipboard)
+{
+ SolarMutexGuard aGuard;
+
+ SwView* pView = m_pDocShell->GetView();
+ if (pView)
+ pView->GetEditWin().SetClipboard(xClipboard);
+}
+
+bool SwXTextDocument::isMimeTypeSupported()
+{
+ SolarMutexGuard aGuard;
+
+ SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
+ if (!pWrtShell)
+ return false;
+
+ TransferableDataHelper aDataHelper(TransferableDataHelper::CreateFromSystemClipboard(&pWrtShell->GetView().GetEditWin()));
+ if (SdrView* pSdrView = pWrtShell->GetDrawView())
+ {
+ if (pSdrView->GetTextEditObject())
+ // Editing shape text
+ return EditEngine::HasValidData(aDataHelper.GetTransferable());
+ }
+
+ return aDataHelper.GetXTransferable().is() && SwTransferable::IsPaste(*pWrtShell, aDataHelper);
+}
+
+void SwXTextDocument::setClientVisibleArea(const tools::Rectangle& rRectangle)
+{
+ if (SwView* pView = m_pDocShell->GetView())
+ {
+ // set the PgUp/PgDown offset
+ pView->ForcePageUpDownOffset(2 * rRectangle.GetHeight() / 3);
+ }
+
+ if (SwViewShell* pViewShell = m_pDocShell->GetWrtShell())
+ {
+ pViewShell->setLOKVisibleArea(rRectangle);
+ }
+}
+
+void SwXTextDocument::setClientZoom(int nTilePixelWidth_, int /*nTilePixelHeight_*/,
+ int nTileTwipWidth_, int /*nTileTwipHeight_*/)
+{
+ // Here we set the zoom value as it has been set by the user in the client.
+ // This value is used in postMouseEvent and setGraphicSelection methods
+ // for in place chart editing. We assume that x and y scale is roughly
+ // the same.
+ SfxInPlaceClient* pIPClient = m_pDocShell->GetView()->GetIPClient();
+ if (!pIPClient)
+ return;
+
+ SwViewShell* pWrtViewShell = m_pDocShell->GetWrtShell();
+ double fScale = 100.0 * nTilePixelWidth_ / nTileTwipWidth_
+ * o3tl::convert(1.0, o3tl::Length::px, o3tl::Length::twip);
+ SwViewOption aOption(*(pWrtViewShell->GetViewOptions()));
+ if (aOption.GetZoom() != fScale)
+ {
+ aOption.SetZoom(fScale);
+ pWrtViewShell->ApplyViewOptions(aOption);
+
+ // Changing the zoom value doesn't always trigger the updating of
+ // the client ole object area, so we call it directly.
+ pIPClient->VisAreaChanged();
+ }
+}
+
+PointerStyle SwXTextDocument::getPointer()
+{
+ SolarMutexGuard aGuard;
+
+ SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
+ if (!pWrtShell)
+ return PointerStyle::Arrow;
+
+ return pWrtShell->GetView().GetEditWin().GetPointer();
+}
+
+void SwXTextDocument::getTrackedChanges(tools::JsonWriter& rJson)
+{
+ auto redlinesNode = rJson.startArray("redlines");
+
+ // Disable since usability is very low beyond some small number of changes.
+ static bool bDisableRedlineComments = getenv("DISABLE_REDLINE") != nullptr;
+ if (bDisableRedlineComments)
+ return;
+
+ const SwRedlineTable& rRedlineTable
+ = GetDocOrThrow().getIDocumentRedlineAccess().GetRedlineTable();
+ for (SwRedlineTable::size_type i = 0; i < rRedlineTable.size(); ++i)
+ {
+ auto redlineNode = rJson.startStruct();
+ rJson.put("index", rRedlineTable[i]->GetId());
+ rJson.put("author", rRedlineTable[i]->GetAuthorString(1));
+ rJson.put("type", SwRedlineTypeToOUString(
+ rRedlineTable[i]->GetRedlineData().GetType()));
+ rJson.put("comment",
+ rRedlineTable[i]->GetRedlineData().GetComment());
+ rJson.put("description", rRedlineTable[i]->GetDescr());
+ OUString sDateTime = utl::toISO8601(
+ rRedlineTable[i]->GetRedlineData().GetTimeStamp().GetUNODateTime());
+ rJson.put("dateTime", sDateTime);
+
+ SwContentNode* pContentNd = rRedlineTable[i]->GetPointContentNode();
+ SwView* pView = dynamic_cast<SwView*>(SfxViewShell::Current());
+ if (pView && pContentNd)
+ {
+ SwShellCursor aCursor(pView->GetWrtShell(), *(rRedlineTable[i]->Start()));
+ aCursor.SetMark();
+ aCursor.GetMark()->Assign(*pContentNd, rRedlineTable[i]->End()->GetContentIndex());
+
+ aCursor.FillRects();
+
+ SwRects* pRects(&aCursor);
+ std::vector<OString> aRects;
+ for (const SwRect& rNextRect : *pRects)
+ aRects.push_back(rNextRect.SVRect().toString());
+
+ const OString sRects = comphelper::string::join("; ", aRects);
+ rJson.put("textRange", sRects);
+ }
+ }
+}
+
+void SwXTextDocument::getTrackedChangeAuthors(tools::JsonWriter& rJsonWriter)
+{
+ SW_MOD()->GetRedlineAuthorInfo(rJsonWriter);
+}
+
+void SwXTextDocument::getRulerState(tools::JsonWriter& rJsonWriter)
+{
+ SwView* pView = m_pDocShell->GetView();
+ dynamic_cast<SwCommentRuler&>(pView->GetHRuler()).CreateJsonNotification(rJsonWriter);
+}
+
+void SwXTextDocument::getPostIts(tools::JsonWriter& rJsonWriter)
+{
+ SolarMutexGuard aGuard;
+ auto commentsNode = rJsonWriter.startArray("comments");
+ for (auto const& sidebarItem : *m_pDocShell->GetView()->GetPostItMgr())
+ {
+ sw::annotation::SwAnnotationWin* pWin = sidebarItem->mpPostIt.get();
+
+ if (!pWin)
+ {
+ continue;
+ }
+
+ const SwPostItField* pField = pWin->GetPostItField();
+ const SwRect& aRect = pWin->GetAnchorRect();
+ tools::Rectangle aSVRect(aRect.Pos().getX(),
+ aRect.Pos().getY(),
+ aRect.Pos().getX() + aRect.SSize().Width(),
+ aRect.Pos().getY() + aRect.SSize().Height());
+
+ if (!sidebarItem->maLayoutInfo.mPositionFromCommentAnchor)
+ {
+ // Comments on frames: anchor position is the corner position, not the whole frame.
+ aSVRect.SetSize(Size(0, 0));
+ }
+
+ std::vector<OString> aRects;
+ for (const basegfx::B2DRange& aRange : pWin->GetAnnotationTextRanges())
+ {
+ const SwRect rect(aRange.getMinX(), aRange.getMinY(), aRange.getWidth(), aRange.getHeight());
+ aRects.push_back(rect.SVRect().toString());
+ }
+ const OString sRects = comphelper::string::join("; ", aRects);
+
+ auto commentNode = rJsonWriter.startStruct();
+ rJsonWriter.put("id", pField->GetPostItId());
+ rJsonWriter.put("parentId", pField->GetParentPostItId());
+ rJsonWriter.put("author", pField->GetPar1());
+ rJsonWriter.put("text", pField->GetPar2());
+ rJsonWriter.put("resolved", pField->GetResolved() ? "true" : "false");
+ rJsonWriter.put("dateTime", utl::toISO8601(pField->GetDateTime().GetUNODateTime()));
+ rJsonWriter.put("anchorPos", aSVRect.toString());
+ rJsonWriter.put("textRange", sRects);
+ }
+}
+
+void SwXTextDocument::executeFromFieldEvent(const StringMap& aArguments)
+{
+ auto aIter = aArguments.find("type");
+ if (aIter == aArguments.end() || aIter->second != "drop-down")
+ return;
+
+ aIter = aArguments.find("cmd");
+ if (aIter == aArguments.end() || aIter->second != "selected")
+ return;
+
+ aIter = aArguments.find("data");
+ if (aIter == aArguments.end())
+ return;
+
+ sal_Int32 nSelection = aIter->second.toInt32();
+ SwPosition aPos(*m_pDocShell->GetWrtShell()->GetCursor()->GetPoint());
+ sw::mark::IFieldmark* pFieldBM = m_pDocShell->GetWrtShell()->getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos);
+ if ( !pFieldBM )
+ {
+ aPos.AdjustContent(-1);
+ pFieldBM = m_pDocShell->GetWrtShell()->getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos);
+ }
+ if (pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDROPDOWN)
+ {
+ if (nSelection >= 0)
+ {
+ (*pFieldBM->GetParameters())[ODF_FORMDROPDOWN_RESULT] <<= nSelection;
+ pFieldBM->Invalidate();
+ m_pDocShell->GetWrtShell()->SetModified();
+ m_pDocShell->GetView()->GetEditWin().LogicInvalidate(nullptr);
+ }
+ }
+}
+
+std::vector<basegfx::B2DRange>
+SwXTextDocument::getSearchResultRectangles(const char* pPayload)
+{
+ SwDoc* pDoc = m_pDocShell->GetDoc();
+ if (!pDoc)
+ return std::vector<basegfx::B2DRange>();
+
+ sw::search::SearchResultLocator aLocator(pDoc);
+ sw::search::LocationResult aResult = aLocator.findForPayload(pPayload);
+ if (aResult.mbFound)
+ {
+ return aResult.maRectangles;
+ }
+ return std::vector<basegfx::B2DRange>();
+}
+
+OString SwXTextDocument::getViewRenderState(SfxViewShell* pViewShell)
+{
+ OStringBuffer aState;
+ SwView* pView = pViewShell ? dynamic_cast<SwView*>(pViewShell) : m_pDocShell->GetView();
+ if (pView && pView->GetWrtShellPtr())
+ {
+ const SwViewOption* pVOpt = pView->GetWrtShell().GetViewOptions();
+ if (pVOpt)
+ {
+ if (pVOpt->IsViewMetaChars())
+ aState.append('P');
+ if (pVOpt->IsOnlineSpell())
+ aState.append('S');
+ aState.append(';');
+
+ OString aThemeName = OUStringToOString(pVOpt->GetThemeName(), RTL_TEXTENCODING_UTF8);
+ aState.append(aThemeName);
+ }
+ }
+ return aState.makeStringAndClear();
+}
+
+namespace
+{
+inline constexpr OUString SELECTED_DATE_FORMAT = u"YYYY-MM-DD"_ustr;
+}
+
+void SwXTextDocument::executeContentControlEvent(const StringMap& rArguments)
+{
+ auto it = rArguments.find("type");
+ if (it == rArguments.end())
+ {
+ return;
+ }
+
+ if (it->second == "drop-down")
+ {
+ SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
+ const SwPosition* pStart = pWrtShell->GetCursor()->Start();
+ SwTextNode* pTextNode = pStart->GetNode().GetTextNode();
+ if (!pTextNode)
+ {
+ return;
+ }
+
+ SwTextAttr* pAttr = pTextNode->GetTextAttrAt(pStart->GetContentIndex(),
+ RES_TXTATR_CONTENTCONTROL, ::sw::GetTextAttrMode::Parent);
+ if (!pAttr)
+ {
+ return;
+ }
+
+ auto pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr);
+ const SwFormatContentControl& rFormatContentControl = pTextContentControl->GetContentControl();
+ std::shared_ptr<SwContentControl> pContentControl = rFormatContentControl.GetContentControl();
+ if (!pContentControl->GetComboBox() && !pContentControl->GetDropDown())
+ {
+ return;
+ }
+
+ it = rArguments.find("selected");
+ if (it == rArguments.end())
+ {
+ return;
+ }
+
+ sal_Int32 nSelection = it->second.toInt32();
+ pContentControl->SetSelectedListItem(nSelection);
+ pWrtShell->GotoContentControl(rFormatContentControl);
+ }
+ else if (it->second == "picture")
+ {
+ it = rArguments.find("changed");
+ if (it == rArguments.end())
+ {
+ return;
+ }
+
+ SwView* pView = m_pDocShell->GetView();
+ if (!pView)
+ {
+ return;
+ }
+
+ // The current placeholder is selected, so this will replace, not insert.
+ SfxStringItem aItem(SID_INSERT_GRAPHIC, it->second);
+ pView->GetViewFrame().GetDispatcher()->ExecuteList(SID_CHANGE_PICTURE,
+ SfxCallMode::SYNCHRON, { &aItem });
+ }
+ else if (it->second == "date")
+ {
+ SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
+ const SwPosition* pStart = pWrtShell->GetCursor()->Start();
+ SwTextNode* pTextNode = pStart->GetNode().GetTextNode();
+ if (!pTextNode)
+ {
+ return;
+ }
+
+ SwTextAttr* pAttr = pTextNode->GetTextAttrAt(pStart->GetContentIndex(),
+ RES_TXTATR_CONTENTCONTROL, ::sw::GetTextAttrMode::Parent);
+ if (!pAttr)
+ {
+ return;
+ }
+
+ auto pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr);
+ const SwFormatContentControl& rFormatContentControl
+ = pTextContentControl->GetContentControl();
+ std::shared_ptr<SwContentControl> pContentControl
+ = rFormatContentControl.GetContentControl();
+ if (!pContentControl->GetDate())
+ {
+ return;
+ }
+
+ it = rArguments.find("selected");
+ if (it == rArguments.end())
+ {
+ return;
+ }
+
+ OUString aSelectedDate = it->second.replaceAll("T00:00:00Z", "");
+ SwDoc& rDoc = pTextNode->GetDoc();
+ SvNumberFormatter* pNumberFormatter = rDoc.GetNumberFormatter();
+ sal_uInt32 nFormat
+ = pNumberFormatter->GetEntryKey(SELECTED_DATE_FORMAT, LANGUAGE_ENGLISH_US);
+ if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
+ {
+ sal_Int32 nCheckPos = 0;
+ SvNumFormatType nType;
+ OUString sFormat = SELECTED_DATE_FORMAT;
+ pNumberFormatter->PutEntry(sFormat, nCheckPos, nType, nFormat, LANGUAGE_ENGLISH_US);
+ }
+
+ if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
+ {
+ return;
+ }
+
+ double dCurrentDate = 0;
+ pNumberFormatter->IsNumberFormat(aSelectedDate, nFormat, dCurrentDate);
+ pContentControl->SetSelectedDate(dCurrentDate);
+ pWrtShell->GotoContentControl(rFormatContentControl);
+ }
+}
+
+int SwXTextDocument::getPart()
+{
+ SolarMutexGuard aGuard;
+
+ SwView* pView = m_pDocShell->GetView();
+ if (!pView)
+ return 0;
+
+ return pView->getPart();
+}
+
+OUString SwXTextDocument::getPartName(int nPart)
+{
+ return SwResId(STR_PAGE) + OUString::number(nPart + 1);
+}
+
+OUString SwXTextDocument::getPartHash(int nPart)
+{
+ OUString sPart(SwResId(STR_PAGE) + OUString::number(nPart + 1));
+
+ return OUString::number(sPart.hashCode());
+}
+
+VclPtr<vcl::Window> SwXTextDocument::getDocWindow()
+{
+ SolarMutexGuard aGuard;
+ SwView* pView = m_pDocShell->GetView();
+ if (!pView)
+ return {};
+
+ if (VclPtr<vcl::Window> pWindow = SfxLokHelper::getInPlaceDocWindow(pView))
+ return pWindow;
+
+ return &(pView->GetEditWin());
+}
+
+void SwXTextDocument::initializeForTiledRendering(const css::uno::Sequence<css::beans::PropertyValue>& rArguments)
+{
+ SolarMutexGuard aGuard;
+
+ SwViewShell* pViewShell = m_pDocShell->GetWrtShell();
+
+ SwView* pView = m_pDocShell->GetView();
+ if (!pView)
+ return;
+
+ pView->SetViewLayout(1/*nColumns*/, false/*bBookMode*/, true);
+
+ // Tiled rendering defaults.
+ SwViewOption aViewOption(*pViewShell->GetViewOptions());
+ aViewOption.SetHardBlank(false);
+
+ // Disable field shadings: the result would depend on the cursor position.
+ aViewOption.SetAppearanceFlag(ViewOptFlags::FieldShadings, false);
+ // The fancy header/footer controls don't work in tiled mode anyway, so
+ // explicitly disable them to enable skipping invalidating the view for
+ // the case of clicking in the header area of a document with no headers
+ aViewOption.SetUseHeaderFooterMenu(false);
+
+ OUString sOrigAuthor = SW_MOD()->GetRedlineAuthor(SW_MOD()->GetRedlineAuthor());
+ OUString sAuthor;
+
+ for (const beans::PropertyValue& rValue : rArguments)
+ {
+ if (rValue.Name == ".uno:HideWhitespace" && rValue.Value.has<bool>())
+ aViewOption.SetHideWhitespaceMode(rValue.Value.get<bool>());
+ else if (rValue.Name == ".uno:ShowBorderShadow" && rValue.Value.has<bool>())
+ aViewOption.SetAppearanceFlag(ViewOptFlags::Shadow , rValue.Value.get<bool>());
+ else if (rValue.Name == ".uno:Author" && rValue.Value.has<OUString>())
+ {
+ sAuthor = rValue.Value.get<OUString>();
+ // Store the author name in the view.
+ pView->SetRedlineAuthor(sAuthor);
+ // Let the actual author name pick up the value from the current
+ // view, which would normally happen only during the next view
+ // switch.
+ m_pDocShell->SetView(pView);
+ }
+ else if (rValue.Name == ".uno:SpellOnline" && rValue.Value.has<bool>())
+ aViewOption.SetOnlineSpell(rValue.Value.get<bool>());
+ }
+
+ if (!sAuthor.isEmpty() && sAuthor != sOrigAuthor)
+ {
+ SwView* pFirstView = static_cast<SwView*>(SfxViewShell::GetFirst());
+ if (pFirstView && SfxViewShell::GetNext(*pFirstView) == nullptr)
+ {
+ if (SwEditShell* pShell = &pFirstView->GetWrtShell())
+ {
+ pShell->SwViewShell::UpdateFields(true);
+ pShell->ResetModified();
+ }
+ }
+ }
+
+ // Set the initial zoom value to 1; usually it is set in setClientZoom and
+ // SwViewShell::PaintTile; zoom value is used for chart in place
+ // editing, see postMouseEvent and setGraphicSelection methods.
+ aViewOption.SetZoom(1 * 100);
+
+ aViewOption.SetPostIts(comphelper::LibreOfficeKit::isTiledAnnotations());
+ pViewShell->ApplyViewOptions(aViewOption);
+
+ // position the pages again after setting view options. Eg: if postit
+ // rendering is false, then there would be no sidebar, so width of the
+ // document needs to be adjusted
+ pViewShell->GetLayout()->CheckViewLayout( pViewShell->GetViewOptions(), nullptr );
+
+ // Disable map mode, so that it's possible to send mouse event coordinates
+ // directly in twips.
+ SwEditWin& rEditWin = m_pDocShell->GetView()->GetEditWin();
+ rEditWin.EnableMapMode(false);
+
+ // when the "This document may contain formatting or content that cannot
+ // be saved..." dialog appears, it is auto-cancelled with tiled rendering,
+ // causing 'Save' being disabled; so let's always save to the original
+ // format
+ auto xChanges = comphelper::ConfigurationChanges::create();
+ officecfg::Office::Common::Save::Document::WarnAlienFormat::set(false, xChanges);
+ xChanges->commit();
+
+ // disable word auto-completion suggestions, the tooltips are not visible,
+ // and the editeng-like auto-completion is annoying
+ SvxAutoCorrCfg::Get().GetAutoCorrect()->GetSwFlags().bAutoCompleteWords = false;
+
+ // don't change the whitespace at the beginning of paragraphs, this is
+ // annoying when taking minutes without further formatting
+ SwEditShell::GetAutoFormatFlags()->bAFormatByInpDelSpacesAtSttEnd = false;
+}
+
+void SwXTextDocument::postKeyEvent(int nType, int nCharCode, int nKeyCode)
+{
+ SolarMutexGuard aGuard;
+ SfxLokHelper::postKeyEventAsync(getDocWindow(), nType, nCharCode, nKeyCode);
+}
+
+void SwXTextDocument::postMouseEvent(int nType, int nX, int nY, int nCount, int nButtons, int nModifier)
+{
+ SolarMutexGuard aGuard;
+
+ SwViewShell* pWrtViewShell = m_pDocShell->GetWrtShell();
+ if (!pWrtViewShell)
+ {
+ return;
+ }
+
+ SwViewOption aOption(*(pWrtViewShell->GetViewOptions()));
+ double fScale = aOption.GetZoom() / o3tl::convert(100.0, o3tl::Length::px, o3tl::Length::twip);
+
+ if (SfxLokHelper::testInPlaceComponentMouseEventHit(
+ m_pDocShell->GetView(), nType, nX, nY, nCount, nButtons, nModifier, fScale, fScale))
+ return;
+
+ // try to forward mouse event to controls
+ SwDrawModel* pDrawLayer = GetDocOrThrow().getIDocumentDrawModelAccess().GetDrawModel();
+ SdrPage* pPage = pDrawLayer->GetPage(sal_uInt16(0));
+ SdrView* pDrawView = pWrtViewShell->GetDrawView();
+ SwEditWin& rEditWin = m_pDocShell->GetView()->GetEditWin();
+ Point aPointTwip(nX, nY);
+ Point aPointHMMDraw = o3tl::convert(aPointTwip, o3tl::Length::twip, o3tl::Length::mm100);
+ if (LokControlHandler::postMouseEvent(pPage, pDrawView, rEditWin, nType, aPointHMMDraw, nCount, nButtons, nModifier))
+ return;
+
+ LokMouseEventData aMouseEventData(nType, Point(nX, nY), nCount,
+ MouseEventModifiers::SIMPLECLICK,
+ nButtons, nModifier);
+ SfxLokHelper::postMouseEventAsync(&rEditWin, aMouseEventData);
+}
+
+void SwXTextDocument::setTextSelection(int nType, int nX, int nY)
+{
+ SolarMutexGuard aGuard;
+
+ SfxViewShell* pViewShell = m_pDocShell->GetView();
+ LokChartHelper aChartHelper(pViewShell);
+ if (aChartHelper.setTextSelection(nType, nX, nY))
+ return;
+
+ SwEditWin& rEditWin = m_pDocShell->GetView()->GetEditWin();
+ switch (nType)
+ {
+ case LOK_SETTEXTSELECTION_START:
+ rEditWin.SetCursorTwipPosition(Point(nX, nY), /*bPoint=*/false, /*bClearMark=*/false);
+ break;
+ case LOK_SETTEXTSELECTION_END:
+ rEditWin.SetCursorTwipPosition(Point(nX, nY), /*bPoint=*/true, /*bClearMark=*/false);
+ break;
+ case LOK_SETTEXTSELECTION_RESET:
+ rEditWin.SetCursorTwipPosition(Point(nX, nY), /*bPoint=*/true, /*bClearMark=*/true);
+ break;
+ default:
+ assert(false);
+ break;
+ }
+}
+
+uno::Reference<datatransfer::XTransferable> SwXTextDocument::getSelection()
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference<datatransfer::XTransferable> xTransferable;
+
+ SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
+ if (SdrView* pSdrView = pWrtShell ? pWrtShell->GetDrawView() : nullptr)
+ {
+ if (pSdrView->GetTextEditObject())
+ {
+ // Editing shape text
+ EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView();
+ xTransferable = rEditView.GetEditEngine()->CreateTransferable(rEditView.GetSelection());
+ }
+ }
+
+ if (SwPostItMgr* pPostItMgr = m_pDocShell->GetView()->GetPostItMgr())
+ {
+ if (sw::annotation::SwAnnotationWin* pWin = pPostItMgr->GetActiveSidebarWin())
+ {
+ // Editing postit text.
+ EditView& rEditView = pWin->GetOutlinerView()->GetEditView();
+ xTransferable = rEditView.GetEditEngine()->CreateTransferable(rEditView.GetSelection());
+ }
+ }
+
+ if (!xTransferable.is() && pWrtShell)
+ xTransferable = new SwTransferable(*pWrtShell);
+
+ return xTransferable;
+}
+
+void SwXTextDocument::setGraphicSelection(int nType, int nX, int nY)
+{
+ SolarMutexGuard aGuard;
+
+ SwViewShell* pWrtViewShell = m_pDocShell->GetWrtShell();
+ SwViewOption aOption(*(pWrtViewShell->GetViewOptions()));
+ double fScale = aOption.GetZoom() / o3tl::convert(100.0, o3tl::Length::px, o3tl::Length::twip);
+
+ SfxViewShell* pViewShell = m_pDocShell->GetView();
+ LokChartHelper aChartHelper(pViewShell);
+ if (aChartHelper.setGraphicSelection(nType, nX, nY, fScale, fScale))
+ return;
+
+ SwEditWin& rEditWin = m_pDocShell->GetView()->GetEditWin();
+ switch (nType)
+ {
+ case LOK_SETGRAPHICSELECTION_START:
+ rEditWin.SetGraphicTwipPosition(/*bStart=*/true, Point(nX, nY));
+ break;
+ case LOK_SETGRAPHICSELECTION_END:
+ rEditWin.SetGraphicTwipPosition(/*bStart=*/false, Point(nX, nY));
+ break;
+ default:
+ assert(false);
+ break;
+ }
+}
+
+void SwXTextDocument::resetSelection()
+{
+ SolarMutexGuard aGuard;
+
+ SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
+ pWrtShell->ResetSelect(nullptr, false);
+}
+
+void SAL_CALL SwXTextDocument::paintTile( const ::css::uno::Any& Parent, ::sal_Int32 nOutputWidth, ::sal_Int32 nOutputHeight, ::sal_Int32 nTilePosX, ::sal_Int32 nTilePosY, ::sal_Int32 nTileWidth, ::sal_Int32 nTileHeight )
+{
+ SystemGraphicsData aData;
+ aData.nSize = sizeof(SystemGraphicsData);
+ #if defined(_WIN32)
+ sal_Int64 nWindowHandle;
+ Parent >>= nWindowHandle;
+ aData.hWnd = reinterpret_cast<HWND>(nWindowHandle);
+ ScopedVclPtrInstance<VirtualDevice> xDevice(aData, Size(1, 1), DeviceFormat::WITHOUT_ALPHA);
+ paintTile(*xDevice, nOutputWidth, nOutputHeight, nTilePosX, nTilePosY, nTileWidth, nTileHeight);
+ #else
+ // TODO: support other platforms
+ (void)Parent;
+ (void)nOutputWidth;
+ (void)nOutputHeight;
+ (void)nTilePosX;
+ (void)nTilePosY;
+ (void)nTileWidth;
+ (void)nTileHeight;
+ #endif
+}
+
+/**
+ * retrieve languages already used in current document
+ */
+uno::Sequence< lang::Locale > SAL_CALL SwXTextDocument::getDocumentLanguages(
+ ::sal_Int16 nScriptTypes,
+ ::sal_Int16 nMaxCount )
+{
+ SolarMutexGuard aGuard;
+
+ // possible canonical values for nScriptTypes
+ // any bit wise combination is allowed
+ const sal_Int16 nLatin = 0x001;
+ const sal_Int16 nAsian = 0x002;
+ const sal_Int16 nComplex = 0x004;
+
+ // script types for which to get the languages
+ const bool bLatin = 0 != (nScriptTypes & nLatin);
+ const bool bAsian = 0 != (nScriptTypes & nAsian);
+ const bool bComplex = 0 != (nScriptTypes & nComplex);
+
+ if (nScriptTypes < nLatin || nScriptTypes > (nLatin | nAsian | nComplex))
+ throw IllegalArgumentException("nScriptTypes ranges from 1 to 7!", Reference< XInterface >(), 1);
+ if (!m_pDocShell)
+ throw DisposedException();
+ SwDoc& rDoc = GetDocOrThrow();
+
+ // avoid duplicate values
+ std::set< LanguageType > aAllLangs;
+
+ //USER STYLES
+
+ const SwCharFormats *pFormats = rDoc.GetCharFormats();
+ for(size_t i = 0; i < pFormats->size(); ++i)
+ {
+ const SwAttrSet &rAttrSet = (*pFormats)[i]->GetAttrSet();
+ LanguageType nLang = LANGUAGE_DONTKNOW;
+ if (bLatin)
+ {
+ nLang = rAttrSet.GetLanguage( false ).GetLanguage();
+ if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
+ aAllLangs.insert( nLang );
+ }
+ if (bAsian)
+ {
+ nLang = rAttrSet.GetCJKLanguage( false ).GetLanguage();
+ if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
+ aAllLangs.insert( nLang );
+ }
+ if (bComplex)
+ {
+ nLang = rAttrSet.GetCTLLanguage( false ).GetLanguage();
+ if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
+ aAllLangs.insert( nLang );
+ }
+ }
+
+ const SwTextFormatColls *pColls = rDoc.GetTextFormatColls();
+ for (size_t i = 0; i < pColls->size(); ++i)
+ {
+ const SwAttrSet &rAttrSet = (*pColls)[i]->GetAttrSet();
+ LanguageType nLang = LANGUAGE_DONTKNOW;
+ if (bLatin)
+ {
+ nLang = rAttrSet.GetLanguage( false ).GetLanguage();
+ if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
+ aAllLangs.insert( nLang );
+ }
+ if (bAsian)
+ {
+ nLang = rAttrSet.GetCJKLanguage( false ).GetLanguage();
+ if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
+ aAllLangs.insert( nLang );
+ }
+ if (bComplex)
+ {
+ nLang = rAttrSet.GetCTLLanguage( false ).GetLanguage();
+ if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
+ aAllLangs.insert( nLang );
+ }
+ }
+
+ //AUTO STYLES
+ const IStyleAccess::SwAutoStyleFamily aFam[2] =
+ {
+ IStyleAccess::AUTO_STYLE_CHAR,
+ IStyleAccess::AUTO_STYLE_PARA
+ };
+ for (IStyleAccess::SwAutoStyleFamily i : aFam)
+ {
+ std::vector< std::shared_ptr<SfxItemSet> > rStyles;
+ rDoc.GetIStyleAccess().getAllStyles(rStyles, i);
+ while (!rStyles.empty())
+ {
+ std::shared_ptr<SfxItemSet> pStyle = rStyles.back();
+ rStyles.pop_back();
+ const SfxItemSet *pSet = pStyle.get();
+
+ LanguageType nLang = LANGUAGE_DONTKNOW;
+ if (bLatin)
+ {
+ assert(pSet);
+ nLang = pSet->Get( RES_CHRATR_LANGUAGE, false ).GetLanguage();
+ if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
+ aAllLangs.insert( nLang );
+ }
+ if (bAsian)
+ {
+ assert(pSet);
+ nLang = pSet->Get( RES_CHRATR_CJK_LANGUAGE, false ).GetLanguage();
+ if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
+ aAllLangs.insert( nLang );
+ }
+ if (bComplex)
+ {
+ assert(pSet);
+ nLang = pSet->Get( RES_CHRATR_CTL_LANGUAGE, false ).GetLanguage();
+ if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
+ aAllLangs.insert( nLang );
+ }
+ }
+ }
+
+ //TODO/mba: it's a strange concept that a view is needed to retrieve core data
+ SwWrtShell *pWrtSh = m_pDocShell->GetWrtShell();
+ SdrView *pSdrView = pWrtSh->GetDrawView();
+
+ if( pSdrView )
+ {
+ SdrOutliner* pOutliner = pSdrView->GetTextEditOutliner();
+ if(pOutliner)
+ {
+ EditEngine& rEditEng = const_cast<EditEngine&>(pOutliner->GetEditEngine());
+ sal_Int32 nParCount = pOutliner->GetParagraphCount();
+ for (sal_Int32 nPar=0; nPar<nParCount; nPar++)
+ {
+ //every paragraph
+ std::vector<sal_Int32> aPortions;
+ rEditEng.GetPortions( nPar, aPortions );
+
+ for ( size_t nPos = aPortions.size(); nPos; )
+ {
+ //every position
+ --nPos;
+ sal_Int32 nEnd = aPortions[ nPos ];
+ sal_Int32 nStart = nPos ? aPortions[ nPos - 1 ] : 0;
+ ESelection aSelection( nPar, nStart, nPar, nEnd );
+ SfxItemSet aAttr = rEditEng.GetAttribs( aSelection );
+
+ LanguageType nLang = LANGUAGE_DONTKNOW;
+ if (bLatin)
+ {
+ nLang = aAttr.Get( EE_CHAR_LANGUAGE, false ).GetLanguage();
+ if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
+ aAllLangs.insert( nLang );
+ }
+ if (bAsian)
+ {
+ nLang = aAttr.Get( EE_CHAR_LANGUAGE_CJK, false ).GetLanguage();
+ if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
+ aAllLangs.insert( nLang );
+ }
+ if (bComplex)
+ {
+ nLang = aAttr.Get( EE_CHAR_LANGUAGE_CTL, false ).GetLanguage();
+ if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
+ aAllLangs.insert( nLang );
+ }
+ }
+ }
+ }
+ }
+ // less than nMaxCount languages
+ if (nMaxCount > static_cast< sal_Int16 >( aAllLangs.size() ))
+ nMaxCount = static_cast< sal_Int16 >( aAllLangs.size() );
+
+ // build return value
+ uno::Sequence< lang::Locale > aLanguages( nMaxCount );
+ lang::Locale* pLanguage = aLanguages.getArray();
+ if (nMaxCount > 0)
+ {
+ sal_Int32 nCount = 0;
+ for (const auto& rLang : aAllLangs)
+ {
+ if (nCount >= nMaxCount)
+ break;
+ if (LANGUAGE_NONE != rLang)
+ {
+ pLanguage[nCount] = LanguageTag::convertToLocale( rLang );
+ pLanguage[nCount].Language = SvtLanguageTable::GetLanguageString( rLang );
+ nCount += 1;
+ }
+ }
+ }
+
+ return aLanguages;
+}
+
+SwXLinkTargetSupplier::SwXLinkTargetSupplier(SwXTextDocument& rxDoc) :
+ m_pxDoc(&rxDoc)
+{
+ m_sTables = SwResId(STR_CONTENT_TYPE_TABLE);
+ m_sFrames = SwResId(STR_CONTENT_TYPE_FRAME);
+ m_sGraphics = SwResId(STR_CONTENT_TYPE_GRAPHIC);
+ m_sOLEs = SwResId(STR_CONTENT_TYPE_OLE);
+ m_sSections = SwResId(STR_CONTENT_TYPE_REGION);
+ m_sOutlines = SwResId(STR_CONTENT_TYPE_OUTLINE);
+ m_sBookmarks = SwResId(STR_CONTENT_TYPE_BOOKMARK);
+ m_sDrawingObjects = SwResId(STR_CONTENT_TYPE_DRAWOBJECT);
+}
+
+SwXLinkTargetSupplier::~SwXLinkTargetSupplier()
+{
+}
+
+Any SwXLinkTargetSupplier::getByName(const OUString& rName)
+{
+ Any aRet;
+ if(!m_pxDoc)
+ throw RuntimeException("No document available");
+ OUString sSuffix("|");
+ if(rName == m_sTables)
+ {
+ sSuffix += "table";
+
+ Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper(
+ m_pxDoc->getTextTables(), rName, sSuffix );
+ aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY);
+ }
+ else if(rName == m_sFrames)
+ {
+ sSuffix += "frame";
+ Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper(
+ m_pxDoc->getTextFrames(), rName, sSuffix );
+ aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY);
+ }
+ else if(rName == m_sSections)
+ {
+ sSuffix += "region";
+ Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper(
+ m_pxDoc->getTextSections(), rName, sSuffix );
+ aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY);
+ }
+ else if(rName == m_sGraphics)
+ {
+ sSuffix += "graphic";
+ Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper(
+ m_pxDoc->getGraphicObjects(), rName, sSuffix );
+ aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY);
+ }
+ else if(rName == m_sOLEs)
+ {
+ sSuffix += "ole";
+ Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper(
+ m_pxDoc->getEmbeddedObjects(), rName, sSuffix );
+ aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY);
+ }
+ else if(rName == m_sOutlines)
+ {
+ sSuffix += "outline";
+ Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper(
+ *m_pxDoc, rName, sSuffix );
+ aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY);
+ }
+ else if(rName == m_sBookmarks)
+ {
+ sSuffix.clear();
+ Reference< XNameAccess > xBkms = new SwXLinkNameAccessWrapper(
+ m_pxDoc->getBookmarks(), rName, sSuffix );
+ aRet <<= Reference< XPropertySet >(xBkms, UNO_QUERY);
+ }
+ else if(rName == m_sDrawingObjects)
+ {
+ sSuffix += "drawingobject";
+ Reference<XNameAccess> xDrawingObjects = new SwXLinkNameAccessWrapper(
+ *m_pxDoc, rName, sSuffix);
+ aRet <<= Reference<XPropertySet>(xDrawingObjects, UNO_QUERY);
+ }
+ else
+ throw NoSuchElementException();
+ return aRet;
+}
+
+Sequence< OUString > SwXLinkTargetSupplier::getElementNames()
+{
+ return { m_sTables,
+ m_sFrames,
+ m_sGraphics,
+ m_sOLEs,
+ m_sSections,
+ m_sOutlines,
+ m_sBookmarks,
+ m_sDrawingObjects };
+}
+
+sal_Bool SwXLinkTargetSupplier::hasByName(const OUString& rName)
+{
+ if( rName == m_sTables ||
+ rName == m_sFrames ||
+ rName == m_sGraphics||
+ rName == m_sOLEs ||
+ rName == m_sSections ||
+ rName == m_sOutlines ||
+ rName == m_sBookmarks ||
+ rName == m_sDrawingObjects )
+ return true;
+ return false;
+}
+
+uno::Type SwXLinkTargetSupplier::getElementType()
+{
+ return cppu::UnoType<XPropertySet>::get();
+
+}
+
+sal_Bool SwXLinkTargetSupplier::hasElements()
+{
+ return nullptr != m_pxDoc;
+}
+
+OUString SwXLinkTargetSupplier::getImplementationName()
+{
+ return "SwXLinkTargetSupplier";
+}
+
+sal_Bool SwXLinkTargetSupplier::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence< OUString > SwXLinkTargetSupplier::getSupportedServiceNames()
+{
+ Sequence< OUString > aRet { "com.sun.star.document.LinkTargets" };
+ return aRet;
+}
+
+SwXLinkNameAccessWrapper::SwXLinkNameAccessWrapper(
+ Reference< XNameAccess > const & xAccess, OUString aLinkDisplayName, OUString sSuffix ) :
+ m_xRealAccess(xAccess),
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)),
+ m_sLinkSuffix(std::move(sSuffix)),
+ m_sLinkDisplayName(std::move(aLinkDisplayName)),
+ m_pxDoc(nullptr)
+{
+}
+
+SwXLinkNameAccessWrapper::SwXLinkNameAccessWrapper(SwXTextDocument& rxDoc,
+ OUString aLinkDisplayName, OUString sSuffix) :
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)),
+ m_sLinkSuffix(std::move(sSuffix)),
+ m_sLinkDisplayName(std::move(aLinkDisplayName)),
+ m_pxDoc(&rxDoc)
+{
+}
+
+SwXLinkNameAccessWrapper::~SwXLinkNameAccessWrapper()
+{
+}
+
+Any SwXLinkNameAccessWrapper::getByName(const OUString& rName)
+{
+ Any aRet;
+ bool bFound = false;
+ //cut link extension and call the real NameAccess
+ OUString sParam = rName;
+ OUString sSuffix(m_sLinkSuffix);
+ if(sParam.getLength() > sSuffix.getLength() )
+ {
+ std::u16string_view sCmp = sParam.subView(sParam.getLength() - sSuffix.getLength(),
+ sSuffix.getLength());
+ if(sCmp == sSuffix)
+ {
+ if(m_pxDoc)
+ {
+ sParam = sParam.copy(0, sParam.getLength() - sSuffix.getLength());
+ if(!m_pxDoc->GetDocShell())
+ throw RuntimeException("No document shell available");
+ SwDoc* pDoc = m_pxDoc->GetDocShell()->GetDoc();
+
+ if (sSuffix == "|outline")
+ {
+ const size_t nOutlineCount = pDoc->GetNodes().GetOutLineNds().size();
+
+ for (size_t i = 0; i < nOutlineCount && !bFound; ++i)
+ {
+ if(sParam == lcl_CreateOutlineString(i, pDoc))
+ {
+ OUString sOutlineText =
+ pDoc->getIDocumentOutlineNodes().getOutlineText(
+ i, pDoc->GetDocShell()->GetWrtShell()->GetLayout());
+ sal_Int32 nOutlineLevel = pDoc->getIDocumentOutlineNodes().getOutlineLevel(i);
+ Reference<XPropertySet> xOutline =
+ new SwXOutlineTarget(sParam, sOutlineText, nOutlineLevel);
+ aRet <<= xOutline;
+ bFound = true;
+ }
+ }
+ }
+ else if (sSuffix == "|drawingobject")
+ {
+ SwDrawModel* pModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel();
+ if (pModel)
+ {
+ SdrPage* pPage = pModel->GetPage(0);
+ for (const rtl::Reference<SdrObject>& pObj : *pPage)
+ {
+ if (sParam == pObj->GetName())
+ {
+ Reference<XPropertySet> xDrawingObject = new SwXDrawingObjectTarget(sParam);
+ aRet <<= xDrawingObject;
+ bFound = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ aRet = m_xRealAccess->getByName(sParam.copy(0, sParam.getLength() - sSuffix.getLength()));
+ Reference< XInterface > xInt;
+ if(!(aRet >>= xInt))
+ throw RuntimeException("Could not retrieve property");
+ Reference< XPropertySet > xProp(xInt, UNO_QUERY);
+ aRet <<= xProp;
+ bFound = true;
+ }
+ }
+ }
+ if(!bFound)
+ throw NoSuchElementException();
+ return aRet;
+}
+
+Sequence< OUString > SwXLinkNameAccessWrapper::getElementNames()
+{
+ Sequence< OUString > aRet;
+ if(m_pxDoc)
+ {
+ if(!m_pxDoc->GetDocShell())
+ throw RuntimeException("No document shell available");
+ SwDoc* pDoc = m_pxDoc->GetDocShell()->GetDoc();
+ if (m_sLinkSuffix == "|outline")
+ {
+ const SwOutlineNodes& rOutlineNodes = pDoc->GetNodes().GetOutLineNds();
+ const size_t nOutlineCount = rOutlineNodes.size();
+ aRet.realloc(nOutlineCount);
+ OUString* pResArr = aRet.getArray();
+ for (size_t i = 0; i < nOutlineCount; ++i)
+ {
+ OUString sEntry = lcl_CreateOutlineString(i, pDoc) + "|outline";
+ pResArr[i] = sEntry;
+ }
+ }
+ else if (m_sLinkSuffix == "|drawingobject")
+ {
+ SwDrawModel* pModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel();
+ if(pModel)
+ {
+ SdrPage* pPage = pModel->GetPage(0);
+ const size_t nObjCount = pPage->GetObjCount();
+ aRet.realloc(nObjCount);
+ OUString* pResArr = aRet.getArray();
+ auto j = 0;
+ for (const rtl::Reference<SdrObject>& pObj : *pPage)
+ {
+ if (!pObj->GetName().isEmpty())
+ pResArr[j++] = pObj->GetName() + "|drawingobject";
+ }
+ }
+ }
+ }
+ else
+ {
+ const Sequence< OUString > aOrg = m_xRealAccess->getElementNames();
+ aRet.realloc(aOrg.getLength());
+ std::transform(aOrg.begin(), aOrg.end(), aRet.getArray(),
+ [this](const OUString& rOrg) -> OUString { return rOrg + m_sLinkSuffix; });
+ }
+ return aRet;
+}
+
+sal_Bool SwXLinkNameAccessWrapper::hasByName(const OUString& rName)
+{
+ bool bRet = false;
+ OUString sParam(rName);
+ if(sParam.getLength() > m_sLinkSuffix.getLength() )
+ {
+ std::u16string_view sCmp = sParam.subView(sParam.getLength() - m_sLinkSuffix.getLength(),
+ m_sLinkSuffix.getLength());
+ if(sCmp == m_sLinkSuffix)
+ {
+ sParam = sParam.copy(0, sParam.getLength() - m_sLinkSuffix.getLength());
+ if(m_pxDoc)
+ {
+ if(!m_pxDoc->GetDocShell())
+ throw RuntimeException("No document shell available");
+ SwDoc* pDoc = m_pxDoc->GetDocShell()->GetDoc();
+ if (m_sLinkSuffix == "|outline")
+ {
+ const size_t nOutlineCount = pDoc->GetNodes().GetOutLineNds().size();
+
+ for (size_t i = 0; i < nOutlineCount && !bRet; ++i)
+ {
+ if(sParam == lcl_CreateOutlineString(i, pDoc))
+ {
+ bRet = true;
+ }
+ }
+ }
+ else if (m_sLinkSuffix == "|drawingobject")
+ {
+ SwDrawModel* pModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel();
+ if (pModel)
+ {
+ SdrPage* pPage = pModel->GetPage(0);
+ for (const rtl::Reference<SdrObject>& pObj : *pPage)
+ {
+ if (sParam == pObj->GetName())
+ {
+ bRet = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ bRet = m_xRealAccess->hasByName(sParam);
+ }
+ }
+ }
+ return bRet;
+}
+
+uno::Type SwXLinkNameAccessWrapper::getElementType()
+{
+ return cppu::UnoType<XPropertySet>::get();
+}
+
+sal_Bool SwXLinkNameAccessWrapper::hasElements()
+{
+ bool bRet = false;
+ if(m_pxDoc)
+ {
+ OSL_FAIL("not implemented");
+ }
+ else
+ {
+ bRet = m_xRealAccess->hasElements();
+ }
+ return bRet;
+}
+
+Reference< XPropertySetInfo > SwXLinkNameAccessWrapper::getPropertySetInfo()
+{
+ static Reference< XPropertySetInfo > xRet = m_pPropSet->getPropertySetInfo();
+ return xRet;
+}
+
+void SwXLinkNameAccessWrapper::setPropertyValue(
+ const OUString& rPropName, const Any& )
+{
+ throw UnknownPropertyException(rPropName);
+}
+
+static Any lcl_GetDisplayBitmap(std::u16string_view sLinkSuffix)
+{
+ Any aRet;
+ if(!sLinkSuffix.empty())
+ sLinkSuffix = sLinkSuffix.substr(1);
+ OUString sImgId;
+
+ if(sLinkSuffix == u"outline")
+ sImgId = RID_BMP_NAVI_OUTLINE;
+ else if(sLinkSuffix == u"table")
+ sImgId = RID_BMP_NAVI_TABLE;
+ else if(sLinkSuffix == u"frame")
+ sImgId = RID_BMP_NAVI_FRAME;
+ else if(sLinkSuffix == u"graphic")
+ sImgId = RID_BMP_NAVI_GRAPHIC;
+ else if(sLinkSuffix == u"ole")
+ sImgId = RID_BMP_NAVI_OLE;
+ else if(sLinkSuffix.empty())
+ sImgId = RID_BMP_NAVI_BOOKMARK;
+ else if(sLinkSuffix == u"region")
+ sImgId = RID_BMP_NAVI_REGION;
+ else if(sLinkSuffix == u"drawingobject")
+ sImgId = RID_BMP_NAVI_DRAWOBJECT;
+
+ if (!sImgId.isEmpty())
+ {
+ aRet <<= VCLUnoHelper::CreateBitmap(BitmapEx(sImgId));
+ }
+ return aRet;
+}
+
+Any SwXLinkNameAccessWrapper::getPropertyValue(const OUString& rPropertyName)
+{
+ Any aRet;
+ if( rPropertyName == UNO_LINK_DISPLAY_NAME )
+ {
+ aRet <<= m_sLinkDisplayName;
+ }
+ else if( rPropertyName == UNO_LINK_DISPLAY_BITMAP )
+ {
+ aRet = lcl_GetDisplayBitmap(m_sLinkSuffix);
+ }
+ else
+ throw UnknownPropertyException(rPropertyName);
+ return aRet;
+}
+
+void SwXLinkNameAccessWrapper::addPropertyChangeListener(
+ const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/)
+{}
+
+void SwXLinkNameAccessWrapper::removePropertyChangeListener(
+ const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/)
+{}
+
+void SwXLinkNameAccessWrapper::addVetoableChangeListener(
+ const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/)
+{}
+
+void SwXLinkNameAccessWrapper::removeVetoableChangeListener(
+ const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/)
+{}
+
+Reference< XNameAccess > SwXLinkNameAccessWrapper::getLinks()
+{
+ return this;
+}
+
+OUString SwXLinkNameAccessWrapper::getImplementationName()
+{
+ return "SwXLinkNameAccessWrapper";
+}
+
+sal_Bool SwXLinkNameAccessWrapper::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence< OUString > SwXLinkNameAccessWrapper::getSupportedServiceNames()
+{
+ Sequence< OUString > aRet { "com.sun.star.document.LinkTargets" };
+ return aRet;
+}
+
+SwXOutlineTarget::SwXOutlineTarget(OUString aOutlineText, OUString aActualText,
+ const sal_Int32 nOutlineLevel) :
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)),
+ m_sOutlineText(std::move(aOutlineText)),
+ m_sActualText(std::move(aActualText)),
+ m_nOutlineLevel(nOutlineLevel)
+{
+}
+
+SwXOutlineTarget::~SwXOutlineTarget()
+{
+}
+
+Reference< XPropertySetInfo > SwXOutlineTarget::getPropertySetInfo()
+{
+ static Reference< XPropertySetInfo > xRet = m_pPropSet->getPropertySetInfo();
+ return xRet;
+}
+
+void SwXOutlineTarget::setPropertyValue(
+ const OUString& rPropertyName, const Any& /*aValue*/)
+{
+ throw UnknownPropertyException(rPropertyName);
+}
+
+Any SwXOutlineTarget::getPropertyValue(const OUString& rPropertyName)
+{
+ if (rPropertyName != UNO_LINK_DISPLAY_NAME && rPropertyName != "ActualOutlineName" &&
+ rPropertyName != "OutlineLevel")
+ throw UnknownPropertyException(rPropertyName);
+
+ if (rPropertyName == "ActualOutlineName")
+ return Any(m_sActualText);
+
+ if (rPropertyName == "OutlineLevel")
+ return Any(m_nOutlineLevel);
+
+ return Any(m_sOutlineText);
+}
+
+void SwXOutlineTarget::addPropertyChangeListener(
+ const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/)
+{
+}
+
+void SwXOutlineTarget::removePropertyChangeListener(
+ const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/)
+{
+}
+
+void SwXOutlineTarget::addVetoableChangeListener(
+ const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/)
+{
+}
+
+void SwXOutlineTarget::removeVetoableChangeListener(
+ const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/)
+{
+}
+
+OUString SwXOutlineTarget::getImplementationName()
+{
+ return "SwXOutlineTarget";
+}
+
+sal_Bool SwXOutlineTarget::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Sequence< OUString > SwXOutlineTarget::getSupportedServiceNames()
+{
+ Sequence<OUString> aRet { "com.sun.star.document.LinkTarget" };
+
+ return aRet;
+}
+
+SwXDrawingObjectTarget::SwXDrawingObjectTarget(OUString aDrawingObjectText) :
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)),
+ m_sDrawingObjectText(std::move(aDrawingObjectText))
+{
+}
+
+SwXDrawingObjectTarget::~SwXDrawingObjectTarget()
+{
+}
+
+Reference< XPropertySetInfo > SwXDrawingObjectTarget::getPropertySetInfo()
+{
+ static Reference< XPropertySetInfo > xRet = m_pPropSet->getPropertySetInfo();
+ return xRet;
+}
+
+void SwXDrawingObjectTarget::setPropertyValue(
+ const OUString& rPropertyName, const Any& /*aValue*/)
+{
+ throw UnknownPropertyException(rPropertyName);
+}
+
+Any SwXDrawingObjectTarget::getPropertyValue(const OUString& rPropertyName)
+{
+ if(rPropertyName != UNO_LINK_DISPLAY_NAME)
+ throw UnknownPropertyException(rPropertyName);
+
+ return Any(m_sDrawingObjectText);
+}
+
+void SwXDrawingObjectTarget::addPropertyChangeListener(
+ const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/)
+{
+}
+
+void SwXDrawingObjectTarget::removePropertyChangeListener(
+ const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/)
+{
+}
+
+void SwXDrawingObjectTarget::addVetoableChangeListener(
+ const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/)
+{
+}
+
+void SwXDrawingObjectTarget::removeVetoableChangeListener(
+ const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/)
+{
+}
+
+OUString SwXDrawingObjectTarget::getImplementationName()
+{
+ return "SwXDrawingObjectTarget";
+}
+
+sal_Bool SwXDrawingObjectTarget::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Sequence< OUString > SwXDrawingObjectTarget::getSupportedServiceNames()
+{
+ Sequence<OUString> aRet { "com.sun.star.document.LinkTarget" };
+
+ return aRet;
+}
+
+SwXDocumentPropertyHelper::SwXDocumentPropertyHelper(SwDoc& rDoc) :
+SvxUnoForbiddenCharsTable ( rDoc.getIDocumentSettingAccess().getForbiddenCharacterTable() )
+,m_pDoc(&rDoc)
+{
+}
+
+SwXDocumentPropertyHelper::~SwXDocumentPropertyHelper()
+{
+}
+
+Reference<XInterface> SwXDocumentPropertyHelper::GetDrawTable(SwCreateDrawTable nWhich)
+{
+ Reference<XInterface> xRet;
+ if(m_pDoc)
+ {
+ switch(nWhich)
+ {
+ // #i52858#
+ // assure that Draw model is created, if it doesn't exist.
+ case SwCreateDrawTable::Dash :
+ if(!m_xDashTable.is())
+ m_xDashTable = SvxUnoDashTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() );
+ xRet = m_xDashTable;
+ break;
+ case SwCreateDrawTable::Gradient :
+ if(!m_xGradientTable.is())
+ m_xGradientTable = SvxUnoGradientTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() );
+ xRet = m_xGradientTable;
+ break;
+ case SwCreateDrawTable::Hatch :
+ if(!m_xHatchTable.is())
+ m_xHatchTable = SvxUnoHatchTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() );
+ xRet = m_xHatchTable;
+ break;
+ case SwCreateDrawTable::Bitmap :
+ if(!m_xBitmapTable.is())
+ m_xBitmapTable = SvxUnoBitmapTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() );
+ xRet = m_xBitmapTable;
+ break;
+ case SwCreateDrawTable::TransGradient:
+ if(!m_xTransGradientTable.is())
+ m_xTransGradientTable = SvxUnoTransGradientTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() );
+ xRet = m_xTransGradientTable;
+ break;
+ case SwCreateDrawTable::Marker :
+ if(!m_xMarkerTable.is())
+ m_xMarkerTable = SvxUnoMarkerTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() );
+ xRet = m_xMarkerTable;
+ break;
+ case SwCreateDrawTable::Defaults:
+ if(!m_xDrawDefaults.is())
+ m_xDrawDefaults = cppu::getXWeak(new SwSvxUnoDrawPool(*m_pDoc));
+ xRet = m_xDrawDefaults;
+ break;
+#if OSL_DEBUG_LEVEL > 0
+ default: OSL_FAIL("which table?");
+#endif
+ }
+ }
+ return xRet;
+}
+
+void SwXDocumentPropertyHelper::Invalidate()
+{
+ m_xDashTable = nullptr;
+ m_xGradientTable = nullptr;
+ m_xHatchTable = nullptr;
+ m_xBitmapTable = nullptr;
+ m_xTransGradientTable = nullptr;
+ m_xMarkerTable = nullptr;
+ m_xDrawDefaults = nullptr;
+ m_pDoc = nullptr;
+ SvxUnoForbiddenCharsTable::mxForbiddenChars.reset();
+}
+
+void SwXDocumentPropertyHelper::onChange()
+{
+ if(m_pDoc)
+ m_pDoc->getIDocumentState().SetModified();
+}
+
+SwViewOptionAdjust_Impl::SwViewOptionAdjust_Impl(
+ SwViewShell& rSh, const SwViewOption &rViewOptions)
+ : m_pShell(&rSh)
+ , m_aOldViewOptions( rViewOptions )
+{
+}
+
+SwViewOptionAdjust_Impl::~SwViewOptionAdjust_Impl()
+{
+ if (m_pShell)
+ {
+ m_pShell->ApplyViewOptions( m_aOldViewOptions );
+ }
+}
+
+void
+SwViewOptionAdjust_Impl::AdjustViewOptions(SwPrintData const*const pPrtOptions, bool setShowPlaceHoldersInPDF)
+{
+ // to avoid unnecessary reformatting the view options related to the content
+ // below should only change if necessary, that is if respective content is present
+ const bool bContainsHiddenChars = m_pShell->GetDoc()->ContainsHiddenChars();
+ const SwFieldType* pFieldType = m_pShell->GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::HiddenText );
+ const bool bContainsHiddenFields = pFieldType && pFieldType->HasWriterListeners();
+ pFieldType = m_pShell->GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::HiddenPara );
+ const bool bContainsHiddenParagraphs = pFieldType && pFieldType->HasWriterListeners();
+ pFieldType = m_pShell->GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::JumpEdit );
+ const bool bContainsPlaceHolders = pFieldType && pFieldType->HasWriterListeners();
+ const bool bContainsFields = m_pShell->IsAnyFieldInDoc();
+
+ SwViewOption aRenderViewOptions( m_aOldViewOptions );
+
+ // disable anything in the view that should not be printed (or exported to PDF) by default
+ // (see also dialog "Tools/Options - StarOffice Writer - Formatting Aids"
+ // in section "Display of ...")
+ aRenderViewOptions.SetParagraph( false ); // paragraph end
+ aRenderViewOptions.SetSoftHyph( false ); // aka custom hyphens
+ aRenderViewOptions.SetBlank( false ); // spaces
+ aRenderViewOptions.SetHardBlank( false ); // non-breaking spaces
+ aRenderViewOptions.SetTab( false ); // tabs
+ aRenderViewOptions.SetShowBookmarks( false ); // bookmarks
+ aRenderViewOptions.SetLineBreak( false ); // breaks (type 1)
+ aRenderViewOptions.SetPageBreak( false ); // breaks (type 2)
+ aRenderViewOptions.SetColumnBreak( false ); // breaks (type 3)
+ bool bVal = pPrtOptions && pPrtOptions->m_bPrintHiddenText;
+ if (bContainsHiddenChars)
+ aRenderViewOptions.SetShowHiddenChar( bVal ); // hidden text
+ if (bContainsHiddenFields)
+ aRenderViewOptions.SetShowHiddenField( bVal );
+ if (bContainsHiddenParagraphs)
+ aRenderViewOptions.SetShowHiddenPara( bVal );
+
+ if (bContainsPlaceHolders)
+ {
+ // should always be printed in PDF export!
+ bVal = !pPrtOptions ? setShowPlaceHoldersInPDF : pPrtOptions->m_bPrintTextPlaceholder;
+ aRenderViewOptions.SetShowPlaceHolderFields( bVal );
+ }
+
+ if (bContainsFields)
+ aRenderViewOptions.SetFieldName( false );
+
+ // we need to set this flag in order to get to see the visible effect of
+ // some of the above settings (needed for correct rendering)
+ aRenderViewOptions.SetViewMetaChars( true );
+
+ if (m_aOldViewOptions != aRenderViewOptions) // check if reformatting is necessary
+ {
+ aRenderViewOptions.SetPrinting( pPrtOptions != nullptr );
+ m_pShell->ApplyViewOptions( aRenderViewOptions );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uno/unotxvw.cxx b/sw/source/uibase/uno/unotxvw.cxx
new file mode 100644
index 0000000000..43f2c7a62c
--- /dev/null
+++ b/sw/source/uibase/uno/unotxvw.cxx
@@ -0,0 +1,1707 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <viscrs.hxx>
+#include <o3tl/any.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <cmdid.h>
+#include <docsh.hxx>
+#include <rubylist.hxx>
+#include <doc.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <unotxvw.hxx>
+#include <unodispatch.hxx>
+#include <unomap.hxx>
+#include <unoprnms.hxx>
+#include <view.hxx>
+#include <viewopt.hxx>
+#include <unomod.hxx>
+#include <unoframe.hxx>
+#include <unocrsr.hxx>
+#include <wrtsh.hxx>
+#include <unotbl.hxx>
+#include <svx/fmshell.hxx>
+#include <svx/svdview.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdouno.hxx>
+#include <editeng/pbinitem.hxx>
+#include <pagedesc.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/request.hxx>
+#include <frmatr.hxx>
+#include <IMark.hxx>
+#include <unodraw.hxx>
+#include <svx/svdpagv.hxx>
+#include <ndtxt.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/drawing/ShapeCollection.hpp>
+#include <editeng/outliner.hxx>
+#include <editeng/editview.hxx>
+#include <unoparagraph.hxx>
+#include <unocrsrhelper.hxx>
+#include <unotextrange.hxx>
+#include <sfx2/docfile.hxx>
+#include <swdtflvr.hxx>
+#include <rootfrm.hxx>
+#include <edtwin.hxx>
+#include <vcl/svapp.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/profilezone.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <tools/UnitConversion.hxx>
+#include <comphelper/dumpxmltostring.hxx>
+#include <fmtanchr.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::view;
+using namespace ::com::sun::star::frame;
+
+using ::com::sun::star::util::URL;
+
+SwXTextView::SwXTextView(SwView* pSwView) :
+ SwXTextView_Base(pSwView),
+ m_SelChangedListeners(m_aMutex),
+ m_pView(pSwView),
+ m_pPropSet( aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_VIEW ) )
+{
+
+}
+
+SwXTextView::~SwXTextView()
+{
+ Invalidate();
+}
+
+void SwXTextView::Invalidate()
+{
+ if(mxViewSettings.is())
+ {
+ mxViewSettings->Invalidate();
+ mxViewSettings.clear();
+ }
+ if(mxTextViewCursor.is())
+ {
+ mxTextViewCursor->Invalidate();
+ mxTextViewCursor.clear();
+ }
+
+ osl_atomic_increment(&m_refCount); //prevent second d'tor call
+
+ {
+ uno::Reference<uno::XInterface> const xInt(static_cast<
+ cppu::OWeakObject*>(static_cast<SfxBaseController*>(this)));
+ lang::EventObject aEvent(xInt);
+ m_SelChangedListeners.disposeAndClear(aEvent);
+ }
+
+ osl_atomic_decrement(&m_refCount);
+ m_pView = nullptr;
+}
+
+sal_Bool SwXTextView::select(const uno::Any& aInterface)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference< uno::XInterface > xInterface;
+ if (!GetView() || !(aInterface >>= xInterface))
+ {
+ return false;
+ }
+
+ SwWrtShell& rSh = GetView()->GetWrtShell();
+ SwDoc* pDoc = GetView()->GetDocShell()->GetDoc();
+ std::vector<SdrObject *> sdrObjects;
+ uno::Reference<awt::XControlModel> const xCtrlModel(xInterface,
+ UNO_QUERY);
+ if (xCtrlModel.is())
+ {
+ uno::Reference<awt::XControl> xControl;
+ SdrObject *const pSdrObject = GetControl(xCtrlModel, xControl);
+ if (pSdrObject) // hmm... needs view to verify it's in right doc...
+ {
+ sdrObjects.push_back(pSdrObject);
+ }
+ }
+ else
+ {
+ SwPaM * pPaM(nullptr);
+ std::pair<OUString, FlyCntType> frame;
+ OUString tableName;
+ SwUnoTableCursor const* pTableCursor(nullptr);
+ ::sw::mark::IMark const* pMark(nullptr);
+ SwUnoCursorHelper::GetSelectableFromAny(xInterface, *pDoc,
+ pPaM, frame, tableName, pTableCursor, pMark, sdrObjects);
+ if (pPaM)
+ {
+ rSh.EnterStdMode();
+ rSh.SetSelection(*pPaM);
+ // the pPaM has been copied - delete it
+ while (pPaM->GetNext() != pPaM)
+ {
+ // coverity[deref_arg] - the SwPaM delete moves a new entry into GetNext()
+ delete pPaM->GetNext();
+ }
+ delete pPaM;
+ return true;
+ }
+ else if (!frame.first.isEmpty())
+ {
+ bool const bSuccess(rSh.GotoFly(frame.first, frame.second));
+ if (bSuccess)
+ {
+ rSh.HideCursor();
+ rSh.EnterSelFrameMode();
+ }
+ return true;
+ }
+ else if (!tableName.isEmpty())
+ {
+ rSh.EnterStdMode();
+ rSh.GotoTable(tableName);
+ return true;
+ }
+ else if (pTableCursor)
+ {
+ UnoActionRemoveContext const aContext(*pTableCursor);
+ rSh.EnterStdMode();
+ rSh.SetSelection(*pTableCursor);
+ return true;
+ }
+ else if (pMark)
+ {
+ rSh.EnterStdMode();
+ rSh.GotoMark(pMark);
+ return true;
+ }
+ // sdrObjects handled below
+ }
+ bool bRet(false);
+ if (!sdrObjects.empty())
+ {
+
+ SdrView *const pDrawView = rSh.GetDrawView();
+ SdrPageView *const pPV = pDrawView->GetSdrPageView();
+
+ pDrawView->SdrEndTextEdit();
+ pDrawView->UnmarkAll();
+
+ for (SdrObject* pSdrObject : sdrObjects)
+ {
+ // GetSelectableFromAny did not check pSdrObject is in right doc!
+ if (pPV && pSdrObject->getSdrPageFromSdrObject() == pPV->GetPage())
+ {
+ pDrawView->MarkObj(pSdrObject, pPV);
+ bRet = true;
+ }
+ }
+
+ // tdf#112696 if we selected every individual element of a group, then
+ // select that group instead
+ const SdrMarkList &rMrkList = pDrawView->GetMarkedObjectList();
+ size_t nMarkCount = rMrkList.GetMarkCount();
+ if (nMarkCount > 1)
+ {
+ SdrObject* pObject = rMrkList.GetMark(0)->GetMarkedSdrObj();
+ SdrObject* pGroupParent = pObject->getParentSdrObjectFromSdrObject();
+ for (size_t i = 1; i < nMarkCount; ++i)
+ {
+ pObject = rMrkList.GetMark(i)->GetMarkedSdrObj();
+ SdrObject* pParent = pObject->getParentSdrObjectFromSdrObject();
+ if (pParent != pGroupParent)
+ {
+ pGroupParent = nullptr;
+ break;
+ }
+ }
+
+ if (pGroupParent && pGroupParent->IsGroupObject() &&
+ pGroupParent->getChildrenOfSdrObject()->GetObjCount() == nMarkCount)
+ {
+ pDrawView->UnmarkAll();
+ pDrawView->MarkObj(pGroupParent, pPV);
+ }
+ }
+ }
+ return bRet;
+}
+
+uno::Any SwXTextView::getSelection()
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< uno::XInterface > aRef;
+ if(GetView())
+ {
+ //force immediat shell update
+ m_pView->StopShellTimer();
+ //Generating an interface from the current selection.
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ ShellMode eSelMode = m_pView->GetShellMode();
+ switch(eSelMode)
+ {
+ case ShellMode::TableText :
+ {
+ if(rSh.GetTableCursor())
+ {
+ OSL_ENSURE(rSh.GetTableFormat(), "not a table format?");
+ uno::Reference< text::XTextTableCursor > xCursor = new SwXTextTableCursor(*rSh.GetTableFormat(),
+ rSh.GetTableCursor());
+ aRef.set(xCursor, uno::UNO_QUERY);
+ break;
+ }
+ [[fallthrough]];
+ // without a table selection the text will be delivered
+ }
+ case ShellMode::ListText :
+ case ShellMode::TableListText:
+ case ShellMode::Text :
+ {
+ uno::Reference< container::XIndexAccess > xPos = SwXTextRanges::Create(rSh.GetCursor());
+ aRef.set(xPos, uno::UNO_QUERY);
+ }
+ break;
+ case ShellMode::Frame :
+ {
+ SwFrameFormat *const pFormat = rSh.GetFlyFrameFormat();
+ if (pFormat)
+ {
+ aRef = cppu::getXWeak(SwXTextFrame::CreateXTextFrame(
+ *pFormat->GetDoc(), pFormat).get());
+ }
+ }
+ break;
+ case ShellMode::Graphic :
+ {
+ SwFrameFormat *const pFormat = rSh.GetFlyFrameFormat();
+ if (pFormat)
+ {
+ aRef = cppu::getXWeak(SwXTextGraphicObject::CreateXTextGraphicObject(
+ *pFormat->GetDoc(), pFormat).get());
+ }
+ }
+ break;
+ case ShellMode::Object :
+ {
+ SwFrameFormat *const pFormat = rSh.GetFlyFrameFormat();
+ if (pFormat)
+ {
+ aRef = cppu::getXWeak(SwXTextEmbeddedObject::CreateXTextEmbeddedObject(
+ *pFormat->GetDoc(), pFormat).get());
+ }
+ }
+ break;
+ case ShellMode::Draw :
+ case ShellMode::DrawForm :
+ case ShellMode::DrawText :
+ case ShellMode::Bezier :
+ {
+ uno::Reference< drawing::XShapes > xShCol = drawing::ShapeCollection::create(
+ comphelper::getProcessComponentContext());
+
+ const SdrMarkList& rMarkList = rSh.GetDrawView()->GetMarkedObjectList();
+ for(size_t i = 0; i < rMarkList.GetMarkCount(); ++i)
+ {
+ SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
+ uno::Reference<drawing::XShape> xShape = SwFmDrawPage::GetShape( pObj );
+ xShCol->add(xShape);
+ }
+ aRef.set(xShCol, uno::UNO_QUERY);
+ }
+ break;
+ default:;//prevent warning
+ }
+ }
+ uno::Any aRet(&aRef, cppu::UnoType<uno::XInterface>::get());
+ return aRet;
+}
+
+void SwXTextView::addSelectionChangeListener(
+ const uno::Reference< view::XSelectionChangeListener > & rxListener)
+{
+ SolarMutexGuard aGuard;
+ m_SelChangedListeners.addInterface(rxListener);
+}
+
+void SwXTextView::removeSelectionChangeListener(
+ const uno::Reference< view::XSelectionChangeListener > & rxListener)
+{
+ SolarMutexGuard aGuard;
+ m_SelChangedListeners.removeInterface(rxListener);
+}
+
+SdrObject* SwXTextView::GetControl(
+ const uno::Reference< awt::XControlModel > & xModel,
+ uno::Reference< awt::XControl >& xToFill )
+{
+ SwView* pView2 = GetView();
+ FmFormShell* pFormShell = pView2 ? pView2->GetFormShell() : nullptr;
+ SdrView* pDrawView = pView2 ? pView2->GetDrawView() : nullptr;
+ vcl::Window* pWindow = pView2 ? pView2->GetWrtShell().GetWin() : nullptr;
+
+ OSL_ENSURE( pFormShell && pDrawView && pWindow, "SwXTextView::GetControl: how could I?" );
+
+ SdrObject* pControl = nullptr;
+ if ( pFormShell && pDrawView && pWindow )
+ pControl = pFormShell->GetFormControl( xModel, *pDrawView, *pWindow->GetOutDev(), xToFill );
+ return pControl;
+}
+
+uno::Reference< awt::XControl > SwXTextView::getControl(const uno::Reference< awt::XControlModel > & xModel)
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< awt::XControl > xRet;
+ GetControl(xModel, xRet);
+ return xRet;
+}
+
+uno::Reference< form::runtime::XFormController > SAL_CALL SwXTextView::getFormController( const uno::Reference< form::XForm >& Form )
+{
+ SolarMutexGuard aGuard;
+
+ SwView* pView2 = GetView();
+ FmFormShell* pFormShell = pView2 ? pView2->GetFormShell() : nullptr;
+ SdrView* pDrawView = pView2 ? pView2->GetDrawView() : nullptr;
+ vcl::Window* pWindow = pView2 ? pView2->GetWrtShell().GetWin() : nullptr;
+ OSL_ENSURE( pFormShell && pDrawView && pWindow, "SwXTextView::getFormController: how could I?" );
+
+ uno::Reference< form::runtime::XFormController > xController;
+ if ( pFormShell && pDrawView && pWindow )
+ xController = FmFormShell::GetFormController( Form, *pDrawView, *pWindow->GetOutDev() );
+ return xController;
+}
+
+sal_Bool SAL_CALL SwXTextView::isFormDesignMode( )
+{
+ SolarMutexGuard aGuard;
+ SwView* pView2 = GetView();
+ FmFormShell* pFormShell = pView2 ? pView2->GetFormShell() : nullptr;
+ return !pFormShell || pFormShell->IsDesignMode();
+}
+
+void SAL_CALL SwXTextView::setFormDesignMode( sal_Bool DesignMode )
+{
+ SolarMutexGuard aGuard;
+ SwView* pView2 = GetView();
+ FmFormShell* pFormShell = pView2 ? pView2->GetFormShell() : nullptr;
+ if ( pFormShell )
+ pFormShell->SetDesignMode( DesignMode );
+}
+
+uno::Reference< text::XTextViewCursor > SwXTextView::getViewCursor()
+{
+ SolarMutexGuard aGuard;
+ comphelper::ProfileZone aZone("getViewCursor");
+ if(!GetView())
+ throw uno::RuntimeException();
+
+ if(!mxTextViewCursor.is())
+ {
+ mxTextViewCursor = new SwXTextViewCursor(GetView());
+ }
+ return mxTextViewCursor;
+}
+
+uno::Reference<text::XTextRange>
+SwXTextView::createTextRangeByPixelPosition(const awt::Point& rPixelPosition)
+{
+ SolarMutexGuard aGuard;
+
+ Point aPixelPoint(rPixelPosition.X, rPixelPosition.Y);
+ if (!m_pView)
+ throw RuntimeException();
+
+ Point aLogicPoint = m_pView->GetEditWin().PixelToLogic(aPixelPoint);
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ SwPosition aPosition(*rSh.GetCurrentShellCursor().GetPoint());
+ rSh.GetLayout()->GetModelPositionForViewPoint(&aPosition, aLogicPoint);
+
+ if (aPosition.GetNode().IsGrfNode())
+ {
+ // The point is closest to a graphic node, look up its format.
+ const SwFrameFormat* pGraphicFormat = aPosition.GetNode().GetFlyFormat();
+ if (pGraphicFormat)
+ {
+ // Get the anchor of this format.
+ const SwFormatAnchor& rAnchor = pGraphicFormat->GetAnchor();
+ const SwPosition* pAnchor = rAnchor.GetContentAnchor();
+ if (pAnchor)
+ {
+ aPosition = *pAnchor;
+ }
+ else
+ {
+ // Page-anchored graphics have no anchor.
+ return {};
+ }
+ }
+ }
+
+ rtl::Reference<SwXTextRange> xRet
+ = SwXTextRange::CreateXTextRange(*rSh.GetDoc(), aPosition, /*pMark=*/nullptr);
+
+ return xRet;
+}
+
+uno::Reference< beans::XPropertySet > SwXTextView::getViewSettings()
+{
+ SolarMutexGuard aGuard;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ if(!mxViewSettings.is())
+ {
+ mxViewSettings = new SwXViewSettings( m_pView );
+ }
+
+ return mxViewSettings;
+}
+
+Sequence< Sequence< PropertyValue > > SwXTextView::getRubyList( sal_Bool /*bAutomatic*/ )
+{
+ SolarMutexGuard aGuard;
+
+ if(!GetView())
+ throw RuntimeException();
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ ShellMode eSelMode = m_pView->GetShellMode();
+ if (eSelMode != ShellMode::ListText &&
+ eSelMode != ShellMode::TableListText &&
+ eSelMode != ShellMode::TableText &&
+ eSelMode != ShellMode::Text )
+ return Sequence< Sequence< PropertyValue > > ();
+
+ SwRubyList aList;
+
+ const sal_uInt16 nCount = SwDoc::FillRubyList( *rSh.GetCursor(), aList );
+ Sequence< Sequence< PropertyValue > > aRet(nCount);
+ Sequence< PropertyValue >* pRet = aRet.getArray();
+ OUString aString;
+ for(sal_uInt16 n = 0; n < nCount; n++)
+ {
+ const SwRubyListEntry* pEntry = aList[n].get();
+
+ const OUString& rEntryText = pEntry->GetText();
+ const SwFormatRuby& rAttr = pEntry->GetRubyAttr();
+
+ pRet[n].realloc(6);
+ PropertyValue* pValues = pRet[n].getArray();
+ pValues[0].Name = UNO_NAME_RUBY_BASE_TEXT;
+ pValues[0].Value <<= rEntryText;
+ pValues[1].Name = UNO_NAME_RUBY_TEXT;
+ pValues[1].Value <<= rAttr.GetText();
+ pValues[2].Name = UNO_NAME_RUBY_CHAR_STYLE_NAME;
+ SwStyleNameMapper::FillProgName(rAttr.GetCharFormatName(), aString, SwGetPoolIdFromName::ChrFmt );
+ pValues[2].Value <<= aString;
+ pValues[3].Name = UNO_NAME_RUBY_ADJUST;
+ pValues[3].Value <<= static_cast<sal_Int16>(rAttr.GetAdjustment());
+ pValues[4].Name = UNO_NAME_RUBY_IS_ABOVE;
+ pValues[4].Value <<= !rAttr.GetPosition();
+ pValues[5].Name = UNO_NAME_RUBY_POSITION;
+ pValues[5].Value <<= rAttr.GetPosition();
+ }
+ return aRet;
+}
+
+void SAL_CALL SwXTextView::setRubyList(
+ const Sequence< Sequence< PropertyValue > >& rRubyList, sal_Bool /*bAutomatic*/ )
+{
+ SolarMutexGuard aGuard;
+
+ if(!GetView() || !rRubyList.hasElements())
+ throw RuntimeException();
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ ShellMode eSelMode = m_pView->GetShellMode();
+ if (eSelMode != ShellMode::ListText &&
+ eSelMode != ShellMode::TableListText &&
+ eSelMode != ShellMode::TableText &&
+ eSelMode != ShellMode::Text )
+ throw RuntimeException();
+
+ SwRubyList aList;
+
+ for(const Sequence<PropertyValue>& rPropList : rRubyList)
+ {
+ std::unique_ptr<SwRubyListEntry> pEntry(new SwRubyListEntry);
+ OUString sTmp;
+ for(const PropertyValue& rProperty : rPropList)
+ {
+ if(rProperty.Name == UNO_NAME_RUBY_BASE_TEXT)
+ {
+ rProperty.Value >>= sTmp;
+ pEntry->SetText(sTmp);
+ }
+ else if(rProperty.Name == UNO_NAME_RUBY_TEXT)
+ {
+ rProperty.Value >>= sTmp;
+ pEntry->GetRubyAttr().SetText(sTmp);
+ }
+ else if(rProperty.Name == UNO_NAME_RUBY_CHAR_STYLE_NAME)
+ {
+ if(rProperty.Value >>= sTmp)
+ {
+ OUString sName;
+ SwStyleNameMapper::FillUIName(sTmp, sName, SwGetPoolIdFromName::ChrFmt );
+ const sal_uInt16 nPoolId = sName.isEmpty() ? 0
+ : SwStyleNameMapper::GetPoolIdFromUIName(sName,
+ SwGetPoolIdFromName::ChrFmt );
+
+ pEntry->GetRubyAttr().SetCharFormatName( sName );
+ pEntry->GetRubyAttr().SetCharFormatId( nPoolId );
+ }
+ }
+ else if(rProperty.Name == UNO_NAME_RUBY_ADJUST)
+ {
+ sal_Int16 nTmp = 0;
+ if(rProperty.Value >>= nTmp)
+ pEntry->GetRubyAttr().SetAdjustment(static_cast<css::text::RubyAdjust>(nTmp));
+ }
+ else if(rProperty.Name == UNO_NAME_RUBY_IS_ABOVE)
+ {
+ bool bValue = !rProperty.Value.hasValue() ||
+ *o3tl::doAccess<bool>(rProperty.Value);
+ pEntry->GetRubyAttr().SetPosition(bValue ? 0 : 1);
+ }
+ else if(rProperty.Name == UNO_NAME_RUBY_POSITION)
+ {
+ sal_Int16 nTmp = 0;
+ if(rProperty.Value >>= nTmp)
+ pEntry->GetRubyAttr().SetPosition( nTmp );
+ }
+ }
+ aList.push_back(std::move(pEntry));
+ }
+ SwDoc* pDoc = m_pView->GetDocShell()->GetDoc();
+ pDoc->SetRubyList( *rSh.GetCursor(), aList );
+}
+
+SfxObjectShellLock SwXTextView::BuildTmpSelectionDoc()
+{
+ SwWrtShell& rOldSh = m_pView->GetWrtShell();
+ SfxPrinter *pPrt = rOldSh.getIDocumentDeviceAccess().getPrinter( false );
+ SwDocShell* pDocSh;
+ SfxObjectShellLock xDocSh( pDocSh = new SwDocShell(SfxObjectCreateMode::STANDARD) );
+ xDocSh->DoInitNew();
+ SwDoc *const pTempDoc( pDocSh->GetDoc() );
+ // #i103634#, #i112425#: do not expand numbering and fields on PDF export
+ pTempDoc->SetClipBoard(true);
+ rOldSh.FillPrtDoc(*pTempDoc, pPrt);
+ SfxViewFrame* pDocFrame = SfxViewFrame::LoadHiddenDocument( *xDocSh, SFX_INTERFACE_NONE );
+ SwView* pDocView = static_cast<SwView*>( pDocFrame->GetViewShell() );
+ pDocView->AttrChangedNotify(nullptr);//So that SelectShell is called.
+ if (SwWrtShell* pSh = pDocView->GetWrtShellPtr())
+ {
+ IDocumentDeviceAccess& rIDDA = pSh->getIDocumentDeviceAccess();
+ SfxPrinter* pTempPrinter = rIDDA.getPrinter( true );
+
+ const SwPageDesc& rCurPageDesc = rOldSh.GetPageDesc(rOldSh.GetCurPageDesc());
+
+ IDocumentDeviceAccess& rIDDA_old = rOldSh.getIDocumentDeviceAccess();
+
+ if( rIDDA_old.getPrinter( false ) )
+ {
+ rIDDA.setJobsetup( *rIDDA_old.getJobsetup() );
+ //#69563# if it isn't the same printer then the pointer has been invalidated!
+ pTempPrinter = rIDDA.getPrinter( true );
+ }
+
+ pTempPrinter->SetPaperBin(rCurPageDesc.GetMaster().GetPaperBin().GetValue());
+ }
+
+ return xDocSh;
+}
+
+void SwXTextView::NotifySelChanged()
+{
+ OSL_ENSURE( m_pView, "view is missing" );
+
+ lang::EventObject const aEvent(getXWeak());
+ m_SelChangedListeners.notifyEach(
+ &view::XSelectionChangeListener::selectionChanged, aEvent);
+}
+
+void SwXTextView::NotifyDBChanged()
+{
+ URL aURL;
+ aURL.Complete = OUString::createFromAscii(SwXDispatch::GetDBChangeURL());
+
+ m_SelChangedListeners.forEach(
+ [&aURL] (const uno::Reference<XSelectionChangeListener>& xListener)
+ {
+ uno::Reference<XDispatch> xDispatch(xListener, UNO_QUERY);
+ if (xDispatch)
+ xDispatch->dispatch(aURL, {});
+ });
+}
+
+uno::Reference< beans::XPropertySetInfo > SAL_CALL SwXTextView::getPropertySetInfo( )
+{
+ SolarMutexGuard aGuard;
+ static uno::Reference< XPropertySetInfo > aRef = m_pPropSet->getPropertySetInfo();
+ return aRef;
+}
+
+void SAL_CALL SwXTextView::setPropertyValue(
+ const OUString& rPropertyName, const uno::Any& rValue )
+{
+ SolarMutexGuard aGuard;
+ const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
+ if (!pEntry)
+ throw UnknownPropertyException(rPropertyName);
+ else if (pEntry->nFlags & PropertyAttribute::READONLY)
+ throw PropertyVetoException();
+ else
+ {
+ switch (pEntry->nWID)
+ {
+ case WID_IS_HIDE_SPELL_MARKS :
+ // deprecated #i91949
+ break;
+ case WID_IS_CONSTANT_SPELLCHECK :
+ {
+ bool bVal = false;
+ const SwViewOption *pOpt = m_pView->GetWrtShell().GetViewOptions();
+ if (!pOpt || !(rValue >>= bVal))
+ throw RuntimeException();
+ SwViewOption aNewOpt( *pOpt );
+ if (pEntry->nWID == WID_IS_CONSTANT_SPELLCHECK)
+ aNewOpt.SetOnlineSpell(bVal);
+ m_pView->GetWrtShell().ApplyViewOptions( aNewOpt );
+ }
+ break;
+ default :
+ OSL_FAIL("unknown WID");
+ }
+ }
+}
+
+uno::Any SAL_CALL SwXTextView::getPropertyValue(
+ const OUString& rPropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ Any aRet;
+
+ const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
+ if (!pEntry)
+ throw UnknownPropertyException(rPropertyName);
+
+ sal_Int16 nWID = pEntry->nWID;
+ switch (nWID)
+ {
+ case WID_PAGE_COUNT :
+ case WID_LINE_COUNT :
+ {
+ // format document completely in order to get meaningful
+ // values for page count and line count
+ m_pView->GetWrtShell().CalcLayout();
+
+ sal_Int32 nCount = -1;
+ if (nWID == WID_PAGE_COUNT)
+ nCount = m_pView->GetWrtShell().GetPageCount();
+ else // WID_LINE_COUNT
+ nCount = m_pView->GetWrtShell().GetLineCount();
+ aRet <<= nCount;
+ }
+ break;
+ case WID_IS_HIDE_SPELL_MARKS :
+ // deprecated #i91949
+ break;
+ case WID_IS_CONSTANT_SPELLCHECK :
+ {
+ const SwViewOption *pOpt = m_pView->GetWrtShell().GetViewOptions();
+ if (!pOpt)
+ throw RuntimeException();
+ aRet <<= pOpt->IsOnlineSpell();
+ }
+ break;
+ default :
+ OSL_FAIL("unknown WID");
+ }
+
+ return aRet;
+}
+
+void SAL_CALL SwXTextView::addPropertyChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*rxListener*/ )
+{
+ OSL_FAIL("not implemented");
+}
+
+void SAL_CALL SwXTextView::removePropertyChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*rxListener*/ )
+{
+ OSL_FAIL("not implemented");
+}
+
+void SAL_CALL SwXTextView::addVetoableChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*rxListener*/ )
+{
+ OSL_FAIL("not implemented");
+}
+
+void SAL_CALL SwXTextView::removeVetoableChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*rxListener*/ )
+{
+ OSL_FAIL("not implemented");
+}
+
+OUString SwXTextView::getImplementationName()
+{
+ return "SwXTextView";
+}
+
+sal_Bool SwXTextView::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence< OUString > SwXTextView::getSupportedServiceNames()
+{
+ return { "com.sun.star.text.TextDocumentView", "com.sun.star.view.OfficeDocumentView" };
+}
+
+SwXTextViewCursor::SwXTextViewCursor(SwView* pVw) :
+ m_pView(pVw),
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR))
+{
+}
+
+SwXTextViewCursor::~SwXTextViewCursor()
+{
+}
+
+// used to determine if there is a text selection or not.
+// If there is no text selection the functions that need a working
+// cursor will be disabled (throw RuntimeException). This will be the case
+// for the following interfaces:
+// - XViewCursor
+// - XTextCursor
+// - XTextRange
+// - XLineCursor
+bool SwXTextViewCursor::IsTextSelection( bool bAllowTables ) const
+{
+
+ bool bRes = false;
+ OSL_ENSURE(m_pView, "m_pView is NULL ???");
+ if(m_pView)
+ {
+ //! m_pView->GetShellMode() will only work after the shell
+ //! has already changed and thus can not be used here!
+ SelectionType eSelType = m_pView->GetWrtShell().GetSelectionType();
+ bRes = ( (SelectionType::Text & eSelType) ||
+ (SelectionType::NumberList & eSelType) ) &&
+ (!(SelectionType::TableCell & eSelType) || bAllowTables);
+ }
+ return bRes;
+}
+
+sal_Bool SwXTextViewCursor::isVisible()
+{
+ OSL_FAIL("not implemented");
+ return true;
+}
+
+void SwXTextViewCursor::setVisible(sal_Bool /*bVisible*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+awt::Point SwXTextViewCursor::getPosition()
+{
+ SolarMutexGuard aGuard;
+ awt::Point aRet;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ const SwWrtShell& rSh = m_pView->GetWrtShell();
+ const SwRect& aCharRect(rSh.GetCharRect());
+
+ const SwFrameFormat& rMaster = rSh.GetPageDesc( rSh.GetCurPageDesc() ).GetMaster();
+
+ const SvxULSpaceItem& rUL = rMaster.GetULSpace();
+ const tools::Long nY = aCharRect.Top() - (rUL.GetUpper() + DOCUMENTBORDER);
+ aRet.Y = convertTwipToMm100(nY);
+
+ const SvxLRSpaceItem& rLR = rMaster.GetLRSpace();
+ const tools::Long nX = aCharRect.Left() - (rLR.GetLeft() + DOCUMENTBORDER);
+ aRet.X = convertTwipToMm100(nX);
+
+ return aRet;
+}
+
+void SwXTextViewCursor::collapseToStart()
+{
+ SolarMutexGuard aGuard;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ if (!IsTextSelection())
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ if(rSh.HasSelection())
+ {
+ SwPaM* pShellCursor = rSh.GetCursor();
+ if(*pShellCursor->GetPoint() > *pShellCursor->GetMark())
+ pShellCursor->Exchange();
+ pShellCursor->DeleteMark();
+ rSh.EnterStdMode();
+ rSh.SetSelection(*pShellCursor);
+ }
+
+}
+
+void SwXTextViewCursor::collapseToEnd()
+{
+ SolarMutexGuard aGuard;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ if (!IsTextSelection())
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ if(rSh.HasSelection())
+ {
+ SwPaM* pShellCursor = rSh.GetCursor();
+ if(*pShellCursor->GetPoint() < *pShellCursor->GetMark())
+ pShellCursor->Exchange();
+ pShellCursor->DeleteMark();
+ rSh.EnterStdMode();
+ rSh.SetSelection(*pShellCursor);
+ }
+
+}
+
+sal_Bool SwXTextViewCursor::isCollapsed()
+{
+ SolarMutexGuard aGuard;
+ bool bRet = false;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ if (!IsTextSelection())
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ const SwWrtShell& rSh = m_pView->GetWrtShell();
+ bRet = !rSh.HasSelection();
+
+ return bRet;
+
+}
+
+sal_Bool SwXTextViewCursor::goLeft(sal_Int16 nCount, sal_Bool bExpand)
+{
+ SolarMutexGuard aGuard;
+ bool bRet = false;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ if (!IsTextSelection())
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ bRet = m_pView->GetWrtShell().Left( SwCursorSkipMode::Chars, bExpand, nCount, true );
+
+ return bRet;
+}
+
+sal_Bool SwXTextViewCursor::goRight(sal_Int16 nCount, sal_Bool bExpand)
+{
+ SolarMutexGuard aGuard;
+ bool bRet = false;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ if (!IsTextSelection())
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ bRet = m_pView->GetWrtShell().Right( SwCursorSkipMode::Chars, bExpand, nCount, true );
+
+ return bRet;
+
+}
+
+void SwXTextViewCursor::gotoRange(
+ const uno::Reference< text::XTextRange > & xRange,
+ sal_Bool bExpand)
+{
+ SolarMutexGuard aGuard;
+ if(!(m_pView && xRange.is()))
+ throw uno::RuntimeException();
+
+ if (!IsTextSelection())
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ SwUnoInternalPaM rDestPam(*m_pView->GetDocShell()->GetDoc());
+ if (!::sw::XTextRangeToSwPaM(rDestPam, xRange))
+ {
+ throw uno::RuntimeException();
+ }
+
+ ShellMode eSelMode = m_pView->GetShellMode();
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ // call EnterStdMode in non-text selections only
+ if(!bExpand ||
+ (eSelMode != ShellMode::TableText &&
+ eSelMode != ShellMode::ListText &&
+ eSelMode != ShellMode::TableListText &&
+ eSelMode != ShellMode::Text ))
+ rSh.EnterStdMode();
+ SwPaM* pShellCursor = rSh.GetCursor();
+ SwPaM aOwnPaM(*pShellCursor->GetPoint());
+ if(pShellCursor->HasMark())
+ {
+ aOwnPaM.SetMark();
+ *aOwnPaM.GetMark() = *pShellCursor->GetMark();
+ }
+
+ SwXTextRange* pRange = dynamic_cast<SwXTextRange*>(xRange.get());
+ SwXParagraph* pPara = dynamic_cast<SwXParagraph*>(xRange.get());
+ OTextCursorHelper* pCursor = dynamic_cast<OTextCursorHelper*>(xRange.get());
+
+ const FrameTypeFlags nFrameType = rSh.GetFrameType(nullptr,true);
+
+ SwStartNodeType eSearchNodeType = SwNormalStartNode;
+ if(nFrameType & FrameTypeFlags::FLY_ANY)
+ eSearchNodeType = SwFlyStartNode;
+ else if(nFrameType &FrameTypeFlags::HEADER)
+ eSearchNodeType = SwHeaderStartNode;
+ else if(nFrameType & FrameTypeFlags::FOOTER)
+ eSearchNodeType = SwFooterStartNode;
+ else if(nFrameType & FrameTypeFlags::TABLE)
+ eSearchNodeType = SwTableBoxStartNode;
+ else if(nFrameType & FrameTypeFlags::FOOTNOTE)
+ eSearchNodeType = SwFootnoteStartNode;
+
+ const SwStartNode* pOwnStartNode = aOwnPaM.GetPointNode().
+ FindSttNodeByType(eSearchNodeType);
+
+ const SwNode* pSrcNode = nullptr;
+ if(pCursor && pCursor->GetPaM())
+ {
+ pSrcNode = &pCursor->GetPaM()->GetPointNode();
+ }
+ else if (pRange)
+ {
+ SwPaM aPam(pRange->GetDoc().GetNodes());
+ if (pRange->GetPositions(aPam))
+ {
+ pSrcNode = &aPam.GetPointNode();
+ }
+ }
+ else if (pPara && pPara->GetTextNode())
+ {
+ pSrcNode = pPara->GetTextNode();
+ }
+ const SwStartNode* pTmp = pSrcNode ? pSrcNode->FindSttNodeByType(eSearchNodeType) : nullptr;
+
+ //Skip SectionNodes
+ while(pTmp && pTmp->IsSectionNode())
+ {
+ pTmp = pTmp->StartOfSectionNode();
+ }
+ while(pOwnStartNode && pOwnStartNode->IsSectionNode())
+ {
+ pOwnStartNode = pOwnStartNode->StartOfSectionNode();
+ }
+ //Without Expand it is allowed to jump out with the ViewCursor everywhere,
+ //with Expand only in the same environment
+ if(bExpand &&
+ (pOwnStartNode != pTmp ||
+ (eSelMode != ShellMode::TableText &&
+ eSelMode != ShellMode::ListText &&
+ eSelMode != ShellMode::TableListText &&
+ eSelMode != ShellMode::Text)))
+ throw uno::RuntimeException();
+
+ //Now, the selection must be expanded.
+ if(bExpand)
+ {
+ // The cursor should include everything that has been included
+ // by him and the transferred Range.
+ SwPosition aOwnLeft(*aOwnPaM.Start());
+ SwPosition aOwnRight(*aOwnPaM.End());
+ auto [pParamLeft, pParamRight] = rDestPam.StartEnd(); // SwPosition*
+ // Now four SwPositions are there, two of them are needed, but which?
+ if(aOwnRight > *pParamRight)
+ *aOwnPaM.GetPoint() = aOwnRight;
+ else
+ *aOwnPaM.GetPoint() = *pParamRight;
+ aOwnPaM.SetMark();
+ if(aOwnLeft < *pParamLeft)
+ *aOwnPaM.GetMark() = aOwnLeft;
+ else
+ *aOwnPaM.GetMark() = *pParamLeft;
+ }
+ else
+ {
+ //The cursor shall match the passed range.
+ *aOwnPaM.GetPoint() = *rDestPam.GetPoint();
+ if(rDestPam.HasMark())
+ {
+ aOwnPaM.SetMark();
+ *aOwnPaM.GetMark() = *rDestPam.GetMark();
+ }
+ else
+ aOwnPaM.DeleteMark();
+ }
+ rSh.SetSelection(aOwnPaM);
+
+
+}
+
+void SwXTextViewCursor::gotoStart(sal_Bool bExpand)
+{
+ SolarMutexGuard aGuard;
+ comphelper::ProfileZone aZone("SwXTextViewCursor::gotoStart");
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ if (!IsTextSelection())
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ m_pView->GetWrtShell().StartOfSection( bExpand );
+
+}
+
+void SwXTextViewCursor::gotoEnd(sal_Bool bExpand)
+{
+ SolarMutexGuard aGuard;
+ comphelper::ProfileZone aZone("SwXTextViewCursor::gotoEnd");
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ if (!IsTextSelection())
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ m_pView->GetWrtShell().EndOfSection( bExpand );
+
+}
+
+sal_Bool SwXTextViewCursor::jumpToFirstPage()
+{
+ SolarMutexGuard aGuard;
+ bool bRet = false;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ if (rSh.IsSelFrameMode())
+ {
+ rSh.UnSelectFrame();
+ rSh.LeaveSelFrameMode();
+ }
+ rSh.EnterStdMode();
+ bRet = rSh.SttEndDoc(true);
+
+ return bRet;
+}
+
+sal_Bool SwXTextViewCursor::jumpToLastPage()
+{
+ SolarMutexGuard aGuard;
+ bool bRet = false;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ if (rSh.IsSelFrameMode())
+ {
+ rSh.UnSelectFrame();
+ rSh.LeaveSelFrameMode();
+ }
+ rSh.EnterStdMode();
+ bRet = rSh.SttEndDoc(false);
+ rSh.SttPg();
+
+ return bRet;
+}
+
+sal_Bool SwXTextViewCursor::jumpToPage(sal_Int16 nPage)
+{
+ SolarMutexGuard aGuard;
+ bool bRet = false;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ bRet = m_pView->GetWrtShell().GotoPage(nPage, true);
+
+ return bRet;
+}
+
+sal_Bool SwXTextViewCursor::jumpToNextPage()
+{
+ SolarMutexGuard aGuard;
+ bool bRet = false;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ bRet = m_pView->GetWrtShell().SttNxtPg();
+
+ return bRet;
+}
+
+sal_Bool SwXTextViewCursor::jumpToPreviousPage()
+{
+ SolarMutexGuard aGuard;
+ bool bRet = false;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ bRet = m_pView->GetWrtShell().EndPrvPg();
+
+ return bRet;
+}
+
+sal_Bool SwXTextViewCursor::jumpToEndOfPage()
+{
+ SolarMutexGuard aGuard;
+ bool bRet = false;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ bRet = m_pView->GetWrtShell().EndPg();
+
+ return bRet;
+}
+
+sal_Bool SwXTextViewCursor::jumpToStartOfPage()
+{
+ SolarMutexGuard aGuard;
+ bool bRet = false;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ bRet = m_pView->GetWrtShell().SttPg();
+
+ return bRet;
+}
+
+sal_Int16 SwXTextViewCursor::getPage()
+{
+ SolarMutexGuard aGuard;
+ sal_Int16 nRet = 0;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ SwPaM* pShellCursor = rSh.GetCursor();
+ nRet = static_cast<sal_Int16>(pShellCursor->GetPageNum());
+
+ return nRet;
+}
+
+sal_Bool SwXTextViewCursor::screenDown()
+{
+ SolarMutexGuard aGuard;
+ bool bRet = false;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ SfxRequest aReq(FN_PAGEDOWN, SfxCallMode::SLOT, m_pView->GetPool());
+ m_pView->Execute(aReq);
+ const SfxPoolItemHolder& rResult(aReq.GetReturnValue());
+ bRet = nullptr != rResult.getItem() && static_cast<const SfxBoolItem*>(rResult.getItem())->GetValue();
+
+ return bRet;
+}
+
+sal_Bool SwXTextViewCursor::screenUp()
+{
+ SolarMutexGuard aGuard;
+ bool bRet = false;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ SfxRequest aReq(FN_PAGEUP, SfxCallMode::SLOT, m_pView->GetPool());
+ m_pView->Execute(aReq);
+ const SfxPoolItemHolder& rResult(aReq.GetReturnValue());
+ bRet = nullptr != rResult.getItem() && static_cast<const SfxBoolItem*>(rResult.getItem())->GetValue();
+
+ return bRet;
+}
+
+uno::Reference< text::XText > SwXTextViewCursor::getText()
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XText > xRet;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ if (!IsTextSelection( false ))
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ SwPaM* pShellCursor = rSh.GetCursor();
+ SwDoc* pDoc = m_pView->GetDocShell()->GetDoc();
+ xRet = ::sw::CreateParentXText(*pDoc, *pShellCursor->Start());
+
+ return xRet;
+}
+
+uno::Reference< text::XTextRange > SwXTextViewCursor::getStart()
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XTextRange > xRet;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ if (!IsTextSelection())
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ SwPaM* pShellCursor = rSh.GetCursor();
+ SwDoc* pDoc = m_pView->GetDocShell()->GetDoc();
+ xRet = SwXTextRange::CreateXTextRange(*pDoc, *pShellCursor->Start(), nullptr);
+
+ return xRet;
+}
+
+uno::Reference< text::XTextRange > SwXTextViewCursor::getEnd()
+{
+ SolarMutexGuard aGuard;
+ rtl::Reference<SwXTextRange> xRet;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ if (!IsTextSelection())
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ SwPaM* pShellCursor = rSh.GetCursor();
+ SwDoc* pDoc = m_pView->GetDocShell()->GetDoc();
+ xRet = SwXTextRange::CreateXTextRange(*pDoc, *pShellCursor->End(), nullptr);
+
+ return xRet;
+}
+
+OUString SwXTextViewCursor::getString()
+{
+ SolarMutexGuard aGuard;
+ OUString uRet;
+ if(m_pView)
+ {
+ if (!IsTextSelection( false ))
+ {
+ SAL_WARN("sw.uno", "no text selection in getString() " << getXWeak());
+ return uRet;
+ }
+
+ ShellMode eSelMode = m_pView->GetShellMode();
+ switch(eSelMode)
+ {
+ //! since setString for SEL_TABLE_TEXT (with possible
+ //! multi selection of cells) would not work properly we
+ //! will ignore this case for both
+ //! functions (setString AND getString) because of symmetrie.
+
+ case ShellMode::ListText :
+ case ShellMode::TableListText:
+ case ShellMode::Text :
+ {
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ SwPaM* pShellCursor = rSh.GetCursor();
+ SwUnoCursorHelper::GetTextFromPam(*pShellCursor, uRet,
+ rSh.GetLayout());
+ break;
+ }
+ default:;//prevent warning
+ }
+ }
+ return uRet;
+}
+
+void SwXTextViewCursor::setString(const OUString& aString)
+{
+ SolarMutexGuard aGuard;
+ if(!m_pView)
+ return;
+
+ if (!IsTextSelection( false ))
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ ShellMode eSelMode = m_pView->GetShellMode();
+ switch(eSelMode)
+ {
+ //! since setString for SEL_TABLE_TEXT (with possible
+ //! multi selection of cells) would not work properly we
+ //! will ignore this case for both
+ //! functions (setString AND getString) because of symmetrie.
+
+ case ShellMode::ListText :
+ case ShellMode::TableListText :
+ case ShellMode::Text :
+ {
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ SwCursor* pShellCursor = rSh.GetCursor();
+ SwUnoCursorHelper::SetString(*pShellCursor, aString);
+ break;
+ }
+ default:;//prevent warning
+ }
+}
+
+uno::Reference< XPropertySetInfo > SwXTextViewCursor::getPropertySetInfo( )
+{
+ static uno::Reference< XPropertySetInfo > xRef = m_pPropSet->getPropertySetInfo();
+ return xRef;
+}
+
+void SwXTextViewCursor::setPropertyValue( const OUString& rPropertyName, const Any& aValue )
+{
+ SolarMutexGuard aGuard;
+ if(!m_pView)
+ throw RuntimeException();
+
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ SwPaM* pShellCursor = rSh.GetCursor();
+ SwNode& rNode = pShellCursor->GetPointNode();
+ if (!rNode.IsTextNode())
+ throw RuntimeException();
+
+ SwUnoCursorHelper::SetPropertyValue(
+ *pShellCursor, *m_pPropSet, rPropertyName, aValue );
+
+
+}
+
+Any SwXTextViewCursor::getPropertyValue( const OUString& rPropertyName )
+{
+ SolarMutexGuard aGuard;
+ Any aRet;
+ if(!m_pView)
+ throw RuntimeException();
+
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ SwPaM* pShellCursor = rSh.GetCursor();
+ aRet = SwUnoCursorHelper::GetPropertyValue(
+ *pShellCursor, *m_pPropSet, rPropertyName);
+
+ return aRet;
+}
+
+void SwXTextViewCursor::addPropertyChangeListener(
+ const OUString& /*aPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*xListener*/ )
+{
+}
+
+void SwXTextViewCursor::removePropertyChangeListener(
+ const OUString& /*aPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*aListener*/ )
+{
+}
+
+void SwXTextViewCursor::addVetoableChangeListener(
+ const OUString& /*PropertyName*/, const uno::Reference< XVetoableChangeListener >& /*aListener*/ )
+{
+}
+
+void SwXTextViewCursor::removeVetoableChangeListener(
+ const OUString& /*PropertyName*/, const uno::Reference< XVetoableChangeListener >& /*aListener*/ )
+{
+}
+
+PropertyState SwXTextViewCursor::getPropertyState( const OUString& rPropertyName )
+{
+ SolarMutexGuard aGuard;
+ PropertyState eState;
+ if(!m_pView)
+ throw RuntimeException();
+
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ SwPaM* pShellCursor = rSh.GetCursor();
+ eState = SwUnoCursorHelper::GetPropertyState(
+ *pShellCursor, *m_pPropSet, rPropertyName);
+
+ return eState;
+}
+
+Sequence< PropertyState > SwXTextViewCursor::getPropertyStates(
+ const Sequence< OUString >& rPropertyNames )
+{
+ SolarMutexGuard aGuard;
+ Sequence< PropertyState > aRet;
+ if(m_pView)
+ {
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ SwPaM* pShellCursor = rSh.GetCursor();
+ aRet = SwUnoCursorHelper::GetPropertyStates(
+ *pShellCursor, *m_pPropSet, rPropertyNames);
+ }
+ return aRet;
+}
+
+void SwXTextViewCursor::setPropertyToDefault( const OUString& rPropertyName )
+{
+ SolarMutexGuard aGuard;
+ if(m_pView)
+ {
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ SwPaM* pShellCursor = rSh.GetCursor();
+ SwUnoCursorHelper::SetPropertyToDefault(
+ *pShellCursor, *m_pPropSet, rPropertyName);
+ }
+}
+
+Any SwXTextViewCursor::getPropertyDefault( const OUString& rPropertyName )
+{
+ Any aRet;
+ SolarMutexGuard aGuard;
+ if(m_pView)
+ {
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ SwPaM* pShellCursor = rSh.GetCursor();
+ aRet = SwUnoCursorHelper::GetPropertyDefault(
+ *pShellCursor, *m_pPropSet, rPropertyName);
+ }
+ return aRet;
+}
+
+sal_Bool SwXTextViewCursor::goDown(sal_Int16 nCount, sal_Bool bExpand)
+{
+ SolarMutexGuard aGuard;
+ comphelper::ProfileZone aZone("SwXTextViewCursor::goDown");
+ bool bRet = false;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ if (!IsTextSelection())
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ bRet = m_pView->GetWrtShell().Down( bExpand, nCount, true );
+
+ return bRet;
+}
+
+sal_Bool SwXTextViewCursor::goUp(sal_Int16 nCount, sal_Bool bExpand)
+{
+ SolarMutexGuard aGuard;
+ comphelper::ProfileZone aZone("SwXTextViewCursor::goUp");
+ bool bRet = false;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ if (!IsTextSelection())
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ bRet = m_pView->GetWrtShell().Up( bExpand, nCount, true );
+
+ return bRet;
+}
+
+sal_Bool SwXTextViewCursor::isAtStartOfLine()
+{
+ SolarMutexGuard aGuard;
+ bool bRet = false;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ if (!IsTextSelection( false ))
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ bRet = m_pView->GetWrtShell().IsAtLeftMargin();
+
+ return bRet;
+}
+
+sal_Bool SwXTextViewCursor::isAtEndOfLine()
+{
+ SolarMutexGuard aGuard;
+ bool bRet = false;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ if (!IsTextSelection( false ))
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ bRet = m_pView->GetWrtShell().IsAtRightMargin();
+
+ return bRet;
+}
+
+void SwXTextViewCursor::gotoEndOfLine(sal_Bool bExpand)
+{
+ SolarMutexGuard aGuard;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ if (!IsTextSelection( false ))
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ m_pView->GetWrtShell().RightMargin(bExpand, true);
+
+}
+
+void SwXTextViewCursor::gotoStartOfLine(sal_Bool bExpand)
+{
+ SolarMutexGuard aGuard;
+ if(!m_pView)
+ throw uno::RuntimeException();
+
+ if (!IsTextSelection( false ))
+ throw uno::RuntimeException("no text selection", getXWeak() );
+
+ m_pView->GetWrtShell().LeftMargin(bExpand, true);
+
+}
+
+OUString SwXTextViewCursor::getImplementationName()
+{
+ return "SwXTextViewCursor";
+}
+
+sal_Bool SwXTextViewCursor::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence< OUString > SwXTextViewCursor::getSupportedServiceNames()
+{
+ return { "com.sun.star.text.TextViewCursor",
+ "com.sun.star.style.CharacterProperties",
+ "com.sun.star.style.CharacterPropertiesAsian",
+ "com.sun.star.style.CharacterPropertiesComplex",
+ "com.sun.star.style.ParagraphProperties",
+ "com.sun.star.style.ParagraphPropertiesAsian",
+ "com.sun.star.style.ParagraphPropertiesComplex" };
+}
+
+const SwDoc* SwXTextViewCursor::GetDoc() const
+{
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ return rSh.GetCursor() ? &rSh.GetCursor()->GetDoc() : nullptr;
+}
+
+SwDoc* SwXTextViewCursor::GetDoc()
+{
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ return rSh.GetCursor() ? &rSh.GetCursor()->GetDoc() : nullptr;
+}
+
+const SwPaM* SwXTextViewCursor::GetPaM() const
+{
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ return rSh.GetCursor();
+}
+
+SwPaM* SwXTextViewCursor::GetPaM()
+{
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+ return rSh.GetCursor();
+}
+
+uno::Reference<datatransfer::XTransferable> SAL_CALL
+SwXTextView::getTransferableForTextRange(uno::Reference<text::XTextRange> const& xTextRange)
+{
+ SolarMutexGuard aGuard;
+
+ // the point is we can copy PaM that wouldn't be legal as shell cursor
+ SwUnoInternalPaM aPam(*m_pView->GetDocShell()->GetDoc());
+ if (!::sw::XTextRangeToSwPaM(aPam, xTextRange, ::sw::TextRangeMode::AllowNonTextNode))
+ {
+ throw uno::RuntimeException("invalid text range");
+ }
+
+ //force immediate shell update
+ GetView()->StopShellTimer();
+ SwWrtShell& rSh = GetView()->GetWrtShell();
+ rtl::Reference<SwTransferable> pTransfer = new SwTransferable(rSh);
+ const bool bLockedView = rSh.IsViewLocked();
+ rSh.LockView( true );
+ pTransfer->PrepareForCopyTextRange(aPam);
+ rSh.LockView( bLockedView );
+ return pTransfer;
+}
+
+OUString SAL_CALL SwXTextView::dump(const OUString& rKind)
+{
+ if (rKind == "layout")
+ {
+ SwRootFrame* pLayout = GetView()->GetWrtShell().GetLayout();
+ return comphelper::dumpXmlToString([pLayout](xmlTextWriterPtr pWriter)
+ { pLayout->dumpAsXml(pWriter); });
+ }
+
+ return OUString();
+}
+
+uno::Reference< datatransfer::XTransferable > SAL_CALL SwXTextView::getTransferable()
+{
+ SolarMutexGuard aGuard;
+
+ //force immediat shell update
+ GetView()->StopShellTimer();
+ SwWrtShell& rSh = GetView()->GetWrtShell();
+ if ( GetView()->GetShellMode() == ShellMode::DrawText )
+ {
+ SdrView *pSdrView = rSh.GetDrawView();
+ OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
+ return pOLV->GetEditView().GetTransferable();
+ }
+ else
+ {
+ rtl::Reference<SwTransferable> pTransfer = new SwTransferable( rSh );
+ const bool bLockedView = rSh.IsViewLocked();
+ rSh.LockView( true ); //lock visible section
+ pTransfer->PrepareForCopy();
+ rSh.LockView( bLockedView );
+ return pTransfer;
+ }
+}
+
+void SAL_CALL SwXTextView::insertTransferable( const uno::Reference< datatransfer::XTransferable >& xTrans )
+{
+ SolarMutexGuard aGuard;
+
+ //force immediat shell update
+ GetView()->StopShellTimer();
+ SwWrtShell& rSh = GetView()->GetWrtShell();
+ if ( GetView()->GetShellMode() == ShellMode::DrawText )
+ {
+ SdrView *pSdrView = rSh.GetDrawView();
+ OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
+ pOLV->GetEditView().InsertText( xTrans, GetView()->GetDocShell()->GetMedium()->GetBaseURL(), false );
+ }
+ else
+ {
+ TransferableDataHelper aDataHelper( xTrans );
+ if ( SwTransferable::IsPaste( rSh, aDataHelper ) )
+ {
+ SwTransferable::Paste( rSh, aDataHelper );
+ if( rSh.IsFrameSelected() || rSh.IsObjSelected() )
+ rSh.EnterSelFrameMode();
+ GetView()->AttrChangedNotify(nullptr);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/AccessibilityStatusBarControl.cxx b/sw/source/uibase/utlui/AccessibilityStatusBarControl.cxx
new file mode 100644
index 0000000000..9a99d3c578
--- /dev/null
+++ b/sw/source/uibase/utlui/AccessibilityStatusBarControl.cxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <swtypes.hxx>
+#include <strings.hrc>
+#include <AccessibilityStatusBarControl.hxx>
+#include <svl/intitem.hxx>
+#include <vcl/status.hxx>
+#include <vcl/event.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <bitmaps.hlst>
+
+SFX_IMPL_STATUSBAR_CONTROL(sw::AccessibilityStatusBarControl, SfxInt32Item);
+
+namespace sw
+{
+AccessibilityStatusBarControl::AccessibilityStatusBarControl(sal_uInt16 _nSlotId, sal_uInt16 _nId,
+ StatusBar& rStb)
+ : SfxStatusBarControl(_nSlotId, _nId, rStb)
+ , mnIssues(0)
+ , maImageIssuesFound(Image(StockImage::Yes, RID_BMP_A11Y_CHECK_ISSUES_FOUND))
+ , maImageIssuesNotFound(Image(StockImage::Yes, RID_BMP_A11Y_CHECK_ISSUES_NOT_FOUND))
+{
+}
+
+AccessibilityStatusBarControl::~AccessibilityStatusBarControl() = default;
+
+void AccessibilityStatusBarControl::StateChangedAtStatusBarControl(sal_uInt16 /*nSID*/,
+ SfxItemState eState,
+ const SfxPoolItem* pState)
+{
+ mnIssues = -1;
+
+ bool bOnlineCheckStatus
+ = officecfg::Office::Common::Accessibility::OnlineAccessibilityCheck::get();
+
+ if (eState == SfxItemState::DEFAULT && bOnlineCheckStatus)
+ {
+ if (auto pItem = dynamic_cast<const SfxInt32Item*>(pState))
+ mnIssues = pItem->GetValue();
+ OUString aString = SwResId(STR_ACCESSIBILITY_CHECK_HINT)
+ .replaceFirst("%issues%", OUString::number(mnIssues));
+ GetStatusBar().SetQuickHelpText(GetId(), aString);
+ }
+ else
+ {
+ GetStatusBar().SetQuickHelpText(GetId(), u""_ustr);
+ }
+
+ GetStatusBar().Invalidate();
+}
+
+void AccessibilityStatusBarControl::Paint(const UserDrawEvent& rUserEvent)
+{
+ if (mnIssues < 0)
+ return;
+
+ vcl::RenderContext* pRenderContext = rUserEvent.GetRenderContext();
+
+ tools::Rectangle aRect = rUserEvent.GetRect();
+ const tools::Rectangle aControlRect = getControlRect();
+
+ Image aImage = mnIssues > 0 ? maImageIssuesFound : maImageIssuesNotFound;
+
+ Size aSize(aImage.GetSizePixel());
+
+ auto aPosition = Point(aRect.Left() + (aControlRect.GetWidth() - aSize.Width()) / 2,
+ aRect.Top() + (aControlRect.GetHeight() - aSize.Height()) / 2);
+
+ pRenderContext->DrawImage(aPosition, aImage);
+}
+
+} // end sw
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/attrdesc.cxx b/sw/source/uibase/utlui/attrdesc.cxx
new file mode 100644
index 0000000000..71fdd4ab54
--- /dev/null
+++ b/sw/source/uibase/utlui/attrdesc.cxx
@@ -0,0 +1,846 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <i18nutil/unicode.hxx>
+#include <svl/itemiter.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/GraphicAttributes.hxx>
+
+#include <editeng/itemtype.hxx>
+#include <editeng/eerdll.hxx>
+#include <unotools/intlwrapper.hxx>
+#include <unotools/syslocale.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <fmtanchr.hxx>
+#include <fmtfsize.hxx>
+#include <fmtinfmt.hxx>
+#include <fchrfmt.hxx>
+#include <fmtautofmt.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtornt.hxx>
+#include <fmtlsplt.hxx>
+#include <fmtrowsplt.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtclds.hxx>
+#include <fmteiro.hxx>
+#include <fmturl.hxx>
+#include <fmthdft.hxx>
+#include <fmtcnct.hxx>
+#include <fmtline.hxx>
+#include <tgrditem.hxx>
+#include <hfspacingitem.hxx>
+#include <fmtruby.hxx>
+#include <paratr.hxx>
+#include <grfatr.hxx>
+#include <pagedesc.hxx>
+#include <charfmt.hxx>
+#include <strings.hrc>
+#include <fmtftntx.hxx>
+#include <fmtfollowtextflow.hxx>
+#include <libxml/xmlwriter.h>
+
+using namespace com::sun::star;
+
+
+// query the attribute descriptions
+void SwAttrSet::GetPresentation(
+ SfxItemPresentation ePres,
+ MapUnit eCoreMetric,
+ MapUnit ePresMetric,
+ OUString &rText ) const
+{
+ rText.clear();
+ OUString aStr;
+ if( !Count() )
+ return;
+
+ SfxItemIter aIter( *this );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ const IntlWrapper aInt(SvtSysLocale().GetUILanguageTag());
+ do
+ {
+ pItem->GetPresentation(ePres, eCoreMetric, ePresMetric, aStr, aInt);
+ if( rText.getLength() && aStr.getLength() )
+ rText += ", ";
+ rText += aStr;
+ pItem = aIter.NextItem();
+ } while (pItem);
+}
+
+bool SwFormatCharFormat::GetPresentation
+(
+ SfxItemPresentation ePres,
+ MapUnit eCoreUnit,
+ MapUnit ePresUnit,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ const SwCharFormat *pCharFormat = GetCharFormat();
+ if ( pCharFormat )
+ {
+ OUString aStr;
+ pCharFormat->GetPresentation( ePres, eCoreUnit, ePresUnit, aStr );
+ rText = SwResId( STR_CHARFMT ) + "(" + aStr + ")";
+ }
+ else
+ rText = SwResId( STR_NO_CHARFMT );
+ return true;
+}
+
+bool SwFormatAutoFormat::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ rText.clear(); //TODO
+ return true;
+}
+
+bool SwFormatINetFormat::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ rText = GetValue();
+ return true;
+}
+
+bool SwFormatRuby::GetPresentation( SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreMetric*/, MapUnit /*ePresMetric*/,
+ OUString &rText, const IntlWrapper& /*rIntl*/ ) const
+{
+ rText.clear();
+ return true;
+}
+
+bool SwFormatDrop::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ rText.clear();
+ if ( GetLines() > 1 )
+ {
+ if ( GetChars() > 1 )
+ {
+ rText = OUString::number( GetChars() ) + " ";
+ }
+ rText += SwResId( STR_DROP_OVER ) +
+ " " +
+ OUString::number( GetLines() ) +
+ " " +
+ SwResId( STR_DROP_LINES );
+ }
+ else
+ rText = SwResId( STR_NO_DROP_LINES );
+ return true;
+}
+
+bool SwRegisterItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ TranslateId pId = GetValue() ? STR_REGISTER_ON : STR_REGISTER_OFF;
+ rText = SwResId(pId);
+ return true;
+}
+
+bool SwNumRuleItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ if( !GetValue().isEmpty() )
+ rText = SwResId( STR_NUMRULE_ON ).replaceFirst("%LISTSTYLENAME", GetValue());
+ else
+ rText = SwResId( STR_NUMRULE_OFF );
+ return true;
+}
+
+bool SwParaConnectBorderItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ TranslateId pId = GetValue() ? STR_CONNECT_BORDER_ON : STR_CONNECT_BORDER_OFF;
+ rText = SwResId(pId);
+ return true;
+}
+
+// Frame attribute
+
+bool SwFormatFrameSize::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit eCoreUnit,
+ MapUnit ePresUnit,
+ OUString& rText,
+ const IntlWrapper& rIntl
+) const
+{
+ rText = SwResId( STR_FRM_WIDTH ) + " ";
+ if ( GetWidthPercent() )
+ {
+ rText += unicode::formatPercent(GetWidthPercent(),
+ Application::GetSettings().GetUILanguageTag());
+ }
+ else
+ {
+ rText += ::GetMetricText( GetWidth(), eCoreUnit, ePresUnit, &rIntl ) +
+ " " + ::EditResId( ::GetMetricId( ePresUnit ) );
+ }
+ if ( SwFrameSize::Variable != GetHeightSizeType() )
+ {
+ TranslateId pId = SwFrameSize::Fixed == m_eFrameHeightType ?
+ STR_FRM_FIXEDHEIGHT : STR_FRM_MINHEIGHT;
+ rText += ", " + SwResId(pId) + " ";
+ if ( GetHeightPercent() )
+ {
+ rText += unicode::formatPercent(GetHeightPercent(),
+ Application::GetSettings().GetUILanguageTag());
+ }
+ else
+ {
+ rText = ::GetMetricText( GetHeight(), eCoreUnit, ePresUnit, &rIntl ) +
+ " " + EditResId( ::GetMetricId( ePresUnit ) );
+ }
+ }
+ return true;
+}
+
+//Header for page formats.
+//Client of FrameFormat which describes the header.
+
+bool SwFormatHeader::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ TranslateId pId = GetHeaderFormat() ? STR_HEADER : STR_NO_HEADER;
+ rText = SwResId(pId);
+ return true;
+}
+
+//Footer for page formats.
+//Client of FrameFormat which describes the footer.
+
+bool SwFormatFooter::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ TranslateId pId = GetFooterFormat() ? STR_FOOTER : STR_NO_FOOTER;
+ rText = SwResId(pId);
+ return true;
+}
+
+bool SwFormatSurround::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ TranslateId pId;
+ switch ( GetValue() )
+ {
+ case css::text::WrapTextMode_NONE:
+ pId = STR_SURROUND_NONE;
+ break;
+ case css::text::WrapTextMode_THROUGH:
+ pId = STR_SURROUND_THROUGH;
+ break;
+ case css::text::WrapTextMode_PARALLEL:
+ pId = STR_SURROUND_PARALLEL;
+ break;
+ case css::text::WrapTextMode_DYNAMIC:
+ pId = STR_SURROUND_IDEAL;
+ break;
+ case css::text::WrapTextMode_LEFT:
+ pId = STR_SURROUND_LEFT;
+ break;
+ case css::text::WrapTextMode_RIGHT:
+ pId = STR_SURROUND_RIGHT;
+ break;
+ default:;//prevent warning
+ }
+ if (pId)
+ rText = SwResId(pId);
+
+ if ( IsAnchorOnly() )
+ {
+ rText += " " + SwResId( STR_SURROUND_ANCHORONLY );
+ }
+ return true;
+}
+
+//VertOrientation, how and by what orientate the FlyFrame in the vertical?
+
+bool SwFormatVertOrient::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit eCoreUnit,
+ MapUnit ePresUnit,
+ OUString& rText,
+ const IntlWrapper& rIntl
+) const
+{
+ TranslateId pId;
+ switch ( GetVertOrient() )
+ {
+ case text::VertOrientation::NONE:
+ {
+ rText += SwResId( STR_POS_Y ) + " " +
+ ::GetMetricText( GetPos(), eCoreUnit, ePresUnit, &rIntl ) +
+ " " + EditResId( ::GetMetricId( ePresUnit ) );
+ }
+ break;
+ case text::VertOrientation::TOP:
+ pId = STR_VERT_TOP;
+ break;
+ case text::VertOrientation::CENTER:
+ pId = STR_VERT_CENTER;
+ break;
+ case text::VertOrientation::BOTTOM:
+ pId = STR_VERT_BOTTOM;
+ break;
+ case text::VertOrientation::LINE_TOP:
+ pId = STR_LINE_TOP;
+ break;
+ case text::VertOrientation::LINE_CENTER:
+ pId = STR_LINE_CENTER;
+ break;
+ case text::VertOrientation::LINE_BOTTOM:
+ pId = STR_LINE_BOTTOM;
+ break;
+ default:;//prevent warning
+ }
+ if (pId)
+ rText += SwResId(pId);
+ return true;
+}
+
+//HoriOrientation, how and by what orientate the FlyFrame in the horizontal?
+
+bool SwFormatHoriOrient::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit eCoreUnit,
+ MapUnit ePresUnit,
+ OUString& rText,
+ const IntlWrapper& rIntl
+) const
+{
+ TranslateId pId;
+ switch ( GetHoriOrient() )
+ {
+ case text::HoriOrientation::NONE:
+ {
+ rText += SwResId( STR_POS_X ) + " " +
+ ::GetMetricText( GetPos(), eCoreUnit, ePresUnit, &rIntl ) +
+ " " + EditResId( ::GetMetricId( ePresUnit ) );
+ }
+ break;
+ case text::HoriOrientation::RIGHT:
+ pId = STR_HORI_RIGHT;
+ break;
+ case text::HoriOrientation::CENTER:
+ pId = STR_HORI_CENTER;
+ break;
+ case text::HoriOrientation::LEFT:
+ pId = STR_HORI_LEFT;
+ break;
+ case text::HoriOrientation::INSIDE:
+ pId = STR_HORI_INSIDE;
+ break;
+ case text::HoriOrientation::OUTSIDE:
+ pId = STR_HORI_OUTSIDE;
+ break;
+ case text::HoriOrientation::FULL:
+ pId = STR_HORI_FULL;
+ break;
+ default:;//prevent warning
+ }
+ if (pId)
+ rText += SwResId(pId);
+ return true;
+}
+
+// FlyAnchor, Anchor of the free-flying frame
+
+bool SwFormatAnchor::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ TranslateId pId;
+ switch ( GetAnchorId() )
+ {
+ case RndStdIds::FLY_AT_PARA:
+ pId = STR_FLY_AT_PARA;
+ break;
+ case RndStdIds::FLY_AS_CHAR:
+ pId = STR_FLY_AS_CHAR;
+ break;
+ case RndStdIds::FLY_AT_CHAR:
+ pId = STR_FLY_AT_CHAR;
+ break;
+ case RndStdIds::FLY_AT_PAGE:
+ pId = STR_FLY_AT_PAGE;
+ break;
+ default:;//prevent warning
+ }
+ if (pId)
+ rText += SwResId(pId);
+ return true;
+}
+
+bool SwFormatPageDesc::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ const SwPageDesc *pPageDesc = GetPageDesc();
+ if ( pPageDesc )
+ rText = pPageDesc->GetName();
+ else
+ rText = SwResId( STR_NO_PAGEDESC );
+ return true;
+}
+
+//The ColumnDescriptor
+
+bool SwFormatCol::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit eCoreUnit,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& rIntl
+) const
+{
+ sal_uInt16 nCnt = GetNumCols();
+ if ( nCnt > 1 )
+ {
+ rText = OUString::number(nCnt) + " " + SwResId( STR_COLUMNS );
+ if ( COLADJ_NONE != GetLineAdj() )
+ {
+ const tools::Long nWdth = static_cast<tools::Long>(GetLineWidth());
+ rText += " " + SwResId( STR_LINE_WIDTH ) + " " +
+ ::GetMetricText( nWdth, eCoreUnit,
+ MapUnit::MapPoint, &rIntl );
+ }
+ }
+ else
+ rText.clear();
+ return true;
+}
+
+//URL's and maps
+
+bool SwFormatURL::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ rText.clear();
+ if ( m_pMap )
+ rText += "Client-Map";
+ if ( !m_sURL.isEmpty() )
+ {
+ if ( m_pMap )
+ rText += " - ";
+ rText += "URL: " + m_sURL;
+ if ( m_bIsServerMap )
+ rText += " (Server-Map)";
+ }
+ if ( !m_sTargetFrameName.isEmpty() )
+ {
+ rText += ", Target: " + m_sTargetFrameName;
+ }
+ return true;
+}
+
+bool SwFormatEditInReadonly::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ rText.clear();
+ if ( GetValue() )
+ rText = SwResId(STR_EDIT_IN_READONLY);
+ return true;
+}
+
+void SwFormatEditInReadonly::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFormatEditInReadonly"));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::boolean(GetValue()).getStr()));
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+bool SwFormatLayoutSplit::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ if ( GetValue() )
+ rText = SwResId(STR_LAYOUT_SPLIT);
+ return true;
+}
+
+bool SwFormatRowSplit::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& /*rText*/,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ return false;
+}
+
+bool SwFormatFootnoteEndAtTextEnd::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& /*rText*/,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ return true;
+}
+
+bool SwFormatChain::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ if ( GetPrev() || GetNext() )
+ {
+ rText = SwResId(STR_CONNECT1);
+ if ( GetPrev() )
+ {
+ rText += GetPrev()->GetName();
+ if ( GetNext() )
+ rText += SwResId(STR_CONNECT2);
+ }
+ if ( GetNext() )
+ rText += GetNext()->GetName();
+ }
+ return true;
+}
+
+bool SwFormatLineNumber::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ if ( IsCount() )
+ rText += SwResId(STR_LINECOUNT);
+ else
+ rText += SwResId(STR_DONTLINECOUNT);
+ if ( GetStartValue() )
+ {
+ rText += " " + SwResId(STR_LINCOUNT_START) +
+ OUString::number( GetStartValue() );
+ }
+ return true;
+}
+
+bool SwTextGridItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& rText,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ TranslateId pId;
+
+ switch ( GetGridType() )
+ {
+ case GRID_NONE :
+ pId = STR_GRID_NONE;
+ break;
+ case GRID_LINES_ONLY :
+ pId = STR_GRID_LINES_ONLY;
+ break;
+ case GRID_LINES_CHARS :
+ pId = STR_GRID_LINES_CHARS;
+ break;
+ }
+ if (pId)
+ rText += SwResId(pId);
+ return true;
+}
+
+bool SwHeaderAndFooterEatSpacingItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit /*eCoreUnit*/,
+ MapUnit /*ePresUnit*/,
+ OUString& /*rText*/,
+ const IntlWrapper& /*rIntl*/
+) const
+{
+ return false;
+}
+
+// Graphic attributes
+
+bool SwMirrorGrf::GetPresentation(
+ SfxItemPresentation /*ePres*/, MapUnit /*eCoreUnit*/, MapUnit /*ePresUnit*/,
+ OUString& rText, const IntlWrapper& /*rIntl*/ ) const
+{
+ TranslateId pId;
+ switch( GetValue() )
+ {
+ case MirrorGraph::Dont: pId = STR_NO_MIRROR; break;
+ case MirrorGraph::Vertical: pId = STR_VERT_MIRROR; break;
+ case MirrorGraph::Horizontal: pId = STR_HORI_MIRROR; break;
+ case MirrorGraph::Both: pId = STR_BOTH_MIRROR; break;
+ default: break;
+ }
+ if (pId)
+ {
+ rText = SwResId(pId);
+ if (m_bGrfToggle)
+ rText += SwResId( STR_MIRROR_TOGGLE );
+ }
+ return true;
+}
+
+bool SwRotationGrf::GetPresentation(
+ SfxItemPresentation ePres, MapUnit /*eCoreUnit*/, MapUnit /*ePresUnit*/,
+ OUString &rText, const IntlWrapper& /*rIntl*/) const
+{
+ if( SfxItemPresentation::Complete == ePres )
+ rText = SwResId( STR_ROTATION );
+ else if( rText.getLength() )
+ rText.clear();
+ rText += OUString::number( toDegrees(GetValue()) ) + "\xB0";
+ return true;
+}
+
+bool SwLuminanceGrf::GetPresentation(
+ SfxItemPresentation ePres, MapUnit /*eCoreUnit*/, MapUnit /*ePresUnit*/,
+ OUString &rText, const IntlWrapper& /*rIntl*/) const
+{
+ if( SfxItemPresentation::Complete == ePres )
+ rText = SwResId( STR_LUMINANCE );
+ else if( rText.getLength() )
+ rText.clear();
+ rText += unicode::formatPercent(GetValue(),
+ Application::GetSettings().GetUILanguageTag());
+ return true;
+}
+
+bool SwContrastGrf::GetPresentation(
+ SfxItemPresentation ePres, MapUnit /*eCoreUnit*/, MapUnit /*ePresUnit*/,
+ OUString &rText, const IntlWrapper& /*rIntl*/) const
+{
+ if( SfxItemPresentation::Complete == ePres )
+ rText = SwResId( STR_CONTRAST );
+ else if( rText.getLength() )
+ rText.clear();
+ rText += unicode::formatPercent(GetValue(),
+ Application::GetSettings().GetUILanguageTag());
+ return true;
+}
+
+bool SwChannelGrf::GetPresentation(
+ SfxItemPresentation ePres, MapUnit /*eCoreUnit*/, MapUnit /*ePresUnit*/,
+ OUString &rText, const IntlWrapper& /*rIntl*/) const
+{
+ if( SfxItemPresentation::Complete == ePres )
+ {
+ TranslateId pId;
+ switch ( Which() )
+ {
+ case RES_GRFATR_CHANNELR: pId = STR_CHANNELR; break;
+ case RES_GRFATR_CHANNELG: pId = STR_CHANNELG; break;
+ case RES_GRFATR_CHANNELB: pId = STR_CHANNELB; break;
+ default: break;
+ }
+ if (pId)
+ rText = SwResId(pId);
+ else if( rText.getLength() )
+ rText.clear();
+ }
+ else if( rText.getLength() )
+ rText.clear();
+ rText += unicode::formatPercent(GetValue(),
+ Application::GetSettings().GetUILanguageTag());
+ return true;
+}
+
+bool SwGammaGrf::GetPresentation(
+ SfxItemPresentation ePres, MapUnit /*eCoreUnit*/, MapUnit /*ePresUnit*/,
+ OUString &rText, const IntlWrapper& /*rIntl*/) const
+{
+ OUStringBuffer aText;
+ if( SfxItemPresentation::Complete == ePres )
+ aText.append(SwResId(STR_GAMMA));
+ aText.append(unicode::formatPercent(GetValue(),
+ Application::GetSettings().GetUILanguageTag()));
+ rText = aText.makeStringAndClear();
+ return true;
+}
+
+bool SwInvertGrf::GetPresentation(
+ SfxItemPresentation ePres, MapUnit /*eCoreUnit*/, MapUnit /*ePresUnit*/,
+ OUString &rText, const IntlWrapper& /*rIntl*/) const
+{
+ rText.clear();
+ if( SfxItemPresentation::Complete == ePres )
+ {
+ TranslateId pId = GetValue() ? STR_INVERT : STR_INVERT_NOT;
+ rText = SwResId(pId);
+ }
+ return true;
+}
+
+bool SwTransparencyGrf::GetPresentation(
+ SfxItemPresentation ePres, MapUnit /*eCoreUnit*/, MapUnit /*ePresUnit*/,
+ OUString &rText, const IntlWrapper& /*rIntl*/) const
+{
+ if( SfxItemPresentation::Complete == ePres )
+ rText = SwResId( STR_TRANSPARENCY );
+ else if( rText.getLength() )
+ rText.clear();
+ rText += unicode::formatPercent(GetValue(),
+ Application::GetSettings().GetUILanguageTag());
+ return true;
+}
+
+bool SwDrawModeGrf::GetPresentation(
+ SfxItemPresentation ePres, MapUnit /*eCoreUnit*/, MapUnit /*ePresUnit*/,
+ OUString &rText, const IntlWrapper& /*rIntl*/) const
+{
+ rText.clear();
+ if( SfxItemPresentation::Complete == ePres )
+ {
+ TranslateId pId;
+ switch ( GetValue() )
+ {
+
+ case GraphicDrawMode::Greys: pId = STR_DRAWMODE_GREY; break;
+ case GraphicDrawMode::Mono: pId = STR_DRAWMODE_BLACKWHITE; break;
+ case GraphicDrawMode::Watermark: pId = STR_DRAWMODE_WATERMARK; break;
+ default: pId = STR_DRAWMODE_STD; break;
+ }
+ rText = SwResId( STR_DRAWMODE ) + SwResId(pId);
+ }
+ return true;
+}
+
+bool SwFormatFollowTextFlow::GetPresentation( SfxItemPresentation ePres,
+ MapUnit /*eCoreMetric*/,
+ MapUnit /*ePresMetric*/,
+ OUString &rText,
+ const IntlWrapper& /*rIntl*/ ) const
+{
+ rText.clear();
+ if( SfxItemPresentation::Complete == ePres )
+ {
+ TranslateId pId = GetValue() ? STR_FOLLOW_TEXT_FLOW : STR_DONT_FOLLOW_TEXT_FLOW;
+ rText = SwResId(pId);
+ }
+ return true;
+}
+
+void SwFormatFollowTextFlow::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFormatFollowTextFlow"));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::boolean(GetValue()).getStr()));
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/bookctrl.cxx b/sw/source/uibase/utlui/bookctrl.cxx
new file mode 100644
index 0000000000..e79821022a
--- /dev/null
+++ b/sw/source/uibase/utlui/bookctrl.cxx
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/intitem.hxx>
+#include <svl/slstitm.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/event.hxx>
+#include <vcl/status.hxx>
+#include <vcl/weldutils.hxx>
+#include <cmdid.h>
+#include <swmodule.hxx>
+#include <wrtsh.hxx>
+#include <IMark.hxx>
+#include <bookctrl.hxx>
+#include <map>
+
+SFX_IMPL_STATUSBAR_CONTROL(SwBookmarkControl, SfxStringListItem);
+
+SwBookmarkControl::SwBookmarkControl( sal_uInt16 _nSlotId,
+ sal_uInt16 _nId,
+ StatusBar& rStb ) :
+ SfxStatusBarControl( _nSlotId, _nId, rStb )
+{
+}
+
+SwBookmarkControl::~SwBookmarkControl()
+{
+}
+
+void SwBookmarkControl::StateChangedAtStatusBarControl(
+ sal_uInt16 /*nSID*/, SfxItemState eState, const SfxPoolItem* pState )
+{
+ if (eState != SfxItemState::DEFAULT || SfxItemState::DISABLED == eState)
+ {
+ GetStatusBar().SetItemText(GetId(), OUString());
+ GetStatusBar().SetQuickHelpText(GetId(), OUString());
+ }
+ else if (auto pStringListItem = dynamic_cast<const SfxStringListItem*>(pState))
+ {
+ const std::vector<OUString>& rStringList(pStringListItem->GetList());
+ GetStatusBar().SetItemText(GetId(), rStringList[0]);
+ GetStatusBar().SetQuickHelpText(GetId(), rStringList[1]);
+ }
+}
+
+void SwBookmarkControl::Paint( const UserDrawEvent& )
+{
+}
+
+void SwBookmarkControl::Command( const CommandEvent& rCEvt )
+{
+ if ( rCEvt.GetCommand() != CommandEventId::ContextMenu ||
+ GetStatusBar().GetItemText( GetId() ).isEmpty())
+ return;
+
+ SwWrtShell* pWrtShell = ::GetActiveWrtShell();
+ if( !(pWrtShell && pWrtShell->getIDocumentMarkAccess()->getAllMarksCount() > 0) )
+ return;
+
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if (!pViewFrm)
+ return;
+
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, "modules/swriter/ui/bookmarkmenu.ui"));
+ std::unique_ptr<weld::Menu> xPopup(xBuilder->weld_menu("menu"));
+
+ IDocumentMarkAccess* const pMarkAccess = pWrtShell->getIDocumentMarkAccess();
+ IDocumentMarkAccess::const_iterator_t ppBookmarkStart = pMarkAccess->getBookmarksBegin();
+ sal_uInt32 nPopupId = 1;
+ std::map<sal_Int32, sal_uInt16> aBookmarkIdx;
+ for(IDocumentMarkAccess::const_iterator_t ppBookmark = ppBookmarkStart;
+ ppBookmark != pMarkAccess->getBookmarksEnd();
+ ++ppBookmark)
+ {
+ if(IDocumentMarkAccess::MarkType::BOOKMARK == IDocumentMarkAccess::GetType(**ppBookmark))
+ {
+ xPopup->append(OUString::number(nPopupId), (*ppBookmark)->GetName());
+ aBookmarkIdx[nPopupId] = o3tl::narrowing<sal_uInt16>(ppBookmark - ppBookmarkStart);
+ nPopupId++;
+ }
+ }
+ ::tools::Rectangle aRect(rCEvt.GetMousePosPixel(), Size(1, 1));
+ weld::Window* pParent = weld::GetPopupParent(GetStatusBar(), aRect);
+ OUString sResult = xPopup->popup_at_rect(pParent, aRect);
+ if (!sResult.isEmpty())
+ {
+ SfxUInt16Item aBookmark( FN_STAT_BOOKMARK, aBookmarkIdx[sResult.toUInt32()] );
+ pViewFrm->GetDispatcher()->ExecuteList(FN_STAT_BOOKMARK,
+ SfxCallMode::ASYNCHRON|SfxCallMode::RECORD,
+ { &aBookmark });
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/condedit.cxx b/sw/source/uibase/utlui/condedit.cxx
new file mode 100644
index 0000000000..1303ddfc75
--- /dev/null
+++ b/sw/source/uibase/utlui/condedit.cxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <condedit.hxx>
+#include <svx/dbaexchange.hxx>
+
+using namespace ::svx;
+using namespace ::com::sun::star::uno;
+
+ConditionEdit::ConditionEdit(std::unique_ptr<weld::Entry> xControl)
+ : m_xControl(std::move(xControl))
+ , m_aDropTargetHelper(*this)
+ , m_bBrackets(true)
+ , m_bEnableDrop(true)
+{
+}
+
+sal_Int8 ConditionEditDropTarget::AcceptDrop( const AcceptDropEvent& /*rEvt*/ )
+{
+ return OColumnTransferable::canExtractColumnDescriptor
+ ( GetDataFlavorExVector(),
+ ColumnTransferFormatFlags::COLUMN_DESCRIPTOR )
+ ? DND_ACTION_COPY
+ : DND_ACTION_NONE;
+}
+
+ConditionEditDropTarget::ConditionEditDropTarget(ConditionEdit& rEdit)
+ : DropTargetHelper(rEdit.get_widget().get_drop_target())
+ , m_rEdit(rEdit)
+{
+}
+
+sal_Int8 ConditionEditDropTarget::ExecuteDrop( const ExecuteDropEvent& rEvt )
+{
+ sal_Int8 nRet = DND_ACTION_NONE;
+ if (m_rEdit.GetDropEnable())
+ {
+ TransferableDataHelper aData( rEvt.maDropEvent.Transferable );
+
+ const DataFlavorExVector& rVector = aData.GetDataFlavorExVector();
+ if (OColumnTransferable::canExtractColumnDescriptor(rVector, ColumnTransferFormatFlags::COLUMN_DESCRIPTOR))
+ {
+ ODataAccessDescriptor aColDesc = OColumnTransferable::extractColumnDescriptor(
+ aData);
+ OUString sDBName;
+ bool bBrackets = m_rEdit.GetBrackets();
+ if (bBrackets)
+ sDBName += "[";
+ OUString sTmp = aColDesc.getDataSource();
+ sDBName += sTmp + ".";
+
+ aColDesc[DataAccessDescriptorProperty::Command] >>= sTmp;
+ sDBName += sTmp + ".";
+
+ aColDesc[DataAccessDescriptorProperty::ColumnName] >>= sTmp;
+ sDBName += sTmp;
+ if (bBrackets)
+ sDBName += "]";
+
+ m_rEdit.get_widget().set_text( sDBName );
+ nRet = DND_ACTION_COPY;
+ }
+ }
+ return nRet;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/content.cxx b/sw/source/uibase/utlui/content.cxx
new file mode 100644
index 0000000000..3bf29979dd
--- /dev/null
+++ b/sw/source/uibase/utlui/content.cxx
@@ -0,0 +1,6647 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <comphelper/lok.hxx>
+#include <comphelper/string.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <svl/urlbmk.hxx>
+#include <osl/thread.h>
+#include <sal/log.hxx>
+#include <tools/urlobj.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/event.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <o3tl/enumrange.hxx>
+#include <o3tl/sorted_vector.hxx>
+#include <utility>
+#include <vcl/commandevent.hxx>
+#include <vcl/weldutils.hxx>
+#include <sot/formats.hxx>
+#include <o3tl/string_view.hxx>
+#include <uiitems.hxx>
+#include <fmtanchr.hxx>
+#include <fmtinfmt.hxx>
+#include <txtinet.hxx>
+#include <fmtfld.hxx>
+#include <swmodule.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <drawdoc.hxx>
+#include <content.hxx>
+#include <frmatr.hxx>
+#include <frmfmt.hxx>
+#include <fldbas.hxx>
+#include <IMark.hxx>
+#include <section.hxx>
+#include <tox.hxx>
+#include <navipi.hxx>
+#include <navicont.hxx>
+#include <navicfg.hxx>
+#include <edtwin.hxx>
+#include <doc.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentOutlineNodes.hxx>
+#include <unotxvw.hxx>
+#include <cmdid.h>
+#include <helpids.h>
+#include <strings.hrc>
+#include <com/sun/star/text/XTextSectionsSupplier.hpp>
+#include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp>
+#include <com/sun/star/text/XTextTablesSupplier.hpp>
+#include <com/sun/star/text/XDocumentIndexesSupplier.hpp>
+#include <com/sun/star/text/XDocumentIndex.hpp>
+#include <com/sun/star/text/XBookmarksSupplier.hpp>
+#include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
+#include <com/sun/star/text/XTextFramesSupplier.hpp>
+#include <com/sun/star/ui/XSidebarProvider.hpp>
+#include <com/sun/star/ui/XDecks.hpp>
+#include <com/sun/star/ui/XDeck.hpp>
+#include <com/sun/star/ui/XPanels.hpp>
+#include <com/sun/star/ui/XPanel.hpp>
+#include <svx/svdpage.hxx>
+#include <svx/svdview.hxx>
+#include <SwRewriter.hxx>
+#include <hints.hxx>
+#include <numrule.hxx>
+#include <swundo.hxx>
+#include <ndtxt.hxx>
+#include <PostItMgr.hxx>
+#include <postithelper.hxx>
+
+#include <swabstdlg.hxx>
+#include <bitmaps.hlst>
+
+#include <AnnotationWin.hxx>
+#include <memory>
+
+#include <fmtcntnt.hxx>
+#include <docstat.hxx>
+
+#include <viewopt.hxx>
+
+#include <IDocumentFieldsAccess.hxx>
+#include <txtfld.hxx>
+#include <fldmgr.hxx>
+
+#include <frameformats.hxx>
+
+#include <ftnidx.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+
+#include <txtannotationfld.hxx>
+#include <txtfrm.hxx>
+#include <txtrfmrk.hxx>
+#include <svx/sdr/overlay/overlayselection.hxx>
+#include <svx/sdr/overlay/overlayobject.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <svx/sdrpaintwindow.hxx>
+#include <node2lay.hxx>
+
+#include <sectfrm.hxx>
+
+#include <docufld.hxx>
+
+#define CTYPE_CNT 0
+#define CTYPE_CTT 1
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+
+namespace {
+
+/*
+ Symbolic name representations of numeric values used for the Outline Content Visibility popup
+ menu item ids. The numbers are chosen arbitrarily to not over overlap other menu item ids.
+ see: SwContentTree::ExecuteContextMenuAction, navigatorcontextmenu.ui
+
+ 1512 toggle outline content visibility of the selected outline entry
+ 1513 make the outline content of the selected outline entry and children not visible
+ 1514 make the outline content of the selected entry and children visible
+*/
+const sal_uInt32 TOGGLE_OUTLINE_CONTENT_VISIBILITY = 1512;
+const sal_uInt32 HIDE_OUTLINE_CONTENT_VISIBILITY = 1513;
+const sal_uInt32 SHOW_OUTLINE_CONTENT_VISIBILITY = 1514;
+
+constexpr char NAVI_BOOKMARK_DELIM = '\x01';
+
+}
+
+class SwContentArr
+ : public o3tl::sorted_vector<std::unique_ptr<SwContent>, o3tl::less_uniqueptr_to<SwContent>,
+ o3tl::find_partialorder_ptrequals>
+{
+};
+
+namespace
+{
+ std::map<OUString, std::map<void*, bool>> lcl_DocOutLineExpandStateMap;
+
+ bool lcl_IsContent(const weld::TreeIter& rEntry, const weld::TreeView& rTreeView)
+ {
+ return weld::fromId<const SwTypeNumber*>(rTreeView.get_id(rEntry))->GetTypeId() == CTYPE_CNT;
+ }
+
+ bool lcl_IsContentType(const weld::TreeIter& rEntry, const weld::TreeView& rTreeView)
+ {
+ return weld::fromId<const SwTypeNumber*>(rTreeView.get_id(rEntry))->GetTypeId() == CTYPE_CTT;
+ }
+
+ bool lcl_IsLowerOutlineContent(const weld::TreeIter& rEntry, const weld::TreeView& rTreeView, sal_uInt8 nLevel)
+ {
+ return weld::fromId<const SwOutlineContent*>(rTreeView.get_id(rEntry))->GetOutlineLevel() < nLevel;
+ }
+
+ bool lcl_FindShell(SwWrtShell const * pShell)
+ {
+ bool bFound = false;
+ SwView *pView = SwModule::GetFirstView();
+ while (pView)
+ {
+ if(pShell == &pView->GetWrtShell())
+ {
+ bFound = true;
+ break;
+ }
+ pView = SwModule::GetNextView(pView);
+ }
+ return bFound;
+ }
+
+ bool lcl_IsUiVisibleBookmark(const ::sw::mark::IMark* pMark)
+ {
+ return IDocumentMarkAccess::GetType(*pMark) == IDocumentMarkAccess::MarkType::BOOKMARK;
+ }
+
+ OUString lcl_GetFootnoteText(const SwTextFootnote& rTextFootnote)
+ {
+ SwNodeIndex aIdx(*rTextFootnote.GetStartNode(), 1);
+ SwContentNode* pCNd = aIdx.GetNode().GetTextNode();
+ if(!pCNd)
+ pCNd = aIdx.GetNodes().GoNext(&aIdx);
+ return pCNd->IsTextNode() ? static_cast<SwTextNode*>(pCNd)->GetText() : OUString();
+ }
+
+ void getAnchorPos(SwPosition& rPos)
+ {
+ // get the top most anchor position of the position
+ if (SwFrameFormat* pFlyFormat = rPos.GetNode().GetFlyFormat())
+ {
+ SwNode* pAnchorNode;
+ SwFrameFormat* pTmp = pFlyFormat;
+ while (pTmp && (pAnchorNode = pTmp->GetAnchor().GetAnchorNode()) &&
+ (pTmp = pAnchorNode->GetFlyFormat()))
+ {
+ pFlyFormat = pTmp;
+ }
+ if (const SwPosition* pPos = pFlyFormat->GetAnchor().GetContentAnchor())
+ rPos = *pPos;
+ }
+ }
+
+ bool lcl_IsLowerRegionContent(const weld::TreeIter& rEntry, const weld::TreeView& rTreeView, sal_uInt8 nLevel)
+ {
+ return weld::fromId<const SwRegionContent*>(rTreeView.get_id(rEntry))->GetRegionLevel() < nLevel;
+ }
+}
+
+// Content, contains names and reference at the content type.
+
+SwContent::SwContent(const SwContentType* pCnt, OUString aName, double nYPos) :
+ SwTypeNumber(CTYPE_CNT),
+ m_pParent(pCnt),
+ m_sContentName(std::move(aName)),
+ m_nYPosition(nYPos),
+ m_bInvisible(false)
+{
+}
+
+
+SwTypeNumber::~SwTypeNumber()
+{
+}
+
+bool SwContent::IsProtect() const
+{
+ return false;
+}
+
+bool SwTextFieldContent::IsProtect() const
+{
+ return m_pFormatField->IsProtect();
+}
+
+bool SwPostItContent::IsProtect() const
+{
+ return m_pField->IsProtect();
+}
+
+bool SwURLFieldContent::IsProtect() const
+{
+ return m_pINetAttr->IsProtect();
+}
+
+bool SwRegionContent::IsProtect() const
+{
+ return m_pSectionFormat->GetSection()->IsProtect();
+}
+
+SwGraphicContent::~SwGraphicContent()
+{
+}
+
+SwTOXBaseContent::~SwTOXBaseContent()
+{
+}
+
+const TranslateId STR_CONTENT_TYPE_ARY[] =
+{
+ STR_CONTENT_TYPE_OUTLINE,
+ STR_CONTENT_TYPE_TABLE,
+ STR_CONTENT_TYPE_FRAME,
+ STR_CONTENT_TYPE_GRAPHIC,
+ STR_CONTENT_TYPE_OLE,
+ STR_CONTENT_TYPE_BOOKMARK,
+ STR_CONTENT_TYPE_REGION,
+ STR_CONTENT_TYPE_URLFIELD,
+ STR_CONTENT_TYPE_REFERENCE,
+ STR_CONTENT_TYPE_INDEX,
+ STR_CONTENT_TYPE_POSTIT,
+ STR_CONTENT_TYPE_DRAWOBJECT,
+ STR_CONTENT_TYPE_TEXTFIELD,
+ STR_CONTENT_TYPE_FOOTNOTE,
+ STR_CONTENT_TYPE_ENDNOTE
+};
+
+const TranslateId STR_CONTENT_TYPE_SINGLE_ARY[] =
+{
+ STR_CONTENT_TYPE_SINGLE_OUTLINE,
+ STR_CONTENT_TYPE_SINGLE_TABLE,
+ STR_CONTENT_TYPE_SINGLE_FRAME,
+ STR_CONTENT_TYPE_SINGLE_GRAPHIC,
+ STR_CONTENT_TYPE_SINGLE_OLE,
+ STR_CONTENT_TYPE_SINGLE_BOOKMARK,
+ STR_CONTENT_TYPE_SINGLE_REGION,
+ STR_CONTENT_TYPE_SINGLE_URLFIELD,
+ STR_CONTENT_TYPE_SINGLE_REFERENCE,
+ STR_CONTENT_TYPE_SINGLE_INDEX,
+ STR_CONTENT_TYPE_SINGLE_POSTIT,
+ STR_CONTENT_TYPE_SINGLE_DRAWOBJECT,
+ STR_CONTENT_TYPE_SINGLE_TEXTFIELD,
+ STR_CONTENT_TYPE_SINGLE_FOOTNOTE,
+ STR_CONTENT_TYPE_SINGLE_ENDNOTE
+};
+
+namespace
+{
+ bool checkVisibilityChanged(
+ const SwContentArr& rSwContentArrA,
+ const SwContentArr& rSwContentArrB)
+ {
+ if(rSwContentArrA.size() != rSwContentArrB.size())
+ {
+ return true;
+ }
+
+ for(size_t a(0); a < rSwContentArrA.size(); a++)
+ {
+ if(rSwContentArrA[a]->IsInvisible() != rSwContentArrB[a]->IsInvisible())
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+// Gets "YPos" for content, i.e. a number used to sort content members in Navigator's list
+sal_Int32 getYPos(const SwNode& rNode)
+{
+ SwNodeOffset nIndex = rNode.GetIndex();
+ if (rNode.GetNodes().GetEndOfExtras().GetIndex() >= nIndex)
+ {
+ // Not a node of BodyText
+ // Are we in a fly?
+ if (const auto pFlyFormat = rNode.GetFlyFormat())
+ {
+ // Get node index of anchor
+ if (SwNode* pAnchorNode = pFlyFormat->GetAnchor().GetAnchorNode())
+ {
+ return getYPos(*pAnchorNode);
+ }
+ }
+ }
+ return sal_Int32(nIndex);
+}
+} // end of anonymous namespace
+
+SwContentType::SwContentType(SwWrtShell* pShell, ContentTypeId nType, sal_uInt8 nLevel) :
+ SwTypeNumber(CTYPE_CTT),
+ m_pWrtShell(pShell),
+ m_sContentTypeName(SwResId(STR_CONTENT_TYPE_ARY[static_cast<int>(nType)])),
+ m_sSingleContentTypeName(SwResId(STR_CONTENT_TYPE_SINGLE_ARY[static_cast<int>(nType)])),
+ m_nMemberCount(0),
+ m_nContentType(nType),
+ m_nOutlineLevel(nLevel),
+ m_bDataValid(false),
+ m_bEdit(false),
+ m_bDelete(true)
+{
+ switch(m_nContentType)
+ {
+ case ContentTypeId::OUTLINE:
+ m_sTypeToken = "outline";
+ break;
+ case ContentTypeId::TABLE:
+ m_sTypeToken = "table";
+ m_bEdit = true;
+ break;
+ case ContentTypeId::FRAME:
+ m_sTypeToken = "frame";
+ m_bEdit = true;
+ break;
+ case ContentTypeId::GRAPHIC:
+ m_sTypeToken = "graphic";
+ m_bEdit = true;
+ break;
+ case ContentTypeId::OLE:
+ m_sTypeToken = "ole";
+ m_bEdit = true;
+ break;
+ case ContentTypeId::TEXTFIELD:
+ m_bEdit = true;
+ m_bDelete = true;
+ break;
+ case ContentTypeId::FOOTNOTE:
+ case ContentTypeId::ENDNOTE:
+ m_bEdit = true;
+ m_bDelete = false;
+ break;
+ case ContentTypeId::BOOKMARK:
+ {
+ const bool bProtectedBM = m_pWrtShell->getIDocumentSettingAccess().get(
+ DocumentSettingId::PROTECT_BOOKMARKS);
+ m_bEdit = true;
+ m_bDelete = !bProtectedBM;
+ }
+ break;
+ case ContentTypeId::REGION:
+ m_sTypeToken = "region";
+ m_bEdit = true;
+ m_bDelete = true;
+ break;
+ case ContentTypeId::INDEX:
+ m_bEdit = true;
+ m_bDelete = true;
+ break;
+ case ContentTypeId::REFERENCE:
+ m_bEdit = false;
+ m_bDelete = true;
+ break;
+ case ContentTypeId::URLFIELD:
+ m_bEdit = true;
+ m_bDelete = true;
+ break;
+ case ContentTypeId::POSTIT:
+ m_bEdit = true;
+ break;
+ case ContentTypeId::DRAWOBJECT:
+ m_sTypeToken = "drawingobject";
+ m_bEdit = true;
+ break;
+ default: break;
+ }
+
+ const int nShift = static_cast<int>(m_nContentType);
+ assert(nShift > -1);
+ const sal_Int32 nMask = 1 << nShift;
+ const sal_Int32 nBlock = SW_MOD()->GetNavigationConfig()->GetSortAlphabeticallyBlock();
+ m_bAlphabeticSort = nBlock & nMask;
+
+ FillMemberList();
+}
+
+SwContentType::~SwContentType()
+{
+}
+
+const SwContent* SwContentType::GetMember(size_t nIndex)
+{
+ if(!m_bDataValid || !m_pMember)
+ {
+ FillMemberList();
+ }
+ if(nIndex < m_pMember->size())
+ return (*m_pMember)[nIndex].get();
+
+ return nullptr;
+}
+
+void SwContentType::Invalidate()
+{
+ m_bDataValid = false;
+}
+
+void SwContentType::FillMemberList(bool* pbContentChanged)
+{
+ std::unique_ptr<SwContentArr> pOldMember;
+ size_t nOldMemberCount = 0;
+ if(m_pMember && pbContentChanged)
+ {
+ pOldMember = std::move(m_pMember);
+ nOldMemberCount = pOldMember->size();
+ m_pMember.reset( new SwContentArr );
+ *pbContentChanged = false;
+ }
+ else if(!m_pMember)
+ m_pMember.reset( new SwContentArr );
+ else
+ m_pMember->clear();
+ switch(m_nContentType)
+ {
+ case ContentTypeId::OUTLINE :
+ {
+ const SwNodeOffset nEndOfExtrasIndex = m_pWrtShell->GetNodes().GetEndOfExtras().GetIndex();
+ // provide for up to 99999 outline nodes in frames to be sorted in document layout order
+ double nOutlinesInFramesIndexAdjustment = 0.00001;
+ const SwOutlineNodes& rOutlineNodes(m_pWrtShell->GetNodes().GetOutLineNds());
+ const size_t nOutlineCount = rOutlineNodes.size();
+
+ for (size_t i = 0; i < nOutlineCount; ++i)
+ {
+ SwTextNode* pNode = rOutlineNodes[i]->GetTextNode();
+ const sal_uInt8 nLevel = pNode->GetAttrOutlineLevel() - 1;
+ if (nLevel >= m_nOutlineLevel)
+ continue;
+ double nYPos = m_bAlphabeticSort ? 0 : static_cast<double>(getYPos(*pNode));
+ if (nEndOfExtrasIndex >= pNode->GetIndex() && pNode->GetFlyFormat())
+ {
+ nYPos += nOutlinesInFramesIndexAdjustment;
+ nOutlinesInFramesIndexAdjustment += 0.00001;
+ }
+ OUString aEntry(comphelper::string::stripStart(
+ m_pWrtShell->getIDocumentOutlineNodesAccess()->getOutlineText(
+ i, m_pWrtShell->GetLayout(), true, false, false), ' '));
+ aEntry = SwNavigationPI::CleanEntry(aEntry);
+ auto pCnt(std::make_unique<SwOutlineContent>(this, aEntry, i, nLevel,
+ m_pWrtShell->IsOutlineMovable(i), nYPos));
+ if (!pNode->getLayoutFrame(m_pWrtShell->GetLayout()))
+ pCnt->SetInvisible();
+ m_pMember->insert(std::move(pCnt));
+ }
+
+ // need to check level and equal entry number after creation due to possible outline
+ // nodes in frames, headers, footers
+ if (pOldMember)
+ {
+ assert(pbContentChanged && "pbContentChanged is always set if pOldMember is");
+ if (pOldMember->size() != m_pMember->size())
+ {
+ *pbContentChanged = true;
+ break;
+ }
+ for (size_t i = 0; i < pOldMember->size(); i++)
+ {
+ if (static_cast<SwOutlineContent*>((*pOldMember)[i].get())->GetOutlineLevel() !=
+ static_cast<SwOutlineContent*>((*m_pMember)[i].get())->GetOutlineLevel())
+ {
+ *pbContentChanged = true;
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case ContentTypeId::TABLE :
+ {
+ const size_t nCount = m_pWrtShell->GetTableFrameFormatCount(true);
+ const sw::TableFrameFormats* pFrameFormats = m_pWrtShell->GetDoc()->GetTableFrameFormats();
+ for(size_t n = 0, i = 0; i < nCount + n; ++i)
+ {
+ const SwTableFormat& rTableFormat = *(*pFrameFormats)[i];
+ if(!rTableFormat.IsUsed()) // skip deleted tables
+ {
+ n++;
+ continue;
+ }
+ tools::Long nYPos = 0;
+ if (!m_bAlphabeticSort)
+ {
+ if (SwTable* pTable = SwTable::FindTable(&rTableFormat))
+ nYPos = getYPos(*pTable->GetTableNode());
+ }
+ auto pCnt = std::make_unique<SwContent>(this, rTableFormat.GetName(), nYPos);
+ if(!rTableFormat.IsVisible())
+ pCnt->SetInvisible();
+ m_pMember->insert(std::move(pCnt));
+ }
+
+ if (pOldMember)
+ {
+ // need to check visibility (and equal entry number) after
+ // creation due to a sorted list being used here (before,
+ // entries with same index were compared already at creation
+ // time what worked before a sorted list was used)
+ *pbContentChanged = checkVisibilityChanged(
+ *pOldMember,
+ *m_pMember);
+ }
+ }
+ break;
+ case ContentTypeId::OLE :
+ case ContentTypeId::FRAME :
+ case ContentTypeId::GRAPHIC :
+ {
+ FlyCntType eType = FLYCNTTYPE_FRM;
+ if(m_nContentType == ContentTypeId::OLE)
+ eType = FLYCNTTYPE_OLE;
+ else if(m_nContentType == ContentTypeId::GRAPHIC)
+ eType = FLYCNTTYPE_GRF;
+ Point aNullPt;
+ size_t nCount = m_pWrtShell->GetFlyCount(eType, /*bIgnoreTextBoxes=*/true);
+ std::vector<SwFrameFormat const*> formats(m_pWrtShell->GetFlyFrameFormats(eType, /*bIgnoreTextBoxes=*/true));
+ SAL_WARN_IF(nCount != formats.size(), "sw.ui", "Count differs");
+ nCount = formats.size();
+ for (size_t i = 0; i < nCount; ++i)
+ {
+ SwFrameFormat const*const pFrameFormat = formats[i];
+ const OUString sFrameName = pFrameFormat->GetName();
+
+ SwContent* pCnt;
+ tools::Long nYPos =
+ m_bAlphabeticSort ? 0 : pFrameFormat->FindLayoutRect(false, &aNullPt).Top();
+ if(ContentTypeId::GRAPHIC == m_nContentType)
+ {
+ OUString sLink;
+ m_pWrtShell->GetGrfNms( &sLink, nullptr, static_cast<const SwFlyFrameFormat*>( pFrameFormat));
+ pCnt = new SwGraphicContent(this, sFrameName, INetURLObject::decode(sLink,
+ INetURLObject::DecodeMechanism::Unambiguous), nYPos);
+ }
+ else
+ {
+ pCnt = new SwContent(this, sFrameName, nYPos);
+ }
+ if(!pFrameFormat->IsVisible())
+ pCnt->SetInvisible();
+ m_pMember->insert(std::unique_ptr<SwContent>(pCnt));
+ }
+
+ if (pOldMember)
+ {
+ // need to check visibility (and equal entry number) after
+ // creation due to a sorted list being used here (before,
+ // entries with same index were compared already at creation
+ // time what worked before a sorted list was used)
+ assert(pbContentChanged && "pbContentChanged is always set if pOldMember is");
+ *pbContentChanged = checkVisibilityChanged(
+ *pOldMember,
+ *m_pMember);
+ }
+ }
+ break;
+ case ContentTypeId::BOOKMARK:
+ {
+ tools::Long nYPos = 0;
+ IDocumentMarkAccess* const pMarkAccess = m_pWrtShell->getIDocumentMarkAccess();
+ for(IDocumentMarkAccess::const_iterator_t ppBookmark = pMarkAccess->getBookmarksBegin();
+ ppBookmark != pMarkAccess->getBookmarksEnd();
+ ++ppBookmark)
+ {
+ if(lcl_IsUiVisibleBookmark(*ppBookmark))
+ {
+ const OUString& rBkmName = (*ppBookmark)->GetName();
+ //nYPos from 0 -> text::Bookmarks will be sorted alphabetically
+ auto pCnt(std::make_unique<SwContent>(this, rBkmName,
+ m_bAlphabeticSort ? 0 : nYPos++));
+ m_pMember->insert(std::move(pCnt));
+ }
+ }
+ }
+ break;
+ case ContentTypeId::TEXTFIELD:
+ {
+ std::vector<SwTextField*> aArr;
+ const SwFieldTypes& rFieldTypes =
+ *m_pWrtShell->GetDoc()->getIDocumentFieldsAccess().GetFieldTypes();
+ const size_t nSize = rFieldTypes.size();
+ for (size_t i = 0; i < nSize; ++i)
+ {
+ const SwFieldType* pFieldType = rFieldTypes[i].get();
+ if (pFieldType->Which() == SwFieldIds::Postit)
+ continue;
+ std::vector<SwFormatField*> vFields;
+ pFieldType->GatherFields(vFields);
+ for (SwFormatField* pFormatField: vFields)
+ {
+ if (SwTextField* pTextField = pFormatField->GetTextField())
+ {
+ // fields in header footer don't behave well, skip them
+ if (m_pWrtShell->GetDoc()->IsInHeaderFooter(pTextField->GetTextNode()))
+ continue;
+ aArr.emplace_back(pTextField);
+ }
+ }
+ }
+ if (!m_bAlphabeticSort)
+ {
+ const SwNodeOffset nEndOfExtrasIndex =
+ m_pWrtShell->GetNodes().GetEndOfExtras().GetIndex();
+ // use stable sort array to list fields in document model order
+ std::stable_sort(aArr.begin(), aArr.end(),
+ [&nEndOfExtrasIndex, this](
+ const SwTextField* a, const SwTextField* b){
+ SwPosition aPos(a->GetTextNode(), a->GetStart());
+ SwPosition bPos(b->GetTextNode(), b->GetStart());
+ // use anchor position for entries that are located in flys
+ if (nEndOfExtrasIndex >= aPos.GetNodeIndex())
+ getAnchorPos(aPos);
+ if (nEndOfExtrasIndex >= bPos.GetNodeIndex())
+ getAnchorPos(bPos);
+ if (aPos == bPos)
+ {
+ // probably in same or nested fly frame
+ // sort using layout position
+ SwRect aCharRect, bCharRect;
+ std::shared_ptr<SwPaM> pPamForTextField;
+ if (SwTextFrame* pFrame = static_cast<SwTextFrame*>(
+ a->GetTextNode().getLayoutFrame(m_pWrtShell->GetLayout())))
+ {
+ SwTextField::GetPamForTextField(*a, pPamForTextField);
+ if (pPamForTextField)
+ pFrame->GetCharRect(aCharRect, *pPamForTextField->GetPoint());
+ }
+ if (SwTextFrame* pFrame = static_cast<SwTextFrame*>(
+ b->GetTextNode().getLayoutFrame(m_pWrtShell->GetLayout())))
+ {
+ SwTextField::GetPamForTextField(*b, pPamForTextField);
+ if (pPamForTextField)
+ pFrame->GetCharRect(bCharRect, *pPamForTextField->GetPoint());
+ }
+ return aCharRect.Top() < bCharRect.Top();
+ }
+ return aPos < bPos;});
+ }
+ std::vector<OUString> aDocumentStatisticsSubTypesList;
+ tools::Long nYPos = 0;
+ for (SwTextField* pTextField : aArr)
+ {
+ const SwField* pField = pTextField->GetFormatField().GetField();
+ OUString sExpandField = pField->ExpandField(true, m_pWrtShell->GetLayout());
+ if (!sExpandField.isEmpty())
+ sExpandField = u" - " + sExpandField;
+ OUString sText;
+ if (pField->GetTypeId() == SwFieldTypesEnum::DocumentStatistics)
+ {
+ if (aDocumentStatisticsSubTypesList.empty())
+ SwFieldMgr(m_pWrtShell).GetSubTypes(SwFieldTypesEnum::DocumentStatistics,
+ aDocumentStatisticsSubTypesList);
+ OUString sSubType;
+ if (pField->GetSubType() < aDocumentStatisticsSubTypesList.size())
+ sSubType = u" - " + aDocumentStatisticsSubTypesList[pField->GetSubType()];
+ sText = pField->GetDescription() + u" - " + pField->GetFieldName() + sSubType +
+ sExpandField;
+ }
+ else if (pField->GetTypeId() == SwFieldTypesEnum::GetRef)
+ {
+ assert(dynamic_cast<const SwGetRefField*>(pField));
+ const SwGetRefField* pRefField(static_cast<const SwGetRefField*>(pField));
+ if (pRefField->IsRefToHeadingCrossRefBookmark() ||
+ pRefField->IsRefToNumItemCrossRefBookmark())
+ {
+ OUString sExpandedTextOfReferencedTextNode =
+ pRefField->GetExpandedTextOfReferencedTextNode(
+ *m_pWrtShell->GetLayout(), nullptr, nullptr);
+ if (sExpandedTextOfReferencedTextNode.getLength() > 80)
+ {
+ sExpandedTextOfReferencedTextNode = OUString::Concat(
+ sExpandedTextOfReferencedTextNode.subView(0, 80)) + u"...";
+ }
+ sText = pField->GetDescription() + u" - "
+ + sExpandedTextOfReferencedTextNode + sExpandField;
+ }
+ else
+ {
+ OUString sFieldSubTypeOrName;
+ auto nSubType = pField->GetSubType();
+ if (nSubType == REF_FOOTNOTE)
+ sFieldSubTypeOrName = SwResId(STR_FLDREF_FOOTNOTE);
+ else if (nSubType == REF_ENDNOTE)
+ sFieldSubTypeOrName = SwResId(STR_FLDREF_ENDNOTE);
+ else
+ sFieldSubTypeOrName = pField->GetFieldName();
+ sText = pField->GetDescription() + u" - " + sFieldSubTypeOrName
+ + sExpandField;
+ }
+ }
+ else
+ sText = pField->GetDescription() + u" - " + pField->GetFieldName()
+ + sExpandField;
+ auto pCnt(std::make_unique<SwTextFieldContent>(this, sText,
+ &pTextField->GetFormatField(),
+ m_bAlphabeticSort ? 0 : nYPos++));
+ if (!pTextField->GetTextNode().getLayoutFrame(m_pWrtShell->GetLayout()))
+ pCnt->SetInvisible();
+ m_pMember->insert(std::move(pCnt));
+ }
+ }
+ break;
+ // We will separate footnotes and endnotes here.
+ case ContentTypeId::FOOTNOTE:
+ case ContentTypeId::ENDNOTE:
+ {
+ const SwFootnoteIdxs& rFootnoteIdxs = m_pWrtShell->GetDoc()->GetFootnoteIdxs();
+ if (rFootnoteIdxs.size() == 0)
+ break;
+ // insert footnotes and endnotes
+ tools::Long nPos = 0;
+ for (const SwTextFootnote* pTextFootnote : rFootnoteIdxs)
+ {
+ if ((!pTextFootnote->GetFootnote().IsEndNote()
+ && m_nContentType == ContentTypeId::FOOTNOTE)
+ || (pTextFootnote->GetFootnote().IsEndNote()
+ && m_nContentType == ContentTypeId::ENDNOTE))
+ {
+ const SwFormatFootnote& rFormatFootnote = pTextFootnote->GetFootnote();
+ const OUString& sText
+ = rFormatFootnote.GetViewNumStr(*m_pWrtShell->GetDoc(),
+ m_pWrtShell->GetLayout(), true)
+ + " " + lcl_GetFootnoteText(*pTextFootnote);
+ auto pCnt(std::make_unique<SwTextFootnoteContent>(
+ this, sText, pTextFootnote, ++nPos));
+ if (!pTextFootnote->GetTextNode().getLayoutFrame(m_pWrtShell->GetLayout()))
+ pCnt->SetInvisible();
+ m_pMember->insert(std::move(pCnt));
+ }
+ }
+ }
+ break;
+ case ContentTypeId::REGION :
+ {
+ size_t nCount = m_pWrtShell->GetSectionFormatCount();
+ for (size_t i = 0; i < nCount; ++i)
+ {
+ const SwSectionFormat* pFormat = &m_pWrtShell->GetSectionFormat(i);
+ if (!pFormat->IsInNodesArr())
+ continue;
+ const SwSection* pSection = pFormat->GetSection();
+ if (SectionType eTmpType = pSection->GetType();
+ eTmpType == SectionType::ToxContent || eTmpType == SectionType::ToxHeader)
+ continue;
+ const SwNodeIndex* pNodeIndex = pFormat->GetContent().GetContentIdx();
+ if (pNodeIndex)
+ {
+ const OUString& sSectionName = pSection->GetSectionName();
+
+ sal_uInt8 nLevel = 0;
+ SwSectionFormat* pParentFormat = pFormat->GetParent();
+ while(pParentFormat)
+ {
+ nLevel++;
+ pParentFormat = pParentFormat->GetParent();
+ }
+
+ auto pCnt(std::make_unique<SwRegionContent>(this, sSectionName, nLevel,
+ m_bAlphabeticSort ? 0 : getYPos(pNodeIndex->GetNode()),
+ pFormat));
+
+ if (!pFormat->IsVisible() || pSection->IsHidden())
+ pCnt->SetInvisible();
+ m_pMember->insert(std::move(pCnt));
+ }
+
+ if (pOldMember)
+ {
+ // need to check visibility (and equal entry number) after
+ // creation due to a sorted list being used here (before,
+ // entries with same index were compared already at creation
+ // time what worked before a sorted list was used)
+ assert(pbContentChanged && "pbContentChanged is always set if pOldMember is");
+ *pbContentChanged = checkVisibilityChanged(
+ *pOldMember,
+ *m_pMember);
+ }
+ }
+ }
+ break;
+ case ContentTypeId::REFERENCE:
+ {
+ std::vector<OUString> aRefMarks;
+ m_pWrtShell->GetRefMarks( &aRefMarks );
+
+ tools::Long nYPos = 0;
+ for (const auto& rRefMark : aRefMarks)
+ {
+ m_pMember->insert(std::make_unique<SwContent>(this, rRefMark,
+ m_bAlphabeticSort ? 0 : nYPos++));
+ }
+ }
+ break;
+ case ContentTypeId::URLFIELD:
+ {
+ SwGetINetAttrs aArr;
+ m_pWrtShell->GetINetAttrs(aArr, false);
+
+ if (m_bAlphabeticSort)
+ {
+ for (auto& r : aArr)
+ {
+ auto pCnt(std::make_unique<SwURLFieldContent>(this, r.sText, INetURLObject::decode(
+ r.rINetAttr.GetINetFormat().GetValue(),
+ INetURLObject::DecodeMechanism::Unambiguous),
+ &r.rINetAttr, 0));
+ m_pMember->insert(std::move(pCnt));
+ }
+ break;
+ }
+
+ // use stable sort array to list hyperlinks in document order
+ const SwNodeOffset nEndOfExtrasIndex = m_pWrtShell->GetNodes().GetEndOfExtras().GetIndex();
+ bool bHasEntryInFly = false;
+ std::vector<SwGetINetAttr*> aStableSortINetAttrsArray;
+
+ for (SwGetINetAttr& r : aArr)
+ {
+ aStableSortINetAttrsArray.emplace_back(&r);
+ if (!bHasEntryInFly)
+ {
+ if (nEndOfExtrasIndex >= r.rINetAttr.GetTextNode().GetIndex())
+ {
+ // Not a node of BodyText
+ // Are we in a fly?
+ if (r.rINetAttr.GetTextNode().GetFlyFormat())
+ bHasEntryInFly = true;
+ }
+ }
+ }
+
+ std::stable_sort(aStableSortINetAttrsArray.begin(), aStableSortINetAttrsArray.end(),
+ [](const SwGetINetAttr* a, const SwGetINetAttr* b){
+ SwPosition aSwPos(a->rINetAttr.GetTextNode(),
+ a->rINetAttr.GetStart());
+ SwPosition bSwPos(b->rINetAttr.GetTextNode(),
+ b->rINetAttr.GetStart());
+ return aSwPos < bSwPos;});
+
+ // When there are hyperlinks in text frames do an additional sort using the text frame
+ // anchor position to place entries in the order of document layout appearance.
+ if (bHasEntryInFly)
+ {
+ std::stable_sort(aStableSortINetAttrsArray.begin(), aStableSortINetAttrsArray.end(),
+ [nEndOfExtrasIndex](const SwGetINetAttr* a, const SwGetINetAttr* b){
+ const SwTextNode& aTextNode = a->rINetAttr.GetTextNode();
+ const SwTextNode& bTextNode = b->rINetAttr.GetTextNode();
+ SwPosition aPos(aTextNode, a->rINetAttr.GetStart());
+ SwPosition bPos(bTextNode, b->rINetAttr.GetStart());
+ // use anchor position for entries that are located in flys
+ if (nEndOfExtrasIndex >= aTextNode.GetIndex())
+ if (auto pFlyFormat = aTextNode.GetFlyFormat())
+ if (const SwPosition* pPos = pFlyFormat->GetAnchor().GetContentAnchor())
+ aPos = *pPos;
+ if (nEndOfExtrasIndex >= bTextNode.GetIndex())
+ if (auto pFlyFormat = bTextNode.GetFlyFormat())
+ if (const SwPosition* pPos = pFlyFormat->GetAnchor().GetContentAnchor())
+ bPos = *pPos;
+ return aPos < bPos;});
+ }
+
+ SwGetINetAttrs::size_type n = 0;
+ for (auto p : aStableSortINetAttrsArray)
+ {
+ auto pCnt = std::make_unique<SwURLFieldContent>(this, p->sText,
+ INetURLObject::decode(p->rINetAttr.GetINetFormat().GetValue(),
+ INetURLObject::DecodeMechanism::Unambiguous),
+ &p->rINetAttr, ++n);
+ m_pMember->insert(std::move(pCnt));
+ }
+ }
+ break;
+ case ContentTypeId::INDEX:
+ {
+ const sal_uInt16 nCount = m_pWrtShell->GetTOXCount();
+
+ for ( sal_uInt16 nTox = 0; nTox < nCount; nTox++ )
+ {
+ const SwTOXBase* pBase = m_pWrtShell->GetTOX( nTox );
+ OUString sTOXNm( pBase->GetTOXName() );
+
+ SwContent* pCnt = new SwTOXBaseContent(
+ this, sTOXNm, m_bAlphabeticSort ? 0 : nTox, *pBase);
+
+ if(pBase && !pBase->IsVisible())
+ pCnt->SetInvisible();
+
+ m_pMember->insert( std::unique_ptr<SwContent>(pCnt) );
+ const size_t nPos = m_pMember->size() - 1;
+ if (pOldMember)
+ {
+ assert(pbContentChanged && "pbContentChanged is always set if pOldMember is");
+ if (!*pbContentChanged && nOldMemberCount > nPos &&
+ (*pOldMember)[nPos]->IsInvisible() != pCnt->IsInvisible())
+ *pbContentChanged = true;
+ }
+ }
+ }
+ break;
+ case ContentTypeId::POSTIT:
+ {
+ SwPostItMgr* aMgr = m_pWrtShell->GetView().GetPostItMgr();
+ if (aMgr)
+ {
+ tools::Long nYPos = 0;
+ for(SwPostItMgr::const_iterator i = aMgr->begin(); i != aMgr->end(); ++i)
+ {
+ if (const SwFormatField* pFormatField = dynamic_cast<const SwFormatField *>((*i)->GetBroadcaster())) // SwPostit
+ {
+ if (pFormatField->GetTextField() && pFormatField->IsFieldInDoc())
+ {
+ OUString sEntry = pFormatField->GetField()->GetPar2();
+ sEntry = RemoveNewline(sEntry);
+ std::unique_ptr<SwPostItContent> pCnt(new SwPostItContent(
+ this,
+ sEntry,
+ pFormatField,
+ nYPos));
+ if (!pFormatField->GetTextField()->GetTextNode().getLayoutFrame(
+ m_pWrtShell->GetLayout()))
+ pCnt->SetInvisible();
+ if (pOldMember)
+ {
+ assert(pbContentChanged && "pbContentChanged is always set if pOldMember is");
+ if (!*pbContentChanged &&
+ nOldMemberCount > o3tl::make_unsigned(nYPos) &&
+ (*pOldMember)[nYPos]->IsInvisible() != pCnt->IsInvisible())
+ *pbContentChanged = true;
+ }
+ m_pMember->insert(std::move(pCnt));
+ nYPos++;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case ContentTypeId::DRAWOBJECT:
+ {
+ IDocumentDrawModelAccess& rIDDMA = m_pWrtShell->getIDocumentDrawModelAccess();
+ SwDrawModel* pModel = rIDDMA.GetDrawModel();
+ if(pModel)
+ {
+ SdrPage* pPage = pModel->GetPage(0);
+ for (const rtl::Reference<SdrObject>& pTemp : *pPage)
+ {
+ // #i51726# - all drawing objects can be named now
+ if (!pTemp->GetName().isEmpty())
+ {
+ tools::Long nYPos = LONG_MIN;
+ const bool bIsVisible = rIDDMA.IsVisibleLayerId(pTemp->GetLayer());
+ if (bIsVisible)
+ nYPos = m_bAlphabeticSort ? 0 : pTemp->GetLogicRect().Top();
+ auto pCnt(std::make_unique<SwContent>(this, pTemp->GetName(), nYPos));
+ if (!bIsVisible)
+ pCnt->SetInvisible();
+ m_pMember->insert(std::move(pCnt));
+ }
+ }
+
+ if (pOldMember)
+ {
+ // need to check visibility (and equal entry number) after
+ // creation due to a sorted list being used here (before,
+ // entries with same index were compared already at creation
+ // time what worked before a sorted list was used)
+ assert(pbContentChanged && "pbContentChanged is always set if pOldMember is");
+ *pbContentChanged = checkVisibilityChanged(
+ *pOldMember,
+ *m_pMember);
+ }
+ }
+ }
+ break;
+ default: break;
+ }
+ m_nMemberCount = m_pMember->size();
+ if (pOldMember)
+ {
+ assert(pbContentChanged && "pbContentChanged is always set if pOldMember is");
+ if (!*pbContentChanged && pOldMember->size() != m_nMemberCount)
+ *pbContentChanged = true;
+ }
+
+ m_bDataValid = true;
+}
+
+namespace {
+
+enum STR_CONTEXT_IDX
+{
+ IDX_STR_OUTLINE_LEVEL = 0,
+ IDX_STR_DRAGMODE = 1,
+ IDX_STR_HYPERLINK = 2,
+ IDX_STR_LINK_REGION = 3,
+ IDX_STR_COPY_REGION = 4,
+ IDX_STR_DISPLAY = 5,
+ IDX_STR_ACTIVE_VIEW = 6,
+ IDX_STR_HIDDEN = 7,
+ IDX_STR_ACTIVE = 8,
+ IDX_STR_INACTIVE = 9,
+ IDX_STR_EDIT_ENTRY = 10,
+ IDX_STR_DELETE_ENTRY = 11,
+ IDX_STR_SEND_OUTLINE_TO_CLIPBOARD_ENTRY = 12,
+ IDX_STR_OUTLINE_TRACKING = 13,
+ IDX_STR_OUTLINE_TRACKING_DEFAULT = 14,
+ IDX_STR_OUTLINE_TRACKING_FOCUS = 15,
+ IDX_STR_OUTLINE_TRACKING_OFF = 16
+};
+
+}
+
+const TranslateId STR_CONTEXT_ARY[] =
+{
+ STR_OUTLINE_LEVEL,
+ STR_DRAGMODE,
+ STR_HYPERLINK,
+ STR_LINK_REGION,
+ STR_COPY_REGION,
+ STR_DISPLAY,
+ STR_ACTIVE_VIEW,
+ STR_HIDDEN,
+ STR_ACTIVE,
+ STR_INACTIVE,
+ STR_EDIT_ENTRY,
+ STR_DELETE_ENTRY,
+ STR_SEND_OUTLINE_TO_CLIPBOARD_ENTRY,
+ STR_OUTLINE_TRACKING,
+ STR_OUTLINE_TRACKING_DEFAULT,
+ STR_OUTLINE_TRACKING_FOCUS,
+ STR_OUTLINE_TRACKING_OFF
+};
+
+SwContentTree::SwContentTree(std::unique_ptr<weld::TreeView> xTreeView, SwNavigationPI* pDialog)
+ : m_xTreeView(std::move(xTreeView))
+ , m_aDropTargetHelper(*this)
+ , m_pDialog(pDialog)
+ , m_sSpace(OUString(" "))
+ , m_aUpdTimer("SwContentTree m_aUpdTimer")
+ , m_aOverlayObjectDelayTimer("SwContentTree m_aOverlayObjectDelayTimer")
+ , m_sInvisible(SwResId(STR_INVISIBLE))
+ , m_pHiddenShell(nullptr)
+ , m_pActiveShell(nullptr)
+ , m_pConfig(SW_MOD()->GetNavigationConfig())
+ , m_nActiveBlock(0)
+ , m_nHiddenBlock(0)
+ , m_nEntryCount(0)
+ , m_nRootType(ContentTypeId::UNKNOWN)
+ , m_nLastSelType(ContentTypeId::UNKNOWN)
+ , m_nOutlineLevel(MAXLEVEL)
+ , m_eState(State::ACTIVE)
+ , m_bIsRoot(false)
+ , m_bIsIdleClear(false)
+ , m_bIsLastReadOnly(false)
+ , m_bIsOutlineMoveable(true)
+ , m_bViewHasChanged(false)
+{
+ m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 30,
+ m_xTreeView->get_text_height() * 14);
+
+ m_xTreeView->set_help_id(HID_NAVIGATOR_TREELIST);
+
+ m_xTreeView->connect_expanding(LINK(this, SwContentTree, ExpandHdl));
+ m_xTreeView->connect_collapsing(LINK(this, SwContentTree, CollapseHdl));
+ m_xTreeView->connect_row_activated(LINK(this, SwContentTree, ContentDoubleClickHdl));
+ m_xTreeView->connect_changed(LINK(this, SwContentTree, SelectHdl));
+ m_xTreeView->connect_focus_in(LINK(this, SwContentTree, FocusInHdl));
+ m_xTreeView->connect_key_press(LINK(this, SwContentTree, KeyInputHdl));
+ m_xTreeView->connect_popup_menu(LINK(this, SwContentTree, CommandHdl));
+ m_xTreeView->connect_query_tooltip(LINK(this, SwContentTree, QueryTooltipHdl));
+ m_xTreeView->connect_drag_begin(LINK(this, SwContentTree, DragBeginHdl));
+ m_xTreeView->connect_mouse_move(LINK(this, SwContentTree, MouseMoveHdl));
+ m_xTreeView->connect_mouse_press(LINK(this, SwContentTree, MousePressHdl));
+
+ for (ContentTypeId i : o3tl::enumrange<ContentTypeId>())
+ {
+ if (i != ContentTypeId::OUTLINE)
+ mTrackContentType[i] = true;
+ m_aActiveContentArr[i] = nullptr;
+ m_aHiddenContentArr[i] = nullptr;
+ }
+ for (int i = 0; i < CONTEXT_COUNT; ++i)
+ {
+ m_aContextStrings[i] = SwResId(STR_CONTEXT_ARY[i]);
+ }
+ m_nActiveBlock = m_pConfig->GetActiveBlock();
+
+ // Restore outline headings expand state (same session persistence only)
+ if (SwView* pView = GetActiveView(); pView && pView->GetDocShell())
+ {
+ OUString sDocTitle = pView->GetDocShell()->GetTitle();
+ auto it = lcl_DocOutLineExpandStateMap.find(sDocTitle);
+ if (it != lcl_DocOutLineExpandStateMap.end())
+ mOutLineNodeMap = it->second;
+ if (comphelper::LibreOfficeKit::isActive()) {
+ if (pView->m_nNaviExpandedStatus < 0)
+ m_nActiveBlock = 1;
+ else
+ m_nActiveBlock = pView->m_nNaviExpandedStatus;
+ }
+ }
+
+ m_aUpdTimer.SetInvokeHandler(LINK(this, SwContentTree, TimerUpdate));
+ m_aUpdTimer.SetTimeout(1000);
+ m_aOverlayObjectDelayTimer.SetInvokeHandler(LINK(this, SwContentTree, OverlayObjectDelayTimerHdl));
+ m_aOverlayObjectDelayTimer.SetTimeout(500);
+}
+
+SwContentTree::~SwContentTree()
+{
+ if (SwView* pView = GetActiveView(); pView && pView->GetDocShell())
+ {
+ OUString sDocTitle = pView->GetDocShell()->GetTitle();
+ lcl_DocOutLineExpandStateMap[sDocTitle] = mOutLineNodeMap;
+ if (comphelper::LibreOfficeKit::isActive())
+ pView->m_nNaviExpandedStatus = m_nActiveBlock;
+ }
+ clear(); // If applicable erase content types previously.
+ m_aUpdTimer.Stop();
+ SetActiveShell(nullptr);
+}
+
+IMPL_LINK(SwContentTree, MousePressHdl, const MouseEvent&, rMEvt, bool)
+{
+ m_bSelectTo = rMEvt.IsShift() && (m_pConfig->IsNavigateOnSelect() || rMEvt.GetClicks() == 2);
+ return false;
+}
+
+IMPL_LINK(SwContentTree, MouseMoveHdl, const MouseEvent&, rMEvt, bool)
+{
+ if (m_eState == State::HIDDEN)
+ return false;
+ if (std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ m_xTreeView->get_dest_row_at_pos(rMEvt.GetPosPixel(), xEntry.get(), false, false) &&
+ !rMEvt.IsLeaveWindow())
+ {
+ if (!m_xOverlayCompareEntry)
+ m_xOverlayCompareEntry.reset(m_xTreeView->make_iterator().release());
+ else if (m_xTreeView->iter_compare(*xEntry, *m_xOverlayCompareEntry) == 0)
+ return false; // The entry under the mouse has not changed.
+ m_xTreeView->copy_iterator(*xEntry, *m_xOverlayCompareEntry);
+ BringEntryToAttention(*xEntry);
+ }
+ else
+ {
+ if (m_xOverlayCompareEntry)
+ m_xOverlayCompareEntry.reset();
+ m_aOverlayObjectDelayTimer.Stop();
+ if (m_xOverlayObject && m_xOverlayObject->getOverlayManager())
+ {
+ m_xOverlayObject->getOverlayManager()->remove(*m_xOverlayObject);
+ m_xOverlayObject.reset();
+ }
+ }
+ return false;
+}
+
+// Drag&Drop methods
+IMPL_LINK(SwContentTree, DragBeginHdl, bool&, rUnsetDragIcon, bool)
+{
+ rUnsetDragIcon = true;
+
+ bool bDisallow = true;
+
+ // don't allow if tree root is selected
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ bool bEntry = m_xTreeView->get_selected(xEntry.get());
+ if (!bEntry || lcl_IsContentType(*xEntry, *m_xTreeView))
+ {
+ return true; // disallow
+ }
+
+ rtl::Reference<TransferDataContainer> xContainer = new TransferDataContainer;
+ sal_Int8 nDragMode = DND_ACTION_COPYMOVE | DND_ACTION_LINK;
+
+ if (FillTransferData(*xContainer, nDragMode))
+ bDisallow = false;
+
+ if (m_bIsRoot && m_nRootType == ContentTypeId::OUTLINE)
+ {
+ // Only move drag entry and continuous selected siblings:
+ m_aDndOutlinesSelected.clear();
+
+ std::unique_ptr<weld::TreeIter> xScratch(m_xTreeView->make_iterator());
+
+ // Find first selected of continuous siblings
+ while (true)
+ {
+ m_xTreeView->copy_iterator(*xEntry, *xScratch);
+ if (!m_xTreeView->iter_previous_sibling(*xScratch))
+ break;
+ if (!m_xTreeView->is_selected(*xScratch))
+ break;
+ m_xTreeView->copy_iterator(*xScratch, *xEntry);
+ }
+ // Record continuous selected siblings
+ do
+ {
+ m_aDndOutlinesSelected.push_back(m_xTreeView->make_iterator(xEntry.get()));
+ }
+ while (m_xTreeView->iter_next_sibling(*xEntry) && m_xTreeView->is_selected(*xEntry));
+ bDisallow = false;
+ }
+
+ if (!bDisallow)
+ m_xTreeView->enable_drag_source(xContainer, nDragMode);
+ return bDisallow;
+}
+
+SwContentTreeDropTarget::SwContentTreeDropTarget(SwContentTree& rTreeView)
+ : DropTargetHelper(rTreeView.get_widget().get_drop_target())
+ , m_rTreeView(rTreeView)
+{
+}
+
+sal_Int8 SwContentTreeDropTarget::AcceptDrop(const AcceptDropEvent& rEvt)
+{
+ sal_Int8 nAccept = m_rTreeView.AcceptDrop(rEvt);
+
+ if (nAccept != DND_ACTION_NONE)
+ {
+ // to enable the autoscroll when we're close to the edges
+ weld::TreeView& rWidget = m_rTreeView.get_widget();
+ rWidget.get_dest_row_at_pos(rEvt.maPosPixel, nullptr, true);
+ }
+
+ return nAccept;
+}
+
+bool SwContentTree::IsInDrag() const
+{
+ return m_xTreeView->get_drag_source() == m_xTreeView.get();
+}
+
+bool SwContentTree::HasHeadings() const
+{
+ const std::unique_ptr<SwContentType>& rpContentT = m_aActiveContentArr[ContentTypeId::OUTLINE];
+ if (rpContentT && rpContentT->GetMemberCount() > 0)
+ return true;
+ return false;
+}
+
+// QueryDrop will be executed in the navigator
+sal_Int8 SwContentTree::AcceptDrop(const AcceptDropEvent& rEvt)
+{
+ sal_Int8 nRet = DND_ACTION_NONE;
+ if( m_bIsRoot )
+ {
+ if( m_bIsOutlineMoveable )
+ nRet = rEvt.mnAction;
+ }
+ else if (!IsInDrag())
+ nRet = GetParentWindow()->AcceptDrop();
+ return nRet;
+}
+
+// Drop will be executed in the navigator
+static void* lcl_GetOutlineKey(SwContentTree& rTree, SwOutlineContent const * pContent)
+{
+ void* key = nullptr;
+ if (pContent)
+ {
+ SwWrtShell* pShell = rTree.GetWrtShell();
+ auto const nPos = pContent->GetOutlinePos();
+
+ key = static_cast<void*>(pShell->getIDocumentOutlineNodesAccess()->getOutlineNode( nPos ));
+ }
+ return key;
+}
+
+sal_Int8 SwContentTreeDropTarget::ExecuteDrop(const ExecuteDropEvent& rEvt)
+{
+ return m_rTreeView.ExecuteDrop(rEvt);
+}
+
+sal_Int8 SwContentTree::ExecuteDrop(const ExecuteDropEvent& rEvt)
+{
+ std::unique_ptr<weld::TreeIter> xDropEntry(m_xTreeView->make_iterator());
+ if (!m_xTreeView->get_dest_row_at_pos(rEvt.maPosPixel, xDropEntry.get(), true))
+ xDropEntry.reset();
+
+ if (m_nRootType == ContentTypeId::OUTLINE)
+ {
+ if (xDropEntry && lcl_IsContent(*xDropEntry, *m_xTreeView))
+ {
+ assert(dynamic_cast<SwContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xDropEntry))));
+ SwOutlineContent* pOutlineContent = weld::fromId<SwOutlineContent*>(m_xTreeView->get_id(*xDropEntry));
+ assert(pOutlineContent);
+
+ void* key = lcl_GetOutlineKey(*this, pOutlineContent);
+ assert(key);
+ if (!mOutLineNodeMap[key])
+ {
+ while (m_xTreeView->iter_has_child(*xDropEntry))
+ {
+ std::unique_ptr<weld::TreeIter> xChildEntry(m_xTreeView->make_iterator(xDropEntry.get()));
+ bool bChildEntry = m_xTreeView->iter_children(*xChildEntry);
+ while (bChildEntry)
+ {
+ m_xTreeView->copy_iterator(*xChildEntry, *xDropEntry);
+ bChildEntry = m_xTreeView->iter_next_sibling(*xChildEntry);
+ }
+ }
+ }
+ }
+
+ SwOutlineNodes::size_type nTargetPos = 0;
+ if (!xDropEntry)
+ {
+ // dropped in blank space -> move to bottom
+ nTargetPos = GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineNodesCount() - 1;
+ }
+ else if (!lcl_IsContent(*xDropEntry, *m_xTreeView))
+ {
+ // dropped on "heading" parent -> move to start
+ nTargetPos = SwOutlineNodes::npos;
+ }
+ else
+ {
+ assert(dynamic_cast<SwOutlineContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xDropEntry))));
+ nTargetPos = weld::fromId<SwOutlineContent*>(m_xTreeView->get_id(*xDropEntry))->GetOutlinePos();
+ }
+
+ if( MAXLEVEL > m_nOutlineLevel && // Not all layers are displayed.
+ nTargetPos != SwOutlineNodes::npos)
+ {
+ std::unique_ptr<weld::TreeIter> xNext(m_xTreeView->make_iterator(xDropEntry.get()));
+ bool bNext = m_xTreeView->iter_next(*xNext);
+ if (bNext)
+ {
+ assert(dynamic_cast<SwOutlineContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xNext))));
+ nTargetPos = weld::fromId<SwOutlineContent*>(m_xTreeView->get_id(*xNext))->GetOutlinePos() - 1;
+ }
+ else
+ nTargetPos = GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineNodesCount() - 1;
+ }
+
+ // remove the drop highlight before we change the contents of the tree so we don't
+ // try and dereference a removed entry in post-processing drop
+ m_xTreeView->unset_drag_dest_row();
+ MoveOutline(nTargetPos);
+
+ }
+ return IsInDrag() ? DND_ACTION_NONE : GetParentWindow()->ExecuteDrop(rEvt);
+}
+
+namespace
+{
+ bool IsAllExpanded(const weld::TreeView& rContentTree, const weld::TreeIter& rEntry)
+ {
+ if (!rContentTree.get_row_expanded(rEntry))
+ return false;
+
+ if (!rContentTree.iter_has_child(rEntry))
+ return false;
+
+ std::unique_ptr<weld::TreeIter> xChild(rContentTree.make_iterator(&rEntry));
+ (void)rContentTree.iter_children(*xChild);
+
+ do
+ {
+ if (rContentTree.iter_has_child(*xChild) || rContentTree.get_children_on_demand(*xChild))
+ {
+ if (!IsAllExpanded(rContentTree, *xChild))
+ return false;
+ }
+ }
+ while (rContentTree.iter_next_sibling(*xChild));
+ return true;
+ }
+
+ void ExpandOrCollapseAll(weld::TreeView& rContentTree, weld::TreeIter& rEntry)
+ {
+ bool bExpand = !IsAllExpanded(rContentTree, rEntry);
+ bExpand ? rContentTree.expand_row(rEntry) : rContentTree.collapse_row(rEntry);
+ int nRefDepth = rContentTree.get_iter_depth(rEntry);
+ while (rContentTree.iter_next(rEntry) && rContentTree.get_iter_depth(rEntry) > nRefDepth)
+ {
+ if (rContentTree.iter_has_child(rEntry))
+ bExpand ? rContentTree.expand_row(rEntry) : rContentTree.collapse_row(rEntry);
+ }
+ }
+}
+
+// Handler for Dragging and ContextMenu
+static bool lcl_InsertExpandCollapseAllItem(const weld::TreeView& rContentTree, const weld::TreeIter& rEntry, weld::Menu& rPop)
+{
+ if (rContentTree.iter_has_child(rEntry) || rContentTree.get_children_on_demand(rEntry))
+ {
+ rPop.set_label(OUString::number(800), IsAllExpanded(rContentTree, rEntry) ? SwResId(STR_COLLAPSEALL) : SwResId(STR_EXPANDALL));
+ return false;
+ }
+ return true;
+}
+
+static void lcl_SetOutlineContentEntriesSensitivities(SwContentTree* pThis, const weld::TreeView& rContentTree, const weld::TreeIter& rEntry, weld::Menu& rPop)
+{
+ rPop.set_sensitive(OUString::number(TOGGLE_OUTLINE_CONTENT_VISIBILITY), false);
+ rPop.set_sensitive(OUString::number(HIDE_OUTLINE_CONTENT_VISIBILITY), false);
+ rPop.set_sensitive(OUString::number(SHOW_OUTLINE_CONTENT_VISIBILITY), false);
+
+ // todo: multi selection
+ if (rContentTree.count_selected_rows() > 1)
+ return;
+
+ bool bIsRoot = lcl_IsContentType(rEntry, rContentTree);
+
+ const SwNodes& rNodes = pThis->GetWrtShell()->GetNodes();
+ const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds();
+ size_t nOutlinePos = weld::GetAbsPos(rContentTree, rEntry);
+
+ if (!bIsRoot)
+ --nOutlinePos;
+
+ if (nOutlinePos >= rOutlineNodes.size())
+ return;
+
+ int nFirstLevel = pThis->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineLevel(nOutlinePos);
+ {
+ // determine if any concerned outline node has content
+ bool bHasContent(false);
+ size_t nPos = nOutlinePos;
+ SwNode* pSttNd = rOutlineNodes[nPos];
+ SwNode* pEndNd = &rNodes.GetEndOfContent();
+ if (rOutlineNodes.size() > nPos + 1)
+ pEndNd = rOutlineNodes[nPos + 1];
+
+ // selected
+ SwNodeIndex aIdx(*pSttNd);
+ if (rNodes.GoNext(&aIdx) != pEndNd)
+ bHasContent = true;
+
+ // descendants
+ if (!bHasContent && (rContentTree.iter_has_child(rEntry) || rContentTree.get_children_on_demand(rEntry)))
+ {
+ while (++nPos < rOutlineNodes.size() &&
+ (bIsRoot || pThis->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nFirstLevel))
+ {
+ pSttNd = rOutlineNodes[nPos];
+ pEndNd = &rNodes.GetEndOfContent();
+ if (rOutlineNodes.size() > nPos + 1)
+ pEndNd = rOutlineNodes[nPos + 1];
+
+ // test for content in outline node
+ aIdx.Assign(*pSttNd);
+ if (rNodes.GoNext(&aIdx) != pEndNd)
+ {
+ bHasContent = true;
+ break;
+ }
+ }
+ }
+
+ if (!bHasContent)
+ return; // no content in any of the concerned outline nodes
+ }
+
+ // determine for subs if all are folded or unfolded or if they are mixed
+ if (rContentTree.iter_has_child(rEntry) || rContentTree.get_children_on_demand(rEntry))
+ {
+ // skip no content nodes
+ // we know there is content from results above so this is presumably safe
+ size_t nPos = nOutlinePos;
+ while (true)
+ {
+ SwNode* pSttNd = rOutlineNodes[nPos];
+ SwNode* pEndNd = rOutlineNodes.back();
+ if (!bIsRoot && rOutlineNodes.size() > nPos + 1)
+ pEndNd = rOutlineNodes[nPos + 1];
+
+ SwNodeIndex aIdx(*pSttNd);
+ if (rNodes.GoNext(&aIdx) != pEndNd)
+ break;
+ nPos++;
+ }
+
+ bool bHasFolded(!pThis->GetWrtShell()->IsOutlineContentVisible(nPos));
+ bool bHasUnfolded(!bHasFolded);
+
+ while ((++nPos < pThis->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineNodesCount()) &&
+ (bIsRoot || pThis->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nFirstLevel))
+ {
+
+ SwNode* pSttNd = rOutlineNodes[nPos];
+ SwNode* pEndNd = &rNodes.GetEndOfContent();
+ if (rOutlineNodes.size() > nPos + 1)
+ pEndNd = rOutlineNodes[nPos + 1];
+
+ SwNodeIndex aIdx(*pSttNd);
+ if (rNodes.GoNext(&aIdx) == pEndNd)
+ continue; // skip if no content
+
+ if (!pThis->GetWrtShell()->IsOutlineContentVisible(nPos))
+ bHasFolded = true;
+ else
+ bHasUnfolded = true;
+
+ if (bHasFolded && bHasUnfolded)
+ break; // mixed so no need to continue
+ }
+
+ rPop.set_sensitive(OUString::number(HIDE_OUTLINE_CONTENT_VISIBILITY), bHasUnfolded);
+ rPop.set_sensitive(OUString::number(SHOW_OUTLINE_CONTENT_VISIBILITY), bHasFolded);
+ }
+
+ rPop.set_sensitive(OUString::number(TOGGLE_OUTLINE_CONTENT_VISIBILITY), !bIsRoot);
+}
+
+IMPL_LINK(SwContentTree, CommandHdl, const CommandEvent&, rCEvt, bool)
+{
+ if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
+ return false;
+
+ grab_focus();
+
+ // select clicked entry or limit selection to root entry if needed
+ if (std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ rCEvt.IsMouseEvent() && m_xTreeView->get_dest_row_at_pos(
+ rCEvt.GetMousePosPixel(), xEntry.get(), false))
+ {
+ // if clicked entry is not currently selected then clear selections and select it
+ if (!m_xTreeView->is_selected(*xEntry))
+ m_xTreeView->set_cursor(*xEntry);
+ // if root entry is selected then clear selections and select it
+ else if (m_xTreeView->is_selected(0))
+ m_xTreeView->set_cursor(0);
+ }
+
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xTreeView.get(), "modules/swriter/ui/navigatorcontextmenu.ui"));
+ std::unique_ptr<weld::Menu> xPop = xBuilder->weld_menu("navmenu");
+
+ bool bOutline(false);
+ std::unique_ptr<weld::Menu> xSubPop1 = xBuilder->weld_menu("outlinelevel");
+ std::unique_ptr<weld::Menu> xSubPop2 = xBuilder->weld_menu("dragmodemenu");
+ std::unique_ptr<weld::Menu> xSubPop3 = xBuilder->weld_menu("displaymenu");
+ std::unique_ptr<weld::Menu> xSubPopOutlineTracking = xBuilder->weld_menu("outlinetracking");
+
+ std::unique_ptr<weld::Menu> xSubPopOutlineContent = xBuilder->weld_menu("outlinecontent");
+
+ xSubPopOutlineContent->append(OUString::number(TOGGLE_OUTLINE_CONTENT_VISIBILITY),
+ SwResId(STR_OUTLINE_CONTENT_VISIBILITY_TOGGLE));
+ xSubPopOutlineContent->append(OUString::number(HIDE_OUTLINE_CONTENT_VISIBILITY),
+ SwResId(STR_OUTLINE_CONTENT_VISIBILITY_HIDE_ALL));
+ xSubPopOutlineContent->append(OUString::number(SHOW_OUTLINE_CONTENT_VISIBILITY),
+ SwResId(STR_OUTLINE_CONTENT_VISIBILITY_SHOW_ALL));
+
+ xSubPopOutlineContent->set_item_help_id(OUString::number(TOGGLE_OUTLINE_CONTENT_VISIBILITY),
+ HID_NAVIGATOR_TREELIST);
+ xSubPopOutlineContent->set_item_help_id(OUString::number(HIDE_OUTLINE_CONTENT_VISIBILITY),
+ HID_NAVIGATOR_TREELIST);
+ xSubPopOutlineContent->set_item_help_id(OUString::number(SHOW_OUTLINE_CONTENT_VISIBILITY),
+ HID_NAVIGATOR_TREELIST);
+
+ // Add entries to the Outline Tracking submenu
+ OUString sId;
+ for(int i = 1; i <= 3; ++i)
+ {
+ sId = OUString::number(i + 10);
+ xSubPopOutlineTracking->append_radio(sId, m_aContextStrings[IDX_STR_OUTLINE_TRACKING + i]);
+ xSubPopOutlineTracking->set_item_help_id(sId, HID_NAV_OUTLINE_TRACKING);
+ }
+ xSubPopOutlineTracking->set_active(OUString::number(10 + m_nOutlineTracking), true);
+
+ // Add entries to the Outline Level submenu
+ for (int i = 1; i <= MAXLEVEL; ++i)
+ {
+ sId = OUString::number(i + 100);
+ xSubPop1->append_radio(sId, OUString::number(i));
+ xSubPop1->set_item_help_id(sId, HID_NAV_OUTLINE_LEVEL);
+ }
+ xSubPop1->set_active(OUString::number(100 + m_nOutlineLevel), true);
+
+ // Add entries to the Drag Mode submenu
+ for (int i=0; i < 3; ++i)
+ {
+ sId = OUString::number(i + 201);
+ xSubPop2->append_radio(sId, m_aContextStrings[IDX_STR_HYPERLINK + i]);
+ xSubPop2->set_item_help_id(sId, HID_NAV_DRAG_MODE);
+ }
+ xSubPop2->set_active(OUString::number(201 + static_cast<int>(GetParentWindow()->GetRegionDropMode())), true);
+
+ // Insert the list of the open files in the Display submenu
+ {
+ sal_uInt16 nId = 301;
+ SwView *pView = SwModule::GetFirstView();
+ while (pView)
+ {
+ OUString sInsert = pView->GetDocShell()->GetTitle() + " (" +
+ m_aContextStrings[pView == GetActiveView() ? IDX_STR_ACTIVE :
+ IDX_STR_INACTIVE] + ")";
+ sId = OUString::number(nId);
+ xSubPop3->append_radio(sId, sInsert);
+ xSubPop3->set_item_help_id(sId, HID_NAV_DISPLAY);
+ if (State::CONSTANT == m_eState && m_pActiveShell == &pView->GetWrtShell())
+ xSubPop3->set_active(sId, true);
+ pView = SwModule::GetNextView(pView);
+ nId++;
+ }
+ // Active Window
+ sId = OUString::number(nId++);
+ xSubPop3->append_radio(sId, m_aContextStrings[IDX_STR_ACTIVE_VIEW]);
+ xSubPop3->set_item_help_id(sId, HID_NAV_DISPLAY);
+ // There can be only one hidden shell
+ if (m_pHiddenShell)
+ {
+ OUString sHiddenEntry = m_pHiddenShell->GetView().GetDocShell()->GetTitle() +
+ " (" +
+ m_aContextStrings[IDX_STR_HIDDEN] +
+ ")";
+ sId = OUString::number(nId);
+ xSubPop3->append_radio(sId, sHiddenEntry);
+ xSubPop3->set_item_help_id(sId, HID_NAV_DISPLAY);
+ }
+ if (State::ACTIVE == m_eState)
+ xSubPop3->set_active(OUString::number(--nId), true);
+ else if (State::HIDDEN == m_eState)
+ xSubPop3->set_active(OUString::number(nId), true);
+ }
+
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ if (!m_xTreeView->get_selected(xEntry.get()))
+ xEntry.reset();
+
+ bool bRemoveGotoEntry = false;
+ if (State::HIDDEN == m_eState || !xEntry || !lcl_IsContent(*xEntry, *m_xTreeView) ||
+ weld::fromId<SwContent*>(m_xTreeView->get_id(*xEntry))->IsInvisible())
+ bRemoveGotoEntry = true;
+
+ bool bRemovePostItEntries = true;
+ bool bRemoveIndexEntries = true;
+ bool bRemoveCopyEntry = true;
+ bool bRemoveEditEntry = true;
+ bool bRemoveUnprotectEntry = true;
+ bool bRemoveDeleteChapterEntry = true,
+ bRemoveDeleteTableEntry = true,
+ bRemoveDeleteFrameEntry = true,
+ bRemoveDeleteImageEntry = true,
+ bRemoveDeleteOLEObjectEntry = true,
+ bRemoveDeleteBookmarkEntry = true,
+ bRemoveDeleteRegionEntry = true,
+ bRemoveDeleteHyperlinkEntry = true,
+ bRemoveDeleteReferenceEntry = true,
+ bRemoveDeleteIndexEntry= true,
+ bRemoveDeleteCommentEntry = true,
+ bRemoveDeleteDrawingObjectEntry = true,
+ bRemoveDeleteFieldEntry = true;
+ bool bRemoveRenameEntry = true;
+ bool bRemoveSelectEntry = true;
+ bool bRemoveToggleExpandEntry = true;
+ bool bRemoveChapterEntries = true;
+ bool bRemoveSendOutlineEntry = true;
+
+ bool bRemoveTableTracking = true;
+ bool bRemoveSectionTracking = true;
+ bool bRemoveFrameTracking = true;
+ bool bRemoveImageTracking = true;
+ bool bRemoveOLEobjectTracking = true;
+ bool bRemoveBookmarkTracking = true;
+ bool bRemoveHyperlinkTracking = true;
+ bool bRemoveReferenceTracking = true;
+ bool bRemoveIndexTracking = true;
+ bool bRemoveCommentTracking = true;
+ bool bRemoveDrawingObjectTracking = true;
+ bool bRemoveFieldTracking = true;
+ bool bRemoveFootnoteTracking = true;
+ bool bRemoveEndnoteTracking = true;
+
+ bool bRemoveSortEntry = true;
+
+ bool bRemoveProtectSection = true;
+ bool bRemoveHideSection = true;
+
+ if (xEntry)
+ {
+ const SwContentType* pType;
+ if (lcl_IsContentType(*xEntry, *m_xTreeView))
+ pType = weld::fromId<SwContentType*>(m_xTreeView->get_id(*xEntry));
+ else
+ pType = weld::fromId<SwContent*>(
+ m_xTreeView->get_id(*xEntry))->GetParent();
+ const ContentTypeId nContentType = pType->GetType();
+
+ if (nContentType != ContentTypeId::FOOTNOTE && nContentType != ContentTypeId::ENDNOTE
+ && nContentType != ContentTypeId::POSTIT && nContentType != ContentTypeId::UNKNOWN)
+ {
+ bRemoveSortEntry = false;
+ const sal_Int32 nMask = 1 << static_cast<int>(nContentType);
+ sal_uInt64 nSortAlphabeticallyBlock = m_pConfig->GetSortAlphabeticallyBlock();
+ xPop->set_active("sort", nSortAlphabeticallyBlock & nMask);
+ }
+
+ OUString aIdent;
+ switch (nContentType)
+ {
+ case ContentTypeId::TABLE:
+ aIdent = "tabletracking";
+ bRemoveTableTracking = false;
+ break;
+ case ContentTypeId::REGION:
+ aIdent = "sectiontracking";
+ bRemoveSectionTracking = false;
+ break;
+ case ContentTypeId::FRAME:
+ aIdent = "frametracking";
+ bRemoveFrameTracking = false;
+ break;
+ case ContentTypeId::GRAPHIC:
+ aIdent = "imagetracking";
+ bRemoveImageTracking = false;
+ break;
+ case ContentTypeId::OLE:
+ aIdent = "oleobjecttracking";
+ bRemoveOLEobjectTracking = false;
+ break;
+ case ContentTypeId::BOOKMARK:
+ aIdent = "bookmarktracking";
+ bRemoveBookmarkTracking = false;
+ break;
+ case ContentTypeId::URLFIELD:
+ aIdent = "hyperlinktracking";
+ bRemoveHyperlinkTracking = false;
+ break;
+ case ContentTypeId::REFERENCE:
+ aIdent = "referencetracking";
+ bRemoveReferenceTracking = false;
+ break;
+ case ContentTypeId::INDEX:
+ aIdent = "indextracking";
+ bRemoveIndexTracking = false;
+ break;
+ case ContentTypeId::POSTIT:
+ aIdent = "commenttracking";
+ bRemoveCommentTracking = false;
+ break;
+ case ContentTypeId::DRAWOBJECT:
+ aIdent = "drawingobjecttracking";
+ bRemoveDrawingObjectTracking = false;
+ break;
+ case ContentTypeId::TEXTFIELD:
+ aIdent = "fieldtracking";
+ bRemoveFieldTracking = false;
+ break;
+ case ContentTypeId::FOOTNOTE:
+ aIdent = "footnotetracking";
+ bRemoveFootnoteTracking = false;
+ break;
+ case ContentTypeId::ENDNOTE:
+ aIdent = "endnotetracking";
+ bRemoveEndnoteTracking = false;
+ break;
+ default: break;
+ }
+ if (!aIdent.isEmpty())
+ xPop->set_active(aIdent, mTrackContentType[nContentType]);
+
+ // Edit only if the shown content is coming from the current view.
+ if (State::HIDDEN != m_eState &&
+ (State::ACTIVE == m_eState || (GetActiveView() && m_pActiveShell == GetActiveView()->GetWrtShellPtr()))
+ && lcl_IsContent(*xEntry, *m_xTreeView))
+ {
+ const bool bReadonly = m_pActiveShell->GetView().GetDocShell()->IsReadOnly();
+ const bool bVisible = !weld::fromId<SwContent*>(m_xTreeView->get_id(*xEntry))->IsInvisible();
+ const bool bProtected = weld::fromId<SwContent*>(m_xTreeView->get_id(*xEntry))->IsProtect();
+ const bool bProtectBM = (ContentTypeId::BOOKMARK == nContentType)
+ && m_pActiveShell->getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS);
+ const bool bEditable = pType->IsEditable() &&
+ ((bVisible && !bProtected) || ContentTypeId::REGION == nContentType);
+ const bool bDeletable = pType->IsDeletable()
+ && ((bVisible && !bProtected && !bProtectBM) || ContentTypeId::REGION == nContentType);
+ const bool bRenamable = bEditable && !bReadonly &&
+ (ContentTypeId::TABLE == nContentType ||
+ ContentTypeId::FRAME == nContentType ||
+ ContentTypeId::GRAPHIC == nContentType ||
+ ContentTypeId::OLE == nContentType ||
+ (ContentTypeId::BOOKMARK == nContentType && !bProtectBM) ||
+ ContentTypeId::REGION == nContentType ||
+ ContentTypeId::INDEX == nContentType ||
+ ContentTypeId::DRAWOBJECT == nContentType);
+ // Choose which Delete entry to show.
+ if (bDeletable)
+ {
+ switch (nContentType)
+ {
+ case ContentTypeId::OUTLINE:
+ bRemoveDeleteChapterEntry = false;
+ break;
+ case ContentTypeId::TABLE:
+ bRemoveDeleteTableEntry = false;
+ break;
+ case ContentTypeId::FRAME:
+ bRemoveDeleteFrameEntry = false;
+ break;
+ case ContentTypeId::GRAPHIC:
+ bRemoveDeleteImageEntry = false;
+ break;
+ case ContentTypeId::OLE:
+ bRemoveDeleteOLEObjectEntry = false;
+ break;
+ case ContentTypeId::BOOKMARK:
+ bRemoveDeleteBookmarkEntry = false;
+ break;
+ case ContentTypeId::REGION:
+ bRemoveDeleteRegionEntry = false;
+ break;
+ case ContentTypeId::URLFIELD:
+ bRemoveDeleteHyperlinkEntry = false;
+ break;
+ case ContentTypeId::REFERENCE:
+ bRemoveDeleteReferenceEntry = false;
+ break;
+ case ContentTypeId::INDEX:
+ bRemoveDeleteIndexEntry = false;
+ break;
+ case ContentTypeId::POSTIT:
+ bRemoveDeleteCommentEntry = false;
+ break;
+ case ContentTypeId::DRAWOBJECT:
+ bRemoveDeleteDrawingObjectEntry = false;
+ break;
+ case ContentTypeId::TEXTFIELD:
+ bRemoveDeleteFieldEntry = false;
+ break;
+ default: break;
+ }
+ }
+ if (ContentTypeId::FOOTNOTE == nContentType || ContentTypeId::ENDNOTE == nContentType)
+ {
+ void* pUserData = weld::fromId<void*>(m_xTreeView->get_id(*xEntry));
+ const SwTextFootnote* pFootnote =
+ static_cast<const SwTextFootnoteContent*>(pUserData)->GetTextFootnote();
+ if (!pFootnote)
+ bRemoveGotoEntry = true;
+ }
+ else if(ContentTypeId::OUTLINE == nContentType)
+ {
+ bOutline = true;
+ lcl_SetOutlineContentEntriesSensitivities(this, *m_xTreeView, *xEntry, *xSubPopOutlineContent);
+ bRemoveToggleExpandEntry = lcl_InsertExpandCollapseAllItem(*m_xTreeView, *xEntry, *xPop);
+ if (!bReadonly)
+ {
+ bRemoveSelectEntry = false;
+ bRemoveChapterEntries = false;
+ }
+ bRemoveCopyEntry = false;
+ }
+ else if (!bReadonly && bEditable)
+ {
+ if(ContentTypeId::INDEX == nContentType)
+ {
+ bRemoveIndexEntries = false;
+
+ const SwTOXBase* pBase = weld::fromId<SwTOXBaseContent*>(m_xTreeView->get_id(*xEntry))->GetTOXBase();
+ if (!pBase->IsTOXBaseInReadonly())
+ bRemoveEditEntry = false;
+
+ xPop->set_active(OUString::number(405), SwEditShell::IsTOXBaseReadonly(*pBase));
+ }
+ else if(ContentTypeId::TABLE == nContentType)
+ {
+ bRemoveSelectEntry = false;
+ bRemoveEditEntry = false;
+ bRemoveUnprotectEntry = false;
+ bool bFull = false;
+ OUString sTableName = weld::fromId<SwContent*>(m_xTreeView->get_id(*xEntry))->GetName();
+ bool bProt = m_pActiveShell->HasTableAnyProtection( &sTableName, &bFull );
+ xPop->set_sensitive(OUString::number(403), !bFull);
+ xPop->set_sensitive(OUString::number(404), bProt);
+ }
+ else if(ContentTypeId::REGION == nContentType)
+ {
+ bRemoveEditEntry = false;
+ bRemoveProtectSection = false;
+ bRemoveHideSection = false;
+ SwContent* pCnt = weld::fromId<SwContent*>(m_xTreeView->get_id(*xEntry));
+ assert(dynamic_cast<SwRegionContent*>(static_cast<SwTypeNumber*>(pCnt)));
+ const SwSectionFormat* pSectionFormat
+ = static_cast<SwRegionContent*>(pCnt)->GetSectionFormat();
+ bool bHidden = pSectionFormat->GetSection()->IsHidden();
+ bRemoveSelectEntry = bHidden || !bVisible;
+ xPop->set_active("protectsection", bProtected);
+ xPop->set_active("hidesection", bHidden);
+ }
+ else if (bEditable)
+ bRemoveEditEntry = false;
+ //Rename object
+ if (bRenamable)
+ bRemoveRenameEntry = false;
+ }
+ }
+ else
+ {
+ if (lcl_IsContentType(*xEntry, *m_xTreeView))
+ pType = weld::fromId<SwContentType*>(m_xTreeView->get_id(*xEntry));
+ else
+ pType = weld::fromId<SwContent*>(
+ m_xTreeView->get_id(*xEntry))->GetParent();
+ if (pType)
+ {
+ if (ContentTypeId::OUTLINE == nContentType)
+ {
+ bOutline = true;
+ if (State::HIDDEN != m_eState)
+ {
+ lcl_SetOutlineContentEntriesSensitivities(this, *m_xTreeView, *xEntry,
+ *xSubPopOutlineContent);
+ bRemoveSendOutlineEntry = false;
+ }
+ bRemoveToggleExpandEntry = lcl_InsertExpandCollapseAllItem(*m_xTreeView, *xEntry,
+ *xPop);
+ }
+ else if (State::HIDDEN != m_eState &&
+ nContentType == ContentTypeId::POSTIT &&
+ !m_pActiveShell->GetView().GetDocShell()->IsReadOnly() &&
+ pType->GetMemberCount() > 0)
+ bRemovePostItEntries = false;
+ }
+ }
+ }
+
+ if (bRemoveToggleExpandEntry)
+ xPop->remove(OUString::number(800));
+
+ if (bRemoveGotoEntry)
+ xPop->remove(OUString::number(900));
+
+ if (bRemoveSelectEntry)
+ xPop->remove(OUString::number(805));
+
+ if (bRemoveChapterEntries)
+ {
+ xPop->remove(OUString::number(801));
+ xPop->remove(OUString::number(802));
+ xPop->remove(OUString::number(803));
+ xPop->remove(OUString::number(804));
+ }
+
+ if (bRemoveSendOutlineEntry)
+ xPop->remove(OUString::number(700));
+
+ if (bRemovePostItEntries)
+ {
+ xPop->remove(OUString::number(600));
+ xPop->remove(OUString::number(601));
+ xPop->remove(OUString::number(602));
+ }
+
+ if (bRemoveDeleteChapterEntry)
+ xPop->remove("deletechapter");
+ if (bRemoveDeleteTableEntry)
+ xPop->remove("deletetable");
+ if (bRemoveDeleteFrameEntry)
+ xPop->remove("deleteframe");
+ if (bRemoveDeleteImageEntry)
+ xPop->remove("deleteimage");
+ if (bRemoveDeleteOLEObjectEntry)
+ xPop->remove("deleteoleobject");
+ if (bRemoveDeleteBookmarkEntry)
+ xPop->remove("deletebookmark");
+ if (bRemoveDeleteRegionEntry)
+ xPop->remove("deleteregion");
+ if (bRemoveDeleteHyperlinkEntry)
+ xPop->remove("deletehyperlink");
+ if (bRemoveDeleteReferenceEntry)
+ xPop->remove("deletereference");
+ if (bRemoveDeleteIndexEntry)
+ xPop->remove("deleteindex");
+ if (bRemoveDeleteCommentEntry)
+ xPop->remove("deletecomment");
+ if (bRemoveDeleteDrawingObjectEntry)
+ xPop->remove("deletedrawingobject");
+ if (bRemoveDeleteFieldEntry)
+ xPop->remove("deletefield");
+
+ bool bRemoveDeleteEntry =
+ bRemoveDeleteChapterEntry &&
+ bRemoveDeleteTableEntry &&
+ bRemoveDeleteFrameEntry &&
+ bRemoveDeleteImageEntry &&
+ bRemoveDeleteOLEObjectEntry &&
+ bRemoveDeleteBookmarkEntry &&
+ bRemoveDeleteRegionEntry &&
+ bRemoveDeleteHyperlinkEntry &&
+ bRemoveDeleteReferenceEntry &&
+ bRemoveDeleteIndexEntry &&
+ bRemoveDeleteCommentEntry &&
+ bRemoveDeleteDrawingObjectEntry &&
+ bRemoveDeleteFieldEntry;
+
+ if (bRemoveRenameEntry)
+ xPop->remove(OUString::number(502));
+
+ if (bRemoveIndexEntries)
+ {
+ xPop->remove(OUString::number(401));
+ xPop->remove(OUString::number(402));
+ xPop->remove(OUString::number(405));
+ }
+
+ if (bRemoveUnprotectEntry)
+ xPop->remove(OUString::number(404));
+
+ if (bRemoveEditEntry)
+ xPop->remove(OUString::number(403));
+
+ if (bRemoveToggleExpandEntry &&
+ bRemoveSendOutlineEntry)
+ xPop->remove("separator1");
+
+ if (bRemoveCopyEntry)
+ xPop->remove("copy");
+
+ if (bRemoveGotoEntry &&
+ bRemoveCopyEntry &&
+ bRemoveSelectEntry &&
+ bRemoveDeleteEntry &&
+ bRemoveChapterEntries &&
+ bRemovePostItEntries &&
+ bRemoveRenameEntry &&
+ bRemoveIndexEntries &&
+ bRemoveUnprotectEntry &&
+ bRemoveEditEntry)
+ xPop->remove("separator2");
+
+ if (!bOutline)
+ {
+ xSubPop1.reset();
+ xPop->remove(OUString::number(1)); // outline level menu
+ }
+ if (!bOutline || State::HIDDEN == m_eState)
+ {
+ xSubPopOutlineTracking.reset();
+ xPop->remove(OUString::number(4)); // outline tracking menu
+ }
+ if (!bOutline || State::HIDDEN == m_eState ||
+ !m_pActiveShell->GetViewOptions()->IsShowOutlineContentVisibilityButton() ||
+ m_pActiveShell->getIDocumentOutlineNodesAccess()->getOutlineNodesCount() == 0)
+ {
+ xSubPopOutlineContent.reset();
+ xPop->remove(OUString::number(5)); // outline folding menu
+ xPop->remove("separator3");
+ }
+
+ if (bRemoveTableTracking)
+ xPop->remove("tabletracking");
+ if (bRemoveSectionTracking)
+ xPop->remove("sectiontracking");
+ if (bRemoveFrameTracking)
+ xPop->remove("frametracking");
+ if (bRemoveImageTracking)
+ xPop->remove("imagetracking");
+ if (bRemoveOLEobjectTracking)
+ xPop->remove("oleobjecttracking");
+ if (bRemoveBookmarkTracking)
+ xPop->remove("bookmarktracking");
+ if (bRemoveHyperlinkTracking)
+ xPop->remove("hyperlinktracking");
+ if (bRemoveReferenceTracking)
+ xPop->remove("referencetracking");
+ if (bRemoveIndexTracking)
+ xPop->remove("indextracking");
+ if (bRemoveCommentTracking)
+ xPop->remove("commenttracking");
+ if (bRemoveDrawingObjectTracking)
+ xPop->remove("drawingobjecttracking");
+ if (bRemoveFieldTracking)
+ xPop->remove("fieldtracking");
+ if (bRemoveFootnoteTracking)
+ xPop->remove("footnotetracking");
+ if (bRemoveEndnoteTracking)
+ xPop->remove("endnotetracking");
+ if (bRemoveSortEntry)
+ xPop->remove("sort");
+ if (bRemoveProtectSection)
+ xPop->remove("protectsection");
+ if (bRemoveHideSection)
+ xPop->remove("hidesection");
+
+ bool bSetSensitiveCollapseAllCategories = false;
+ if (!m_bIsRoot && xEntry)
+ {
+ bool bEntry = m_xTreeView->get_iter_first(*xEntry);
+ while (bEntry)
+ {
+ if (m_xTreeView->get_row_expanded(*xEntry))
+ {
+ bSetSensitiveCollapseAllCategories = true;
+ break;
+ }
+ bEntry = m_xTreeView->iter_next_sibling(*xEntry);
+ }
+ }
+ xPop->set_sensitive("collapseallcategories", bSetSensitiveCollapseAllCategories);
+
+ OUString sCommand = xPop->popup_at_rect(m_xTreeView.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)));
+ if (!sCommand.isEmpty())
+ ExecuteContextMenuAction(sCommand);
+
+ return true;
+}
+
+void SwContentTree::InsertContent(const weld::TreeIter& rParent)
+{
+ assert(dynamic_cast<SwContentType*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(rParent))));
+ SwContentType* pCntType = weld::fromId<SwContentType*>(m_xTreeView->get_id(rParent));
+ bool bGraphic = pCntType->GetType() == ContentTypeId::GRAPHIC;
+ std::unique_ptr<weld::TreeIter> xChild = m_xTreeView->make_iterator();
+ const size_t nCount = pCntType->GetMemberCount();
+ for(size_t i = 0; i < nCount; ++i)
+ {
+ const SwContent* pCnt = pCntType->GetMember(i);
+ OUString sEntry = pCnt->GetName();
+ if (sEntry.isEmpty())
+ sEntry = m_sSpace;
+ OUString sId(weld::toId(pCnt));
+ insert(&rParent, sEntry, sId, false, xChild.get());
+ m_xTreeView->set_sensitive(*xChild, !pCnt->IsInvisible());
+ if (bGraphic && !static_cast<const SwGraphicContent*>(pCnt)->GetLink().isEmpty())
+ m_xTreeView->set_image(*xChild, RID_BMP_NAVI_GRAPHIC_LINK);
+ }
+}
+
+void SwContentTree::insert(const weld::TreeIter* pParent, const OUString& rStr, const OUString& rId,
+ bool bChildrenOnDemand, weld::TreeIter* pRet)
+{
+ m_xTreeView->insert(pParent, -1, &rStr, &rId, nullptr, nullptr, bChildrenOnDemand, pRet);
+ ++m_nEntryCount;
+}
+
+void SwContentTree::remove(const weld::TreeIter& rIter)
+{
+ if (m_xTreeView->iter_has_child(rIter))
+ {
+ std::unique_ptr<weld::TreeIter> xChild = m_xTreeView->make_iterator(&rIter);
+ (void)m_xTreeView->iter_children(*xChild);
+ remove(*xChild);
+ }
+ m_xTreeView->remove(rIter);
+ --m_nEntryCount;
+}
+
+// Content will be integrated into the Box only on demand.
+bool SwContentTree::RequestingChildren(const weld::TreeIter& rParent)
+{
+ // Does the parent already have children or is it not a 'children on demand' node?
+ if (m_xTreeView->iter_has_child(rParent) || !m_xTreeView->get_children_on_demand(rParent))
+ return false;
+
+ // Is this a content type?
+ if (lcl_IsContentType(rParent, *m_xTreeView))
+ {
+ std::unique_ptr<weld::TreeIter> xChild = m_xTreeView->make_iterator();
+
+ assert(dynamic_cast<SwContentType*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(rParent))));
+ SwContentType* pCntType = weld::fromId<SwContentType*>(m_xTreeView->get_id(rParent));
+
+ const size_t nCount = pCntType->GetMemberCount();
+ // Add for outline plus/minus
+ if (pCntType->GetType() == ContentTypeId::OUTLINE)
+ {
+ std::vector<std::unique_ptr<weld::TreeIter>> aParentCandidates;
+ for(size_t i = 0; i < nCount; ++i)
+ {
+ const SwContent* pCnt = pCntType->GetMember(i);
+ if(pCnt)
+ {
+ const auto nLevel = static_cast<const SwOutlineContent*>(pCnt)->GetOutlineLevel();
+ OUString sEntry = pCnt->GetName();
+ if(sEntry.isEmpty())
+ sEntry = m_sSpace;
+ OUString sId(weld::toId(pCnt));
+
+ auto lambda = [nLevel, this](const std::unique_ptr<weld::TreeIter>& entry)
+ {
+ return lcl_IsLowerOutlineContent(*entry, *m_xTreeView, nLevel);
+ };
+
+ // if there is a preceding outline node candidate with a lower outline level use
+ // that as a parent, otherwise use the root node
+ auto aFind = std::find_if(aParentCandidates.rbegin(), aParentCandidates.rend(), lambda);
+ if (aFind != aParentCandidates.rend())
+ insert(aFind->get(), sEntry, sId, false, xChild.get());
+ else
+ insert(&rParent, sEntry, sId, false, xChild.get());
+ m_xTreeView->set_sensitive(*xChild, !pCnt->IsInvisible());
+ m_xTreeView->set_extra_row_indent(*xChild, nLevel + 1 - m_xTreeView->get_iter_depth(*xChild));
+
+ // remove any parent candidates equal to or higher than this node
+ std::erase_if(aParentCandidates, std::not_fn(lambda));
+
+ // add this node as a parent candidate for any following nodes at a higher outline level
+ aParentCandidates.emplace_back(m_xTreeView->make_iterator(xChild.get()));
+ }
+ }
+ }
+ else if (pCntType->GetType() == ContentTypeId::REGION)
+ {
+ if (pCntType->IsAlphabeticSort())
+ {
+ for(size_t i = 0; i < nCount; ++i)
+ {
+ const SwRegionContent* pCnt =
+ static_cast<const SwRegionContent*>(pCntType->GetMember(i));
+
+ OUString sEntry = pCnt->GetName();
+ OUString sId(weld::toId(pCnt));
+
+ const auto nLevel = pCnt->GetRegionLevel();
+ insert(&rParent, sEntry, sId, false, xChild.get());
+
+ m_xTreeView->set_sensitive(*xChild, !pCnt->IsInvisible());
+ m_xTreeView->set_extra_row_indent(*xChild, nLevel);
+
+ bool bHidden = pCnt->GetSectionFormat()->GetSection()->IsHidden();
+ if (pCnt->IsProtect())
+ m_xTreeView->set_image(*xChild, bHidden ? RID_BMP_PROT_HIDE : RID_BMP_PROT_NO_HIDE);
+ else
+ m_xTreeView->set_image(*xChild, bHidden ? RID_BMP_HIDE : RID_BMP_NO_HIDE);
+ }
+ }
+ else
+ {
+ std::vector<std::unique_ptr<weld::TreeIter>> aParentCandidates;
+ for(size_t i = 0; i < nCount; ++i)
+ {
+ const SwRegionContent* pCnt =
+ static_cast<const SwRegionContent*>(pCntType->GetMember(i));
+
+ OUString sEntry = pCnt->GetName();
+ OUString sId(weld::toId(pCnt));
+
+ const auto nLevel = pCnt->GetRegionLevel();
+ auto lambda = [nLevel, this](const std::unique_ptr<weld::TreeIter>& xEntry)
+ {
+ return lcl_IsLowerRegionContent(*xEntry, *m_xTreeView, nLevel);
+ };
+
+ // if there is a preceding region node candidate with a lower region level use
+ // that as a parent, otherwise use the root node
+ auto aFind = std::find_if(aParentCandidates.rbegin(), aParentCandidates.rend(), lambda);
+ if (aFind != aParentCandidates.rend())
+ insert(aFind->get(), sEntry, sId, false, xChild.get());
+ else
+ insert(&rParent, sEntry, sId, false, xChild.get());
+ m_xTreeView->set_sensitive(*xChild, !pCnt->IsInvisible());
+
+ bool bHidden = pCnt->GetSectionFormat()->GetSection()->IsHidden();
+ if (pCnt->IsProtect())
+ m_xTreeView->set_image(*xChild, bHidden ? RID_BMP_PROT_HIDE : RID_BMP_PROT_NO_HIDE);
+ else
+ m_xTreeView->set_image(*xChild, bHidden ? RID_BMP_HIDE : RID_BMP_NO_HIDE);
+
+ // remove any parent candidates equal to or higher than this node
+ std::erase_if(aParentCandidates, std::not_fn(lambda));
+
+ // add this node as a parent candidate for any following nodes at a higher region level
+ aParentCandidates.emplace_back(m_xTreeView->make_iterator(xChild.get()));
+ }
+ }
+ }
+ else if (pCntType->GetType() == ContentTypeId::POSTIT)
+ {
+ std::vector<std::unique_ptr<weld::TreeIter>> aParentCandidates;
+ for(size_t i = 0; i < nCount; ++i)
+ {
+ const SwPostItContent* pCnt =
+ static_cast<const SwPostItContent*>(pCntType->GetMember(i));
+
+ OUString sEntry = pCnt->GetName();
+ OUString sId(weld::toId(pCnt));
+
+ const SwPostItField* pPostItField =
+ static_cast<const SwPostItField*>(pCnt->GetPostIt()->GetField());
+ auto lambda = [&pPostItField, this](const std::unique_ptr<weld::TreeIter>& xEntry)
+ {
+ SwPostItContent* pParentCandidateCnt =
+ weld::fromId<SwPostItContent*>(m_xTreeView->get_id(*xEntry));
+ return pPostItField->GetParentPostItId() ==
+ static_cast<const SwPostItField*>(pParentCandidateCnt->GetPostIt()
+ ->GetField())->GetPostItId();
+ };
+
+ // if a parent candidate is not found use the passed root node
+ auto aFind = std::find_if(aParentCandidates.rbegin(), aParentCandidates.rend(), lambda);
+ if (aFind != aParentCandidates.rend())
+ insert(aFind->get(), sEntry, sId, false, xChild.get());
+ else
+ insert(&rParent, sEntry, sId, false, xChild.get());
+
+ m_xTreeView->set_sensitive(*xChild, !pCnt->IsInvisible());
+
+ // clear parent candidates when encountering a postit that doesn't have a parent
+ // following postits can't have a parent that is in these candidates
+ if (pPostItField->GetParentPostItId() == 0)
+ aParentCandidates.clear();
+
+ aParentCandidates.emplace_back(m_xTreeView->make_iterator(xChild.get()));
+ }
+ }
+ else
+ InsertContent(rParent);
+
+ return nCount != 0;
+ }
+
+ return false;
+}
+
+void SwContentTree::ExpandAllHeadings()
+{
+ if (HasHeadings())
+ {
+ std::unique_ptr<weld::TreeIter> xEntry = GetEntryAtAbsPos(0);
+ if (xEntry)
+ {
+ if (!IsAllExpanded(*m_xTreeView, *xEntry))
+ ExpandOrCollapseAll(*m_xTreeView, *xEntry);
+ }
+ }
+}
+
+SdrObject* SwContentTree::GetDrawingObjectsByContent(const SwContent *pCnt)
+{
+ SdrObject *pRetObj = nullptr;
+ switch(pCnt->GetParent()->GetType())
+ {
+ case ContentTypeId::DRAWOBJECT:
+ {
+ SdrView* pDrawView = m_pActiveShell->GetDrawView();
+ if (pDrawView)
+ {
+ SwDrawModel* pDrawModel = m_pActiveShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
+ SdrPage* pPage = pDrawModel->GetPage(0);
+
+ for (const rtl::Reference<SdrObject>& pTemp : *pPage)
+ {
+ if( pTemp->GetName() == pCnt->GetName())
+ {
+ pRetObj = pTemp.get();
+ break;
+ }
+ }
+ }
+ break;
+ }
+ default:
+ pRetObj = nullptr;
+ }
+ return pRetObj;
+}
+
+void SwContentTree::Expand(const weld::TreeIter& rParent,
+ std::vector<std::unique_ptr<weld::TreeIter>>* pNodesToExpand)
+{
+ if (!m_xTreeView->iter_has_child(rParent) && !m_xTreeView->get_children_on_demand(rParent))
+ return;
+
+ // pNodesToExpand is used by the Display function to restore the trees expand structure for
+ // hierarchical content types, e.g., OUTLINE and REGION.
+ if (pNodesToExpand)
+ pNodesToExpand->emplace_back(m_xTreeView->make_iterator(&rParent));
+
+ // rParentId is a string representation of a pointer to SwContentType or SwContent
+ const OUString& rParentId = m_xTreeView->get_id(rParent);
+ // bParentIsContentType tells if the passed rParent tree entry is a content type or content
+ const bool bParentIsContentType = lcl_IsContentType(rParent, *m_xTreeView);
+ // eParentContentTypeId is the content type of the passed rParent tree entry
+ const ContentTypeId eParentContentTypeId =
+ bParentIsContentType ? weld::fromId<SwContentType*>(rParentId)->GetType() :
+ weld::fromId<SwContent*>(rParentId)->GetParent()->GetType();
+
+ if (m_nRootType == ContentTypeId::UNKNOWN && bParentIsContentType)
+ {
+ // m_nActiveBlock and m_nHiddenBlock are used to persist the content type expand state for
+ // the all content view mode
+ const int nShift = static_cast<int>(eParentContentTypeId);
+ SAL_WARN_IF(nShift < 0, "sw.ui", "ContentTypeId::UNKNOWN negative shift");
+ if (nShift >= 0)
+ {
+ const sal_Int32 nOr = 1 << nShift; //linear -> Bitposition
+ if (State::HIDDEN != m_eState)
+ {
+ m_nActiveBlock |= nOr;
+ m_pConfig->SetActiveBlock(m_nActiveBlock);
+ }
+ else
+ m_nHiddenBlock |= nOr;
+ }
+ }
+
+ if (m_nRootType == ContentTypeId::OUTLINE || (m_nRootType == ContentTypeId::UNKNOWN &&
+ eParentContentTypeId == ContentTypeId::OUTLINE))
+ {
+ if (bParentIsContentType)
+ {
+ std::map< void*, bool > aCurrOutLineNodeMap;
+
+ SwWrtShell* pShell = GetWrtShell();
+ bool bParentHasChild = RequestingChildren(rParent);
+ if (bParentHasChild)
+ {
+ std::unique_ptr<weld::TreeIter> xChild(m_xTreeView->make_iterator(&rParent));
+ bool bChild = m_xTreeView->iter_next(*xChild);
+ while (bChild && lcl_IsContent(*xChild, *m_xTreeView))
+ {
+ if (m_xTreeView->iter_has_child(*xChild))
+ {
+ assert(dynamic_cast<SwOutlineContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xChild))));
+ auto const nPos = weld::fromId<SwOutlineContent*>(m_xTreeView->get_id(*xChild))->GetOutlinePos();
+ void* key = static_cast<void*>(pShell->getIDocumentOutlineNodesAccess()->getOutlineNode( nPos ));
+ aCurrOutLineNodeMap.emplace( key, false );
+ std::map<void*, bool>::iterator iter = mOutLineNodeMap.find( key );
+ if( iter != mOutLineNodeMap.end() && mOutLineNodeMap[key])
+ {
+ aCurrOutLineNodeMap[key] = true;
+ RequestingChildren(*xChild);
+ if (pNodesToExpand)
+ pNodesToExpand->emplace_back(m_xTreeView->make_iterator(xChild.get()));
+ m_xTreeView->set_children_on_demand(*xChild, false);
+ }
+ }
+ bChild = m_xTreeView->iter_next(*xChild);
+ }
+ }
+ mOutLineNodeMap = aCurrOutLineNodeMap;
+ return;
+ }
+ else // content entry
+ {
+ SwWrtShell* pShell = GetWrtShell();
+ assert(dynamic_cast<SwOutlineContent*>(weld::fromId<SwTypeNumber*>(rParentId)));
+ auto const nPos = weld::fromId<SwOutlineContent*>(rParentId)->GetOutlinePos();
+ void* key = static_cast<void*>(pShell->getIDocumentOutlineNodesAccess()->getOutlineNode( nPos ));
+ mOutLineNodeMap[key] = true;
+ }
+ }
+ else if (m_nRootType == ContentTypeId::REGION || (m_nRootType == ContentTypeId::UNKNOWN &&
+ eParentContentTypeId == ContentTypeId::REGION))
+ {
+ if (bParentIsContentType)
+ {
+ std::map<const void*, bool> aCurrentRegionNodeExpandMap;
+ if (RequestingChildren(rParent))
+ {
+ std::unique_ptr<weld::TreeIter> xChild(m_xTreeView->make_iterator(&rParent));
+ while (m_xTreeView->iter_next(*xChild) && lcl_IsContent(*xChild, *m_xTreeView))
+ {
+ if (m_xTreeView->iter_has_child(*xChild))
+ {
+ assert(dynamic_cast<SwRegionContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xChild))));
+ const void* key =
+ static_cast<const void*>(weld::fromId<SwRegionContent*>(
+ m_xTreeView->get_id(*xChild))->GetSectionFormat());
+ bool bExpandNode =
+ m_aRegionNodeExpandMap.contains(key) && m_aRegionNodeExpandMap[key];
+ aCurrentRegionNodeExpandMap.emplace(key, bExpandNode);
+ if (bExpandNode)
+ {
+ if (pNodesToExpand)
+ pNodesToExpand->emplace_back(m_xTreeView->make_iterator(xChild.get()));
+ RequestingChildren(*xChild);
+ m_xTreeView->set_children_on_demand(*xChild, false);
+ }
+ }
+ }
+ }
+ m_aRegionNodeExpandMap = aCurrentRegionNodeExpandMap;
+ return;
+ }
+ else // content entry
+ {
+ assert(dynamic_cast<SwRegionContent*>(weld::fromId<SwTypeNumber*>(rParentId)));
+ const void* key = static_cast<const void*>(
+ weld::fromId<SwRegionContent*>(rParentId)->GetSectionFormat());
+ m_aRegionNodeExpandMap[key] = true;
+ }
+ }
+ else if (m_nRootType == ContentTypeId::POSTIT || (m_nRootType == ContentTypeId::UNKNOWN &&
+ eParentContentTypeId == ContentTypeId::POSTIT))
+ {
+ if (bParentIsContentType)
+ {
+ std::map<const void*, bool> aCurrentPostItNodeExpandMap;
+ if (RequestingChildren(rParent))
+ {
+ std::unique_ptr<weld::TreeIter> xChild(m_xTreeView->make_iterator(&rParent));
+ while (m_xTreeView->iter_next(*xChild) && lcl_IsContent(*xChild, *m_xTreeView))
+ {
+ if (m_xTreeView->iter_has_child(*xChild))
+ {
+ assert(dynamic_cast<SwPostItContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xChild))));
+ const void* key =
+ static_cast<const void*>(weld::fromId<SwPostItContent*>(
+ m_xTreeView->get_id(*xChild))->GetPostIt());
+ bool bExpandNode =
+ m_aPostItNodeExpandMap.contains(key) && m_aPostItNodeExpandMap[key];
+ aCurrentPostItNodeExpandMap.emplace(key, bExpandNode);
+ if (bExpandNode)
+ {
+ if (pNodesToExpand)
+ pNodesToExpand->emplace_back(m_xTreeView->make_iterator(xChild.get()));
+ RequestingChildren(*xChild);
+ m_xTreeView->set_children_on_demand(*xChild, false);
+ }
+ }
+ }
+ }
+ m_aPostItNodeExpandMap = aCurrentPostItNodeExpandMap;
+ return;
+ }
+ else // content entry
+ {
+ assert(dynamic_cast<SwPostItContent*>(weld::fromId<SwTypeNumber*>(rParentId)));
+ const void* key = static_cast<const void*>(
+ weld::fromId<SwPostItContent*>(rParentId)->GetPostIt());
+ m_aPostItNodeExpandMap[key] = true;
+ }
+ }
+
+ RequestingChildren(rParent);
+}
+
+IMPL_LINK(SwContentTree, ExpandHdl, const weld::TreeIter&, rParent, bool)
+{
+ Expand(rParent, nullptr);
+ return true;
+}
+
+IMPL_LINK(SwContentTree, CollapseHdl, const weld::TreeIter&, rParent, bool)
+{
+ if (!m_xTreeView->iter_has_child(rParent) || m_xTreeView->get_children_on_demand(rParent))
+ return true;
+
+ if (lcl_IsContentType(rParent, *m_xTreeView))
+ {
+ if (m_bIsRoot)
+ {
+ // collapse to children of root node
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator(&rParent));
+ if (m_xTreeView->iter_children(*xEntry))
+ {
+ do
+ {
+ m_xTreeView->collapse_row(*xEntry);
+ }
+ while (m_xTreeView->iter_next(*xEntry));
+ }
+ return false; // return false to notify caller not to do collapse
+ }
+ ContentTypeId eContentTypeId =
+ weld::fromId<SwContentType*>(m_xTreeView->get_id(rParent))->GetType();
+ const int nShift = static_cast<int>(eContentTypeId);
+ SAL_WARN_IF(nShift < 0, "sw.ui", "ContentTypeId::UNKNOWN negative shift");
+ if (nShift >= 0)
+ {
+ const sal_Int32 nAnd = ~(1 << nShift);
+ if (State::HIDDEN != m_eState)
+ {
+ m_nActiveBlock &= nAnd;
+ m_pConfig->SetActiveBlock(m_nActiveBlock);
+ }
+ else
+ m_nHiddenBlock &= nAnd;
+ }
+ }
+ else // content entry
+ {
+ SwWrtShell* pShell = GetWrtShell();
+ ContentTypeId eContentTypeId =
+ weld::fromId<SwContent*>(m_xTreeView->get_id(rParent))->GetParent()->GetType();
+ if (eContentTypeId == ContentTypeId::OUTLINE)
+ {
+ assert(dynamic_cast<SwOutlineContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(rParent))));
+ auto const nPos = weld::fromId<SwOutlineContent*>(m_xTreeView->get_id(rParent))->GetOutlinePos();
+ void* key = static_cast<void*>(pShell->getIDocumentOutlineNodesAccess()->getOutlineNode( nPos ));
+ mOutLineNodeMap[key] = false;
+ }
+ else if(eContentTypeId == ContentTypeId::REGION)
+ {
+ assert(dynamic_cast<SwRegionContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(rParent))));
+ const void* key = static_cast<const void*>(weld::fromId<SwRegionContent*>(m_xTreeView->get_id(rParent))->GetSectionFormat());
+ m_aRegionNodeExpandMap[key] = false;
+ }
+ else if(eContentTypeId == ContentTypeId::POSTIT)
+ {
+ assert(dynamic_cast<SwPostItContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(rParent))));
+ const void* key = static_cast<const void*>(weld::fromId<SwPostItContent*>(m_xTreeView->get_id(rParent))->GetPostIt());
+ m_aPostItNodeExpandMap[key] = false;
+ }
+ }
+
+ return true;
+}
+
+// Also on double click will be initially opened only.
+IMPL_LINK_NOARG(SwContentTree, ContentDoubleClickHdl, weld::TreeView&, bool)
+{
+ if (m_nRowActivateEventId)
+ Application::RemoveUserEvent(m_nRowActivateEventId);
+ // post the event to process row activate after mouse press event to be able to set key
+ // modifier for selection feature (tdf#154211)
+ m_nRowActivateEventId
+ = Application::PostUserEvent(LINK(this, SwContentTree, AsyncContentDoubleClickHdl));
+
+ bool bConsumed = false;
+
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ if (m_xTreeView->get_cursor(xEntry.get()) && lcl_IsContent(*xEntry, *m_xTreeView) &&
+ (State::HIDDEN != m_eState))
+ {
+ SwContent* pCnt = weld::fromId<SwContent*>(m_xTreeView->get_id(*xEntry));
+ assert(pCnt && "no UserData");
+ if (pCnt && !pCnt->IsInvisible())
+ {
+ // fdo#36308 don't expand outlines on double-click
+ bConsumed = pCnt->GetParent()->GetType() == ContentTypeId::OUTLINE;
+ }
+ }
+
+ return bConsumed; // false/true == allow/disallow more to be done, i.e. expand/collapse children
+}
+
+IMPL_LINK_NOARG(SwContentTree, AsyncContentDoubleClickHdl, void*, void)
+{
+ m_nRowActivateEventId = nullptr;
+
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ bool bEntry = m_xTreeView->get_cursor(xEntry.get());
+ // Is it a content type?
+ OSL_ENSURE(bEntry, "no current entry!");
+ if (bEntry)
+ {
+ if (lcl_IsContentType(*xEntry, *m_xTreeView) && !m_xTreeView->iter_has_child(*xEntry))
+ {
+ RequestingChildren(*xEntry);
+ m_xTreeView->set_children_on_demand(*xEntry, false);
+ }
+ else if (!lcl_IsContentType(*xEntry, *m_xTreeView) && (State::HIDDEN != m_eState))
+ {
+ assert(dynamic_cast<SwContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xEntry))));
+ SwContent* pCnt = weld::fromId<SwContent*>(m_xTreeView->get_id(*xEntry));
+ assert(pCnt && "no UserData");
+ if (pCnt && !pCnt->IsInvisible())
+ {
+ if (State::CONSTANT == m_eState)
+ {
+ m_pActiveShell->GetView().GetViewFrame().GetWindow().ToTop();
+ }
+ //Jump to content type:
+ GotoContent(pCnt);
+ }
+ }
+ }
+}
+
+namespace
+{
+ OUString GetImageIdForContentTypeId(ContentTypeId eType)
+ {
+ OUString sResId;
+
+ switch (eType)
+ {
+ case ContentTypeId::OUTLINE:
+ sResId = RID_BMP_NAVI_OUTLINE;
+ break;
+ case ContentTypeId::TABLE:
+ sResId = RID_BMP_NAVI_TABLE;
+ break;
+ case ContentTypeId::FRAME:
+ sResId = RID_BMP_NAVI_FRAME;
+ break;
+ case ContentTypeId::GRAPHIC:
+ sResId = RID_BMP_NAVI_GRAPHIC;
+ break;
+ case ContentTypeId::OLE:
+ sResId = RID_BMP_NAVI_OLE;
+ break;
+ case ContentTypeId::BOOKMARK:
+ sResId = RID_BMP_NAVI_BOOKMARK;
+ break;
+ case ContentTypeId::REGION:
+ sResId = RID_BMP_NAVI_REGION;
+ break;
+ case ContentTypeId::URLFIELD:
+ sResId = RID_BMP_NAVI_URLFIELD;
+ break;
+ case ContentTypeId::REFERENCE:
+ sResId = RID_BMP_NAVI_REFERENCE;
+ break;
+ case ContentTypeId::INDEX:
+ sResId = RID_BMP_NAVI_INDEX;
+ break;
+ case ContentTypeId::POSTIT:
+ sResId = RID_BMP_NAVI_POSTIT;
+ break;
+ case ContentTypeId::DRAWOBJECT:
+ sResId = RID_BMP_NAVI_DRAWOBJECT;
+ break;
+ case ContentTypeId::TEXTFIELD:
+ sResId = RID_BMP_NAVI_TEXTFIELD;
+ break;
+ case ContentTypeId::FOOTNOTE:
+ sResId = RID_BMP_NAVI_FOOTNOTE;
+ break;
+ case ContentTypeId::ENDNOTE:
+ sResId = RID_BMP_NAVI_ENDNOTE;
+ break;
+ case ContentTypeId::UNKNOWN:
+ SAL_WARN("sw.ui", "ContentTypeId::UNKNOWN has no bitmap preview");
+ break;
+ }
+
+ return sResId;
+ };
+}
+
+size_t SwContentTree::GetAbsPos(const weld::TreeIter& rIter)
+{
+ return weld::GetAbsPos(*m_xTreeView, rIter);
+}
+
+size_t SwContentTree::GetEntryCount() const
+{
+ return m_nEntryCount;
+}
+
+size_t SwContentTree::GetChildCount(const weld::TreeIter& rParent) const
+{
+ if (!m_xTreeView->iter_has_child(rParent))
+ return 0;
+
+ std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator(&rParent));
+
+ size_t nCount = 0;
+ auto nRefDepth = m_xTreeView->get_iter_depth(*xParent);
+ auto nActDepth = nRefDepth;
+ do
+ {
+ if (!m_xTreeView->iter_next(*xParent))
+ xParent.reset();
+ else
+ nActDepth = m_xTreeView->get_iter_depth(*xParent);
+ nCount++;
+ } while(xParent && nRefDepth < nActDepth);
+
+ nCount--;
+ return nCount;
+}
+
+std::unique_ptr<weld::TreeIter> SwContentTree::GetEntryAtAbsPos(size_t nAbsPos) const
+{
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ if (!m_xTreeView->get_iter_first(*xEntry))
+ xEntry.reset();
+
+ while (nAbsPos && xEntry)
+ {
+ if (!m_xTreeView->iter_next(*xEntry))
+ xEntry.reset();
+ nAbsPos--;
+ }
+ return xEntry;
+}
+
+void SwContentTree::Display( bool bActive )
+{
+ // First read the selected entry to select it later again if necessary
+ // -> the user data here are no longer valid!
+ std::unique_ptr<weld::TreeIter> xOldSelEntry(m_xTreeView->make_iterator());
+ if (!m_xTreeView->get_selected(xOldSelEntry.get()))
+ xOldSelEntry.reset();
+ OUString sOldSelEntryId;
+ size_t nEntryRelPos = 0; // relative position to their parent
+ size_t nOldEntryCount = GetEntryCount();
+ sal_Int32 nOldScrollPos = 0;
+ if (xOldSelEntry)
+ {
+ UpdateLastSelType();
+ sOldSelEntryId = m_xTreeView->get_id(*xOldSelEntry);
+ nOldScrollPos = m_xTreeView->vadjustment_get_value();
+ std::unique_ptr<weld::TreeIter> xParentEntry = m_xTreeView->make_iterator(xOldSelEntry.get());
+ while (m_xTreeView->get_iter_depth(*xParentEntry))
+ m_xTreeView->iter_parent(*xParentEntry);
+ if (m_xTreeView->get_iter_depth(*xOldSelEntry))
+ nEntryRelPos = GetAbsPos(*xOldSelEntry) - GetAbsPos(*xParentEntry);
+ }
+
+ clear();
+
+ if (!bActive)
+ {
+ m_aOverlayObjectDelayTimer.Stop();
+ if (m_xOverlayObject && m_xOverlayObject->getOverlayManager())
+ {
+ m_xOverlayObject->getOverlayManager()->remove(*m_xOverlayObject);
+ m_xOverlayObject.reset();
+ }
+ m_eState = State::HIDDEN;
+ }
+ else if (State::HIDDEN == m_eState)
+ m_eState = State::ACTIVE;
+ SwWrtShell* pShell = GetWrtShell();
+ const bool bReadOnly = !pShell || pShell->GetView().GetDocShell()->IsReadOnly();
+ if(bReadOnly != m_bIsLastReadOnly)
+ {
+ m_bIsLastReadOnly = bReadOnly;
+ bool bDisable = pShell == nullptr || bReadOnly;
+ SwNavigationPI* pNavi = GetParentWindow();
+ pNavi->m_xContent6ToolBox->set_item_sensitive("chapterup", !bDisable);
+ pNavi->m_xContent6ToolBox->set_item_sensitive("chapterdown", !bDisable);
+ pNavi->m_xContent6ToolBox->set_item_sensitive("promote", !bDisable);
+ pNavi->m_xContent6ToolBox->set_item_sensitive("demote", !bDisable);
+ pNavi->m_xContent5ToolBox->set_item_sensitive("reminder", !bDisable);
+ }
+
+ if (pShell)
+ {
+ std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
+ std::unique_ptr<weld::TreeIter> xCntTypeEntry;
+ std::vector<std::unique_ptr<weld::TreeIter>> aNodesToExpand;
+ // all content navigation view
+ if(m_nRootType == ContentTypeId::UNKNOWN)
+ {
+ m_xTreeView->freeze();
+
+ for( ContentTypeId nCntType : o3tl::enumrange<ContentTypeId>() )
+ {
+ std::unique_ptr<SwContentType>& rpContentT = bActive ?
+ m_aActiveContentArr[nCntType] :
+ m_aHiddenContentArr[nCntType];
+ if(!rpContentT)
+ rpContentT.reset(new SwContentType(pShell, nCntType, m_nOutlineLevel ));
+
+ OUString aImage(GetImageIdForContentTypeId(nCntType));
+ bool bChOnDemand = 0 != rpContentT->GetMemberCount();
+
+ // In case of LOK, empty content types must be hidden in the contenttree
+ if (comphelper::LibreOfficeKit::isActive() && !bChOnDemand)
+ {
+ continue;
+ }
+
+ OUString sId(weld::toId(rpContentT.get()));
+ insert(nullptr, rpContentT->GetName(), sId, bChOnDemand, xEntry.get());
+ m_xTreeView->set_image(*xEntry, aImage);
+
+ m_xTreeView->set_sensitive(*xEntry, bChOnDemand);
+
+ if (nCntType == m_nLastSelType)
+ xCntTypeEntry = m_xTreeView->make_iterator(xEntry.get());
+
+ sal_Int32 nExpandOptions = (State::HIDDEN == m_eState)
+ ? m_nHiddenBlock
+ : m_nActiveBlock;
+ if (nExpandOptions & (1 << static_cast<int>(nCntType)))
+ {
+ // fill contents of to-be expanded entries while frozen
+ Expand(*xEntry, &aNodesToExpand);
+ m_xTreeView->set_children_on_demand(*xEntry, false);
+ }
+ }
+
+ m_xTreeView->thaw();
+
+ // restore visual expanded tree state
+ for (const auto& rNode : aNodesToExpand)
+ m_xTreeView->expand_row(*rNode);
+ }
+ // root content navigation view
+ else
+ {
+ m_xTreeView->freeze();
+
+ std::unique_ptr<SwContentType>& rpRootContentT = bActive ?
+ m_aActiveContentArr[m_nRootType] :
+ m_aHiddenContentArr[m_nRootType];
+ if(!rpRootContentT)
+ rpRootContentT.reset(new SwContentType(pShell, m_nRootType, m_nOutlineLevel ));
+ OUString aImage(GetImageIdForContentTypeId(m_nRootType));
+ bool bChOnDemand(m_nRootType == ContentTypeId::OUTLINE ||
+ m_nRootType == ContentTypeId::REGION ||
+ m_nRootType == ContentTypeId::POSTIT);
+ OUString sId(weld::toId(rpRootContentT.get()));
+ insert(nullptr, rpRootContentT->GetName(), sId, bChOnDemand, xEntry.get());
+ m_xTreeView->set_image(*xEntry, aImage);
+
+ xCntTypeEntry = m_xTreeView->make_iterator(xEntry.get());
+
+ if (!bChOnDemand)
+ InsertContent(*xEntry);
+ else
+ {
+ // fill contents of to-be expanded entries while frozen
+ Expand(*xEntry, &aNodesToExpand);
+ m_xTreeView->set_children_on_demand(*xEntry, false);
+ }
+
+ m_xTreeView->set_sensitive(*xEntry, m_xTreeView->iter_has_child(*xEntry));
+
+ m_xTreeView->thaw();
+
+ if (bChOnDemand)
+ {
+ // restore visual expanded tree state
+ for (const auto& rNode : aNodesToExpand)
+ m_xTreeView->expand_row(*rNode);
+ }
+ else
+ m_xTreeView->expand_row(*xEntry);
+ }
+
+ // Reselect the old selected entry. If it is not available, select the entry at the old
+ // selected entry position unless that entry position is now a content type or is past the
+ // end of the member list then select the entry at the previous entry position.
+ if (xOldSelEntry)
+ {
+ std::unique_ptr<weld::TreeIter> xSelEntry = m_xTreeView->make_iterator(xCntTypeEntry.get());
+ if (nEntryRelPos)
+ {
+ std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator(xCntTypeEntry.get()));
+ std::unique_ptr<weld::TreeIter> xTemp(m_xTreeView->make_iterator(xIter.get()));
+ sal_uLong nPos = 1;
+ bool bNext;
+ while ((bNext = m_xTreeView->iter_next(*xIter) && lcl_IsContent(*xIter, *m_xTreeView)))
+ {
+ if (m_xTreeView->get_id(*xIter) == sOldSelEntryId || nPos == nEntryRelPos)
+ {
+ m_xTreeView->copy_iterator(*xIter, *xSelEntry);
+ break;
+ }
+ m_xTreeView->copy_iterator(*xIter, *xTemp); // note previous entry
+ nPos++;
+ }
+ if (!bNext)
+ xSelEntry = std::move(xTemp);
+ }
+ // set_cursor unselects all entries, makes passed entry visible, and selects it
+ m_xTreeView->set_cursor(*xSelEntry);
+ Select();
+ }
+ }
+
+ if (!m_bIgnoreDocChange && GetEntryCount() == nOldEntryCount)
+ {
+ m_xTreeView->vadjustment_set_value(nOldScrollPos);
+ }
+}
+
+void SwContentTree::clear()
+{
+ m_xTreeView->freeze();
+ m_xTreeView->clear();
+ m_nEntryCount = 0;
+ m_xTreeView->thaw();
+}
+
+bool SwContentTree::FillTransferData( TransferDataContainer& rTransfer,
+ sal_Int8& rDragMode )
+{
+ bool bRet = false;
+ SwWrtShell* pWrtShell = GetWrtShell();
+ OSL_ENSURE(pWrtShell, "no Shell!");
+
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ bool bEntry = m_xTreeView->get_cursor(xEntry.get());
+ if (!bEntry || lcl_IsContentType(*xEntry, *m_xTreeView) || !pWrtShell)
+ return false;
+ OUString sEntry;
+ assert(dynamic_cast<SwContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xEntry))));
+ SwContent* pCnt = weld::fromId<SwContent*>(m_xTreeView->get_id(*xEntry));
+
+ const ContentTypeId nActType = pCnt->GetParent()->GetType();
+ OUString sUrl;
+ bool bOutline = false;
+ OUString sOutlineText;
+ switch( nActType )
+ {
+ case ContentTypeId::OUTLINE:
+ {
+ const SwOutlineNodes::size_type nPos = static_cast<SwOutlineContent*>(pCnt)->GetOutlinePos();
+ OSL_ENSURE(nPos < pWrtShell->getIDocumentOutlineNodesAccess()->getOutlineNodesCount(),
+ "outlinecnt changed");
+
+ // make sure outline may actually be copied
+ if( pWrtShell->IsOutlineCopyable( nPos ) )
+ {
+ const SwNumRule* pOutlRule = pWrtShell->GetOutlineNumRule();
+ const SwTextNode* pTextNd =
+ pWrtShell->getIDocumentOutlineNodesAccess()->getOutlineNode(nPos);
+ if (pTextNd && pOutlRule && pTextNd->IsNumbered(pWrtShell->GetLayout()))
+ {
+ SwNumberTree::tNumberVector aNumVector =
+ pTextNd->GetNumberVector(pWrtShell->GetLayout());
+ for( int nLevel = 0;
+ nLevel <= pTextNd->GetActualListLevel();
+ nLevel++ )
+ {
+ const SwNumberTree::tSwNumTreeNumber nVal = aNumVector[nLevel] + 1;
+ sEntry += OUString::number( nVal - pOutlRule->Get(nLevel).GetStart() ) + ".";
+ }
+ }
+ sEntry += pWrtShell->getIDocumentOutlineNodesAccess()->getOutlineText(nPos, pWrtShell->GetLayout(), false);
+ sOutlineText = pWrtShell->getIDocumentOutlineNodesAccess()->getOutlineText(nPos, pWrtShell->GetLayout());
+ m_bIsOutlineMoveable = static_cast<SwOutlineContent*>(pCnt)->IsMoveable();
+ bOutline = true;
+ }
+ }
+ break;
+ case ContentTypeId::POSTIT:
+ case ContentTypeId::INDEX:
+ case ContentTypeId::REFERENCE :
+ case ContentTypeId::TEXTFIELD:
+ case ContentTypeId::FOOTNOTE:
+ case ContentTypeId::ENDNOTE:
+ // cannot be inserted, neither as URL nor as section
+ break;
+ case ContentTypeId::URLFIELD:
+ sUrl = static_cast<SwURLFieldContent*>(pCnt)->GetURL();
+ [[fallthrough]];
+ case ContentTypeId::OLE:
+ case ContentTypeId::GRAPHIC:
+ if(GetParentWindow()->GetRegionDropMode() != RegionMode::NONE)
+ break;
+ else
+ rDragMode &= ~( DND_ACTION_MOVE | DND_ACTION_LINK );
+ [[fallthrough]];
+ default:
+ sEntry = m_xTreeView->get_text(*xEntry);
+ }
+
+ if(!sEntry.isEmpty())
+ {
+ const SwDocShell* pDocShell = pWrtShell->GetView().GetDocShell();
+ if(sUrl.isEmpty())
+ {
+ if(pDocShell->HasName())
+ {
+ SfxMedium* pMedium = pDocShell->GetMedium();
+ sUrl = pMedium->GetURLObject().GetURLNoMark();
+ // only if a primarily link shall be integrated.
+ bRet = true;
+ }
+ else if ( nActType == ContentTypeId::REGION || nActType == ContentTypeId::BOOKMARK )
+ {
+ // For field and bookmarks a link is also allowed
+ // without a filename into its own document.
+ bRet = true;
+ }
+ else if (State::CONSTANT == m_eState &&
+ ( !::GetActiveView() ||
+ m_pActiveShell != ::GetActiveView()->GetWrtShellPtr()))
+ {
+ // Urls of inactive views cannot dragged without
+ // file names, also.
+ bRet = false;
+ }
+ else
+ {
+ bRet = GetParentWindow()->GetRegionDropMode() == RegionMode::NONE;
+ rDragMode = DND_ACTION_MOVE;
+ }
+
+ const OUString& rToken = pCnt->GetParent()->GetTypeToken();
+ sUrl += "#" + sEntry;
+ if(!rToken.isEmpty())
+ {
+ sUrl += OUStringChar(cMarkSeparator) + rToken;
+ }
+ }
+ else
+ bRet = true;
+
+ if( bRet )
+ {
+ // In Outlines of heading text must match
+ // the real number into the description.
+ if(bOutline)
+ sEntry = sOutlineText;
+
+ {
+ NaviContentBookmark aBmk( sUrl, sEntry,
+ GetParentWindow()->GetRegionDropMode(),
+ pDocShell);
+ aBmk.Copy( rTransfer );
+ }
+
+ // An INetBookmark must a be delivered to foreign DocShells
+ if( pDocShell->HasName() )
+ {
+ INetBookmark aBkmk( sUrl, sEntry );
+ rTransfer.CopyINetBookmark( aBkmk );
+ }
+ }
+ }
+ return bRet;
+}
+
+void SwContentTree::ToggleToRoot()
+{
+ if(!m_bIsRoot)
+ {
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ bool bEntry = m_xTreeView->get_cursor(xEntry.get());
+ if (bEntry)
+ {
+ const SwContentType* pCntType;
+ if (lcl_IsContentType(*xEntry, *m_xTreeView))
+ {
+ assert(dynamic_cast<SwContentType*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xEntry))));
+ pCntType = weld::fromId<SwContentType*>(m_xTreeView->get_id(*xEntry));
+ }
+ else
+ {
+ assert(dynamic_cast<SwContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xEntry))));
+ pCntType = weld::fromId<SwContent*>(m_xTreeView->get_id(*xEntry))->GetParent();
+ }
+ m_nRootType = pCntType->GetType();
+ m_bIsRoot = true;
+ if (m_nRootType == ContentTypeId::OUTLINE || m_nRootType == ContentTypeId::DRAWOBJECT)
+ {
+ m_xTreeView->set_selection_mode(SelectionMode::Multiple);
+ }
+ Display(State::HIDDEN != m_eState);
+ }
+ }
+ else
+ {
+ m_xTreeView->set_selection_mode(SelectionMode::Single);
+ m_nLastSelType = m_nRootType;
+ m_nRootType = ContentTypeId::UNKNOWN;
+ m_bIsRoot = false;
+ // Other content type member data could have changed while in root view. Fill the content
+ // member lists excluding the toggled from root content which should already have the most
+ // recent data.
+ if (State::HIDDEN != m_eState)
+ {
+ for (ContentTypeId i : o3tl::enumrange<ContentTypeId>())
+ {
+ if (i != m_nLastSelType && m_aActiveContentArr[i])
+ m_aActiveContentArr[i]->FillMemberList();
+ }
+ }
+ Display(State::HIDDEN != m_eState);
+ }
+ m_pConfig->SetRootType( m_nRootType );
+ weld::Toolbar* pBox = GetParentWindow()->m_xContent5ToolBox.get();
+ pBox->set_item_active("root", m_bIsRoot);
+}
+
+bool SwContentTree::HasContentChanged()
+{
+ bool bContentChanged = false;
+
+// - Run through the local array and the Treelistbox in parallel.
+// - Are the records not expanded, they are discarded only in the array
+// and the content type will be set as the new UserData.
+// - Is the root mode is active only this will be updated.
+
+// Valid for the displayed content types is:
+// the Memberlist will be erased and the membercount will be updated
+// If content will be checked, the memberlists will be replenished
+// at the same time. Once a difference occurs it will be only replenished
+// no longer checked. Finally, the box is filled again.
+
+ if (State::HIDDEN == m_eState)
+ {
+ for(ContentTypeId i : o3tl::enumrange<ContentTypeId>())
+ {
+ if(m_aActiveContentArr[i])
+ m_aActiveContentArr[i]->Invalidate();
+ }
+ return false;
+ }
+
+ // single content type navigation view
+ if(m_bIsRoot)
+ {
+ std::unique_ptr<weld::TreeIter> xRootEntry(m_xTreeView->make_iterator());
+ if (!m_xTreeView->get_iter_first(*xRootEntry))
+ return true;
+
+ assert(dynamic_cast<SwContentType*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xRootEntry))));
+ const ContentTypeId nType = weld::fromId<SwContentType*>(m_xTreeView->get_id(*xRootEntry))->GetType();
+ SwContentType* pArrType = m_aActiveContentArr[nType].get();
+ assert(weld::toId(pArrType) == m_xTreeView->get_id(*xRootEntry));
+ if (!pArrType)
+ return true;
+
+ pArrType->FillMemberList(&bContentChanged);
+ if (bContentChanged)
+ return true;
+
+ // FillMemberList tests if member count in old member array equals member count in new
+ // member array. Test here for member count difference between array and tree.
+ const size_t nChildCount = GetChildCount(*xRootEntry);
+ if (nChildCount != pArrType->GetMemberCount())
+ return true;
+
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator(xRootEntry.get()));
+ for (size_t j = 0; j < nChildCount; ++j)
+ {
+ if (!m_xTreeView->iter_next(*xEntry))
+ {
+ SAL_WARN("sw.ui", "unexpected missing entry");
+ return true;
+ }
+
+ // FillMemberList clears the content type member list and refills with new data.
+ // Treeview entry user data is set here to the string representation of the pointer to
+ // the member data in the array. The Display function will clear and recreate the
+ // treeview from the content type member arrays if content change is detected.
+ const SwContent* pCnt = pArrType->GetMember(j);
+
+ if (pCnt->IsInvisible() != m_xTreeView->get_sensitive(*xEntry, 0))
+ return true;
+
+ OUString sEntryText = m_xTreeView->get_text(*xEntry);
+ if (sEntryText != pCnt->GetName() &&
+ !(sEntryText == m_sSpace && pCnt->GetName().isEmpty()))
+ {
+ return true;
+ }
+
+ // Set_id needs to be done here because FillMemberList clears the content type member
+ // list and refills with new data making the previously set id invalid. If there is no
+ // content change detected the Display function will not be called and the tree entry
+ // user data will not be set to the new content member pointer address.
+ OUString sSubId(weld::toId(pCnt));
+ m_xTreeView->set_id(*xEntry, sSubId);
+ }
+ }
+ // all content types navigation view
+ else
+ {
+ // Fill member list for each content type and check for content change. If content change
+ // is detected only fill member lists for remaining content types. The Display function
+ // will clear and recreate the treeview from the content type member arrays if content has
+ // changed.
+
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ // In case of LOK, empty contentTypes are hidden, even in all content view
+ // so it is not enough to check only the m_xTreeView.
+ bool bCountChanged = false;
+ bool bHasContentChanged = false;
+ for (ContentTypeId i : o3tl::enumrange<ContentTypeId>())
+ {
+ if (m_aActiveContentArr[i])
+ {
+ auto nLastTMCount = m_aActiveContentArr[i]->GetMemberCount();
+ if (i == ContentTypeId::OUTLINE) // this is required for checking if header level is changed
+ m_aActiveContentArr[i]->FillMemberList(&bHasContentChanged);
+ else
+ m_aActiveContentArr[i]->FillMemberList();
+ // If the member count of a type is changed, then the content is surely changed
+ if (m_aActiveContentArr[i]->GetMemberCount() != nLastTMCount)
+ bCountChanged = true;
+ if (bHasContentChanged)
+ bContentChanged = true;
+ }
+ }
+ if (bCountChanged || bContentChanged)
+ return true;
+ }
+
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+
+ // lambda function to find the next content type entry
+ auto lcl_nextContentTypeEntry = [this, &xEntry](){
+ while (m_xTreeView->get_iter_depth(*xEntry))
+ m_xTreeView->iter_parent(*xEntry);
+ return m_xTreeView->iter_next_sibling(*xEntry);
+ };
+
+ for (bool bEntry = m_xTreeView->get_iter_first(*xEntry); bEntry;
+ bEntry = lcl_nextContentTypeEntry())
+ {
+ assert(dynamic_cast<SwContentType*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xEntry))));
+ SwContentType* pCntType = weld::fromId<SwContentType*>(m_xTreeView->get_id(*xEntry));
+ const size_t nCntCount = pCntType->GetMemberCount();
+ const ContentTypeId nType = pCntType->GetType();
+ SwContentType* pArrType = m_aActiveContentArr[nType].get();
+ assert(weld::toId(pArrType) == m_xTreeView->get_id(*xEntry));
+
+ if (!pArrType)
+ {
+ bContentChanged = true;
+ continue;
+ }
+
+ // all content type member lists must be filled!
+ if (bContentChanged)
+ {
+ // If content change has already been detected there is no need to detect
+ // other content change so no argument is supplied here to FillMemberList.
+ pArrType->FillMemberList();
+ continue;
+ }
+
+ pArrType->FillMemberList(&bContentChanged);
+ if (bContentChanged)
+ continue;
+
+ // does entry have children?
+ if (m_xTreeView->get_row_expanded(*xEntry))
+ {
+ const size_t nChildCount = GetChildCount(*xEntry);
+ if(nChildCount != pArrType->GetMemberCount())
+ {
+ bContentChanged = true;
+ continue;
+ }
+
+ for(size_t j = 0; j < nChildCount; ++j)
+ {
+ if (!m_xTreeView->iter_next(*xEntry))
+ {
+ SAL_WARN("sw.ui", "unexpected missing entry");
+ bContentChanged = true;
+ break;
+ }
+
+ const SwContent* pCnt = pArrType->GetMember(j);
+
+ if (pCnt->IsInvisible() != m_xTreeView->get_sensitive(*xEntry, 0))
+ {
+ bContentChanged = true;
+ break;
+ }
+
+ OUString sEntryText = m_xTreeView->get_text(*xEntry);
+ if( sEntryText != pCnt->GetName() &&
+ !(sEntryText == m_sSpace && pCnt->GetName().isEmpty()))
+ {
+ bContentChanged = true;
+ break;
+ }
+
+ // See comment above in single content type navigation view block for why the
+ // following is done here.
+ OUString sSubId(weld::toId(pCnt));
+ m_xTreeView->set_id(*xEntry, sSubId);
+ }
+ }
+ // not expanded and has children
+ else if (m_xTreeView->iter_has_child(*xEntry))
+ {
+ bool bRemoveChildren = false;
+ const size_t nOldChildCount = GetChildCount(*xEntry);
+ const size_t nNewChildCount = pArrType->GetMemberCount();
+ if (nOldChildCount != nNewChildCount)
+ {
+ bRemoveChildren = true;
+ }
+ else
+ {
+ std::unique_ptr<weld::TreeIter> xChild(m_xTreeView->make_iterator(xEntry.get()));
+ (void)m_xTreeView->iter_children(*xChild);
+ for (size_t j = 0; j < nOldChildCount; ++j)
+ {
+ const SwContent* pCnt = pArrType->GetMember(j);
+ OUString sSubId(weld::toId(pCnt));
+ m_xTreeView->set_id(*xChild, sSubId);
+ OUString sEntryText = m_xTreeView->get_text(*xChild);
+ if( sEntryText != pCnt->GetName() &&
+ !(sEntryText == m_sSpace && pCnt->GetName().isEmpty()))
+ {
+ bRemoveChildren = true;
+ }
+ (void)m_xTreeView->iter_next(*xChild);
+ }
+ }
+ if (bRemoveChildren)
+ {
+ std::unique_ptr<weld::TreeIter> xRemove(m_xTreeView->make_iterator(xEntry.get()));
+ while (m_xTreeView->iter_children(*xRemove))
+ {
+ remove(*xRemove);
+ m_xTreeView->copy_iterator(*xEntry, *xRemove);
+ }
+ m_xTreeView->set_children_on_demand(*xEntry, nNewChildCount != 0);
+ }
+ }
+ else if((nCntCount != 0)
+ != (pArrType->GetMemberCount()!=0))
+ {
+ bContentChanged = true;
+ continue;
+ }
+ }
+ }
+
+ return bContentChanged;
+}
+
+void SwContentTree::UpdateLastSelType()
+{
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ if (m_xTreeView->get_selected(xEntry.get()))
+ {
+ while (m_xTreeView->get_iter_depth(*xEntry))
+ m_xTreeView->iter_parent(*xEntry);
+ void* pId = weld::fromId<void*>(m_xTreeView->get_id(*xEntry));
+ if (pId && lcl_IsContentType(*xEntry, *m_xTreeView))
+ {
+ assert(dynamic_cast<SwContentType*>(static_cast<SwTypeNumber*>(pId)));
+ m_nLastSelType = static_cast<SwContentType*>(pId)->GetType();
+ }
+ }
+}
+
+void SwContentTree::FindActiveTypeAndRemoveUserData()
+{
+ UpdateLastSelType();
+
+ // If clear is called by TimerUpdate:
+ // Only for root can the validity of the UserData be guaranteed.
+ m_xTreeView->all_foreach([this](weld::TreeIter& rEntry){
+ m_xTreeView->set_id(rEntry, "");
+ return false;
+ });
+}
+
+void SwContentTree::SetHiddenShell(SwWrtShell* pSh)
+{
+ m_pHiddenShell = pSh;
+ m_eState = State::HIDDEN;
+ FindActiveTypeAndRemoveUserData();
+ for(ContentTypeId i : o3tl::enumrange<ContentTypeId>())
+ {
+ m_aHiddenContentArr[i].reset();
+ }
+ Display(false);
+
+ GetParentWindow()->UpdateListBox();
+}
+
+void SwContentTree::SetActiveShell(SwWrtShell* pSh)
+{
+ bool bClear = m_pActiveShell != pSh;
+ if (State::ACTIVE == m_eState && bClear)
+ {
+ EndListeningAll();
+ m_pActiveShell = pSh;
+ FindActiveTypeAndRemoveUserData();
+ clear();
+ }
+ else if (State::CONSTANT == m_eState)
+ {
+ EndListeningAll();
+ m_pActiveShell = pSh;
+ m_eState = State::ACTIVE;
+ bClear = true;
+ }
+
+ // tdf#148432 in LTR UI override the navigator treeview direction based on
+ // the first page directionality
+ if (m_pActiveShell && !AllSettings::GetLayoutRTL())
+ {
+ const SwPageDesc& rDesc = m_pActiveShell->GetPageDesc(0);
+ const SvxFrameDirectionItem& rFrameDir = rDesc.GetMaster().GetFrameDir();
+ m_xTreeView->set_direction(rFrameDir.GetValue() == SvxFrameDirection::Horizontal_RL_TB);
+ }
+
+ // Only if it is the active view, the array will be deleted and
+ // the screen filled new.
+ if (State::ACTIVE == m_eState && bClear)
+ {
+ if (m_pActiveShell)
+ StartListening(*m_pActiveShell->GetView().GetDocShell());
+ FindActiveTypeAndRemoveUserData();
+ for(ContentTypeId i : o3tl::enumrange<ContentTypeId>())
+ {
+ m_aActiveContentArr[i].reset();
+ }
+ Display(true);
+ }
+}
+
+void SwContentTree::SetConstantShell(SwWrtShell* pSh)
+{
+ EndListeningAll();
+ m_pActiveShell = pSh;
+ m_eState = State::CONSTANT;
+ StartListening(*m_pActiveShell->GetView().GetDocShell());
+ FindActiveTypeAndRemoveUserData();
+ for(ContentTypeId i : o3tl::enumrange<ContentTypeId>())
+ {
+ m_aActiveContentArr[i].reset();
+ }
+ Display(true);
+}
+
+void SwContentTree::Notify(SfxBroadcaster & rBC, SfxHint const& rHint)
+{
+ SfxViewEventHint const*const pVEHint(dynamic_cast<SfxViewEventHint const*>(&rHint));
+ SwXTextView* pDyingShell = nullptr;
+ if (m_pActiveShell && pVEHint && pVEHint->GetEventName() == "OnViewClosed")
+ pDyingShell = dynamic_cast<SwXTextView*>(pVEHint->GetController().get());
+ if (pDyingShell && pDyingShell->GetView() == &m_pActiveShell->GetView())
+ {
+ SetActiveShell(nullptr); // our view is dying, clear our pointers to it
+ }
+ else
+ {
+ SfxListener::Notify(rBC, rHint);
+ }
+ switch (rHint.GetId())
+ {
+ case SfxHintId::SwNavigatorUpdateTracking:
+ UpdateTracking();
+ break;
+ case SfxHintId::SwNavigatorSelectOutlinesWithSelections:
+ {
+ if (m_nRootType == ContentTypeId::OUTLINE)
+ {
+ SelectOutlinesWithSelection();
+ // make first selected entry visible
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ if (xEntry && m_xTreeView->get_selected(xEntry.get()))
+ m_xTreeView->scroll_to_row(*xEntry);
+ }
+ else if (m_nRootType == ContentTypeId::UNKNOWN)
+ m_xTreeView->unselect_all();
+ break;
+ }
+ case SfxHintId::DocChanged:
+ OverlayObject();
+ if (!m_bIgnoreDocChange)
+ {
+ m_bDocHasChanged = true;
+ TimerUpdate(&m_aUpdTimer);
+ }
+ break;
+ case SfxHintId::ModeChanged:
+ if (SwWrtShell* pShell = GetWrtShell())
+ {
+ const bool bReadOnly = pShell->GetView().GetDocShell()->IsReadOnly();
+ if (bReadOnly != m_bIsLastReadOnly)
+ {
+ m_bIsLastReadOnly = bReadOnly;
+
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ if (m_xTreeView->get_cursor(xEntry.get()))
+ {
+ m_xTreeView->select(*xEntry);
+ Select();
+ }
+ else
+ m_xTreeView->unselect_all();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+// Handler for outline entry up/down left/right movement
+void SwContentTree::ExecCommand(std::u16string_view rCmd, bool bOutlineWithChildren)
+{
+ if (m_xTreeView->count_selected_rows() == 0)
+ return;
+
+ const bool bUp = rCmd == u"chapterup";
+ const bool bUpDown = bUp || rCmd == u"chapterdown";
+ const bool bLeft = rCmd == u"promote";
+ const bool bLeftRight = bLeft || rCmd == u"demote";
+ if (!bUpDown && !bLeftRight)
+ return;
+ if (GetWrtShell()->GetView().GetDocShell()->IsReadOnly() ||
+ (State::ACTIVE != m_eState &&
+ (State::CONSTANT != m_eState || m_pActiveShell != GetParentWindow()->GetCreateView()->GetWrtShellPtr())))
+ {
+ return;
+ }
+
+ SwWrtShell *const pShell = GetWrtShell();
+
+ const SwNodes& rNodes = pShell->GetNodes();
+ const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds();
+ const SwOutlineNodes::size_type nOutlineNdsSize = rOutlineNodes.size();
+
+ std::vector<SwTextNode*> selectedOutlineNodes;
+ std::vector<std::unique_ptr<weld::TreeIter>> selected;
+
+ m_xTreeView->selected_foreach([&](weld::TreeIter& rEntry){
+ // it's possible to select the root node too which is a really bad idea
+ if (lcl_IsContentType(rEntry, *m_xTreeView))
+ return false;
+ // filter out children of selected parents so they don't get promoted
+ // or moved twice (except if there is Ctrl modifier, since in that
+ // case children are re-parented)
+ if ((bLeftRight || bOutlineWithChildren) && !selected.empty())
+ {
+ std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator(&rEntry));
+ for (bool bParent = m_xTreeView->iter_parent(*xParent); bParent; bParent = m_xTreeView->iter_parent(*xParent))
+ {
+ if (m_xTreeView->iter_compare(*selected.back(), *xParent) == 0)
+ {
+ return false;
+ }
+ }
+ }
+ selected.emplace_back(m_xTreeView->make_iterator(&rEntry));
+
+ // Use the outline node position in the SwOutlineNodes array. Bad things
+ // happen if the tree entry position is used and it doesn't match the node position
+ // in SwOutlineNodes, which is usually the case for outline nodes in frames.
+ const SwOutlineNodes::size_type nPos
+ = weld::fromId<SwOutlineContent*>(m_xTreeView->get_id(rEntry))->GetOutlinePos();
+ if (nPos < nOutlineNdsSize)
+ {
+ SwNode* pNode = rNodes.GetOutLineNds()[ nPos ];
+ if (pNode)
+ {
+ selectedOutlineNodes.push_back(pNode->GetTextNode());
+ }
+ }
+ return false;
+ });
+
+ if (!selected.size())
+ return;
+
+ if (bUpDown && !bUp)
+ { // to move down, start at the end!
+ std::reverse(selected.begin(), selected.end());
+ }
+
+ m_bIgnoreDocChange = true;
+
+ SwOutlineNodes::size_type nActPos;
+ bool bStartedAction = false;
+
+ MakeAllOutlineContentTemporarilyVisible a(GetWrtShell()->GetDoc());
+
+ // get first regular document content node outline node position in outline nodes array
+ SwOutlineNodes::size_type nFirstRegularDocContentOutlineNodePos = SwOutlineNodes::npos;
+ SwNodeOffset nEndOfExtrasIndex = rNodes.GetEndOfExtras().GetIndex();
+ for (SwOutlineNodes::size_type nPos = 0; nPos < nOutlineNdsSize; nPos++)
+ {
+ if (rOutlineNodes[nPos]->GetIndex() > nEndOfExtrasIndex)
+ {
+ nFirstRegularDocContentOutlineNodePos = nPos;
+ break;
+ }
+ }
+
+ for (auto const& pCurrentEntry : selected)
+ {
+ nActPos = weld::fromId<SwOutlineContent*>(
+ m_xTreeView->get_id(*pCurrentEntry))->GetOutlinePos();
+
+ // outline nodes in frames and tables are not up/down moveable
+ if (nActPos == SwOutlineNodes::npos ||
+ (bUpDown && (!pShell->IsOutlineMovable(nActPos) ||
+ nFirstRegularDocContentOutlineNodePos == SwOutlineNodes::npos)))
+ {
+ continue;
+ }
+
+ if (!bStartedAction)
+ {
+ pShell->StartAllAction();
+ pShell->StartUndo(bLeftRight ? SwUndoId::OUTLINE_LR : SwUndoId::OUTLINE_UD);
+ bStartedAction = true;
+ }
+
+ pShell->GotoOutline( nActPos); // If text selection != box selection
+ pShell->Push();
+
+ if (bUpDown)
+ {
+ // move outline position up/down (outline position promote/demote)
+ SwOutlineNodes::difference_type nDir = bUp ? -1 : 1;
+ if ((nDir == -1 && nActPos > 0) || (nDir == 1 && nActPos < nOutlineNdsSize - 1))
+ {
+ // make outline selection for use by MoveOutlinePara
+ pShell->MakeOutlineSel(nActPos, nActPos, bOutlineWithChildren);
+
+ int nActPosOutlineLevel =
+ rOutlineNodes[nActPos]->GetTextNode()->GetAttrOutlineLevel();
+ SwOutlineNodes::size_type nPos = nActPos;
+ if (!bUp)
+ {
+ // move down
+ int nPosOutlineLevel = -1;
+ while (++nPos < nOutlineNdsSize)
+ {
+ nPosOutlineLevel =
+ rOutlineNodes[nPos]->GetTextNode()->GetAttrOutlineLevel();
+ // discontinue if moving out of parent or equal level is found
+ if (nPosOutlineLevel <= nActPosOutlineLevel)
+ break;
+ // count the children of the node when they are not included in the move
+ if (!bOutlineWithChildren)
+ nDir++;
+ }
+ if (nPosOutlineLevel >= nActPosOutlineLevel)
+ {
+ // move past children
+ while (++nPos < nOutlineNdsSize)
+ {
+ nPosOutlineLevel =
+ rOutlineNodes[nPos]->GetTextNode()->GetAttrOutlineLevel();
+ // discontinue if moving out of parent or equal level is found
+ if (nPosOutlineLevel <= nActPosOutlineLevel)
+ break;
+ nDir++;
+ }
+ }
+ }
+ else
+ {
+ // move up
+ while (nPos && --nPos >= nFirstRegularDocContentOutlineNodePos)
+ {
+ int nPosOutlineLevel =
+ rOutlineNodes[nPos]->GetTextNode()->GetAttrOutlineLevel();
+ // discontinue if equal level is found
+ if (nPosOutlineLevel == nActPosOutlineLevel)
+ break;
+ // discontinue if moving out of parent
+ if (nPosOutlineLevel < nActPosOutlineLevel)
+ {
+ // Required for expected chapter placement when the chapter being moved
+ // up has an outline level less than the outline level of chapters it
+ // is being moved above and then encounters a chapter with an outline
+ // level that is greater before reaching a chapter with the same
+ // outline level as itself.
+ if (nDir < -1)
+ nDir++;
+ break;
+ }
+ nDir--;
+ }
+ }
+ pShell->MoveOutlinePara(nDir);
+ }
+ pShell->ClearMark();
+ }
+ else
+ {
+ // move outline left/right (outline level promote/demote)
+ if (!pShell->IsProtectedOutlinePara())
+ {
+ bool bAllow = true;
+ const SwOutlineNodes& rOutlNds = pShell->GetDoc()->GetNodes().GetOutLineNds();
+ const int nActLevel = rOutlNds[nActPos]->GetTextNode()->GetAttrOutlineLevel();
+ if (!bLeft)
+ {
+ // disallow if any outline node to demote will exceed MAXLEVEL
+ SwOutlineNodes::size_type nPos = nActPos;
+ do
+ {
+ int nLevel = rOutlNds[nPos]->GetTextNode()->GetAttrOutlineLevel();
+ if (nLevel == MAXLEVEL)
+ {
+ bAllow = false;
+ break;
+ }
+ } while (bOutlineWithChildren && ++nPos < rOutlNds.size() &&
+ rOutlNds[nPos]->GetTextNode()->GetAttrOutlineLevel() > nActLevel);
+ }
+ else
+ {
+ // disallow if trying to promote outline of level 1
+ if (nActLevel == 1)
+ bAllow = false;
+ }
+ if (bAllow)
+ {
+ SwOutlineNodes::size_type nPos = nActPos;
+ do
+ {
+ pShell->SwCursorShell::GotoOutline(nPos);
+ pShell->OutlineUpDown(bLeft ? -1 : 1);
+ } while (bOutlineWithChildren && ++nPos < rOutlNds.size() &&
+ rOutlNds[nPos]->GetTextNode()->GetAttrOutlineLevel() > nActLevel);
+ }
+ }
+ }
+
+ pShell->Pop(SwCursorShell::PopMode::DeleteCurrent); // Cursor is now back at the current heading.
+ }
+
+ if (bStartedAction)
+ {
+ pShell->EndUndo();
+ pShell->EndAllAction();
+ if (m_aActiveContentArr[ContentTypeId::OUTLINE])
+ m_aActiveContentArr[ContentTypeId::OUTLINE]->Invalidate();
+
+ // tdf#143547 LO Writer: navigator should stand still on promoting and demoting
+ // In addition to m_bIgnoreDocChange being true, selections are cleared before the Display
+ // call. Either of these conditions disable restore of scroll position happening in the
+ // Display function so it needs to be done here.
+ auto nOldScrollPos = m_xTreeView->vadjustment_get_value();
+
+ // clear all selections to prevent the Display function from trying to reselect selected entries
+ m_xTreeView->unselect_all();
+ Display(true);
+ m_xTreeView->vadjustment_set_value(nOldScrollPos);
+
+ if (m_bIsRoot)
+ {
+ // reselect entries, do this only when in outline content navigation mode
+ const SwOutlineNodes& rOutlineNds = pShell->GetNodes().GetOutLineNds();
+ for (SwTextNode* pNode : selectedOutlineNodes)
+ {
+ m_xTreeView->all_foreach([this, &rOutlineNds, pNode](weld::TreeIter& rEntry){
+ if (lcl_IsContentType(rEntry, *m_xTreeView))
+ return false;
+ SwOutlineNodes::size_type nPos = weld::fromId<SwOutlineContent*>(
+ m_xTreeView->get_id(rEntry))->GetOutlinePos();
+ if (pNode == rOutlineNds[nPos]->GetTextNode())
+ {
+ std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator(&rEntry));
+ if (m_xTreeView->iter_parent(*xParent)
+ && !m_xTreeView->get_row_expanded(*xParent))
+ {
+ m_xTreeView->expand_row(*xParent);
+ }
+ m_xTreeView->select(rEntry);
+ return true;
+ }
+ return false;
+ });
+ }
+ }
+ else
+ {
+ m_pActiveShell->GetView().GetEditWin().GrabFocus();
+ m_bIgnoreDocChange = false;
+ UpdateTracking();
+ grab_focus();
+ }
+ }
+ m_bIgnoreDocChange = false;
+}
+
+void SwContentTree::ShowTree()
+{
+ m_xTreeView->show();
+ m_aUpdTimer.Start();
+}
+
+void SwContentTree::HideTree()
+{
+ // folded together will not be idled
+ m_aUpdTimer.Stop();
+ m_xTreeView->hide();
+}
+
+static void lcl_SelectByContentTypeAndAddress(SwContentTree* pThis, weld::TreeView& rContentTree,
+ ContentTypeId nType, const void* ptr)
+{
+ if (!ptr)
+ {
+ rContentTree.set_cursor(-1);
+ pThis->Select();
+ return;
+ }
+
+ // find content type entry
+ std::unique_ptr<weld::TreeIter> xIter(rContentTree.make_iterator());
+
+ bool bFoundEntry = rContentTree.get_iter_first(*xIter);
+ while (bFoundEntry)
+ {
+ void* pUserData = weld::fromId<void*>(rContentTree.get_id(*xIter));
+ assert(dynamic_cast<SwContentType*>(static_cast<SwTypeNumber*>(pUserData)));
+ if (nType == static_cast<SwContentType*>(pUserData)->GetType())
+ break;
+ bFoundEntry = rContentTree.iter_next_sibling(*xIter);
+ }
+
+ if (!bFoundEntry)
+ {
+ rContentTree.set_cursor(-1);
+ pThis->Select();
+ return;
+ }
+
+ // assure content type entry is expanded
+ rContentTree.expand_row(*xIter);
+
+ // find content type content entry and select it
+ const void* p = nullptr;
+ while (rContentTree.iter_next(*xIter) && lcl_IsContent(*xIter, rContentTree))
+ {
+ void* pUserData = weld::fromId<void*>(rContentTree.get_id(*xIter));
+ switch( nType )
+ {
+ case ContentTypeId::FOOTNOTE:
+ case ContentTypeId::ENDNOTE:
+ {
+ assert(dynamic_cast<SwTextFootnoteContent*>(static_cast<SwTypeNumber*>(pUserData)));
+ SwTextFootnoteContent* pCnt = static_cast<SwTextFootnoteContent*>(pUserData);
+ p = pCnt->GetTextFootnote();
+ break;
+ }
+ case ContentTypeId::URLFIELD:
+ {
+ assert(dynamic_cast<SwURLFieldContent*>(static_cast<SwTypeNumber*>(pUserData)));
+ SwURLFieldContent* pCnt = static_cast<SwURLFieldContent*>(pUserData);
+ p = static_cast<const SwTextAttr*>(pCnt->GetINetAttr());
+ break;
+ }
+ case ContentTypeId::TEXTFIELD:
+ {
+ assert(dynamic_cast<SwTextFieldContent*>(static_cast<SwTypeNumber*>(pUserData)));
+ SwTextFieldContent* pCnt = static_cast<SwTextFieldContent*>(pUserData);
+ p = pCnt->GetFormatField()->GetField();
+ break;
+ }
+ case ContentTypeId::POSTIT:
+ {
+ assert(dynamic_cast<SwPostItContent*>(static_cast<SwTypeNumber*>(pUserData)));
+ SwPostItContent* pCnt = static_cast<SwPostItContent*>(pUserData);
+ p = pCnt->GetPostIt()->GetField();
+ break;
+ }
+ default:
+ break;
+ }
+ if (ptr == p)
+ {
+ // get first selected for comparison
+ std::unique_ptr<weld::TreeIter> xFirstSelected(rContentTree.make_iterator());
+ if (!rContentTree.get_selected(xFirstSelected.get()))
+ xFirstSelected.reset();
+ if (rContentTree.count_selected_rows() != 1 || !xFirstSelected ||
+ rContentTree.iter_compare(*xIter, *xFirstSelected) != 0)
+ {
+ // unselect all entries and make passed entry visible and selected
+ rContentTree.set_cursor(*xIter);
+ pThis->Select();
+ }
+ return;
+ }
+ }
+
+ rContentTree.set_cursor(-1);
+ pThis->Select();
+ return;
+}
+
+static void lcl_SelectByContentTypeAndName(SwContentTree* pThis, weld::TreeView& rContentTree,
+ std::u16string_view rContentTypeName, std::u16string_view rName)
+{
+ if (rName.empty())
+ return;
+
+ // find content type entry
+ std::unique_ptr<weld::TreeIter> xIter(rContentTree.make_iterator());
+ bool bFoundEntry = rContentTree.get_iter_first(*xIter);
+ while (bFoundEntry && rContentTypeName != rContentTree.get_text(*xIter))
+ bFoundEntry = rContentTree.iter_next_sibling(*xIter);
+ // find content type content entry and select it
+ if (!bFoundEntry)
+ return;
+
+ rContentTree.expand_row(*xIter); // assure content type entry is expanded
+ while (rContentTree.iter_next(*xIter) && lcl_IsContent(*xIter, rContentTree))
+ {
+ if (rName == rContentTree.get_text(*xIter))
+ {
+ // get first selected for comparison
+ std::unique_ptr<weld::TreeIter> xFirstSelected(rContentTree.make_iterator());
+ if (!rContentTree.get_selected(xFirstSelected.get()))
+ xFirstSelected.reset();
+ if (rContentTree.count_selected_rows() != 1 || !xFirstSelected ||
+ rContentTree.iter_compare(*xIter, *xFirstSelected) != 0)
+ {
+ // unselect all entries and make passed entry visible and selected
+ rContentTree.set_cursor(*xIter);
+ pThis->Select();
+ }
+ break;
+ }
+ }
+}
+
+static void lcl_SelectDrawObjectByName(weld::TreeView& rContentTree, std::u16string_view rName)
+{
+ if (rName.empty())
+ return;
+
+ // find content type entry
+ std::unique_ptr<weld::TreeIter> xIter(rContentTree.make_iterator());
+ bool bFoundEntry = rContentTree.get_iter_first(*xIter);
+ while (bFoundEntry && SwResId(STR_CONTENT_TYPE_DRAWOBJECT) != rContentTree.get_text(*xIter))
+ bFoundEntry = rContentTree.iter_next_sibling(*xIter);
+ // find content type content entry and select it
+ if (bFoundEntry)
+ {
+ rContentTree.expand_row(*xIter); // assure content type entry is expanded
+ while (rContentTree.iter_next(*xIter) && lcl_IsContent(*xIter, rContentTree))
+ {
+ if (rName == rContentTree.get_text(*xIter))
+ {
+ if (!rContentTree.is_selected(*xIter))
+ {
+ rContentTree.select(*xIter);
+ rContentTree.scroll_to_row(*xIter);
+ }
+ break;
+ }
+ }
+ }
+}
+
+/** No idle with focus or while dragging */
+IMPL_LINK_NOARG(SwContentTree, TimerUpdate, Timer *, void)
+{
+ // No need to update if content tree is not visible
+ if (!m_xTreeView->is_visible())
+ return;
+
+ // No update while focus is not in document.
+ // No update while drag and drop.
+ // Query view because the Navigator is cleared too late.
+ SwView* pView = GetParentWindow()->GetCreateView();
+
+ SwWrtShell* pActShell = pView ? pView->GetWrtShellPtr() : nullptr;
+ if(pActShell && pActShell->GetWin() &&
+ (pActShell->GetWin()->HasFocus() || m_bDocHasChanged || m_bViewHasChanged) &&
+ !IsInDrag() && !pActShell->ActionPend())
+ {
+ if (m_bDocHasChanged || m_bViewHasChanged)
+ {
+ if (State::CONSTANT == m_eState && !lcl_FindShell(m_pActiveShell))
+ {
+ SetActiveShell(pActShell);
+ GetParentWindow()->UpdateListBox();
+ }
+ if (State::ACTIVE == m_eState && pActShell != GetWrtShell())
+ {
+ SetActiveShell(pActShell);
+ }
+ else if ((State::ACTIVE == m_eState || (State::CONSTANT == m_eState && pActShell == GetWrtShell())) &&
+ HasContentChanged())
+ {
+ FindActiveTypeAndRemoveUserData();
+ Display(true);
+ }
+ }
+ UpdateTracking();
+ m_bIsIdleClear = false;
+ m_bDocHasChanged = false;
+ m_bViewHasChanged = false;
+ }
+ else if (!pView && State::ACTIVE == m_eState && !m_bIsIdleClear) // this block seems never to be entered
+ {
+ if(m_pActiveShell)
+ {
+ SetActiveShell(nullptr);
+ }
+ clear();
+ m_bIsIdleClear = true;
+ }
+}
+
+void SwContentTree::UpdateTracking()
+{
+ if (State::HIDDEN == m_eState || !m_pActiveShell)
+ return;
+
+ // only when treeview or treeview context menu does not have focus
+ if (m_xTreeView->has_focus() || m_xTreeView->has_child_focus())
+ return;
+
+ // m_bIgnoreDocChange is set on delete and outline visibility toggle
+ if (m_bIgnoreDocChange)
+ {
+ m_bIgnoreDocChange = false;
+ return;
+ }
+
+ // bTrack is used to disallow tracking after jumping to an outline until the outline position
+ // that was jumped to is no longer the current outline position.
+ bool bTrack = true;
+ if (m_nLastGotoContentWasOutlinePos != SwOutlineNodes::npos)
+ {
+ if (m_pActiveShell->GetOutlinePos() == m_nLastGotoContentWasOutlinePos)
+ bTrack = false;
+ else
+ m_nLastGotoContentWasOutlinePos = SwOutlineNodes::npos;
+ }
+
+ if (bTrack)
+ {
+ // graphic, frame, and ole
+ if (m_pActiveShell->GetSelectionType() &
+ (SelectionType::Graphic | SelectionType::Frame | SelectionType::Ole))
+ {
+ OUString aContentTypeName;
+ if (m_pActiveShell->GetSelectionType() == SelectionType::Graphic &&
+ !(m_bIsRoot && m_nRootType != ContentTypeId::GRAPHIC))
+ {
+ if (!mTrackContentType[ContentTypeId::GRAPHIC]) return;
+ aContentTypeName = SwResId(STR_CONTENT_TYPE_GRAPHIC);
+ }
+ else if (m_pActiveShell->GetSelectionType() == SelectionType::Frame &&
+ !(m_bIsRoot && m_nRootType != ContentTypeId::FRAME))
+ {
+ if (!mTrackContentType[ContentTypeId::FRAME]) return;
+ aContentTypeName = SwResId(STR_CONTENT_TYPE_FRAME);
+ }
+ else if (m_pActiveShell->GetSelectionType() == SelectionType::Ole &&
+ !(m_bIsRoot && m_nRootType != ContentTypeId::OLE))
+ {
+ if (!mTrackContentType[ContentTypeId::OLE]) return;
+ aContentTypeName = SwResId(STR_CONTENT_TYPE_OLE);
+ }
+ if (!aContentTypeName.isEmpty())
+ {
+ OUString aName(m_pActiveShell->GetFlyName());
+ lcl_SelectByContentTypeAndName(this, *m_xTreeView, aContentTypeName, aName);
+ return;
+ }
+ }
+ // drawing
+ if ((m_pActiveShell->GetSelectionType() & (SelectionType::DrawObject |
+ SelectionType::DrawObjectEditMode |
+ SelectionType::DbForm)) &&
+ !(m_bIsRoot && m_nRootType != ContentTypeId::DRAWOBJECT))
+ {
+ if (mTrackContentType[ContentTypeId::DRAWOBJECT])
+ {
+ // Multiple selection is possible when in root content navigation view so unselect all
+ // selected entries before reselecting. This causes a bit of an annoyance when the treeview
+ // scroll bar is used and focus is in the document by causing the last selected entry to
+ // scroll back into view.
+ if (m_bIsRoot)
+ m_xTreeView->unselect_all();
+ SdrView* pSdrView = m_pActiveShell->GetDrawView();
+ if (pSdrView)
+ {
+ for (size_t nIdx(0); nIdx < pSdrView->GetMarkedObjectCount(); nIdx++)
+ {
+ SdrObject* pSelected = pSdrView->GetMarkedObjectByIndex(nIdx);
+ OUString aName(pSelected->GetName());
+ if (!aName.isEmpty())
+ lcl_SelectDrawObjectByName(*m_xTreeView, aName);
+ }
+ }
+ else
+ {
+ // clear treeview selections
+ m_xTreeView->unselect_all();
+ }
+ Select();
+ }
+ return;
+ }
+ // footnotes and endnotes
+ if (SwContentAtPos aContentAtPos(IsAttrAtPos::Ftn);
+ m_pActiveShell->GetContentAtPos(m_pActiveShell->GetCursorDocPos(), aContentAtPos)
+ && aContentAtPos.pFndTextAttr &&
+ !(m_bIsRoot && (m_nRootType != ContentTypeId::FOOTNOTE &&
+ m_nRootType != ContentTypeId::ENDNOTE)))
+ {
+ if (!aContentAtPos.pFndTextAttr->GetFootnote().IsEndNote())
+ {
+ if (mTrackContentType[ContentTypeId::FOOTNOTE])
+ lcl_SelectByContentTypeAndAddress(this, *m_xTreeView, ContentTypeId::FOOTNOTE,
+ aContentAtPos.pFndTextAttr);
+ }
+ else if (mTrackContentType[ContentTypeId::ENDNOTE])
+ lcl_SelectByContentTypeAndAddress(this, *m_xTreeView, ContentTypeId::ENDNOTE,
+ aContentAtPos.pFndTextAttr);
+ return;
+ }
+ // bookmarks - track first bookmark at cursor
+ if (mTrackContentType[ContentTypeId::BOOKMARK] &&
+ (m_pActiveShell->GetSelectionType() & SelectionType::Text))
+ {
+ SwPaM* pCursor = m_pActiveShell->GetCursor();
+ IDocumentMarkAccess* const pMarkAccess = m_pActiveShell->getIDocumentMarkAccess();
+ IDocumentMarkAccess::const_iterator_t ppBookmark = pMarkAccess->getBookmarksBegin();
+ if (pCursor && ppBookmark != pMarkAccess->getBookmarksEnd() &&
+ !(m_bIsRoot && m_nRootType != ContentTypeId::BOOKMARK))
+ {
+ OUString sBookmarkName;
+ SwPosition* pCursorPoint = pCursor->GetPoint();
+ while (ppBookmark != pMarkAccess->getBookmarksEnd())
+ {
+ if (lcl_IsUiVisibleBookmark(*ppBookmark) &&
+ *pCursorPoint >= (*ppBookmark)->GetMarkStart() &&
+ *pCursorPoint <= (*ppBookmark)->GetMarkEnd())
+ {
+ sBookmarkName = (*ppBookmark)->GetName();
+ // keep previously selected bookmark instead
+ // of selecting a different bookmark inside of it
+ if (sBookmarkName == m_sSelectedItem)
+ break;
+ }
+ else if (!sBookmarkName.isEmpty() &&
+ *pCursorPoint < (*ppBookmark)->GetMarkStart())
+ {
+ // don't search a different bookmark inside the
+ // previous one, if the starting position of the next bookmarks
+ // is after the cursor position (assuming that the
+ // bookmark iterator jumps inside the same text by positions)
+ break;
+ }
+ ++ppBookmark;
+ }
+
+ if (!sBookmarkName.isEmpty())
+ {
+ // select the bookmark
+ lcl_SelectByContentTypeAndName(this, *m_xTreeView,
+ SwResId(STR_CONTENT_TYPE_BOOKMARK),
+ sBookmarkName);
+ return;
+ }
+ }
+ }
+ // references
+ if (SwContentAtPos aContentAtPos(IsAttrAtPos::RefMark);
+ m_pActiveShell->GetContentAtPos(m_pActiveShell->GetCursorDocPos(), aContentAtPos) &&
+ aContentAtPos.pFndTextAttr &&
+ !(m_bIsRoot && m_nRootType != ContentTypeId::REFERENCE))
+ {
+ if (mTrackContentType[ContentTypeId::REFERENCE])
+ {
+ const SwFormatRefMark& rRefMark = aContentAtPos.pFndTextAttr->GetRefMark();
+ lcl_SelectByContentTypeAndName(this, *m_xTreeView, SwResId(STR_CONTENT_TYPE_REFERENCE),
+ rRefMark.GetRefName());
+ }
+ return;
+ }
+ // hyperlinks
+ // not in ToxContent tdf#148312
+ if (const SwSection* pSection = m_pActiveShell->GetCurrSection(); !pSection
+ || (pSection && pSection->GetType() != SectionType::ToxContent))
+ {
+ if (SwContentAtPos aContentAtPos(IsAttrAtPos::InetAttr);
+ m_pActiveShell->GetContentAtPos(m_pActiveShell->GetCursorDocPos(), aContentAtPos)
+ && (!m_bIsRoot || m_nRootType == ContentTypeId::URLFIELD))
+ {
+ // Because hyperlink item names do not need to be unique, finding the corresponding
+ // item in the tree by name may result in incorrect selection. Find the item in the
+ // tree by comparing the SwTextINetFormat pointer at the document cursor position to
+ // that stored in the item SwURLFieldContent.
+ if (mTrackContentType[ContentTypeId::URLFIELD])
+ lcl_SelectByContentTypeAndAddress(this, *m_xTreeView, ContentTypeId::URLFIELD,
+ aContentAtPos.pFndTextAttr);
+ return;
+ }
+ }
+ // fields, comments
+ if (SwField* pField = m_pActiveShell->GetCurField(); pField &&
+ !(m_bIsRoot &&
+ m_nRootType != ContentTypeId::TEXTFIELD &&
+ m_nRootType != ContentTypeId::POSTIT))
+ {
+ ContentTypeId eCntTypeId =
+ pField->GetTypeId() == SwFieldTypesEnum::Postit ? ContentTypeId::POSTIT :
+ ContentTypeId::TEXTFIELD;
+ if (mTrackContentType[eCntTypeId])
+ lcl_SelectByContentTypeAndAddress(this, *m_xTreeView, eCntTypeId, pField);
+ return;
+ }
+ // table
+ if (m_pActiveShell->IsCursorInTable() &&
+ !(m_bIsRoot && m_nRootType != ContentTypeId::TABLE))
+ {
+ if (mTrackContentType[ContentTypeId::TABLE] && m_pActiveShell->GetTableFormat())
+ {
+ OUString aName = m_pActiveShell->GetTableFormat()->GetName();
+ lcl_SelectByContentTypeAndName(this, *m_xTreeView, SwResId(STR_CONTENT_TYPE_TABLE),
+ aName);
+ return;
+ }
+ }
+ // indexes
+ if (const SwTOXBase* pTOX = m_pActiveShell->GetCurTOX(); pTOX &&
+ !(m_bIsRoot && m_nRootType != ContentTypeId::INDEX))
+ {
+ if (mTrackContentType[ContentTypeId::INDEX])
+ lcl_SelectByContentTypeAndName(this, *m_xTreeView, SwResId(STR_CONTENT_TYPE_INDEX),
+ pTOX->GetTOXName());
+ return;
+ }
+ // section
+ if (const SwSection* pSection = m_pActiveShell->GetCurrSection(); pSection &&
+ !(m_bIsRoot && m_nRootType != ContentTypeId::REGION))
+ {
+ if (mTrackContentType[ContentTypeId::REGION])
+ {
+ lcl_SelectByContentTypeAndName(this, *m_xTreeView, SwResId(STR_CONTENT_TYPE_REGION),
+ pSection->GetSectionName());
+ return;
+ }
+ else
+ {
+ // prevent fall through to outline tracking when section tracking is off and the last
+ // GotoContent is the current section
+ if (m_nLastSelType == ContentTypeId::REGION &&
+ m_xTreeView->get_selected_text() == pSection->GetSectionName())
+ return;
+ }
+ // fall through to outline tracking when section tracking is off and the last GotoContent
+ // is not the current section
+ }
+ }
+ // outline
+ if (m_nOutlineTracking == 3)
+ return;
+ // find out where the cursor is
+ const SwOutlineNodes::size_type nActPos = GetWrtShell()->GetOutlinePos(MAXLEVEL);
+ if (!((m_bIsRoot && m_nRootType != ContentTypeId::OUTLINE) || nActPos == SwOutlineNodes::npos))
+ {
+ // assure outline content type is expanded
+ // this assumes outline content type is first in treeview
+ std::unique_ptr<weld::TreeIter> xFirstEntry(m_xTreeView->make_iterator());
+ if (m_xTreeView->get_iter_first(*xFirstEntry))
+ m_xTreeView->expand_row(*xFirstEntry);
+
+ m_xTreeView->all_foreach([this, nActPos](weld::TreeIter& rEntry){
+ bool bRet = false;
+ if (lcl_IsContent(rEntry, *m_xTreeView) && weld::fromId<SwContent*>(
+ m_xTreeView->get_id(rEntry))->GetParent()->GetType() ==
+ ContentTypeId::OUTLINE)
+ {
+ if (weld::fromId<SwOutlineContent*>(
+ m_xTreeView->get_id(rEntry))->GetOutlinePos() == nActPos)
+ {
+ std::unique_ptr<weld::TreeIter> xFirstSelected(
+ m_xTreeView->make_iterator());
+ if (!m_xTreeView->get_selected(xFirstSelected.get()))
+ xFirstSelected.reset();
+ // only select if not already selected or tree has multiple entries selected
+ if (m_xTreeView->count_selected_rows() != 1 || !xFirstSelected ||
+ m_xTreeView->iter_compare(rEntry, *xFirstSelected) != 0)
+ {
+ if (m_nOutlineTracking == 2) // focused outline tracking
+ {
+ // collapse to children of root node
+ std::unique_ptr<weld::TreeIter> xChildEntry(
+ m_xTreeView->make_iterator());
+ if (m_xTreeView->get_iter_first(*xChildEntry) &&
+ m_xTreeView->iter_children(*xChildEntry))
+ {
+ do
+ {
+ if (weld::fromId<SwContent*>(
+ m_xTreeView->get_id(*xChildEntry))->
+ GetParent()->GetType() == ContentTypeId::OUTLINE)
+ m_xTreeView->collapse_row(*xChildEntry);
+ else
+ break;
+ }
+ while (m_xTreeView->iter_next(*xChildEntry));
+ }
+ }
+ // unselect all entries, make pEntry visible, and select
+ m_xTreeView->set_cursor(rEntry);
+ Select();
+
+ // tdf#149279 show at least two outline entries before the set cursor entry
+ std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator(&rEntry));
+ for (int i = 0; i < 2; i++)
+ {
+ if (m_xTreeView->get_iter_depth(*xIter) == 0)
+ break;
+ if (!m_xTreeView->iter_previous(*xIter))
+ break;
+ while (!weld::IsEntryVisible(*m_xTreeView, *xIter))
+ m_xTreeView->iter_parent(*xIter);
+ }
+ // Assure the scroll to row is collapsed after scrolling if it was collapsed
+ // before. This is required here to make gtkinst scroll_to_row behave like
+ // salinst.
+ const bool bRowExpanded = m_xTreeView->get_row_expanded(*xIter);
+ m_xTreeView->scroll_to_row(*xIter);
+ if (!bRowExpanded)
+ m_xTreeView->collapse_row(*xIter);
+ }
+ bRet = true;
+ }
+ }
+ else
+ {
+ // use of this break assumes outline content type is first in tree
+ if (lcl_IsContentType(rEntry, *m_xTreeView) &&
+ weld::fromId<SwContentType*>(
+ m_xTreeView->get_id(rEntry))->GetType() !=
+ ContentTypeId::OUTLINE)
+ bRet = true;
+ }
+ return bRet;
+ });
+ }
+ else
+ {
+ // clear treeview selections
+ if (m_xTreeView->count_selected_rows() > 0)
+ {
+ m_xTreeView->unselect_all();
+ m_xTreeView->set_cursor(-1);
+ Select();
+ }
+ }
+}
+
+void SwContentTree::SelectOutlinesWithSelection()
+{
+ SwCursor* pFirstCursor = m_pActiveShell->GetCursor();
+ SwCursor* pCursor = pFirstCursor;
+ std::vector<SwOutlineNodes::size_type> aOutlinePositions;
+ do
+ {
+ if (pCursor)
+ {
+ if (pCursor->HasMark())
+ {
+ aOutlinePositions.push_back(m_pActiveShell->GetOutlinePos(UCHAR_MAX, pCursor));
+ }
+ pCursor = pCursor->GetNext();
+ }
+ } while (pCursor && pCursor != pFirstCursor);
+
+ if (aOutlinePositions.empty())
+ return;
+
+ // remove duplicates before selecting
+ aOutlinePositions.erase(std::unique(aOutlinePositions.begin(), aOutlinePositions.end()),
+ aOutlinePositions.end());
+
+ m_xTreeView->unselect_all();
+
+ for (auto nOutlinePosition : aOutlinePositions)
+ {
+ m_xTreeView->all_foreach([this, nOutlinePosition](const weld::TreeIter& rEntry){
+ if (lcl_IsContent(rEntry, *m_xTreeView) &&
+ weld::fromId<SwContent*>(
+ m_xTreeView->get_id(rEntry))->GetParent()->GetType() ==
+ ContentTypeId::OUTLINE)
+ {
+ if (weld::fromId<SwOutlineContent*>(
+ m_xTreeView->get_id(rEntry))->GetOutlinePos() ==
+ nOutlinePosition)
+ {
+ std::unique_ptr<weld::TreeIter> xParent =
+ m_xTreeView->make_iterator(&rEntry);
+ if (m_xTreeView->iter_parent(*xParent) &&
+ !m_xTreeView->get_row_expanded(*xParent))
+ m_xTreeView->expand_row(*xParent);
+ m_xTreeView->select(rEntry);
+ return true;
+ }
+ }
+ return false;
+ });
+ }
+
+ Select();
+}
+
+void SwContentTree::MoveOutline(SwOutlineNodes::size_type nTargetPos)
+{
+ MakeAllOutlineContentTemporarilyVisible a(GetWrtShell()->GetDoc());
+
+ SwWrtShell *const pShell = GetWrtShell();
+ pShell->StartAllAction();
+ pShell->StartUndo(SwUndoId::OUTLINE_UD);
+
+ SwOutlineNodes::size_type nPrevSourcePos = SwOutlineNodes::npos;
+ SwOutlineNodes::size_type nPrevTargetPosOrOffset = SwOutlineNodes::npos;
+
+ bool bFirstMove = true;
+
+ for (const auto& source : m_aDndOutlinesSelected)
+ {
+ SwOutlineNodes::size_type nSourcePos = weld::fromId<SwOutlineContent*>(m_xTreeView->get_id(*source))->GetOutlinePos();
+
+ // Done on the first selection move
+ if (bFirstMove) // only do once
+ {
+ if (nTargetPos == SwOutlineNodes::npos || nSourcePos > nTargetPos)
+ {
+ // Up moves
+ // The first up move sets the up move amount for the remaining selected outlines to be moved
+ if (nTargetPos != SwOutlineNodes::npos)
+ nPrevTargetPosOrOffset = nSourcePos - nTargetPos;
+ else
+ nPrevTargetPosOrOffset = nSourcePos + 1;
+ }
+ else if (nSourcePos < nTargetPos)
+ {
+ // Down moves
+ // The first down move sets the source and target positions for the remaining selected outlines to be moved
+ nPrevSourcePos = nSourcePos;
+ nPrevTargetPosOrOffset = nTargetPos;
+ }
+ bFirstMove = false;
+ }
+ else
+ {
+ if (nTargetPos == SwOutlineNodes::npos || nSourcePos > nTargetPos)
+ {
+ // Move up
+ nTargetPos = nSourcePos - nPrevTargetPosOrOffset;
+ }
+ else if (nSourcePos < nTargetPos)
+ {
+ // Move down
+ nSourcePos = nPrevSourcePos;
+ nTargetPos = nPrevTargetPosOrOffset;
+ }
+ }
+ GetParentWindow()->MoveOutline(nSourcePos, nTargetPos);
+ }
+
+ pShell->EndUndo();
+ pShell->EndAllAction();
+ m_aActiveContentArr[ContentTypeId::OUTLINE]->Invalidate();
+ Display(true);
+ m_aDndOutlinesSelected.clear();
+}
+
+// Update immediately
+IMPL_LINK_NOARG(SwContentTree, FocusInHdl, weld::Widget&, void)
+{
+ SwView* pActView = GetParentWindow()->GetCreateView();
+ if(pActView)
+ {
+ SwWrtShell* pActShell = pActView->GetWrtShellPtr();
+ if (State::CONSTANT == m_eState && !lcl_FindShell(m_pActiveShell))
+ {
+ SetActiveShell(pActShell);
+ }
+
+ if (State::ACTIVE == m_eState && pActShell != GetWrtShell())
+ SetActiveShell(pActShell);
+ // Only call HasContentChanged() if the document has changed since last called
+ else if ((State::ACTIVE == m_eState || (State::CONSTANT == m_eState && pActShell == GetWrtShell())) &&
+ m_bDocHasChanged)
+ {
+ if (HasContentChanged())
+ Display(true);
+ m_bDocHasChanged = false;
+ }
+ }
+ else if (State::ACTIVE == m_eState)
+ clear();
+}
+
+IMPL_LINK(SwContentTree, KeyInputHdl, const KeyEvent&, rEvent, bool)
+{
+ bool bConsumed = true;
+
+ const vcl::KeyCode aCode = rEvent.GetKeyCode();
+ if (aCode.GetCode() == KEY_MULTIPLY && aCode.IsMod1())
+ {
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ if (m_xTreeView->get_selected(xEntry.get()))
+ ExpandOrCollapseAll(*m_xTreeView, *xEntry);
+ }
+ else if (aCode.GetCode() == KEY_RETURN)
+ {
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ if (m_xTreeView->get_selected(xEntry.get()))
+ {
+ switch(aCode.GetModifier())
+ {
+ case KEY_MOD2:
+ // Switch boxes
+ GetParentWindow()->ToggleTree();
+ break;
+ case KEY_MOD1:
+ // Switch RootMode
+ ToggleToRoot();
+ break;
+ case 0:
+ if (lcl_IsContentType(*xEntry, *m_xTreeView))
+ {
+ m_xTreeView->get_row_expanded(*xEntry) ? m_xTreeView->collapse_row(*xEntry)
+ : m_xTreeView->expand_row(*xEntry);
+ }
+ else
+ ContentDoubleClickHdl(*m_xTreeView);
+ break;
+ case KEY_SHIFT:
+ m_bSelectTo = true;
+ ContentDoubleClickHdl(*m_xTreeView);
+ break;
+ }
+ }
+ }
+ else if(aCode.GetCode() == KEY_DELETE && 0 == aCode.GetModifier())
+ {
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ if (m_xTreeView->get_selected(xEntry.get()) && lcl_IsContent(*xEntry, *m_xTreeView))
+ {
+ assert(dynamic_cast<SwContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xEntry))));
+ if (weld::fromId<SwContent*>(m_xTreeView->get_id(*xEntry))->GetParent()->IsDeletable() &&
+ !m_pActiveShell->GetView().GetDocShell()->IsReadOnly())
+ {
+ EditEntry(*xEntry, EditEntryMode::DELETE);
+ }
+ }
+ }
+ //Make KEY_SPACE has same function as DoubleClick, and realize
+ //multi-selection.
+ else if (aCode.GetCode() == KEY_SPACE && 0 == aCode.GetModifier())
+ {
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ if (m_xTreeView->get_cursor(xEntry.get()))
+ {
+ if (State::HIDDEN != m_eState)
+ {
+ if (State::CONSTANT == m_eState)
+ {
+ m_pActiveShell->GetView().GetViewFrame().GetWindow().ToTop();
+ }
+
+ SwContent* pCnt = dynamic_cast<SwContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xEntry)));
+
+ if (pCnt && pCnt->GetParent()->GetType() == ContentTypeId::DRAWOBJECT)
+ {
+ SdrView* pDrawView = m_pActiveShell->GetDrawView();
+ if (pDrawView)
+ {
+ pDrawView->SdrEndTextEdit();
+
+ SwDrawModel* pDrawModel = m_pActiveShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
+ SdrPage* pPage = pDrawModel->GetPage(0);
+ bool hasObjectMarked = false;
+
+ if (SdrObject* pObject = GetDrawingObjectsByContent(pCnt))
+ {
+ SdrPageView* pPV = pDrawView->GetSdrPageView/*GetPageViewPvNum*/(/*0*/);
+ if( pPV )
+ {
+ bool bUnMark = pDrawView->IsObjMarked(pObject);
+ pDrawView->MarkObj( pObject, pPV, bUnMark);
+
+ }
+ }
+ for (const rtl::Reference<SdrObject>& pTemp : *pPage)
+ {
+ bool bMark = pDrawView->IsObjMarked(pTemp.get());
+ switch( pTemp->GetObjIdentifier() )
+ {
+ case SdrObjKind::Group:
+ case SdrObjKind::Text:
+ case SdrObjKind::Line:
+ case SdrObjKind::Rectangle:
+ case SdrObjKind::CircleOrEllipse:
+ case SdrObjKind::CircleSection:
+ case SdrObjKind::CircleArc:
+ case SdrObjKind::CircleCut:
+ case SdrObjKind::Polygon:
+ case SdrObjKind::PolyLine:
+ case SdrObjKind::PathLine:
+ case SdrObjKind::PathFill:
+ case SdrObjKind::FreehandLine:
+ case SdrObjKind::FreehandFill:
+ case SdrObjKind::PathPoly:
+ case SdrObjKind::PathPolyLine:
+ case SdrObjKind::Caption:
+ case SdrObjKind::CustomShape:
+ if( bMark )
+ hasObjectMarked = true;
+ break;
+ default:
+ if ( bMark )
+ {
+ SdrPageView* pPV = pDrawView->GetSdrPageView/*GetPageViewPvNum*/(/*0*/);
+ if (pPV)
+ {
+ pDrawView->MarkObj(pTemp.get(), pPV, true);
+ }
+ }
+ }
+ //mod end
+ }
+ if ( !hasObjectMarked )
+ {
+ SwEditWin& rEditWindow = m_pActiveShell->GetView().GetEditWin();
+ vcl::KeyCode tempKeycode( KEY_ESCAPE );
+ KeyEvent rKEvt( 0 , tempKeycode );
+ static_cast<vcl::Window*>(&rEditWindow)->KeyInput( rKEvt );
+ }
+ }
+ }
+
+ m_bViewHasChanged = true;
+ }
+ }
+ }
+ else
+ {
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ if (m_xTreeView->get_cursor(xEntry.get()))
+ {
+ SwContent* pCnt = dynamic_cast<SwContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xEntry)));
+ if (pCnt && pCnt->GetParent()->GetType() == ContentTypeId::OUTLINE)
+ {
+ if (m_bIsRoot && aCode.GetCode() == KEY_LEFT && aCode.GetModifier() == 0)
+ {
+ m_xTreeView->unselect_all();
+ bConsumed = false;
+ }
+ else if (aCode.IsMod1())
+ {
+ if (aCode.GetCode() == KEY_LEFT)
+ ExecCommand(u"promote", !aCode.IsShift());
+ else if (aCode.GetCode() == KEY_RIGHT)
+ ExecCommand(u"demote", !aCode.IsShift());
+ else if (aCode.GetCode() == KEY_UP)
+ ExecCommand(u"chapterup", !aCode.IsShift());
+ else if (aCode.GetCode() == KEY_DOWN)
+ ExecCommand(u"chapterdown", !aCode.IsShift());
+ else if (aCode.GetCode() == KEY_C)
+ CopyOutlineSelections();
+ else
+ bConsumed = false;
+ }
+ else
+ bConsumed = false;
+ }
+ else
+ bConsumed = false;
+ }
+ else
+ bConsumed = false;
+ }
+ return bConsumed;
+}
+
+IMPL_LINK(SwContentTree, QueryTooltipHdl, const weld::TreeIter&, rEntry, OUString)
+{
+ ContentTypeId nType;
+ bool bContent = false;
+ void* pUserData = weld::fromId<void*>(m_xTreeView->get_id(rEntry));
+ if (lcl_IsContentType(rEntry, *m_xTreeView))
+ {
+ assert(dynamic_cast<SwContentType*>(static_cast<SwTypeNumber*>(pUserData)));
+ nType = static_cast<SwContentType*>(pUserData)->GetType();
+ }
+ else
+ {
+ assert(dynamic_cast<SwContent*>(static_cast<SwTypeNumber*>(pUserData)));
+ nType = static_cast<SwContent*>(pUserData)->GetParent()->GetType();
+ bContent = true;
+ }
+ OUString sEntry;
+ if(bContent)
+ {
+ switch( nType )
+ {
+ case ContentTypeId::URLFIELD:
+ assert(dynamic_cast<SwURLFieldContent*>(static_cast<SwTypeNumber*>(pUserData)));
+ sEntry = static_cast<SwURLFieldContent*>(pUserData)->GetURL();
+ break;
+
+ case ContentTypeId::POSTIT:
+ assert(dynamic_cast<SwPostItContent*>(static_cast<SwTypeNumber*>(pUserData)));
+ sEntry = static_cast<SwPostItContent*>(pUserData)->GetName();
+ break;
+ case ContentTypeId::OUTLINE:
+ assert(dynamic_cast<SwOutlineContent*>(static_cast<SwTypeNumber*>(pUserData)));
+ sEntry = static_cast<SwOutlineContent*>(pUserData)->GetName();
+ break;
+ case ContentTypeId::GRAPHIC:
+ assert(dynamic_cast<SwGraphicContent*>(static_cast<SwTypeNumber*>(pUserData)));
+ sEntry = static_cast<SwGraphicContent*>(pUserData)->GetLink();
+ break;
+ case ContentTypeId::REGION:
+ {
+ assert(dynamic_cast<SwRegionContent*>(static_cast<SwTypeNumber*>(pUserData)));
+ sEntry = static_cast<SwRegionContent*>(pUserData)->GetName();
+ const SwSectionFormats& rFormats = GetWrtShell()->GetDoc()->GetSections();
+ for (SwSectionFormats::size_type n = rFormats.size(); n;)
+ {
+ const SwNodeIndex* pIdx = nullptr;
+ const SwSectionFormat* pFormat = rFormats[--n];
+ const SwSection* pSect;
+ if (nullptr != (pSect = pFormat->GetSection()) &&
+ pSect->GetSectionName() == sEntry &&
+ nullptr != (pIdx = pFormat->GetContent().GetContentIdx()) &&
+ pIdx->GetNode().GetNodes().IsDocNodes())
+ {
+ SwDocStat aDocStat;
+ SwPaM aPaM(pIdx->GetNode(), *pIdx->GetNode().EndOfSectionNode());
+ SwDoc::CountWords(aPaM, aDocStat);
+ sEntry = SwResId(STR_REGION_DEFNAME) + ": " + sEntry + "\n" +
+ SwResId(FLD_STAT_WORD) + ": " + OUString::number(aDocStat.nWord) + "\n" +
+ SwResId(FLD_STAT_CHAR) + ": " + OUString::number(aDocStat.nChar);
+ break;
+ }
+ }
+ }
+ break;
+ case ContentTypeId::FOOTNOTE:
+ case ContentTypeId::ENDNOTE:
+ {
+ assert(dynamic_cast<SwTextFootnoteContent*>(static_cast<SwTypeNumber*>(pUserData)));
+ const SwTextFootnote* pFootnote =
+ static_cast<const SwTextFootnoteContent*>(pUserData)->GetTextFootnote();
+
+ sEntry = pFootnote->GetFootnote().IsEndNote() ? SwResId(STR_CONTENT_ENDNOTE) :
+ SwResId(STR_CONTENT_FOOTNOTE);
+ }
+ break;
+ default: break;
+ }
+ if(static_cast<SwContent*>(pUserData)->IsInvisible())
+ {
+ if(!sEntry.isEmpty())
+ sEntry += ", ";
+ sEntry += m_sInvisible;
+ }
+ }
+ else
+ {
+ size_t nMemberCount = static_cast<SwContentType*>(pUserData)->GetMemberCount();
+ sEntry = OUString::number(nMemberCount) + " " +
+ (nMemberCount == 1
+ ? static_cast<SwContentType*>(pUserData)->GetSingleName()
+ : static_cast<SwContentType*>(pUserData)->GetName());
+ }
+
+ return sEntry;
+}
+
+void SwContentTree::ExecuteContextMenuAction(const OUString& rSelectedPopupEntry)
+{
+ if (rSelectedPopupEntry == "copy")
+ {
+ CopyOutlineSelections();
+ return;
+ }
+ if (rSelectedPopupEntry == "collapseallcategories")
+ {
+ std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
+ bool bEntry = m_xTreeView->get_iter_first(*xEntry);
+ while (bEntry)
+ {
+ m_xTreeView->collapse_row(*xEntry);
+ bEntry = m_xTreeView->iter_next_sibling(*xEntry);
+ }
+ return;
+ }
+
+ {
+ std::map<OUString, ContentTypeId> mPopupEntryToContentTypeId
+ {
+ {"tabletracking", ContentTypeId::TABLE},
+ {"frametracking", ContentTypeId::FRAME},
+ {"imagetracking", ContentTypeId::GRAPHIC},
+ {"oleobjecttracking", ContentTypeId::OLE},
+ {"bookmarktracking", ContentTypeId::BOOKMARK},
+ {"sectiontracking", ContentTypeId::REGION},
+ {"hyperlinktracking", ContentTypeId::URLFIELD},
+ {"referencetracking", ContentTypeId::REFERENCE},
+ {"indextracking", ContentTypeId::INDEX},
+ {"commenttracking", ContentTypeId::POSTIT},
+ {"drawingobjecttracking", ContentTypeId::DRAWOBJECT},
+ {"fieldtracking", ContentTypeId::TEXTFIELD},
+ {"footnotetracking", ContentTypeId::FOOTNOTE},
+ {"endnotetracking", ContentTypeId::ENDNOTE}
+ };
+
+ if (mPopupEntryToContentTypeId.count(rSelectedPopupEntry))
+ {
+ ContentTypeId eCntTypeId = mPopupEntryToContentTypeId[rSelectedPopupEntry];
+ SetContentTypeTracking(eCntTypeId, !mTrackContentType[eCntTypeId]);
+ return;
+ }
+ }
+
+ std::unique_ptr<weld::TreeIter> xFirst(m_xTreeView->make_iterator());
+ if (!m_xTreeView->get_selected(xFirst.get()))
+ return; // this shouldn't happen, but better to be safe than ...
+
+ if (rSelectedPopupEntry == "protectsection" || rSelectedPopupEntry == "hidesection")
+ {
+ SwRegionContent* pCnt = weld::fromId<SwRegionContent*>(m_xTreeView->get_id(*xFirst));
+ assert(dynamic_cast<SwRegionContent*>(static_cast<SwTypeNumber*>(pCnt)));
+ const SwSectionFormat* pSectionFormat = pCnt->GetSectionFormat();
+ SwSection* pSection = pSectionFormat->GetSection();
+ SwSectionData aSectionData(*pSection);
+ if (rSelectedPopupEntry == "protectsection")
+ aSectionData.SetProtectFlag(!pSection->IsProtect());
+ else
+ aSectionData.SetHidden(!pSection->IsHidden());
+ m_pActiveShell->UpdateSection(m_pActiveShell->GetSectionFormatPos(*pSectionFormat),
+ aSectionData);
+ }
+ else if (rSelectedPopupEntry == "sort")
+ {
+ SwContentType* pCntType;
+ const OUString& rId(m_xTreeView->get_id(*xFirst));
+ if (lcl_IsContentType(*xFirst, *m_xTreeView))
+ pCntType = weld::fromId<SwContentType*>(rId);
+ else
+ pCntType = const_cast<SwContentType*>(weld::fromId<SwContent*>(rId)->GetParent());
+
+ // toggle and persist alphabetical sort setting
+ const int nShift = static_cast<int>(pCntType->GetType());
+ assert(nShift > -1);
+ const sal_Int32 nMask = 1 << nShift;
+ const sal_Int32 nBlock = m_pConfig->GetSortAlphabeticallyBlock();
+ pCntType->SetAlphabeticSort(~nBlock & nMask);
+ m_pConfig->SetSortAlphabeticallyBlock(nBlock ^ nMask);
+
+ pCntType->FillMemberList();
+ Display(true);
+ return;
+ }
+ else if (rSelectedPopupEntry == "deletechapter" ||
+ rSelectedPopupEntry == "deletetable" ||
+ rSelectedPopupEntry == "deleteframe" ||
+ rSelectedPopupEntry == "deleteimage" ||
+ rSelectedPopupEntry == "deleteoleobject" ||
+ rSelectedPopupEntry == "deletebookmark" ||
+ rSelectedPopupEntry == "deleteregion" ||
+ rSelectedPopupEntry == "deletehyperlink" ||
+ rSelectedPopupEntry == "deletereference" ||
+ rSelectedPopupEntry == "deleteindex" ||
+ rSelectedPopupEntry == "deletecomment" ||
+ rSelectedPopupEntry == "deletedrawingobject" ||
+ rSelectedPopupEntry == "deletefield")
+ {
+ EditEntry(*xFirst, EditEntryMode::DELETE);
+ return;
+ }
+
+ auto nSelectedPopupEntry = rSelectedPopupEntry.toUInt32();
+ switch (nSelectedPopupEntry)
+ {
+ case TOGGLE_OUTLINE_CONTENT_VISIBILITY:
+ case HIDE_OUTLINE_CONTENT_VISIBILITY:
+ case SHOW_OUTLINE_CONTENT_VISIBILITY:
+ {
+ m_pActiveShell->EnterStdMode();
+ m_bIgnoreDocChange = true;
+ SwOutlineContent* pCntFirst = weld::fromId<SwOutlineContent*>(m_xTreeView->get_id(*xFirst));
+
+ // toggle the outline node outline content visible attribute
+ if (nSelectedPopupEntry == TOGGLE_OUTLINE_CONTENT_VISIBILITY)
+ {
+ SwNode* pNode = m_pActiveShell->GetDoc()->GetNodes().GetOutLineNds()[pCntFirst->GetOutlinePos()];
+ pNode->GetTextNode()->SetAttrOutlineContentVisible(
+ !m_pActiveShell->GetAttrOutlineContentVisible(pCntFirst->GetOutlinePos()));
+ }
+ else
+ {
+ // with subs
+ SwOutlineNodes::size_type nPos = pCntFirst->GetOutlinePos();
+ if (lcl_IsContentType(*xFirst, *m_xTreeView)) // Headings root entry
+ nPos = SwOutlineNodes::npos;
+ SwOutlineNodes::size_type nOutlineNodesCount = m_pActiveShell->getIDocumentOutlineNodesAccess()->getOutlineNodesCount();
+ int nLevel = -1;
+ if (nPos != SwOutlineNodes::npos) // not root
+ nLevel = m_pActiveShell->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos);
+ else
+ nPos = 0;
+ bool bShow(nSelectedPopupEntry == SHOW_OUTLINE_CONTENT_VISIBILITY);
+ do
+ {
+ if (m_pActiveShell->IsOutlineContentVisible(nPos) != bShow)
+ m_pActiveShell->GetDoc()->GetNodes().GetOutLineNds()[nPos]->GetTextNode()->SetAttrOutlineContentVisible(bShow);
+ } while (++nPos < nOutlineNodesCount
+ && (nLevel == -1 || m_pActiveShell->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nLevel));
+ }
+ m_pActiveShell->InvalidateOutlineContentVisibility();
+ // show in the document what was toggled
+ if (lcl_IsContentType(*xFirst, *m_xTreeView)) // Headings root entry
+ m_pActiveShell->GotoPage(1, true);
+ else
+ m_pActiveShell->GotoOutline(pCntFirst->GetOutlinePos());
+ grab_focus();
+ m_bIgnoreDocChange = false;
+ m_pActiveShell->SetModified();
+ m_pActiveShell->GetDoc()->GetDocShell()->Broadcast(SfxHint(SfxHintId::DocChanged));
+ }
+ break;
+ case 11:
+ case 12:
+ case 13:
+ nSelectedPopupEntry -= 10;
+ if(m_nOutlineTracking != nSelectedPopupEntry)
+ SetOutlineTracking(static_cast<sal_uInt8>(nSelectedPopupEntry));
+ break;
+ //Outlinelevel
+ case 101:
+ case 102:
+ case 103:
+ case 104:
+ case 105:
+ case 106:
+ case 107:
+ case 108:
+ case 109:
+ case 110:
+ nSelectedPopupEntry -= 100;
+ if(m_nOutlineLevel != nSelectedPopupEntry )
+ SetOutlineLevel(static_cast<sal_Int8>(nSelectedPopupEntry));
+ break;
+ case 201:
+ case 202:
+ case 203:
+ GetParentWindow()->SetRegionDropMode(static_cast<RegionMode>(nSelectedPopupEntry - 201));
+ break;
+ case 401:
+ case 402:
+ EditEntry(*xFirst, nSelectedPopupEntry == 401 ? EditEntryMode::RMV_IDX : EditEntryMode::UPD_IDX);
+ break;
+ // Edit entry
+ case 403:
+ EditEntry(*xFirst, EditEntryMode::EDIT);
+ break;
+ case 404:
+ EditEntry(*xFirst, EditEntryMode::UNPROTECT_TABLE);
+ break;
+ case 405 :
+ {
+ const SwTOXBase* pBase = weld::fromId<SwTOXBaseContent*>(m_xTreeView->get_id(*xFirst))
+ ->GetTOXBase();
+ m_pActiveShell->SetTOXBaseReadonly(*pBase, !SwEditShell::IsTOXBaseReadonly(*pBase));
+ }
+ break;
+ case 502 :
+ EditEntry(*xFirst, EditEntryMode::RENAME);
+ break;
+ case 600:
+ m_pActiveShell->GetView().GetPostItMgr()->Show();
+ break;
+ case 601:
+ m_pActiveShell->GetView().GetPostItMgr()->Hide();
+ break;
+ case 602:
+ {
+ m_pActiveShell->GetView().GetPostItMgr()->SetActiveSidebarWin(nullptr);
+ m_pActiveShell->GetView().GetPostItMgr()->Delete();
+ break;
+ }
+ case 700:
+ {
+ m_pActiveShell->GetView().GetViewFrame().GetDispatcher()->Execute(FN_OUTLINE_TO_CLIPBOARD);
+ break;
+ }
+ case 800:
+ ExpandOrCollapseAll(*m_xTreeView, *xFirst);
+ break;
+ case 801:
+ ExecCommand(u"chapterup", true);
+ break;
+ case 802:
+ ExecCommand(u"chapterdown", true);
+ break;
+ case 803:
+ ExecCommand(u"promote", true);
+ break;
+ case 804:
+ ExecCommand(u"demote", true);
+ break;
+ case 805: // select document content
+ {
+ m_pActiveShell->KillPams();
+ m_pActiveShell->ClearMark();
+ m_pActiveShell->EnterAddMode();
+ SwContent* pCnt = weld::fromId<SwContent*>(m_xTreeView->get_id(*xFirst));
+ const ContentTypeId eTypeId = pCnt->GetParent()->GetType();
+ if (eTypeId == ContentTypeId::OUTLINE)
+ {
+ SwOutlineNodes::size_type nActPos = weld::fromId<SwOutlineContent*>(
+ m_xTreeView->get_id(*xFirst))->GetOutlinePos();
+ m_pActiveShell->GotoOutline(nActPos);
+ m_xTreeView->selected_foreach([this](weld::TreeIter& rEntry){
+ SwOutlineNodes::size_type nPos = weld::fromId<SwOutlineContent*>(
+ m_xTreeView->get_id(rEntry))->GetOutlinePos();
+ m_pActiveShell->SttSelect();
+ // select children if not expanded and don't kill PaMs
+ m_pActiveShell->MakeOutlineSel(nPos, nPos,
+ !m_xTreeView->get_row_expanded(rEntry), false);
+ m_pActiveShell->EndSelect();
+ return false;
+ });
+ }
+ else if (eTypeId == ContentTypeId::TABLE)
+ {
+ m_pActiveShell->GotoTable(pCnt->GetName());
+ m_pActiveShell->GetView().GetViewFrame().GetDispatcher()->Execute(FN_TABLE_SELECT_ALL);
+ }
+ else if (eTypeId == ContentTypeId::REGION)
+ {
+ m_pActiveShell->EnterStdMode();
+ m_pActiveShell->GotoRegion(pCnt->GetName());
+ GotoCurrRegionAndSkip(m_pActiveShell->GetCurrentShellCursor(), fnRegionEnd, m_pActiveShell->IsReadOnlyAvailable());
+ m_pActiveShell->SttSelect();
+ GotoCurrRegionAndSkip(m_pActiveShell->GetCurrentShellCursor(), fnRegionStart, m_pActiveShell->IsReadOnlyAvailable());
+ m_pActiveShell->EndSelect();
+ m_pActiveShell->UpdateCursor();
+ }
+ m_pActiveShell->LeaveAddMode();
+ }
+ break;
+ case 900:
+ {
+ SwContent* pCnt = weld::fromId<SwContent*>(m_xTreeView->get_id(*xFirst));
+ GotoContent(pCnt);
+ }
+ break;
+ //Display
+ default:
+ if(nSelectedPopupEntry > 300 && nSelectedPopupEntry < 400)
+ {
+ nSelectedPopupEntry -= 300;
+ SwView *pView = SwModule::GetFirstView();
+ while (pView)
+ {
+ nSelectedPopupEntry --;
+ if(nSelectedPopupEntry == 0)
+ {
+ SetConstantShell(&pView->GetWrtShell());
+ break;
+ }
+ pView = SwModule::GetNextView(pView);
+ }
+ if(nSelectedPopupEntry)
+ {
+ m_bViewHasChanged = nSelectedPopupEntry == 1;
+ m_eState = (nSelectedPopupEntry == 1) ? State::ACTIVE : State::HIDDEN;
+ Display(nSelectedPopupEntry == 1);
+ }
+ GetParentWindow()->UpdateListBox();
+ }
+ }
+}
+
+void SwContentTree::DeleteOutlineSelections()
+{
+ const SwOutlineNodes& rOutlineNodes = m_pActiveShell->GetNodes().GetOutLineNds();
+ auto nChapters(0);
+
+ m_pActiveShell->StartAction();
+
+ m_pActiveShell->EnterAddMode();
+ m_xTreeView->selected_foreach([this, &rOutlineNodes, &nChapters](weld::TreeIter& rEntry){
+ ++nChapters;
+ if (m_xTreeView->iter_has_child(rEntry) &&
+ !m_xTreeView->get_row_expanded(rEntry)) // only count children if not expanded
+ {
+ nChapters += m_xTreeView->iter_n_children(rEntry);
+ }
+ SwOutlineNodes::size_type nActPos = weld::fromId<SwOutlineContent*>(m_xTreeView->get_id(rEntry))->GetOutlinePos();
+ if (m_pActiveShell->GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ {
+ // make folded content visible so it can be selected
+ if (!m_pActiveShell->IsOutlineContentVisible(nActPos))
+ m_pActiveShell->MakeOutlineContentVisible(nActPos);
+ if (!m_xTreeView->get_row_expanded(rEntry))
+ {
+ // include children
+ SwNode* pNode = rOutlineNodes[nActPos];
+ const int nLevel = pNode->GetTextNode()->GetAttrOutlineLevel() - 1;
+ for (auto nPos = nActPos + 1; nPos < rOutlineNodes.size(); ++nPos)
+ {
+ pNode = rOutlineNodes[nPos];
+ const int nNextLevel = pNode->GetTextNode()->GetAttrOutlineLevel() - 1;
+ if (nNextLevel <= nLevel)
+ break;
+ if (!m_pActiveShell->IsOutlineContentVisible(nNextLevel))
+ m_pActiveShell->MakeOutlineContentVisible(nNextLevel);
+ }
+ }
+ }
+ m_pActiveShell->SttSelect();
+ m_pActiveShell->MakeOutlineSel(nActPos, nActPos, !m_xTreeView->get_row_expanded(rEntry), false); // select children if not expanded
+ // The outline selection may already be to the start of the following outline paragraph
+ // as happens when a table is the last content of the to be deleted outline. In this case
+ // do not extend the to be deleted selection right or the first character of the following
+ // outline paragraph will be removed. Also check if no selection was made which indicates
+ // an empty paragraph and selection right is needed.
+ if (!m_pActiveShell->IsSttPara() || !m_pActiveShell->HasSelection())
+ m_pActiveShell->Right(SwCursorSkipMode::Chars, true, 1, false);
+ m_pActiveShell->EndSelect();
+ return false;
+ });
+ m_pActiveShell->LeaveAddMode();
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, SwResId(STR_CHAPTERS, nChapters));
+ m_pActiveShell->StartUndo(SwUndoId::DELETE, &aRewriter);
+ m_pActiveShell->Delete(false);
+ m_pActiveShell->EndUndo();
+
+ m_pActiveShell->EndAction();
+}
+
+void SwContentTree::SetOutlineLevel(sal_uInt8 nSet)
+{
+ if (nSet == m_nOutlineLevel)
+ return;
+ m_nOutlineLevel = nSet;
+ m_pConfig->SetOutlineLevel( m_nOutlineLevel );
+ std::unique_ptr<SwContentType>& rpContentT = (State::ACTIVE == m_eState)
+ ? m_aActiveContentArr[ContentTypeId::OUTLINE]
+ : m_aHiddenContentArr[ContentTypeId::OUTLINE];
+ if(rpContentT)
+ {
+ rpContentT->SetOutlineLevel(m_nOutlineLevel);
+ rpContentT->FillMemberList();
+ }
+ Display(State::ACTIVE == m_eState);
+}
+
+void SwContentTree::SetOutlineTracking(sal_uInt8 nSet)
+{
+ m_nOutlineTracking = nSet;
+ m_pConfig->SetOutlineTracking(m_nOutlineTracking);
+}
+
+void SwContentTree::SetContentTypeTracking(ContentTypeId eCntTypeId, bool bSet)
+{
+ mTrackContentType[eCntTypeId] = bSet;
+ m_pConfig->SetContentTypeTrack(eCntTypeId, bSet);
+}
+
+// Mode Change: Show dropped Doc
+void SwContentTree::ShowHiddenShell()
+{
+ if(m_pHiddenShell)
+ {
+ m_eState = State::HIDDEN;
+ Display(false);
+ }
+}
+
+// Mode Change: Show active view
+void SwContentTree::ShowActualView()
+{
+ m_eState = State::ACTIVE;
+ Display(true);
+ GetParentWindow()->UpdateListBox();
+}
+
+IMPL_LINK_NOARG(SwContentTree, SelectHdl, weld::TreeView&, void)
+{
+ if (m_pConfig->IsNavigateOnSelect())
+ {
+ ContentDoubleClickHdl(*m_xTreeView);
+ grab_focus();
+ }
+ Select();
+ if (m_bIsRoot)
+ return;
+ // Select the content type in the Navigate By control
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ if (!m_xTreeView->get_selected(xEntry.get()))
+ return;
+ while (m_xTreeView->get_iter_depth(*xEntry))
+ m_xTreeView->iter_parent(*xEntry);
+ m_pDialog->SelectNavigateByContentType(m_xTreeView->get_text(*xEntry));
+}
+
+// Here the buttons for moving outlines are en-/disabled.
+void SwContentTree::Select()
+{
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ if (!m_xTreeView->get_selected(xEntry.get()))
+ return;
+
+ bool bEnable = false;
+ std::unique_ptr<weld::TreeIter> xParentEntry(m_xTreeView->make_iterator(xEntry.get()));
+ bool bParentEntry = m_xTreeView->iter_parent(*xParentEntry);
+ while (bParentEntry && (!lcl_IsContentType(*xParentEntry, *m_xTreeView)))
+ bParentEntry = m_xTreeView->iter_parent(*xParentEntry);
+ if (!m_bIsLastReadOnly)
+ {
+ if (!m_xTreeView->get_visible())
+ bEnable = true;
+ else if (bParentEntry)
+ {
+ if ((m_bIsRoot && m_nRootType == ContentTypeId::OUTLINE) ||
+ (lcl_IsContent(*xEntry, *m_xTreeView) &&
+ weld::fromId<SwContentType*>(m_xTreeView->get_id(*xParentEntry))->GetType() == ContentTypeId::OUTLINE))
+ {
+ bEnable = true;
+ }
+ }
+ }
+
+ SwNavigationPI* pNavi = GetParentWindow();
+ pNavi->m_xContent6ToolBox->set_item_sensitive("chapterup", bEnable);
+ pNavi->m_xContent6ToolBox->set_item_sensitive("chapterdown", bEnable);
+ pNavi->m_xContent6ToolBox->set_item_sensitive("promote", bEnable);
+ pNavi->m_xContent6ToolBox->set_item_sensitive("demote", bEnable);
+}
+
+void SwContentTree::SetRootType(ContentTypeId nType)
+{
+ m_nRootType = nType;
+ m_bIsRoot = true;
+ m_pConfig->SetRootType( m_nRootType );
+}
+
+OUString SwContentType::RemoveNewline(const OUString& rEntry)
+{
+ if (rEntry.isEmpty())
+ return rEntry;
+
+ OUStringBuffer aEntry(rEntry);
+ for (sal_Int32 i = 0; i < rEntry.getLength(); ++i)
+ if(aEntry[i] == 10 || aEntry[i] == 13)
+ aEntry[i] = 0x20;
+
+ return aEntry.makeStringAndClear();
+}
+
+void SwContentTree::EditEntry(const weld::TreeIter& rEntry, EditEntryMode nMode)
+{
+ SwContent* pCnt = weld::fromId<SwContent*>(m_xTreeView->get_id(rEntry));
+ GotoContent(pCnt);
+ const ContentTypeId nType = pCnt->GetParent()->GetType();
+ sal_uInt16 nSlot = 0;
+
+ if(EditEntryMode::DELETE == nMode)
+ m_bIgnoreDocChange = true;
+
+ uno::Reference< container::XNameAccess > xNameAccess, xSecond, xThird;
+ switch(nType)
+ {
+ case ContentTypeId::OUTLINE :
+ if(nMode == EditEntryMode::DELETE)
+ {
+ DeleteOutlineSelections();
+ }
+ break;
+
+ case ContentTypeId::TABLE :
+ if(nMode == EditEntryMode::UNPROTECT_TABLE)
+ {
+ m_pActiveShell->GetView().GetDocShell()->
+ GetDoc()->UnProtectCells( pCnt->GetName());
+ }
+ else if(nMode == EditEntryMode::DELETE)
+ {
+ m_pActiveShell->StartAction();
+ OUString sTable = SwResId(STR_TABLE_NAME);
+ SwRewriter aRewriterTableName;
+ aRewriterTableName.AddRule(UndoArg1, SwResId(STR_START_QUOTE));
+ aRewriterTableName.AddRule(UndoArg2, pCnt->GetName());
+ aRewriterTableName.AddRule(UndoArg3, SwResId(STR_END_QUOTE));
+ sTable = aRewriterTableName.Apply(sTable);
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, sTable);
+ m_pActiveShell->StartUndo(SwUndoId::DELETE, &aRewriter);
+ m_pActiveShell->GetView().GetViewFrame().GetDispatcher()->Execute(FN_TABLE_SELECT_ALL);
+ m_pActiveShell->DeleteRow();
+ m_pActiveShell->EndUndo();
+ m_pActiveShell->EndAction();
+ }
+ else if(nMode == EditEntryMode::RENAME)
+ {
+ uno::Reference< frame::XModel > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel();
+ uno::Reference< text::XTextTablesSupplier > xTables(xModel, uno::UNO_QUERY);
+ xNameAccess = xTables->getTextTables();
+ }
+ else
+ nSlot = FN_FORMAT_TABLE_DLG;
+ break;
+
+ case ContentTypeId::GRAPHIC :
+ if(nMode == EditEntryMode::DELETE)
+ {
+ m_pActiveShell->DelRight();
+ }
+ else if(nMode == EditEntryMode::RENAME)
+ {
+ uno::Reference< frame::XModel > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel();
+ uno::Reference< text::XTextGraphicObjectsSupplier > xGraphics(xModel, uno::UNO_QUERY);
+ xNameAccess = xGraphics->getGraphicObjects();
+ uno::Reference< text::XTextFramesSupplier > xFrames(xModel, uno::UNO_QUERY);
+ xSecond = xFrames->getTextFrames();
+ uno::Reference< text::XTextEmbeddedObjectsSupplier > xObjs(xModel, uno::UNO_QUERY);
+ xThird = xObjs->getEmbeddedObjects();
+ }
+ else
+ nSlot = FN_FORMAT_GRAFIC_DLG;
+ break;
+
+ case ContentTypeId::FRAME :
+ case ContentTypeId::OLE :
+ if(nMode == EditEntryMode::DELETE)
+ {
+ m_pActiveShell->DelRight();
+ }
+ else if(nMode == EditEntryMode::RENAME)
+ {
+ uno::Reference< frame::XModel > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel();
+ uno::Reference< text::XTextFramesSupplier > xFrames(xModel, uno::UNO_QUERY);
+ uno::Reference< text::XTextEmbeddedObjectsSupplier > xObjs(xModel, uno::UNO_QUERY);
+ if(ContentTypeId::FRAME == nType)
+ {
+ xNameAccess = xFrames->getTextFrames();
+ xSecond = xObjs->getEmbeddedObjects();
+ }
+ else
+ {
+ xNameAccess = xObjs->getEmbeddedObjects();
+ xSecond = xFrames->getTextFrames();
+ }
+ uno::Reference< text::XTextGraphicObjectsSupplier > xGraphics(xModel, uno::UNO_QUERY);
+ xThird = xGraphics->getGraphicObjects();
+ }
+ else
+ nSlot = FN_FORMAT_FRAME_DLG;
+ break;
+ case ContentTypeId::BOOKMARK :
+ if(nMode == EditEntryMode::DELETE)
+ {
+ assert(!m_pActiveShell->getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS));
+ IDocumentMarkAccess* const pMarkAccess = m_pActiveShell->getIDocumentMarkAccess();
+ pMarkAccess->deleteMark(pMarkAccess->findMark(pCnt->GetName()), false);
+ }
+ else if(nMode == EditEntryMode::RENAME)
+ {
+ assert(!m_pActiveShell->getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS));
+ uno::Reference< frame::XModel > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel();
+ uno::Reference< text::XBookmarksSupplier > xBkms(xModel, uno::UNO_QUERY);
+ xNameAccess = xBkms->getBookmarks();
+ }
+ else
+ {
+ // allowed despite PROTECT_BOOKMARKS: the dialog itself enforces it
+ SfxStringItem const name(FN_EDIT_BOOKMARK, pCnt->GetName());
+ SfxPoolItem const* args[2] = { &name, nullptr };
+ m_pActiveShell->GetView().GetViewFrame().
+ GetDispatcher()->Execute(FN_EDIT_BOOKMARK, SfxCallMode::SYNCHRON, args);
+ }
+ break;
+
+ case ContentTypeId::REGION :
+ if (nMode == EditEntryMode::DELETE)
+ {
+ assert(dynamic_cast<SwRegionContent*>(static_cast<SwTypeNumber*>(pCnt)));
+ const SwSectionFormat* pSectionFormat
+ = static_cast<SwRegionContent*>(pCnt)->GetSectionFormat();
+ m_pActiveShell->GetDoc()->DelSectionFormat(
+ const_cast<SwSectionFormat*>(pSectionFormat), false);
+ }
+ else if (nMode == EditEntryMode::RENAME)
+ {
+ uno::Reference< frame::XModel > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel();
+ uno::Reference< text::XTextSectionsSupplier > xSects(xModel, uno::UNO_QUERY);
+ xNameAccess = xSects->getTextSections();
+ }
+ else
+ nSlot = FN_EDIT_REGION;
+ break;
+
+ case ContentTypeId::URLFIELD:
+ if (nMode == EditEntryMode::DELETE)
+ nSlot = SID_REMOVE_HYPERLINK;
+ else
+ nSlot = SID_EDIT_HYPERLINK;
+ break;
+ case ContentTypeId::REFERENCE:
+ {
+ if(nMode == EditEntryMode::DELETE)
+ {
+ const OUString& rName = pCnt->GetName();
+ for (const SfxPoolItem* pItem :
+ m_pActiveShell->GetDoc()->GetAttrPool().GetItemSurrogates(RES_TXTATR_REFMARK))
+ {
+ assert(dynamic_cast<const SwFormatRefMark*>(pItem));
+ const auto pFormatRefMark = static_cast<const SwFormatRefMark*>(pItem);
+ if (!pFormatRefMark)
+ continue;
+ const SwTextRefMark* pTextRef = pFormatRefMark->GetTextRefMark();
+ if (pTextRef && &pTextRef->GetTextNode().GetNodes() ==
+ &m_pActiveShell->GetNodes() && rName == pFormatRefMark->GetRefName())
+ {
+ m_pActiveShell->GetDoc()->DeleteFormatRefMark(pFormatRefMark);
+ m_pActiveShell->SwViewShell::UpdateFields();
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case ContentTypeId::TEXTFIELD:
+ {
+ if (nMode == EditEntryMode::DELETE)
+ {
+ const SwTextFieldContent* pTextFieldCnt =
+ static_cast<const SwTextFieldContent*>(pCnt);
+ const SwTextField* pTextField = pTextFieldCnt->GetFormatField()->GetTextField();
+ SwTextField::DeleteTextField(*pTextField);
+ }
+ else
+ nSlot = FN_EDIT_FIELD;
+ }
+ break;
+ case ContentTypeId::POSTIT:
+ {
+ auto& rView = m_pActiveShell->GetView();
+ auto pPostItMgr = rView.GetPostItMgr();
+ pPostItMgr->AssureStdModeAtShell();
+ pPostItMgr->SetActiveSidebarWin(nullptr);
+ rView.GetEditWin().GrabFocus();
+ if(nMode == EditEntryMode::DELETE)
+ m_pActiveShell->DelRight();
+ else
+ nSlot = FN_POSTIT;
+ }
+ break;
+ case ContentTypeId::INDEX:
+ {
+ const SwTOXBase* pBase = static_cast<SwTOXBaseContent*>(pCnt)->GetTOXBase();
+ switch(nMode)
+ {
+ case EditEntryMode::EDIT:
+ if(pBase)
+ {
+ SwPtrItem aPtrItem( FN_INSERT_MULTI_TOX, const_cast<SwTOXBase *>(pBase));
+ m_pActiveShell->GetView().GetViewFrame().
+ GetDispatcher()->ExecuteList(FN_INSERT_MULTI_TOX,
+ SfxCallMode::ASYNCHRON, { &aPtrItem });
+
+ }
+ break;
+ case EditEntryMode::RMV_IDX:
+ case EditEntryMode::DELETE:
+ {
+ if( pBase )
+ m_pActiveShell->DeleteTOX(*pBase, EditEntryMode::DELETE == nMode);
+ }
+ break;
+ case EditEntryMode::UPD_IDX:
+ case EditEntryMode::RENAME:
+ {
+ Reference< frame::XModel > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel();
+ Reference< XDocumentIndexesSupplier > xIndexes(xModel, UNO_QUERY);
+ Reference< XIndexAccess> xIdxAcc(xIndexes->getDocumentIndexes());
+ Reference< XNameAccess >xLocalNameAccess(xIdxAcc, UNO_QUERY);
+ if(EditEntryMode::RENAME == nMode)
+ xNameAccess = xLocalNameAccess;
+ else if(xLocalNameAccess.is() && xLocalNameAccess->hasByName(pBase->GetTOXName()))
+ {
+ Any aIdx = xLocalNameAccess->getByName(pBase->GetTOXName());
+ Reference< XDocumentIndex> xIdx;
+ if(aIdx >>= xIdx)
+ xIdx->update();
+ }
+ }
+ break;
+ default: break;
+ }
+ }
+ break;
+ case ContentTypeId::DRAWOBJECT :
+ if(EditEntryMode::DELETE == nMode)
+ nSlot = SID_DELETE;
+ else if(nMode == EditEntryMode::RENAME)
+ nSlot = FN_NAME_SHAPE;
+ else if (nMode == EditEntryMode::EDIT)
+ {
+ vcl::KeyCode aKeyCode(KEY_RETURN, false, false, false, false);
+ KeyEvent aKeyEvent(0, aKeyCode);
+ m_pActiveShell->GetWin()->KeyInput(aKeyEvent);
+ }
+ break;
+ case ContentTypeId::FOOTNOTE:
+ case ContentTypeId::ENDNOTE:
+ if (EditEntryMode::EDIT == nMode)
+ nSlot = FN_FORMAT_FOOTNOTE_DLG;
+ break;
+ default: break;
+ }
+ if(nSlot)
+ m_pActiveShell->GetView().GetViewFrame().
+ GetDispatcher()->Execute(nSlot, SfxCallMode::SYNCHRON);
+ else if(xNameAccess.is())
+ {
+ uno::Any aObj = xNameAccess->getByName(pCnt->GetName());
+ uno::Reference< uno::XInterface > xTmp;
+ aObj >>= xTmp;
+ uno::Reference< container::XNamed > xNamed(xTmp, uno::UNO_QUERY);
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractSwRenameXNamedDlg> pDlg(pFact->CreateSwRenameXNamedDlg(m_xTreeView.get(), xNamed, xNameAccess));
+ if(xSecond.is())
+ pDlg->SetAlternativeAccess( xSecond, xThird);
+
+ OUString sForbiddenChars;
+ if(ContentTypeId::BOOKMARK == nType)
+ {
+ sForbiddenChars = "/\\@:*?\";,.#";
+ }
+ else if(ContentTypeId::TABLE == nType)
+ {
+ sForbiddenChars = " .<>";
+ }
+ pDlg->SetForbiddenChars(sForbiddenChars);
+ pDlg->Execute();
+ }
+ if(EditEntryMode::DELETE == nMode)
+ {
+ auto nPos = m_xTreeView->vadjustment_get_value();
+ m_bViewHasChanged = true;
+ TimerUpdate(&m_aUpdTimer);
+ grab_focus();
+ m_xTreeView->vadjustment_set_value(nPos);
+ }
+}
+
+void SwContentTree::CopyOutlineSelections()
+{
+ m_pActiveShell->LockView(true);
+ {
+ MakeAllOutlineContentTemporarilyVisible a(m_pActiveShell->GetDoc());
+ m_pActiveShell->AssureStdMode();
+ m_pActiveShell->EnterAddMode();
+ size_t nCount = m_xTreeView->get_selected_rows().size();
+ m_xTreeView->selected_foreach([this, &nCount](weld::TreeIter& rEntry){
+ SwOutlineNodes::size_type nOutlinePos = reinterpret_cast<SwOutlineContent*>(
+ m_xTreeView->get_id(rEntry).toInt64())->GetOutlinePos();
+ m_pActiveShell->SttSelect();
+ m_pActiveShell->MakeOutlineSel(nOutlinePos, nOutlinePos,
+ !m_xTreeView->get_row_expanded(rEntry), false);
+ // don't move if this is the last selected outline or the cursor is at start of para
+ if (--nCount && !m_pActiveShell->IsSttPara())
+ m_pActiveShell->Right(SwCursorSkipMode::Chars, true, 1, false);
+ m_pActiveShell->EndSelect();
+ return false;
+ });
+ m_pActiveShell->LeaveAddMode();
+ m_pActiveShell->GetView().GetViewFrame().GetBindings().Execute(SID_COPY);
+ }
+ m_pActiveShell->LockView(false);
+}
+
+void SwContentTree::GotoContent(const SwContent* pCnt)
+{
+ if (pCnt->GetParent()->GetType() == ContentTypeId::OUTLINE)
+ {
+ // Maybe the outline node doesn't have a layout frame to go to.
+ const SwOutlineNodes::size_type nPos =
+ static_cast<const SwOutlineContent*>(pCnt)->GetOutlinePos();
+ const SwNodes& rNds = m_pActiveShell->GetDoc()->GetNodes();
+ SwTextNode* pTextNd = rNds.GetOutLineNds()[nPos]->GetTextNode();
+ if (!pTextNd->getLayoutFrame(m_pActiveShell->GetLayout()))
+ return;
+ }
+
+ if (m_bSelectTo)
+ {
+ if (m_pActiveShell->IsCursorInTable() ||
+ (m_pActiveShell->GetCursor()->GetPoint()->nNode.GetIndex() <=
+ m_pActiveShell->GetDoc()->GetNodes().GetEndOfExtras().GetIndex()))
+ {
+ m_bSelectTo = false;
+ m_pActiveShell->GetView().GetEditWin().GrabFocus();
+ return;
+ }
+ }
+
+ m_nLastGotoContentWasOutlinePos = SwOutlineNodes::npos;
+ m_sSelectedItem = "";
+
+ m_pActiveShell->AssureStdMode();
+
+ std::optional<std::unique_ptr<SwPosition>> oPosition;
+ if (m_bSelectTo)
+ oPosition.emplace(new SwPosition(m_pActiveShell->GetCursor()->GetPoint()->nNode,
+ m_pActiveShell->GetCursor()->GetPoint()->nContent));
+
+ switch(m_nLastSelType = pCnt->GetParent()->GetType())
+ {
+ case ContentTypeId::TEXTFIELD:
+ {
+ m_pActiveShell->GotoFormatField(
+ *static_cast<const SwTextFieldContent*>(pCnt)->GetFormatField());
+ }
+ break;
+ case ContentTypeId::OUTLINE :
+ {
+ const SwOutlineNodes::size_type nPos =
+ static_cast<const SwOutlineContent*>(pCnt)->GetOutlinePos();
+ m_pActiveShell->GotoOutline(nPos);
+ m_nLastGotoContentWasOutlinePos = nPos;
+ }
+ break;
+ case ContentTypeId::TABLE :
+ {
+ m_pActiveShell->GotoTable(pCnt->GetName());
+ }
+ break;
+ case ContentTypeId::FRAME :
+ case ContentTypeId::GRAPHIC :
+ case ContentTypeId::OLE :
+ {
+ m_pActiveShell->GotoFly(pCnt->GetName());
+ }
+ break;
+ case ContentTypeId::BOOKMARK:
+ {
+ m_pActiveShell->StartAction();
+ m_pActiveShell->GotoMark(pCnt->GetName());
+ m_pActiveShell->EndAction();
+ m_sSelectedItem = pCnt->GetName();
+
+ // If the hidden title of SwNavigatorPanel was emptied via UNO XPanel interface,
+ // store the name of the selected bookmark there. This allows to query the
+ // selected bookmark using UNO e.g. in add-ons, i.e. to disambiguate when
+ // multiple bookmarks are there on the selected text range.
+ // Note: this is a workaround because getDialog() of XPanel is not implemented
+ // for SwNavigatorPanel.
+ uno::Reference< frame::XModel > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel();
+
+ Reference<frame::XController2> xController( xModel->getCurrentController(), uno::UNO_QUERY);
+ if ( !xController.is() )
+ break;
+
+ Reference<ui::XSidebarProvider> xSidebarProvider = xController->getSidebar();
+ if ( !xSidebarProvider.is() )
+ break;
+
+ Reference<ui::XDecks> xDecks = xSidebarProvider->getDecks();
+ if ( !xDecks.is() )
+ break;
+
+ if (!xDecks->hasByName("NavigatorDeck"))
+ break;
+
+ Reference<ui::XDeck> xDeck ( xDecks->getByName("NavigatorDeck"), uno::UNO_QUERY);
+ if ( !xDeck.is() )
+ break;
+
+ Reference<ui::XPanels> xPanels = xDeck->getPanels();
+ if ( !xPanels.is() )
+ break;
+
+ if (xPanels->hasByName("SwNavigatorPanel"))
+ {
+ Reference<ui::XPanel> xPanel ( xPanels->getByName("SwNavigatorPanel"), uno::UNO_QUERY);
+ if ( !xPanel.is() || !xPanel->getTitle().isEmpty() )
+ break;
+
+ xPanel->setTitle( pCnt->GetName() );
+ }
+ }
+ break;
+ case ContentTypeId::REGION :
+ {
+ m_pActiveShell->GotoRegion(pCnt->GetName());
+ }
+ break;
+ case ContentTypeId::URLFIELD:
+ {
+ if(m_pActiveShell->GotoINetAttr(
+ *static_cast<const SwURLFieldContent*>(pCnt)->GetINetAttr() ))
+ {
+ m_pActiveShell->Right( SwCursorSkipMode::Chars, true, 1, false);
+ m_pActiveShell->SwCursorShell::SelectTextAttr( RES_TXTATR_INETFMT, true );
+ }
+ }
+ break;
+ case ContentTypeId::REFERENCE:
+ {
+ m_pActiveShell->GotoRefMark(pCnt->GetName());
+ }
+ break;
+ case ContentTypeId::INDEX:
+ {
+ const OUString& sName(pCnt->GetName());
+ if (!m_pActiveShell->GotoNextTOXBase(&sName))
+ m_pActiveShell->GotoPrevTOXBase(&sName);
+ }
+ break;
+ case ContentTypeId::POSTIT:
+ m_pActiveShell->GotoFormatField(*static_cast<const SwPostItContent*>(pCnt)->GetPostIt());
+ break;
+ case ContentTypeId::DRAWOBJECT:
+ {
+ m_pActiveShell->GotoDrawingObject(pCnt->GetName());
+ }
+ break;
+ case ContentTypeId::FOOTNOTE:
+ case ContentTypeId::ENDNOTE:
+ {
+ const SwTextFootnote* pFootnote =
+ static_cast<const SwTextFootnoteContent*>(pCnt)->GetTextFootnote();
+ if (!pFootnote)
+ return;
+ m_pActiveShell->GotoFootnoteAnchor(*pFootnote);
+ }
+ break;
+ default: break;
+ }
+
+ if (m_bSelectTo)
+ {
+ m_pActiveShell->SttCursorMove();
+ while (m_pActiveShell->IsCursorInTable())
+ {
+ m_pActiveShell->MoveTable(GotoCurrTable, fnTableStart);
+ if (!m_pActiveShell->Left(SwCursorSkipMode::Chars, false, 1, false))
+ break; // Table is at the beginning of the document. It can't be selected this way.
+ }
+ m_pActiveShell->EndCursorMove();
+
+ m_pActiveShell->AssureStdMode();
+
+ m_pActiveShell->SetMark();
+ m_pActiveShell->GetCursor()->GetMark()->nNode = oPosition.value()->nNode;
+ m_pActiveShell->GetCursor()->GetMark()->nContent = oPosition.value()->nContent;
+ m_pActiveShell->UpdateCursor();
+
+ m_pActiveShell->GetView().GetEditWin().GrabFocus();
+
+ m_bSelectTo = false;
+ }
+ else
+ {
+ if (m_pActiveShell->IsFrameSelected() || m_pActiveShell->IsObjSelected())
+ {
+ m_pActiveShell->HideCursor();
+ m_pActiveShell->EnterSelFrameMode();
+ }
+
+ SwView& rView = m_pActiveShell->GetView();
+ rView.StopShellTimer();
+ rView.GetPostItMgr()->SetActiveSidebarWin(nullptr);
+ rView.GetEditWin().GrabFocus();
+
+ // Assure cursor is in visible view area.
+ // (tdf#147041) Always show the navigated outline at the top of the visible view area.
+ if (pCnt->GetParent()->GetType() == ContentTypeId::OUTLINE ||
+ (!m_pActiveShell->IsCursorVisible() && !m_pActiveShell->IsFrameSelected() &&
+ !m_pActiveShell->IsObjSelected()))
+ {
+ Point aPoint(rView.GetVisArea().getX(), m_pActiveShell->GetCursorDocPos().getY());
+ rView.SetVisArea(aPoint);
+ }
+ }
+}
+
+// Now even the matching text::Bookmark
+NaviContentBookmark::NaviContentBookmark()
+ :
+ m_nDocSh(0),
+ m_nDefaultDrag( RegionMode::NONE )
+{
+}
+
+NaviContentBookmark::NaviContentBookmark( OUString aUrl,
+ OUString aDesc,
+ RegionMode nDragType,
+ const SwDocShell* pDocSh ) :
+ m_aUrl(std::move( aUrl )),
+ m_aDescription(std::move(aDesc)),
+ m_nDocSh(reinterpret_cast<sal_IntPtr>(pDocSh)),
+ m_nDefaultDrag( nDragType )
+{
+}
+
+void NaviContentBookmark::Copy( TransferDataContainer& rData ) const
+{
+ rtl_TextEncoding eSysCSet = osl_getThreadTextEncoding();
+
+ OString sStrBuf(OUStringToOString(m_aUrl, eSysCSet) + OStringChar(NAVI_BOOKMARK_DELIM) +
+ OUStringToOString(m_aDescription, eSysCSet) + OStringChar(NAVI_BOOKMARK_DELIM) +
+ OString::number(static_cast<int>(m_nDefaultDrag)) + OStringChar(NAVI_BOOKMARK_DELIM) +
+ OString::number(m_nDocSh));
+ rData.CopyByteString(SotClipboardFormatId::SONLK, sStrBuf);
+}
+
+bool NaviContentBookmark::Paste( const TransferableDataHelper& rData, const OUString& rsDesc )
+{
+ OUString sStr;
+ bool bRet = rData.GetString( SotClipboardFormatId::SONLK, sStr );
+ if( bRet )
+ {
+ sal_Int32 nPos = 0;
+ m_aUrl = sStr.getToken(0, NAVI_BOOKMARK_DELIM, nPos );
+ m_aDescription = sStr.getToken(0, NAVI_BOOKMARK_DELIM, nPos );
+ m_nDefaultDrag= static_cast<RegionMode>( o3tl::toInt32(o3tl::getToken(sStr, 0, NAVI_BOOKMARK_DELIM, nPos )) );
+ m_nDocSh = o3tl::toInt32(o3tl::getToken(sStr, 0, NAVI_BOOKMARK_DELIM, nPos ));
+ if (!rsDesc.isEmpty())
+ m_aDescription = rsDesc;
+ }
+ return bRet;
+}
+
+SwNavigationPI* SwContentTree::GetParentWindow()
+{
+ return m_pDialog;
+}
+
+void SwContentTree::SelectContentType(std::u16string_view rContentTypeName)
+{
+ std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator());
+ if (!m_xTreeView->get_iter_first(*xIter))
+ return;
+ do
+ {
+ if (m_xTreeView->get_text(*xIter) == rContentTypeName)
+ {
+ m_xTreeView->set_cursor(*xIter);
+ Select();
+ break;
+ }
+ } while (m_xTreeView->iter_next_sibling(*xIter));
+}
+
+IMPL_LINK_NOARG(SwContentTree, OverlayObjectDelayTimerHdl, Timer *, void)
+{
+ m_aOverlayObjectDelayTimer.Stop();
+ if (m_xOverlayObject)
+ {
+ if (SdrView* pView = m_pActiveShell->GetDrawView())
+ {
+ if (SdrPaintWindow* pPaintWindow = pView->GetPaintWindow(0))
+ {
+ const rtl::Reference<sdr::overlay::OverlayManager>& xOverlayManager =
+ pPaintWindow->GetOverlayManager();
+ xOverlayManager->add(*m_xOverlayObject);
+ }
+ }
+ }
+}
+
+void SwContentTree::OverlayObject(std::vector<basegfx::B2DRange>&& aRanges)
+{
+ m_aOverlayObjectDelayTimer.Stop();
+ if (m_xOverlayObject && m_xOverlayObject->getOverlayManager())
+ m_xOverlayObject->getOverlayManager()->remove(*m_xOverlayObject);
+ if (aRanges.empty())
+ m_xOverlayObject.reset();
+ else
+ {
+ m_xOverlayObject.reset(new sdr::overlay::OverlaySelection(
+ sdr::overlay::OverlayType::Invert,
+ Color(), std::move(aRanges), true/*unused for Invert type*/));
+ m_aOverlayObjectDelayTimer.Start();
+ }
+}
+
+void SwContentTree::BringEntryToAttention(const weld::TreeIter& rEntry)
+{
+ if (lcl_IsContent(rEntry, *m_xTreeView)) // content entry
+ {
+ SwContent* pCnt = weld::fromId<SwContent*>(m_xTreeView->get_id(rEntry));
+ if (pCnt->IsInvisible())
+ OverlayObject();
+ else
+ {
+ const ContentTypeId nType = pCnt->GetParent()->GetType();
+ if (nType == ContentTypeId::OUTLINE)
+ {
+ BringTypesWithFlowFramesToAttention({m_pActiveShell->GetNodes().
+ GetOutLineNds()[static_cast<SwOutlineContent*>(pCnt)->GetOutlinePos()]},
+ /*bIncludeTopMargin*/ false);
+ }
+ else if (nType == ContentTypeId::TABLE)
+ {
+ if (const sw::TableFrameFormats* pFrameFormats = m_pActiveShell->GetDoc()->GetTableFrameFormats())
+ if (const SwTableFormat* pFrameFormat = pFrameFormats->FindFrameFormatByName(pCnt->GetName()))
+ {
+ SwTable* pTable = SwTable::FindTable(pFrameFormat);
+ if (pTable)
+ BringTypesWithFlowFramesToAttention({pTable->GetTableNode()}, false);
+ }
+ }
+ else if (nType == ContentTypeId::FRAME || nType == ContentTypeId::GRAPHIC ||
+ nType == ContentTypeId::OLE)
+ {
+ SwNodeType eNodeType = SwNodeType::Text;
+ if(nType == ContentTypeId::GRAPHIC)
+ eNodeType = SwNodeType::Grf;
+ else if(nType == ContentTypeId::OLE)
+ eNodeType = SwNodeType::Ole;
+ if (const SwFrameFormat* pFrameFormat =
+ m_pActiveShell->GetDoc()->FindFlyByName(pCnt->GetName(), eNodeType))
+ BringFramesToAttention(std::vector<const SwFrameFormat*> {pFrameFormat});
+ }
+ else if (nType == ContentTypeId::BOOKMARK)
+ {
+ BringBookmarksToAttention(std::vector<OUString> {pCnt->GetName()});
+ }
+ else if (nType == ContentTypeId::REGION || nType == ContentTypeId::INDEX)
+ {
+ size_t nSectionFormatCount = m_pActiveShell->GetSectionFormatCount();
+ for (size_t i = 0; i < nSectionFormatCount; ++i)
+ {
+ const SwSectionFormat& rSectionFormat = m_pActiveShell->GetSectionFormat(i);
+ if (!rSectionFormat.IsInNodesArr())
+ continue;
+ const SwSection* pSection = rSectionFormat.GetSection();
+ if (!pSection)
+ continue;
+ if (pCnt->GetName() == pSection->GetSectionName())
+ {
+ BringTypesWithFlowFramesToAttention({rSectionFormat.GetSectionNode()});
+ break;
+ }
+ }
+ }
+ else if (nType == ContentTypeId::URLFIELD)
+ {
+ // tdf#159147 - Assure the SwURLFieldContent::SwTextINetFormat pointer is valid
+ // before bringing to attention.
+ const SwTextINetFormat* pTextINetFormat
+ = static_cast<SwURLFieldContent*>(pCnt)->GetINetAttr();
+ const SwCharFormats* pFormats = m_pActiveShell->GetDoc()->GetCharFormats();
+ for (auto n = pFormats->size(); 1 < n;)
+ {
+ SwIterator<SwTextINetFormat, SwCharFormat> aIter(*(*pFormats)[--n]);
+ for (SwTextINetFormat* pFnd = aIter.First(); pFnd; pFnd = aIter.Next() )
+ {
+ if (pTextINetFormat == pFnd)
+ {
+ BringURLFieldsToAttention(SwGetINetAttrs {SwGetINetAttr(pCnt->GetName(),
+ *pTextINetFormat)});
+ break;
+ }
+ }
+ }
+ }
+ else if (nType == ContentTypeId::REFERENCE)
+ {
+ if (const SwTextAttr* pTextAttr =
+ m_pActiveShell->GetDoc()->GetRefMark(pCnt->GetName())->GetTextRefMark())
+ {
+ std::vector<const SwTextAttr*> aTextAttrArr {pTextAttr};
+ BringReferencesToAttention(aTextAttrArr);
+ }
+ }
+ else if (nType == ContentTypeId::POSTIT)
+ {
+ if (const SwTextAttr* pTextAttr =
+ static_cast<SwPostItContent*>(pCnt)->GetPostIt()->GetTextField())
+ {
+ std::vector<const SwTextAttr*> aTextAttrArr {pTextAttr};
+ BringPostItFieldsToAttention(aTextAttrArr);
+ }
+ }
+ else if (nType == ContentTypeId::DRAWOBJECT)
+ {
+ std::vector<const SdrObject*> aSdrObjectArr {GetDrawingObjectsByContent(pCnt)};
+ BringDrawingObjectsToAttention(aSdrObjectArr);
+ }
+ else if (nType == ContentTypeId::TEXTFIELD)
+ {
+ if (const SwTextAttr* pTextAttr =
+ static_cast<SwTextFieldContent*>(pCnt)->GetFormatField()->GetTextField())
+ {
+ std::vector<const SwTextAttr*> aTextAttrArr {pTextAttr};
+ BringTextFieldsToAttention(aTextAttrArr);
+ }
+ }
+ else if (nType == ContentTypeId::FOOTNOTE || nType == ContentTypeId::ENDNOTE)
+ {
+ if (const SwTextAttr* pTextAttr =
+ static_cast<SwTextFootnoteContent*> (pCnt)->GetTextFootnote())
+ {
+ std::vector<const SwTextAttr*> aTextAttrArr {pTextAttr};
+ BringFootnotesToAttention(aTextAttrArr);
+ }
+ }
+ }
+ }
+ else // content type entry
+ {
+ SwContentType* pCntType = weld::fromId<SwContentType*>(m_xTreeView->get_id(rEntry));
+ if (pCntType->GetMemberCount() == 0)
+ OverlayObject();
+ else
+ {
+ const ContentTypeId nType = pCntType->GetType();
+ if (nType == ContentTypeId::OUTLINE)
+ {
+ std::vector<const SwNode*> aNodesArr(
+ m_pActiveShell->GetNodes().GetOutLineNds().begin(),
+ m_pActiveShell->GetNodes().GetOutLineNds().end());
+ BringTypesWithFlowFramesToAttention(aNodesArr, /*bIncludeTopMargin*/ false);
+ }
+ else if (nType == ContentTypeId::TABLE)
+ {
+ std::vector<const SwNode*> aNodesArr;
+ const size_t nCount = m_pActiveShell->GetTableFrameFormatCount(false);
+ const sw::TableFrameFormats& rTableFormats = *m_pActiveShell->GetDoc()->GetTableFrameFormats();
+ for(size_t i = 0; i < nCount; ++i)
+ {
+ if (const SwTableFormat* pTableFormat = rTableFormats[i])
+ if(pTableFormat->IsUsed()) // skip deleted tables
+ {
+ SwTable* pTable = SwTable::FindTable(pTableFormat);
+ if (pTable)
+ aNodesArr.push_back(pTable->GetTableNode());
+ }
+ }
+ BringTypesWithFlowFramesToAttention(aNodesArr, false);
+ }
+ else if (nType == ContentTypeId::FRAME || nType == ContentTypeId::GRAPHIC ||
+ nType == ContentTypeId::OLE)
+ {
+ FlyCntType eType = FLYCNTTYPE_FRM;
+ if(nType == ContentTypeId::GRAPHIC)
+ eType = FLYCNTTYPE_GRF;
+ else if(nType == ContentTypeId::OLE)
+ eType = FLYCNTTYPE_OLE;
+ BringFramesToAttention(m_pActiveShell->GetFlyFrameFormats(eType, true));
+ }
+ else if (nType == ContentTypeId::BOOKMARK)
+ {
+ std::vector<OUString> aNames;
+ const auto nCount = pCntType->GetMemberCount();
+ for (size_t i = 0; i < nCount; i++)
+ {
+ const SwContent* pMember = pCntType->GetMember(i);
+ if (pMember && !pMember->IsInvisible())
+ aNames.push_back(pMember->GetName());
+ }
+ BringBookmarksToAttention(aNames);
+ }
+ else if (nType == ContentTypeId::REGION || nType == ContentTypeId::INDEX)
+ {
+ std::vector<const SwNode*> aNodesArr;
+ const SwSectionFormats& rFormats = m_pActiveShell->GetDoc()->GetSections();
+ const size_t nSize = rFormats.size();
+ for (SwSectionFormats::size_type n = nSize; n;)
+ {
+ const SwSectionFormat* pSectionFormat = rFormats[--n];
+ if (pSectionFormat && pSectionFormat->IsInNodesArr())
+ {
+ const SwSection* pSection = pSectionFormat->GetSection();
+ if (pSection && !pSection->IsHiddenFlag())
+ {
+ const SectionType eSectionType = pSection->GetType();
+ if (nType == ContentTypeId::REGION &&
+ (eSectionType == SectionType::ToxContent ||
+ eSectionType == SectionType::ToxHeader))
+ continue;
+ if (nType == ContentTypeId::INDEX &&
+ eSectionType != SectionType::ToxContent)
+ continue;
+ if (const SwNode* pNode = pSectionFormat->GetSectionNode())
+ aNodesArr.push_back(pNode);
+ }
+ }
+ }
+ BringTypesWithFlowFramesToAttention(aNodesArr);
+ }
+ else if (nType == ContentTypeId::URLFIELD)
+ {
+ SwGetINetAttrs aINetAttrsArr;
+ m_pActiveShell->GetINetAttrs(aINetAttrsArr, false);
+ BringURLFieldsToAttention(aINetAttrsArr);
+ }
+ else if (nType == ContentTypeId::REFERENCE)
+ {
+ std::vector<const SwTextAttr*> aTextAttrArr;
+ for (const SfxPoolItem* pItem :
+ m_pActiveShell->GetAttrPool().GetItemSurrogates(RES_TXTATR_REFMARK))
+ {
+ if (const auto pRefMark = dynamic_cast<const SwFormatRefMark*>(pItem))
+ {
+ const SwTextRefMark* pTextRef = pRefMark->GetTextRefMark();
+ if (pTextRef && &pTextRef->GetTextNode().GetNodes() ==
+ &m_pActiveShell->GetNodes())
+ aTextAttrArr.push_back(pTextRef);
+ }
+ }
+ BringReferencesToAttention(aTextAttrArr);
+ }
+ else if (nType == ContentTypeId::POSTIT)
+ {
+ std::vector<const SwTextAttr*> aTextAttrArr;
+ const auto nCount = pCntType->GetMemberCount();
+ for (size_t i = 0; i < nCount; i++)
+ {
+ const SwPostItContent* pPostItContent = static_cast<const SwPostItContent*>(
+ pCntType->GetMember(i));
+ if (pPostItContent && !pPostItContent->IsInvisible())
+ if (const SwFormatField* pFormatField = pPostItContent->GetPostIt())
+ if (const SwTextAttr* pTextAttr = pFormatField->GetTextField())
+ aTextAttrArr.push_back(pTextAttr);
+ }
+ BringPostItFieldsToAttention(aTextAttrArr);
+ }
+ else if (nType == ContentTypeId::DRAWOBJECT)
+ {
+ IDocumentDrawModelAccess& rIDDMA = m_pActiveShell->getIDocumentDrawModelAccess();
+ if (const SwDrawModel* pModel = rIDDMA.GetDrawModel())
+ {
+ if (const SdrPage* pPage = pModel->GetPage(0))
+ {
+ if (pPage->GetObjCount())
+ {
+ std::vector<const SdrObject*> aSdrObjectArr;
+ for (const rtl::Reference<SdrObject>& pObject : *pPage)
+ {
+ if (pObject && !pObject->GetName().isEmpty() &&
+ rIDDMA.IsVisibleLayerId(pObject->GetLayer()))
+ aSdrObjectArr.push_back(pObject.get());
+ }
+ BringDrawingObjectsToAttention(aSdrObjectArr);
+ }
+ }
+ }
+ }
+ else if (nType == ContentTypeId::TEXTFIELD)
+ {
+ std::vector<const SwTextAttr*> aTextAttrArr;
+ const auto nCount = pCntType->GetMemberCount();
+ for (size_t i = 0; i < nCount; i++)
+ {
+ const SwTextFieldContent* pTextFieldCnt =
+ static_cast<const SwTextFieldContent*>(pCntType->GetMember(i));
+ if (pTextFieldCnt && !pTextFieldCnt->IsInvisible())
+ if (const SwFormatField* pFormatField = pTextFieldCnt->GetFormatField())
+ if (const SwTextAttr* pTextAttr = pFormatField->GetTextField())
+ aTextAttrArr.push_back(pTextAttr);
+ }
+ BringTextFieldsToAttention(aTextAttrArr);
+ }
+ else if (nType == ContentTypeId::FOOTNOTE || nType == ContentTypeId::ENDNOTE)
+ {
+ std::vector<const SwTextAttr*> aTextAttrArr;
+ const auto nCount = pCntType->GetMemberCount();
+ for (size_t i = 0; i < nCount; i++)
+ {
+ const SwTextFootnoteContent* pTextFootnoteCnt =
+ static_cast<const SwTextFootnoteContent*>(pCntType->GetMember(i));
+ if (pTextFootnoteCnt && !pTextFootnoteCnt->IsInvisible())
+ if (const SwTextAttr* pTextAttr = pTextFootnoteCnt->GetTextFootnote())
+ aTextAttrArr.push_back(pTextAttr);
+ }
+ BringFootnotesToAttention(aTextAttrArr);
+ }
+ }
+ }
+}
+
+static void lcl_CalcOverlayRanges(const SwTextFrame* pStartFrame, const SwTextFrame* pEndFrame,
+ const SwPosition& aStartPos, const SwPosition& aEndPos,
+ std::vector<basegfx::B2DRange>& aRanges)
+{
+ if (pStartFrame && pEndFrame)
+ {
+ SwRect aStartCharRect;
+ pStartFrame->GetCharRect(aStartCharRect, aStartPos);
+ SwRect aEndCharRect;
+ pEndFrame->GetCharRect(aEndCharRect, aEndPos);
+ if (aStartCharRect.Top() == aEndCharRect.Top())
+ {
+ // single line range
+ aRanges.emplace_back(aStartCharRect.Left(), aStartCharRect.Top(),
+ aEndCharRect.Right() + 1, aEndCharRect.Bottom() + 1);
+ }
+ else
+ {
+ // multi line range
+ SwRect aFrameRect = pStartFrame->getFrameArea();
+ aRanges.emplace_back(aStartCharRect.Left(), aStartCharRect.Top(),
+ aFrameRect.Right(), aStartCharRect.Bottom() + 1);
+ if (aStartCharRect.Bottom() + 1 != aEndCharRect.Top())
+ aRanges.emplace_back(aFrameRect.Left(), aStartCharRect.Bottom() + 1,
+ aFrameRect.Right(), aEndCharRect.Top() + 1);
+ aRanges.emplace_back(aFrameRect.Left(), aEndCharRect.Top() + 1,
+ aEndCharRect.Right() + 1, aEndCharRect.Bottom() + 1);
+ }
+ }
+}
+
+void SwContentTree::BringFramesToAttention(const std::vector<const SwFrameFormat*>& rFrameFormats)
+{
+ std::vector<basegfx::B2DRange> aRanges;
+ for (const SwFrameFormat* pFrameFormat : rFrameFormats)
+ {
+ if (!pFrameFormat)
+ continue;
+ SwRect aFrameRect = pFrameFormat->FindLayoutRect();
+ if (!aFrameRect.IsEmpty())
+ aRanges.emplace_back(aFrameRect.Left(), aFrameRect.Top(), aFrameRect.Right(),
+ aFrameRect.Bottom());
+ }
+ OverlayObject(std::move(aRanges));
+}
+
+void SwContentTree::BringBookmarksToAttention(const std::vector<OUString>& rNames)
+{
+ std::vector<basegfx::B2DRange> aRanges;
+ IDocumentMarkAccess* const pMarkAccess = m_pActiveShell->getIDocumentMarkAccess();
+ for (const auto& rName : rNames)
+ {
+ IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->findBookmark(rName);
+ if (ppBkmk == pMarkAccess->getBookmarksEnd())
+ continue;
+ SwPosition aMarkStart = (*ppBkmk)->GetMarkStart();
+ const SwTextNode* pMarkStartTextNode = aMarkStart.GetNode().GetTextNode();
+ if (!pMarkStartTextNode)
+ continue;
+ const SwTextFrame* pMarkStartFrame = static_cast<const SwTextFrame*>(
+ pMarkStartTextNode->getLayoutFrame(m_pActiveShell->GetLayout()));
+ if (!pMarkStartFrame)
+ continue;
+ SwPosition aMarkEnd = (*ppBkmk)->GetMarkEnd();
+ const SwTextNode* pMarkEndTextNode = aMarkEnd.GetNode().GetTextNode();
+ if (!pMarkEndTextNode)
+ continue;
+ const SwTextFrame* pMarkEndFrame = static_cast<const SwTextFrame*>(
+ pMarkEndTextNode->getLayoutFrame(m_pActiveShell->GetLayout()));
+ if (!pMarkEndFrame)
+ continue;
+ // adjust span when mark start equals mark end
+ if (aMarkStart == aMarkEnd)
+ {
+ if (aMarkEnd.GetContentIndex() < pMarkEndTextNode->Len() - 1)
+ aMarkEnd.AdjustContent(+1);
+ else if (aMarkStart.GetContentIndex() > 0)
+ aMarkStart.AdjustContent(-1);
+ }
+ lcl_CalcOverlayRanges(pMarkStartFrame, pMarkEndFrame, aMarkStart, aMarkEnd, aRanges);
+ }
+ OverlayObject(std::move(aRanges));
+}
+
+void SwContentTree::BringTypesWithFlowFramesToAttention(const std::vector<const SwNode*>& rNodes,
+ const bool bIncludeTopMargin)
+{
+ std::vector<basegfx::B2DRange> aRanges;
+ for (const auto* pNode : rNodes)
+ {
+ if (!pNode)
+ continue;
+ const SwFrame* pFrame;
+ if (pNode->IsContentNode() || pNode->IsTableNode())
+ {
+ if (pNode->IsContentNode())
+ pFrame = pNode->GetContentNode()->getLayoutFrame(m_pActiveShell->GetLayout());
+ else // table node
+ {
+ SwNode2Layout aTmp(*pNode, pNode->GetIndex() - 1);
+ pFrame = aTmp.NextFrame();
+ }
+ while (pFrame)
+ {
+ const SwRect& rFrameRect = pFrame->getFrameArea();
+ if (!rFrameRect.IsEmpty())
+ aRanges.emplace_back(rFrameRect.Left(), bIncludeTopMargin ? rFrameRect.Top() :
+ rFrameRect.Top() + pFrame->GetTopMargin(),
+ rFrameRect.Right(), rFrameRect.Bottom());
+ if (!pFrame->IsFlowFrame())
+ break;
+ const SwFlowFrame *pFollow = SwFlowFrame::CastFlowFrame(pFrame)->GetFollow();
+ if (!pFollow)
+ break;
+ pFrame = &pFollow->GetFrame();
+ }
+ }
+ else if (pNode->IsSectionNode())
+ {
+ const SwNode* pEndOfSectionNode = pNode->EndOfSectionNode();
+ SwNodeIndex aIdx(*pNode);
+ while (&aIdx.GetNode() != pEndOfSectionNode)
+ {
+ if (aIdx.GetNode().IsContentNode())
+ {
+ if ((pFrame = aIdx.GetNode().GetContentNode()->
+ getLayoutFrame(m_pActiveShell->GetLayout())))
+ {
+ if (pFrame->IsInSct())
+ pFrame = pFrame->FindSctFrame();
+ if (pFrame)
+ {
+ const SwRect& rFrameRect = pFrame->getFrameArea();
+ if (!rFrameRect.IsEmpty())
+ aRanges.emplace_back(rFrameRect.Left(), rFrameRect.Top(),
+ rFrameRect.Right(), rFrameRect.Bottom());
+ }
+ }
+ ++aIdx;
+ while (!aIdx.GetNode().IsEndNode() && !aIdx.GetNode().IsSectionNode())
+ ++aIdx;
+ continue;
+ }
+ if (!aIdx.GetNode().IsSectionNode())
+ {
+ ++aIdx;
+ continue;
+ }
+ SwNode2Layout aTmp(aIdx.GetNode(), aIdx.GetNode().GetIndex() - 1);
+ pFrame = aTmp.NextFrame();
+ if (pFrame)
+ {
+ if (!pFrame->getFrameArea().IsEmpty())
+ {
+ const SwRect& rFrameRect = pFrame->getFrameArea();
+ aRanges.emplace_back(rFrameRect.Left(), rFrameRect.Top(),
+ rFrameRect.Right(), rFrameRect.Bottom());
+ }
+ if (pFrame->IsSctFrame())
+ {
+ const SwSectionFrame* pSectionFrame
+ = static_cast<const SwSectionFrame*>(pFrame);
+ if (pSectionFrame->HasFollow())
+ {
+ const SwFlowFrame *pFollow
+ = SwFlowFrame::CastFlowFrame(pSectionFrame)->GetFollow();
+ while (pFollow)
+ {
+ pFrame = &pFollow->GetFrame();
+ if (!pFrame->getFrameArea().IsEmpty())
+ {
+ const SwRect& rFrameRect = pFrame->getFrameArea();
+ aRanges.emplace_back(rFrameRect.Left(), rFrameRect.Top(),
+ rFrameRect.Right(), rFrameRect.Bottom());
+ }
+ pFollow = SwFlowFrame::CastFlowFrame(pFrame)->GetFollow();
+ }
+ }
+ }
+ }
+ ++aIdx;
+ while (!aIdx.GetNode().IsEndNode() && !aIdx.GetNode().IsSectionNode())
+ ++aIdx;
+ }
+ // Remove nested sections. This wouldn't be needed if the overlay wasn't invert type.
+ auto end = aRanges.end();
+ for (auto it = aRanges.begin(); it != end; ++it)
+ end = std::remove_if(it + 1, end, [&it](auto itt){ return it->isInside(itt); });
+ aRanges.erase(end, aRanges.end());
+ }
+ }
+ OverlayObject(std::move(aRanges));
+}
+
+void SwContentTree::BringURLFieldsToAttention(const SwGetINetAttrs& rINetAttrsArr)
+{
+ std::vector<basegfx::B2DRange> aRanges;
+ for (const auto& r : rINetAttrsArr)
+ {
+ const SwTextNode& rTextNode = r.rINetAttr.GetTextNode();
+ if (SwTextFrame* pFrame = static_cast<SwTextFrame*>(
+ rTextNode.getLayoutFrame(m_pActiveShell->GetLayout())))
+ {
+ auto nStart = r.rINetAttr.GetStart();
+ auto nEnd = r.rINetAttr.GetAnyEnd();
+ SwPosition aStartPos(rTextNode, nStart), aEndPos(rTextNode, nEnd);
+ lcl_CalcOverlayRanges(pFrame, pFrame, aStartPos, aEndPos, aRanges);
+ }
+ }
+ OverlayObject(std::move(aRanges));
+}
+
+void SwContentTree::BringReferencesToAttention(std::vector<const SwTextAttr*>& rTextAttrsArr)
+{
+ std::vector<basegfx::B2DRange> aRanges;
+ for (const SwTextAttr* p : rTextAttrsArr)
+ {
+ if (!p)
+ continue;
+ const SwTextRefMark* pTextRefMark = p->GetRefMark().GetTextRefMark();
+ if (!pTextRefMark)
+ continue;
+ const SwTextNode& rTextNode = pTextRefMark->GetTextNode();
+ if (SwTextFrame* pFrame = static_cast<SwTextFrame*>(
+ rTextNode.getLayoutFrame(m_pActiveShell->GetLayout())))
+ {
+ auto nStart = p->GetStart();
+ auto nEnd = p->GetAnyEnd();
+ SwPosition aStartPos(rTextNode, nStart), aEndPos(rTextNode, nEnd);
+ lcl_CalcOverlayRanges(pFrame, pFrame, aStartPos, aEndPos, aRanges);
+ }
+ }
+ OverlayObject(std::move(aRanges));
+}
+
+void SwContentTree::BringPostItFieldsToAttention(std::vector<const SwTextAttr*>& rTextAttrsArr)
+{
+ std::vector<basegfx::B2DRange> aRanges;
+ for (const SwTextAttr* p : rTextAttrsArr)
+ {
+ if (!p)
+ continue;
+ const SwTextField* pTextField = p->GetFormatField().GetTextField();
+ if (!pTextField)
+ continue;
+ // use as a fallback when there is no mark
+ SwTextNode& rTextNode = pTextField->GetTextNode();
+ if (!rTextNode.getLayoutFrame(m_pActiveShell->GetLayout()))
+ continue;
+ assert(dynamic_cast<const SwTextAnnotationField*>(pTextField));
+ const SwTextAnnotationField* pTextAnnotationField =
+ static_cast<const SwTextAnnotationField*>(pTextField);
+ const ::sw::mark::IMark* pAnnotationMark = pTextAnnotationField->GetAnnotationMark();
+ const SwPosition aMarkStart = pAnnotationMark ? pAnnotationMark->GetMarkStart()
+ : SwPosition(rTextNode, p->GetStart());
+ const SwPosition aMarkEnd = pAnnotationMark ? pAnnotationMark->GetMarkEnd()
+ : SwPosition(rTextNode, p->GetAnyEnd());
+ const SwTextFrame* pMarkStartFrame = static_cast<SwTextFrame*>(
+ aMarkStart.GetNode().GetTextNode()->getLayoutFrame(m_pActiveShell->GetLayout()));
+ const SwTextFrame* pMarkEndFrame = static_cast<SwTextFrame*>(
+ aMarkEnd.GetNode().GetTextNode()->getLayoutFrame(m_pActiveShell->GetLayout()));
+ if (!pMarkStartFrame || !pMarkEndFrame)
+ continue;
+ lcl_CalcOverlayRanges(pMarkStartFrame, pMarkEndFrame, aMarkStart,
+ aMarkEnd, aRanges);
+ }
+ OverlayObject(std::move(aRanges));
+}
+
+void SwContentTree::BringFootnotesToAttention(std::vector<const SwTextAttr*>& rTextAttrsArr)
+{
+ std::vector<basegfx::B2DRange> aRanges;
+ for (const SwTextAttr* p : rTextAttrsArr)
+ {
+ if (!p)
+ continue;
+ const SwTextFootnote* pTextFootnote = p->GetFootnote().GetTextFootnote();
+ if (!pTextFootnote)
+ continue;
+ const SwTextNode& rTextNode = pTextFootnote->GetTextNode();
+ if (SwTextFrame* pFrame = static_cast<SwTextFrame*>(
+ rTextNode.getLayoutFrame(m_pActiveShell->GetLayout())))
+ {
+ auto nStart = p->GetStart();
+ auto nEnd = nStart + 1;
+ SwPosition aStartPos(rTextNode, nStart), aEndPos(rTextNode, nEnd);
+ lcl_CalcOverlayRanges(pFrame, pFrame, aStartPos, aEndPos, aRanges);
+ }
+ }
+ OverlayObject(std::move(aRanges));
+}
+
+void SwContentTree::BringDrawingObjectsToAttention(std::vector<const SdrObject*>& rDrawingObjectsArr)
+{
+ std::vector<basegfx::B2DRange> aRanges;
+ for (const SdrObject* pObject : rDrawingObjectsArr)
+ {
+ if (pObject)
+ {
+ tools::Rectangle aRect(pObject->GetLogicRect());
+ if (!aRect.IsEmpty())
+ aRanges.emplace_back(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
+ }
+ }
+ OverlayObject(std::move(aRanges));
+}
+
+void SwContentTree::BringTextFieldsToAttention(std::vector<const SwTextAttr*>& rTextAttrsArr)
+{
+ std::vector<basegfx::B2DRange> aRanges;
+ std::shared_ptr<SwPaM> pPamForTextField;
+ for (const SwTextAttr* p : rTextAttrsArr)
+ {
+ if (!p)
+ continue;
+ const SwTextField* pTextField = p->GetFormatField().GetTextField();
+ if (!pTextField)
+ continue;
+ if (SwTextFrame* pFrame = static_cast<SwTextFrame*>(
+ pTextField->GetTextNode().getLayoutFrame(m_pActiveShell->GetLayout())))
+ {
+ SwTextField::GetPamForTextField(*pTextField, pPamForTextField);
+ if (!pPamForTextField)
+ continue;
+ SwPosition aStartPos(*pPamForTextField->GetMark());
+ SwPosition aEndPos(*pPamForTextField->GetPoint());
+ lcl_CalcOverlayRanges(pFrame, pFrame, aStartPos, aEndPos, aRanges);
+ }
+ }
+ OverlayObject(std::move(aRanges));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/glbltree.cxx b/sw/source/uibase/utlui/glbltree.cxx
new file mode 100644
index 0000000000..4ddf32dd02
--- /dev/null
+++ b/sw/source/uibase/utlui/glbltree.cxx
@@ -0,0 +1,1185 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <o3tl/safeint.hxx>
+#include <svl/stritem.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/event.hxx>
+#include <sot/filelist.hxx>
+#include <svl/eitem.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <osl/diagnose.h>
+
+#include <sfx2/docinsert.hxx>
+#include <sfx2/filedlghelper.hxx>
+
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <edglbldc.hxx>
+#include <section.hxx>
+#include <tox.hxx>
+#include <navipi.hxx>
+#include <edtwin.hxx>
+#include <toxmgr.hxx>
+
+#include <cmdid.h>
+#include <helpids.h>
+#include <strings.hrc>
+#include <bitmaps.hlst>
+#include <swabstdlg.hxx>
+#include <memory>
+
+#include <sfx2/event.hxx>
+#include <unotxvw.hxx>
+
+using namespace ::com::sun::star::uno;
+
+#define GLOBAL_UPDATE_TIMEOUT 2000
+
+const SfxObjectShell* SwGlobalTree::s_pShowShell = nullptr;
+
+namespace {
+
+class SwGlobalFrameListener_Impl : public SfxListener
+{
+ bool m_bValid;
+public:
+ explicit SwGlobalFrameListener_Impl(SfxViewFrame& rFrame)
+ : m_bValid(true)
+ {
+ StartListening(rFrame);
+ }
+
+ virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
+
+ bool IsValid() const {return m_bValid;}
+};
+
+}
+
+void SwGlobalFrameListener_Impl::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
+{
+ if( rHint.GetId() == SfxHintId::Dying)
+ m_bValid = false;
+}
+
+namespace {
+
+enum GLOBAL_CONTEXT_IDX
+{
+ IDX_STR_UPDATE = 0,
+ IDX_STR_EDIT_CONTENT = 1,
+ IDX_STR_EDIT_INSERT = 2,
+ IDX_STR_INDEX = 3,
+ IDX_STR_FILE = 4,
+ IDX_STR_NEW_FILE = 5,
+ IDX_STR_INSERT_TEXT = 6,
+ IDX_STR_DELETE = 7,
+ IDX_STR_UPDATE_SEL = 8,
+ IDX_STR_UPDATE_INDEX = 9,
+ IDX_STR_UPDATE_LINK = 10,
+ IDX_STR_UPDATE_ALL = 11,
+ IDX_STR_BROKEN_LINK = 12,
+ IDX_STR_EDIT_LINK = 13
+};
+
+}
+
+const TranslateId GLOBAL_CONTEXT_ARY[] =
+{
+ STR_UPDATE,
+ STR_EDIT_CONTENT,
+ STR_EDIT_INSERT,
+ STR_INDEX,
+ STR_FILE,
+ STR_NEW_FILE,
+ STR_INSERT_TEXT,
+ STR_DELETE,
+ STR_UPDATE_SEL,
+ STR_UPDATE_INDEX,
+ STR_UPDATE_LINK,
+ STR_UPDATE_ALL,
+ STR_BROKEN_LINK,
+ STR_EDIT_LINK
+};
+
+SwGlobalTree::SwGlobalTree(std::unique_ptr<weld::TreeView> xTreeView, SwNavigationPI* pDialog)
+ : m_xTreeView(std::move(xTreeView))
+ , m_aDropTargetHelper(*this)
+ , m_pDialog(pDialog)
+ , m_aUpdateTimer("SwGlobalTree m_aUpdateTimer")
+ , m_pActiveShell(nullptr)
+{
+ m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 30,
+ m_xTreeView->get_text_height() * 14);
+
+ m_aUpdateTimer.SetTimeout(GLOBAL_UPDATE_TIMEOUT);
+ m_aUpdateTimer.SetInvokeHandler(LINK(this, SwGlobalTree, Timeout));
+ m_aUpdateTimer.Start();
+ for (sal_uInt16 i = 0; i < GLOBAL_CONTEXT_COUNT; i++)
+ {
+ m_aContextStrings[i] = SwResId(GLOBAL_CONTEXT_ARY[i]);
+ }
+ m_xTreeView->set_help_id(HID_NAVIGATOR_GLOB_TREELIST);
+ Select();
+ m_xTreeView->connect_row_activated(LINK(this, SwGlobalTree, DoubleClickHdl));
+ m_xTreeView->connect_changed(LINK(this, SwGlobalTree, SelectHdl));
+ m_xTreeView->connect_focus_in(LINK(this, SwGlobalTree, FocusInHdl));
+ m_xTreeView->connect_key_press(LINK(this, SwGlobalTree, KeyInputHdl));
+ m_xTreeView->connect_popup_menu(LINK(this, SwGlobalTree, CommandHdl));
+ m_xTreeView->connect_query_tooltip(LINK(this, SwGlobalTree, QueryTooltipHdl));
+}
+
+SwGlobalTree::~SwGlobalTree()
+{
+ m_pSwGlblDocContents.reset();
+ m_pDocInserter.reset();
+ m_aUpdateTimer.Stop();
+}
+
+SwGlobalTreeDropTarget::SwGlobalTreeDropTarget(SwGlobalTree& rTreeView)
+ : DropTargetHelper(rTreeView.get_widget().get_drop_target())
+ , m_rTreeView(rTreeView)
+{
+}
+
+sal_Int8 SwGlobalTreeDropTarget::ExecuteDrop( const ExecuteDropEvent& rEvt )
+{
+ sal_Int8 nRet = DND_ACTION_NONE;
+
+ weld::TreeView& rWidget = m_rTreeView.get_widget();
+ std::unique_ptr<weld::TreeIter> xDropEntry(rWidget.make_iterator());
+ if (!rWidget.get_dest_row_at_pos(rEvt.maPosPixel, xDropEntry.get(), true))
+ xDropEntry.reset();
+
+ if (rWidget.get_drag_source() == &rWidget) // internal drag
+ m_rTreeView.MoveSelectionTo(xDropEntry.get());
+ else
+ {
+ TransferableDataHelper aData( rEvt.maDropEvent.Transferable );
+
+ OUString sFileName;
+ const SwGlblDocContent* pCnt = xDropEntry ?
+ weld::fromId<const SwGlblDocContent*>(rWidget.get_id(*xDropEntry)) :
+ nullptr;
+ if( aData.HasFormat( SotClipboardFormatId::FILE_LIST ))
+ {
+ nRet = rEvt.mnAction;
+ SwGlblDocContents aTempContents;
+ int nAbsContPos = xDropEntry ?
+ rWidget.get_iter_index_in_parent(*xDropEntry):
+ - 1;
+ size_t nEntryCount = rWidget.n_children();
+
+ // Get data
+ FileList aFileList;
+ aData.GetFileList( SotClipboardFormatId::FILE_LIST, aFileList );
+ for ( size_t n = aFileList.Count(); n--; )
+ {
+ sFileName = aFileList.GetFile(n);
+ m_rTreeView.InsertRegion(pCnt, &sFileName);
+ // The list of contents must be newly fetched after inserting,
+ // to not work on an old content.
+ if(n)
+ {
+ if (const SwWrtShell* pSh = m_rTreeView.GetActiveWrtShell())
+ {
+ pSh->GetGlobalDocContent(aTempContents);
+ // If the file was successfully inserted,
+ // then the next content must also be fetched.
+ if(nEntryCount < aTempContents.size())
+ {
+ nEntryCount++;
+ nAbsContPos++;
+ pCnt = aTempContents[ nAbsContPos ].get();
+ }
+ }
+ }
+ }
+ }
+ else if( !(sFileName =
+ SwNavigationPI::CreateDropFileName( aData )).isEmpty())
+ {
+ INetURLObject aTemp(sFileName);
+ GraphicDescriptor aDesc(aTemp);
+ if( !aDesc.Detect() ) // accept no graphics
+ {
+ nRet = rEvt.mnAction;
+ m_rTreeView.InsertRegion(pCnt, &sFileName);
+ }
+ }
+ }
+ return nRet;
+}
+
+sal_Int8 SwGlobalTreeDropTarget::AcceptDrop( const AcceptDropEvent& rEvt )
+{
+ // to enable the autoscroll when we're close to the edges
+ weld::TreeView& rWidget = m_rTreeView.get_widget();
+ rWidget.get_dest_row_at_pos(rEvt.maPosPixel, nullptr, true);
+
+ sal_Int8 nRet = rEvt.mnAction;
+
+ if (rWidget.get_drag_source() == &rWidget) // internal drag
+ return nRet;
+
+ if (IsDropFormatSupported( SotClipboardFormatId::SIMPLE_FILE) ||
+ IsDropFormatSupported( SotClipboardFormatId::STRING) ||
+ IsDropFormatSupported( SotClipboardFormatId::FILE_LIST) ||
+ IsDropFormatSupported( SotClipboardFormatId::SOLK) ||
+ IsDropFormatSupported( SotClipboardFormatId::NETSCAPE_BOOKMARK )||
+ IsDropFormatSupported( SotClipboardFormatId::FILECONTENT) ||
+ IsDropFormatSupported( SotClipboardFormatId::FILEGRPDESCRIPTOR) ||
+ IsDropFormatSupported( SotClipboardFormatId::UNIFORMRESOURCELOCATOR) ||
+ IsDropFormatSupported( SotClipboardFormatId::FILENAME))
+ {
+ nRet = DND_ACTION_LINK;
+ }
+
+ return nRet;
+}
+
+IMPL_LINK(SwGlobalTree, CommandHdl, const CommandEvent&, rCEvt, bool)
+{
+ if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
+ return false;
+
+ bool bPop = false;
+ if (m_pActiveShell && !m_pActiveShell->GetView().GetDocShell()->IsReadOnly())
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xTreeView.get(), "modules/swriter/ui/mastercontextmenu.ui"));
+ std::unique_ptr<weld::Menu> xPopup = xBuilder->weld_menu("navmenu");
+ std::unique_ptr<weld::Menu> xSubPopup = xBuilder->weld_menu("insertmenu");
+
+ const MenuEnableFlags nEnableFlags = GetEnableFlags();
+
+ xPopup->set_sensitive("updatesel", bool(nEnableFlags & MenuEnableFlags::UpdateSel));
+
+ xPopup->set_sensitive("editlink", bool(nEnableFlags & MenuEnableFlags::EditLink));
+
+ //disabling if applicable
+ xSubPopup->set_sensitive("insertindex", bool(nEnableFlags & MenuEnableFlags::InsertIdx ));
+ xSubPopup->set_sensitive("insertfile", bool(nEnableFlags & MenuEnableFlags::InsertFile));
+ xSubPopup->set_sensitive("insertnewfile", bool(nEnableFlags & MenuEnableFlags::InsertFile));
+ xSubPopup->set_sensitive("inserttext", bool(nEnableFlags & MenuEnableFlags::InsertText));
+
+ xPopup->set_sensitive("update", bool(nEnableFlags & MenuEnableFlags::Update));
+ xPopup->set_sensitive("insert", bool(nEnableFlags & MenuEnableFlags::InsertIdx));
+ xPopup->set_sensitive("editcontent", bool(nEnableFlags & MenuEnableFlags::Edit));
+ xPopup->set_sensitive("deleteentry", bool(nEnableFlags & MenuEnableFlags::Delete));
+
+ OUString sCommand = xPopup->popup_at_rect(m_xTreeView.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)));
+ if (!sCommand.isEmpty())
+ ExecuteContextMenuAction(sCommand);
+
+ bPop = true;
+ }
+ return bPop;
+}
+
+void SwGlobalTree::TbxMenuHdl(std::u16string_view rCommand, weld::Menu& rMenu)
+{
+ const MenuEnableFlags nEnableFlags = GetEnableFlags();
+ if (rCommand == u"insert")
+ {
+ rMenu.set_sensitive("insertindex", bool(nEnableFlags & MenuEnableFlags::InsertIdx));
+ rMenu.set_sensitive("insertfile", bool(nEnableFlags & MenuEnableFlags::InsertFile));
+ rMenu.set_sensitive("insertnewfile", bool(nEnableFlags & MenuEnableFlags::InsertFile));
+ rMenu.set_sensitive("inserttext", bool(nEnableFlags & MenuEnableFlags::InsertText));
+ }
+ else if (rCommand == u"update")
+ {
+ rMenu.set_sensitive("updatesel", bool(nEnableFlags & MenuEnableFlags::UpdateSel));
+ }
+}
+
+MenuEnableFlags SwGlobalTree::GetEnableFlags() const
+{
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ bool bEntry = m_xTreeView->get_selected(xEntry.get());
+
+ int nSelCount = m_xTreeView->count_selected_rows();
+ size_t nEntryCount = m_xTreeView->n_children();
+ std::unique_ptr<weld::TreeIter> xPrevEntry;
+ bool bPrevEntry = false;
+ if (bEntry)
+ {
+ xPrevEntry = m_xTreeView->make_iterator(xEntry.get());
+ bPrevEntry = m_xTreeView->iter_previous(*xPrevEntry);
+ }
+
+ MenuEnableFlags nRet = MenuEnableFlags::NONE;
+ if(nSelCount == 1 || !nEntryCount)
+ nRet |= MenuEnableFlags::InsertIdx|MenuEnableFlags::InsertFile;
+ if(nSelCount == 1)
+ {
+ nRet |= MenuEnableFlags::Edit;
+ if (bEntry && weld::fromId<SwGlblDocContent*>(m_xTreeView->get_id(*xEntry))->GetType() != GLBLDOC_UNKNOWN &&
+ (!bPrevEntry || weld::fromId<SwGlblDocContent*>(m_xTreeView->get_id(*xPrevEntry))->GetType() != GLBLDOC_UNKNOWN))
+ nRet |= MenuEnableFlags::InsertText;
+ if (bEntry && GLBLDOC_SECTION == weld::fromId<SwGlblDocContent*>(m_xTreeView->get_id(*xEntry))->GetType())
+ nRet |= MenuEnableFlags::EditLink;
+ }
+ else if(!nEntryCount)
+ {
+ nRet |= MenuEnableFlags::InsertText;
+ }
+ if(nEntryCount)
+ nRet |= MenuEnableFlags::Update|MenuEnableFlags::Delete;
+ if(nSelCount)
+ nRet |= MenuEnableFlags::UpdateSel;
+ return nRet;
+}
+
+IMPL_LINK(SwGlobalTree, QueryTooltipHdl, const weld::TreeIter&, rIter, OUString)
+{
+ OUString sEntry;
+
+ const SwGlblDocContent* pCont = weld::fromId<const SwGlblDocContent*>(m_xTreeView->get_id(rIter));
+ if (pCont && GLBLDOC_SECTION == pCont->GetType())
+ {
+ const SwSection* pSect = pCont->GetSection();
+ sEntry = pSect->GetLinkFileName().getToken(0, sfx2::cTokenSeparator);
+ if (!pSect->IsConnectFlag())
+ sEntry = m_aContextStrings[IDX_STR_BROKEN_LINK] + sEntry;
+ }
+
+ return sEntry;
+}
+
+IMPL_LINK_NOARG(SwGlobalTree, SelectHdl, weld::TreeView&, void)
+{
+ Select();
+}
+
+void SwGlobalTree::Select()
+{
+ int nSelCount = m_xTreeView->count_selected_rows();
+ int nSel = m_xTreeView->get_selected_index();
+ int nAbsPos = nSel != -1 ? nSel : 0;
+ SwNavigationPI* pNavi = GetParentWindow();
+ bool bReadonly = !m_pActiveShell ||
+ m_pActiveShell->GetView().GetDocShell()->IsReadOnly();
+ pNavi->m_xGlobalToolBox->set_item_sensitive("edit", nSelCount == 1 && !bReadonly);
+ pNavi->m_xGlobalToolBox->set_item_sensitive("insert", nSelCount <= 1 && !bReadonly);
+ pNavi->m_xGlobalToolBox->set_item_sensitive("update", m_xTreeView->n_children() > 0 && !bReadonly);
+ pNavi->m_xGlobalToolBox->set_item_sensitive("moveup",
+ nSelCount == 1 && nAbsPos && !bReadonly);
+ pNavi->m_xGlobalToolBox->set_item_sensitive("movedown",
+ nSelCount == 1 && nAbsPos < m_xTreeView->n_children() - 1 && !bReadonly);
+
+}
+
+void SwGlobalTree::MoveSelectionTo(const weld::TreeIter* pDropEntry)
+{
+ int nSource = m_xTreeView->get_selected_index();
+
+ int nDest = pDropEntry ? m_xTreeView->get_iter_index_in_parent(*pDropEntry)
+ : m_pSwGlblDocContents->size();
+
+ if (m_pActiveShell->MoveGlobalDocContent(
+ *m_pSwGlblDocContents, nSource, nSource + 1, nDest ) &&
+ Update( false ))
+ Display();
+}
+
+IMPL_LINK_NOARG(SwGlobalTree, FocusInHdl, weld::Widget&, void)
+{
+ if (Update(false))
+ Display();
+}
+
+IMPL_LINK(SwGlobalTree, KeyInputHdl, const KeyEvent&, rKEvt, bool)
+{
+ bool bHandled = false;
+ const vcl::KeyCode aCode = rKEvt.GetKeyCode();
+ if (aCode.GetCode() == KEY_RETURN)
+ {
+ switch (aCode.GetModifier())
+ {
+ case KEY_MOD2:
+ // Switch boxes
+ GetParentWindow()->ToggleTree();
+ bHandled = true;
+ break;
+ }
+ }
+ return bHandled;
+}
+
+void SwGlobalTree::Display(bool bOnlyUpdateUserData)
+{
+ size_t nCount = m_pSwGlblDocContents->size();
+ size_t nChildren = m_xTreeView->n_children();
+ if (bOnlyUpdateUserData && nChildren == m_pSwGlblDocContents->size())
+ {
+ std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
+ bool bEntry = m_xTreeView->get_iter_first(*xEntry);
+ for (size_t i = 0; i < nCount && bEntry; i++)
+ {
+ const SwGlblDocContent* pCont = (*m_pSwGlblDocContents)[i].get();
+ OUString sId(weld::toId(pCont));
+ m_xTreeView->set_id(*xEntry, sId);
+ if (pCont->GetType() == GLBLDOC_SECTION && !pCont->GetSection()->IsConnectFlag())
+ m_xTreeView->set_font_color(*xEntry, COL_LIGHTRED);
+ else
+ m_xTreeView->set_font_color(*xEntry, COL_AUTO);
+ bEntry = m_xTreeView->iter_next(*xEntry);
+ assert(bEntry || i == nCount - 1);
+ }
+ }
+ else
+ {
+ int nOldSelEntry = m_xTreeView->get_selected_index();
+ OUString sEntryName; // Name of the entry
+ int nSelPos = -1;
+ if (nOldSelEntry != -1)
+ {
+ sEntryName = m_xTreeView->get_text(nOldSelEntry);
+ nSelPos = nOldSelEntry;
+ }
+ m_xTreeView->freeze();
+ m_xTreeView->clear();
+
+ int nSelEntry = -1;
+ for (size_t i = 0; i < nCount; ++i)
+ {
+ const SwGlblDocContent* pCont = (*m_pSwGlblDocContents)[i].get();
+
+ OUString sId(weld::toId(pCont));
+ OUString sEntry;
+ OUString aImage;
+ switch (pCont->GetType())
+ {
+ case GLBLDOC_UNKNOWN:
+ sEntry = m_aContextStrings[IDX_STR_INSERT_TEXT];
+ break;
+ case GLBLDOC_TOXBASE:
+ {
+ const SwTOXBase* pBase = pCont->GetTOX();
+ sEntry = pBase->GetTitle();
+ aImage = RID_BMP_NAVI_INDEX;
+ }
+ break;
+ case GLBLDOC_SECTION:
+ {
+ const SwSection* pSect = pCont->GetSection();
+ sEntry = pSect->GetSectionName();
+ aImage = RID_BMP_DROP_REGION;
+ }
+ break;
+ }
+
+ m_xTreeView->append(sId, sEntry);
+ if (!aImage.isEmpty())
+ m_xTreeView->set_image(i, aImage);
+
+ if (pCont->GetType() == GLBLDOC_SECTION && !pCont->GetSection()->IsConnectFlag())
+ m_xTreeView->set_font_color(i, COL_LIGHTRED);
+
+ if (sEntry == sEntryName)
+ nSelEntry = i;
+ }
+ m_xTreeView->thaw();
+ if (nSelEntry != -1)
+ m_xTreeView->select(nSelEntry);
+ else if (nSelPos != -1 && o3tl::make_unsigned(nSelPos) < nCount)
+ m_xTreeView->select(nSelPos);
+ else if (nCount)
+ m_xTreeView->select(0);
+ Select();
+ }
+}
+
+void SwGlobalTree::InsertRegion( const SwGlblDocContent* pCont, const OUString* pFileName )
+{
+ Sequence< OUString > aFileNames;
+ if ( !pFileName )
+ {
+ SwNavigationPI* pNavi = GetParentWindow();
+ m_pDocInserter.reset(new ::sfx2::DocumentInserter(pNavi->GetFrameWeld(), "swriter", sfx2::DocumentInserter::Mode::InsertMulti));
+ m_pDocInserter->StartExecuteModal( LINK( this, SwGlobalTree, DialogClosedHdl ) );
+ }
+ else if ( !pFileName->isEmpty() )
+ {
+ aFileNames.realloc(1);
+ INetURLObject aFileName;
+ aFileName.SetSmartURL( *pFileName );
+ // tdf#127978 - don't URL encode filename for navigator's tooltip
+ aFileNames.getArray()[0]
+ = aFileName.GetMainURL(INetURLObject::DecodeMechanism::Unambiguous);
+ InsertRegion( pCont, aFileNames );
+ }
+}
+
+void SwGlobalTree::EditContent(const SwGlblDocContent* pCont )
+{
+ sal_uInt16 nSlot = 0;
+ switch( pCont->GetType() )
+ {
+ case GLBLDOC_UNKNOWN:
+ m_pActiveShell->GetView().GetEditWin().GrabFocus();
+ break;
+ case GLBLDOC_TOXBASE:
+ {
+ const SwTOXBase* pBase = pCont->GetTOX();
+ if(pBase)
+ nSlot = FN_INSERT_MULTI_TOX;
+ }
+ break;
+ case GLBLDOC_SECTION:
+ {
+ OpenDoc(pCont);
+
+ nSlot = 0;
+ pCont = nullptr;
+ }
+ break;
+ }
+ if(pCont)
+ GotoContent(pCont);
+ if(nSlot)
+ {
+ m_pActiveShell->GetView().GetViewFrame().GetDispatcher()->Execute(nSlot);
+ if(Update( false ))
+ Display();
+ }
+}
+
+void SwGlobalTree::ExecuteContextMenuAction(std::u16string_view rSelectedPopupEntry)
+{
+ bool bUpdateHard = false;
+
+ int nEntry = m_xTreeView->get_selected_index();
+ SwGlblDocContent* pCont = nEntry != -1 ? weld::fromId<SwGlblDocContent*>(m_xTreeView->get_id(nEntry)) : nullptr;
+ // If a RequestHelp is called during the dialogue,
+ // then the content gets lost. Because of that a copy
+ // is created in which only the DocPos is set correctly.
+ std::optional<SwGlblDocContent> oContCopy;
+ if(pCont)
+ oContCopy.emplace(pCont->GetDocPos());
+ SfxDispatcher& rDispatch = *m_pActiveShell->GetView().GetViewFrame().GetDispatcher();
+ sal_uInt16 nSlot = 0;
+ if (rSelectedPopupEntry == u"updatesel")
+ {
+ // Two passes: first update the areas, then the directories.
+ m_xTreeView->selected_foreach([this](weld::TreeIter& rSelEntry){
+ SwGlblDocContent* pContent = weld::fromId<SwGlblDocContent*>(m_xTreeView->get_id(rSelEntry));
+ if (GLBLDOC_SECTION == pContent->GetType() &&
+ pContent->GetSection()->IsConnected())
+ {
+ const_cast<SwSection*>(pContent->GetSection())->UpdateNow();
+ }
+ return false;
+ });
+ m_xTreeView->selected_foreach([this](weld::TreeIter& rSelEntry){
+ SwGlblDocContent* pContent = weld::fromId<SwGlblDocContent*>(m_xTreeView->get_id(rSelEntry));
+ if (GLBLDOC_TOXBASE == pContent->GetType())
+ m_pActiveShell->UpdateTableOf(*pContent->GetTOX());
+ return false;
+ });
+
+ bUpdateHard = true;
+ }
+ else if (rSelectedPopupEntry == u"updateindex")
+ {
+ nSlot = FN_UPDATE_TOX;
+ bUpdateHard = true;
+ }
+ else if (rSelectedPopupEntry == u"updatelinks" || rSelectedPopupEntry == u"updateall")
+ {
+ m_pActiveShell->GetLinkManager().UpdateAllLinks(true, false, nullptr);
+ if (rSelectedPopupEntry == u"updateall")
+ nSlot = FN_UPDATE_TOX;
+ pCont = nullptr;
+ bUpdateHard = true;
+ }
+ else if (rSelectedPopupEntry == u"editcontent")
+ {
+ OSL_ENSURE(pCont, "edit without entry ? " );
+ if (pCont)
+ {
+ EditContent(pCont);
+ }
+ }
+ else if (rSelectedPopupEntry == u"editlink")
+ {
+ OSL_ENSURE(pCont, "edit without entry ? " );
+ if (pCont)
+ {
+ SfxStringItem aName(FN_EDIT_REGION,
+ pCont->GetSection()->GetSectionName());
+ rDispatch.ExecuteList(FN_EDIT_REGION, SfxCallMode::ASYNCHRON,
+ { &aName });
+ }
+ }
+ else if (rSelectedPopupEntry == u"deleteentry")
+ {
+ // If several entries selected, then after each delete the array
+ // must be refilled. So you do not have to remember anything,
+ // deleting begins at the end.
+ std::vector<int> aRows = m_xTreeView->get_selected_rows();
+ std::sort(aRows.begin(), aRows.end());
+
+ std::unique_ptr<SwGlblDocContents> pTempContents;
+ m_pActiveShell->StartAction();
+ for (auto iter = aRows.rbegin(); iter != aRows.rend(); ++iter)
+ {
+ m_pActiveShell->DeleteGlobalDocContent(
+ pTempContents ? *pTempContents : *m_pSwGlblDocContents,
+ *iter);
+ pTempContents.reset(new SwGlblDocContents);
+ m_pActiveShell->GetGlobalDocContent(*pTempContents);
+ }
+ pTempContents.reset();
+ m_pActiveShell->EndAction();
+ pCont = nullptr;
+ }
+ else if (rSelectedPopupEntry == u"insertindex")
+ {
+ if(oContCopy)
+ {
+ SfxItemSetFixed<
+ RES_FRM_SIZE, RES_FRM_SIZE,
+ RES_LR_SPACE, RES_LR_SPACE,
+ RES_BACKGROUND, RES_BACKGROUND,
+ RES_COL, RES_COL,
+ SID_ATTR_PAGE_SIZE, SID_ATTR_PAGE_SIZE,
+ FN_PARAM_TOX_TYPE, FN_PARAM_TOX_TYPE>
+ aSet( m_pActiveShell->GetView().GetPool() );
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractMultiTOXTabDialog> pDlg(pFact->CreateMultiTOXTabDialog(
+ m_xTreeView.get(), aSet,
+ *m_pActiveShell,
+ nullptr,
+ true));
+ if(RET_OK == pDlg->Execute())
+ {
+ SwTOXDescription& rDesc = pDlg->GetTOXDescription(
+ pDlg->GetCurrentTOXType());
+ SwTOXMgr aMgr(m_pActiveShell);
+ SwTOXBase* pToInsert = nullptr;
+ if(aMgr.UpdateOrInsertTOX(rDesc, &pToInsert, pDlg->GetOutputItemSet()))
+ m_pActiveShell->InsertGlobalDocContent( *oContCopy, *pToInsert );
+ }
+ pCont = nullptr;
+ }
+ }
+ else if (rSelectedPopupEntry == u"insertfile")
+ {
+ m_oDocContent = std::move(oContCopy);
+ InsertRegion( &*m_oDocContent );
+ pCont = nullptr;
+ }
+ else if (rSelectedPopupEntry == u"insertnewfile")
+ {
+ SfxViewFrame& rGlobFrame = m_pActiveShell->GetView().GetViewFrame();
+ SwGlobalFrameListener_Impl aFrameListener(rGlobFrame);
+
+ // Creating a new doc
+ SfxStringItem aFactory(SID_NEWDOCDIRECT,
+ SwDocShell::Factory().GetFilterContainer()->GetName());
+
+ SfxPoolItemHolder aResult(
+ rDispatch.ExecuteList(SID_NEWDOCDIRECT,
+ SfxCallMode::SYNCHRON, { &aFactory }));
+ const SfxFrameItem* pItem(static_cast<const SfxFrameItem*>(aResult.getItem()));
+
+ // save at
+ SfxFrame* pFrame = pItem ? pItem->GetFrame() : nullptr;
+ SfxViewFrame* pViewFrame = pFrame ? pFrame->GetCurrentViewFrame() : nullptr;
+ if (pViewFrame)
+ {
+ aResult = pViewFrame->GetDispatcher()->Execute(
+ SID_SAVEASDOC, SfxCallMode::SYNCHRON );
+ const SfxBoolItem* pBool(static_cast<const SfxBoolItem*>(aResult.getItem()));
+ SfxObjectShell& rObj = *pViewFrame->GetObjectShell();
+ const SfxMedium* pMedium = rObj.GetMedium();
+ OUString sNewFile(pMedium->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::ToIUri));
+ // Insert the area with the Doc-Name
+ // Bring the own Doc in the foreground
+ if(aFrameListener.IsValid() && !sNewFile.isEmpty())
+ {
+ rGlobFrame.ToTop();
+ // Due to the update the entries are invalid
+ if (nEntry != -1)
+ {
+ Update( false );
+ Display();
+ m_xTreeView->select(nEntry);
+ Select();
+ nEntry = m_xTreeView->get_selected_index();
+ pCont = nEntry != -1 ? weld::fromId<SwGlblDocContent*>(m_xTreeView->get_id(nEntry)) : nullptr;
+ }
+ else
+ {
+ nEntry = -1;
+ pCont = nullptr;
+ }
+ if(pBool->GetValue())
+ {
+ InsertRegion(pCont, &sNewFile);
+ pViewFrame->ToTop();
+ }
+ else
+ pViewFrame->GetDispatcher()->Execute(SID_CLOSEWIN, SfxCallMode::SYNCHRON);
+ }
+ else
+ {
+ pViewFrame->ToTop();
+ return;
+ }
+ }
+ }
+ else if (rSelectedPopupEntry == u"inserttext")
+ {
+ if (pCont)
+ m_pActiveShell->InsertGlobalDocContent(*pCont);
+ else
+ {
+ m_pActiveShell->SplitNode(); // Empty document
+ m_pActiveShell->Up( false );
+ }
+ m_pActiveShell->GetView().GetEditWin().GrabFocus();
+ }
+ else if (rSelectedPopupEntry == u"update")
+ pCont = nullptr;
+
+ if (pCont)
+ GotoContent(pCont);
+ if (nSlot)
+ rDispatch.Execute(nSlot);
+ if (Update(bUpdateHard))
+ Display();
+}
+
+IMPL_LINK_NOARG(SwGlobalTree, Timeout, Timer *, void)
+{
+ SwView* pView = GetParentWindow()->GetCreateView();
+ if (pView && pView->GetEditWin().HasFocus())
+ {
+ if (Update(false))
+ Display();
+ UpdateTracking();
+ }
+}
+
+// track GlobalDocContentType at the cursor position in the document
+void SwGlobalTree::UpdateTracking()
+{
+ if (!m_pActiveShell)
+ return;
+
+ m_xTreeView->unselect_all();
+
+ const SwSection* pActiveShellCurrSection = m_pActiveShell->GetCurrSection();
+ if (pActiveShellCurrSection)
+ {
+ const SwSection* pSection = pActiveShellCurrSection;
+ while (SwSection* pParent = pSection->GetParent())
+ pSection = pParent;
+ for (const std::unique_ptr<SwGlblDocContent>& rGlblDocContent : *m_pSwGlblDocContents)
+ {
+ if (rGlblDocContent->GetType() == GlobalDocContentType::GLBLDOC_UNKNOWN)
+ continue;
+ if ((pSection->GetType() == SectionType::ToxContent
+ && rGlblDocContent->GetTOX() == pSection->GetTOXBase())
+ || (pSection->GetType() != SectionType::ToxContent
+ && rGlblDocContent->GetSection() == pSection))
+ {
+ const OUString& rId(weld::toId(rGlblDocContent.get()));
+ m_xTreeView->select(m_xTreeView->find_id(rId));
+ break;
+ }
+ }
+ }
+ else
+ {
+ const SwCursor* pCursor = m_pActiveShell->GetCursor();
+ const SwNode& rNode = pCursor->GetPoint()->GetNode();
+ if (rNode.IsTextNode())
+ {
+ // only the first text node in each series of text nodes is stored in the
+ // SwGlblDocContents array
+ SwNodeIndex aIdx(rNode);
+ do
+ {
+ --aIdx;
+ } while (aIdx.GetNode().IsTextNode());
+ ++aIdx;
+ SwNodeOffset aTextNodeIndex(aIdx.GetNode().GetIndex());
+ for (const std::unique_ptr<SwGlblDocContent>& rGlblDocContent : *m_pSwGlblDocContents)
+ {
+ if (rGlblDocContent->GetType() == GlobalDocContentType::GLBLDOC_UNKNOWN
+ && rGlblDocContent->GetDocPos() == aTextNodeIndex)
+ {
+ const OUString& rId(weld::toId(rGlblDocContent.get()));
+ m_xTreeView->select(m_xTreeView->find_id(rId));
+ }
+ }
+ }
+ }
+
+ Select();
+}
+
+void SwGlobalTree::GotoContent(const SwGlblDocContent* pCont)
+{
+ m_pActiveShell->EnterStdMode();
+
+ switch( pCont->GetType() )
+ {
+ case GLBLDOC_UNKNOWN:
+ m_pActiveShell->GotoGlobalDocContent(*pCont);
+ break;
+ case GLBLDOC_TOXBASE:
+ {
+ const OUString sName = pCont->GetTOX()->GetTOXName();
+ if (!m_pActiveShell->GotoNextTOXBase(&sName))
+ m_pActiveShell->GotoPrevTOXBase(&sName);
+ }
+ break;
+ case GLBLDOC_SECTION:
+ break;
+ }
+
+}
+
+void SwGlobalTree::ShowTree()
+{
+ m_aUpdateTimer.Start();
+ m_xTreeView->show();
+ UpdateTracking();
+}
+
+void SwGlobalTree::HideTree()
+{
+ m_aUpdateTimer.Stop();
+ m_xTreeView->hide();
+}
+
+void SwGlobalTree::ExecCommand(std::u16string_view rCmd)
+{
+ int nEntry = m_xTreeView->get_selected_index();
+ if (nEntry == -1)
+ return;
+ if (rCmd == u"edit")
+ {
+ const SwGlblDocContent* pCont = weld::fromId<const SwGlblDocContent*>(
+ m_xTreeView->get_id(nEntry));
+ EditContent(pCont);
+ }
+ else
+ {
+ if (m_xTreeView->count_selected_rows() == 1)
+ {
+ bool bMove = false;
+ int nSource = nEntry;
+ int nDest = nSource;
+ if (rCmd == u"movedown")
+ {
+ int nEntryCount = m_xTreeView->n_children();
+ bMove = nEntryCount > nSource + 1;
+ nDest+= 2;
+ }
+ else if (rCmd == u"moveup")
+ {
+ bMove = 0 != nSource;
+ nDest--;
+ }
+ if( bMove && m_pActiveShell->MoveGlobalDocContent(
+ *m_pSwGlblDocContents, nSource, nSource + 1, nDest ) &&
+ Update( false ))
+ Display();
+ }
+ }
+}
+
+bool SwGlobalTree::Update(bool bHard)
+{
+ SwView* pActView = GetParentWindow()->GetCreateView();
+ bool bRet = false;
+ if (pActView && pActView->GetWrtShellPtr())
+ {
+ const SwWrtShell* pOldShell = m_pActiveShell;
+ m_pActiveShell = pActView->GetWrtShellPtr();
+ if(m_pActiveShell != pOldShell)
+ {
+ m_pSwGlblDocContents.reset();
+ if (!IsListening(*m_pActiveShell->GetView().GetDocShell()))
+ StartListening(*m_pActiveShell->GetView().GetDocShell());
+ }
+ if(!m_pSwGlblDocContents)
+ {
+ m_pSwGlblDocContents.reset(new SwGlblDocContents);
+ bRet = true;
+ m_pActiveShell->GetGlobalDocContent(*m_pSwGlblDocContents);
+ }
+ else
+ {
+ bool bCopy = false;
+ SwGlblDocContents aTempContents;
+ m_pActiveShell->GetGlobalDocContent(aTempContents);
+ size_t nChildren = m_xTreeView->n_children();
+ if (aTempContents.size() != m_pSwGlblDocContents->size() ||
+ aTempContents.size() != nChildren)
+ {
+ bRet = true;
+ bCopy = true;
+ }
+ else
+ {
+ for(size_t i = 0; i < aTempContents.size() && !bCopy; i++)
+ {
+ SwGlblDocContent* pLeft = aTempContents[i].get();
+ SwGlblDocContent* pRight = (*m_pSwGlblDocContents)[i].get();
+ GlobalDocContentType eType = pLeft->GetType();
+ OUString sTemp = m_xTreeView->get_text(i);
+ if (
+ eType != pRight->GetType() ||
+ (
+ eType == GLBLDOC_SECTION &&
+ pLeft->GetSection()->GetSectionName() != sTemp
+ ) ||
+ (
+ eType == GLBLDOC_TOXBASE &&
+ pLeft->GetTOX()->GetTitle() != sTemp
+ )
+ )
+ {
+ bCopy = true;
+ }
+ }
+ }
+ if (bCopy || bHard)
+ {
+ *m_pSwGlblDocContents = std::move( aTempContents );
+ bRet = true;
+ }
+ }
+ }
+ else
+ {
+ m_xTreeView->clear();
+ if(m_pSwGlblDocContents)
+ m_pSwGlblDocContents->clear();
+ }
+ // FIXME: Implement a test for changes!
+ return bRet;
+}
+
+void SwGlobalTree::OpenDoc(const SwGlblDocContent* pCont)
+{
+ const OUString sFileName(pCont->GetSection()->GetLinkFileName().getToken(0,
+ sfx2::cTokenSeparator));
+ bool bFound = false;
+ const SfxObjectShell* pCurr = SfxObjectShell::GetFirst();
+ while( !bFound && pCurr )
+ {
+ if(pCurr->GetMedium() &&
+ pCurr->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::ToIUri) == sFileName)
+ {
+ bFound = true;
+ SwGlobalTree::SetShowShell(pCurr);
+ Application::PostUserEvent(LINK(this, SwGlobalTree, ShowFrameHdl));
+ pCurr = nullptr;
+ }
+ else
+ pCurr = SfxObjectShell::GetNext(*pCurr);
+ }
+ if(!bFound)
+ {
+ SfxStringItem aURL(SID_FILE_NAME, sFileName);
+ SfxBoolItem aReadOnly(SID_DOC_READONLY, false);
+ SfxStringItem aTargetFrameName( SID_TARGETNAME, "_blank" );
+ SfxStringItem aReferer(SID_REFERER, m_pActiveShell->GetView().GetDocShell()->GetTitle());
+ m_pActiveShell->GetView().GetViewFrame().GetDispatcher()->
+ ExecuteList(SID_OPENDOC, SfxCallMode::ASYNCHRON,
+ { &aURL, &aReadOnly, &aReferer, &aTargetFrameName });
+ }
+}
+
+IMPL_LINK_NOARG( SwGlobalTree, DoubleClickHdl, weld::TreeView&, bool)
+{
+ int nEntry = m_xTreeView->get_cursor_index();
+ SwGlblDocContent* pCont = weld::fromId<SwGlblDocContent*>(m_xTreeView->get_id(nEntry));
+ if (pCont->GetType() == GLBLDOC_SECTION)
+ OpenDoc(pCont);
+ else
+ {
+ GotoContent(pCont);
+ m_pActiveShell->GetView().GetEditWin().GrabFocus();
+ }
+ return false;
+}
+
+SwNavigationPI* SwGlobalTree::GetParentWindow()
+{
+ return m_pDialog;
+}
+
+IMPL_STATIC_LINK_NOARG(SwGlobalTree, ShowFrameHdl, void*, void)
+{
+ SfxViewFrame* pFirst = s_pShowShell ? SfxViewFrame::GetFirst(s_pShowShell) : nullptr;
+ if (pFirst)
+ pFirst->ToTop();
+ SwGlobalTree::SetShowShell(nullptr);
+}
+
+void SwGlobalTree::InsertRegion( const SwGlblDocContent* _pContent, const Sequence< OUString >& _rFiles )
+{
+ sal_Int32 nFiles = _rFiles.getLength();
+ if (!nFiles)
+ return;
+
+ size_t nEntryCount = m_xTreeView->n_children();
+
+ bool bMove = _pContent == nullptr;
+ const OUString* pFileNames = _rFiles.getConstArray();
+ SwWrtShell& rSh = GetParentWindow()->GetCreateView()->GetWrtShell();
+ rSh.StartAction();
+ // after insertion of the first new content the 'pCont' parameter becomes invalid
+ // find the index of the 'anchor' content to always use a current anchor content
+ size_t nAnchorContent = m_pSwGlblDocContents->size() - 1;
+ if (!bMove)
+ {
+ for (size_t nContent = 0; nContent < m_pSwGlblDocContents->size();
+ ++nContent)
+ {
+ if( *_pContent == *(*m_pSwGlblDocContents)[ nContent ] )
+ {
+ nAnchorContent = nContent;
+ break;
+ }
+ }
+ }
+ SwGlblDocContents aTempContents;
+ for ( sal_Int32 nFile = 0; nFile < nFiles; ++nFile )
+ {
+ //update the global document content after each inserted document
+ rSh.GetGlobalDocContent(aTempContents);
+ SwGlblDocContent* pAnchorContent = nullptr;
+ OSL_ENSURE(aTempContents.size() > (nAnchorContent + nFile), "invalid anchor content -> last insertion failed");
+ if ( aTempContents.size() > (nAnchorContent + nFile) )
+ pAnchorContent = aTempContents[nAnchorContent + nFile].get();
+ else
+ pAnchorContent = aTempContents.back().get();
+ OUString sFileName(pFileNames[nFile]);
+ INetURLObject aFileUrl;
+ aFileUrl.SetSmartURL( sFileName );
+ OUString sSectionName(aFileUrl.GetLastName(
+ INetURLObject::DecodeMechanism::Unambiguous).getToken(0, sfx2::cTokenSeparator));
+ sal_uInt16 nSectCount = rSh.GetSectionFormatCount();
+ OUString sTempSectionName(sSectionName);
+ sal_uInt16 nAddNumber = 0;
+ sal_uInt16 nCount = 0;
+ // if applicable: add index if the range name is already in use.
+ while ( nCount < nSectCount )
+ {
+ const SwSectionFormat& rFormat = rSh.GetSectionFormat(nCount);
+ if ((rFormat.GetSection()->GetSectionName() == sTempSectionName)
+ && rFormat.IsInNodesArr())
+ {
+ nCount = 0;
+ nAddNumber++;
+ sTempSectionName = sSectionName + ":" + OUString::number( nAddNumber );
+ }
+ else
+ nCount++;
+ }
+
+ if ( nAddNumber )
+ sSectionName = sTempSectionName;
+
+ SwSectionData aSectionData(SectionType::Content, sSectionName);
+ aSectionData.SetProtectFlag(true);
+ aSectionData.SetHidden(false);
+
+ aSectionData.SetLinkFileName(sFileName);
+ aSectionData.SetType(SectionType::FileLink);
+ aSectionData.SetLinkFilePassword( OUString() );
+
+ rSh.InsertGlobalDocContent( *pAnchorContent, aSectionData );
+ }
+ if (bMove)
+ {
+ Update( false );
+ rSh.MoveGlobalDocContent(
+ *m_pSwGlblDocContents, nEntryCount, nEntryCount + nFiles, nEntryCount - nFiles );
+ }
+ rSh.EndAction();
+ Update( false );
+ Display();
+
+}
+
+IMPL_LINK( SwGlobalTree, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg, void )
+{
+ if ( ERRCODE_NONE != _pFileDlg->GetError() )
+ return;
+
+ SfxMediumList aMedList(m_pDocInserter->CreateMediumList());
+ if ( aMedList.empty() )
+ return;
+
+ Sequence< OUString >aFileNames( aMedList.size() );
+ OUString* pFileNames = aFileNames.getArray();
+ sal_Int32 nPos = 0;
+ for (const std::unique_ptr<SfxMedium>& pMed : aMedList)
+ {
+ // tdf#127978 - don't URL encode filename for navigator's tooltip
+ OUString sFileName
+ = pMed->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::Unambiguous)
+ + OUStringChar(sfx2::cTokenSeparator)
+ + pMed->GetFilter()->GetFilterName()
+ + OUStringChar(sfx2::cTokenSeparator);
+ pFileNames[nPos++] = sFileName;
+ }
+ InsertRegion( &*m_oDocContent, aFileNames );
+ m_oDocContent.reset();
+}
+
+void SwGlobalTree::Notify(SfxBroadcaster& rBC, SfxHint const& rHint)
+{
+ SfxViewEventHint const*const pVEHint(dynamic_cast<SfxViewEventHint const*>(&rHint));
+ SwXTextView* pDyingShell = nullptr;
+ if (m_pActiveShell && pVEHint && pVEHint->GetEventName() == "OnViewClosed")
+ pDyingShell = dynamic_cast<SwXTextView*>(pVEHint->GetController().get());
+ if (pDyingShell && pDyingShell->GetView() == &m_pActiveShell->GetView())
+ {
+ EndListening(*m_pActiveShell->GetView().GetDocShell());
+ m_pActiveShell = nullptr;
+ }
+ else
+ {
+ SfxListener::Notify(rBC, rHint);
+ if (rHint.GetId() == SfxHintId::SwNavigatorUpdateTracking)
+ UpdateTracking();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/gloslst.cxx b/sw/source/uibase/utlui/gloslst.cxx
new file mode 100644
index 0000000000..9878d0aa67
--- /dev/null
+++ b/sw/source/uibase/utlui/gloslst.cxx
@@ -0,0 +1,445 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/weld.hxx>
+#include <svl/fstathelper.hxx>
+#include <unotools/pathoptions.hxx>
+#include <unotools/transliterationwrapper.hxx>
+#include <osl/diagnose.h>
+#include <o3tl/string_view.hxx>
+#include <swtypes.hxx>
+#include <swmodule.hxx>
+#include <shellio.hxx>
+#include <initui.hxx>
+#include <glosdoc.hxx>
+#include <gloslst.hxx>
+#include <swunohelper.hxx>
+#include <view.hxx>
+
+#include <vector>
+
+#define STRING_DELIM char(0x0A)
+#define GLOS_TIMEOUT 30000 // update every 30 seconds
+#define FIND_MAX_GLOS 20
+
+namespace {
+
+struct TripleString
+{
+ OUString sGroup;
+ OUString sBlock;
+ OUString sShort;
+};
+
+class SwGlossDecideDlg : public weld::GenericDialogController
+{
+ std::unique_ptr<weld::Button> m_xOk;
+ std::unique_ptr<weld::TreeView> m_xListLB;
+
+ DECL_LINK(DoubleClickHdl, weld::TreeView&, bool);
+ DECL_LINK(SelectHdl, weld::TreeView&, void);
+
+public:
+ explicit SwGlossDecideDlg(weld::Window* pParent);
+
+ weld::TreeView& GetTreeView() {return *m_xListLB;}
+};
+
+}
+
+SwGlossDecideDlg::SwGlossDecideDlg(weld::Window* pParent)
+ : GenericDialogController(pParent, "modules/swriter/ui/selectautotextdialog.ui", "SelectAutoTextDialog")
+ , m_xOk(m_xBuilder->weld_button("ok"))
+ , m_xListLB(m_xBuilder->weld_tree_view("treeview"))
+{
+ m_xListLB->set_size_request(m_xListLB->get_approximate_digit_width() * 32,
+ m_xListLB->get_height_rows(8));
+ m_xListLB->connect_row_activated(LINK(this, SwGlossDecideDlg, DoubleClickHdl));
+ m_xListLB->connect_changed(LINK(this, SwGlossDecideDlg, SelectHdl));
+}
+
+IMPL_LINK_NOARG(SwGlossDecideDlg, DoubleClickHdl, weld::TreeView&, bool)
+{
+ m_xDialog->response(RET_OK);
+ return true;
+}
+
+IMPL_LINK_NOARG(SwGlossDecideDlg, SelectHdl, weld::TreeView&, void)
+{
+ m_xOk->set_sensitive(m_xListLB->get_selected_index() != -1);
+}
+
+SwGlossaryList::SwGlossaryList() :
+ AutoTimer("SwGlossaryList"), m_bFilled(false)
+{
+ SvtPathOptions aPathOpt;
+ m_sPath = aPathOpt.GetAutoTextPath();
+ SetTimeout(GLOS_TIMEOUT);
+}
+
+SwGlossaryList::~SwGlossaryList()
+{
+ ClearGroups();
+}
+
+// If the GroupName is already known, then only rShortName
+// will be filled. Otherwise also rGroupName will be set and
+// on demand asked for the right group.
+
+bool SwGlossaryList::GetShortName(std::u16string_view rLongName,
+ OUString& rShortName, OUString& rGroupName )
+{
+ if(!m_bFilled)
+ Update();
+
+ std::vector<TripleString> aTripleStrings;
+
+ size_t nCount = m_aGroupArr.size();
+ for(size_t i = 0; i < nCount; i++ )
+ {
+ AutoTextGroup* pGroup = m_aGroupArr[i].get();
+ if(!rGroupName.isEmpty() && rGroupName != pGroup->sName)
+ continue;
+
+ sal_Int32 nPosLong = 0;
+ for(sal_uInt16 j = 0; j < pGroup->nCount; j++)
+ {
+ const OUString sLong = pGroup->sLongNames.getToken(0, STRING_DELIM, nPosLong);
+ if(rLongName != sLong)
+ continue;
+
+ TripleString aTriple;
+ aTriple.sGroup = pGroup->sName;
+ aTriple.sBlock = sLong;
+ aTriple.sShort = pGroup->sShortNames.getToken(j, STRING_DELIM);
+ aTripleStrings.push_back(aTriple);
+ }
+ }
+
+ bool bRet = false;
+ nCount = aTripleStrings.size();
+ if(1 == nCount)
+ {
+ const TripleString& rTriple(aTripleStrings.front());
+ rShortName = rTriple.sShort;
+ rGroupName = rTriple.sGroup;
+ bRet = true;
+ }
+ else if(1 < nCount)
+ {
+ SwView *pView = ::GetActiveView();
+ if (!pView)
+ return bRet;
+ SwGlossDecideDlg aDlg(pView->GetFrameWeld());
+ OUString sTitle = aDlg.get_title() + " " + aTripleStrings.front().sBlock;
+ aDlg.set_title(sTitle);
+
+ weld::TreeView& rLB = aDlg.GetTreeView();
+ for (const auto& rTriple : aTripleStrings)
+ rLB.append_text(rTriple.sGroup.getToken(0, GLOS_DELIM));
+
+ rLB.select(0);
+ if (aDlg.run() == RET_OK && rLB.get_selected_index() != -1)
+ {
+ const TripleString& rTriple(aTripleStrings[rLB.get_selected_index()]);
+ rShortName = rTriple.sShort;
+ rGroupName = rTriple.sGroup;
+ bRet = true;
+ }
+ else
+ bRet = false;
+ }
+ return bRet;
+}
+
+size_t SwGlossaryList::GetGroupCount()
+{
+ if(!m_bFilled)
+ Update();
+ return m_aGroupArr.size();
+}
+
+OUString SwGlossaryList::GetGroupName(size_t nPos)
+{
+ OSL_ENSURE(m_aGroupArr.size() > nPos, "group not available");
+ if(nPos < m_aGroupArr.size())
+ {
+ AutoTextGroup* pGroup = m_aGroupArr[nPos].get();
+ OUString sRet = pGroup->sName;
+ return sRet;
+ }
+ return OUString();
+}
+
+OUString SwGlossaryList::GetGroupTitle(size_t nPos)
+{
+ OSL_ENSURE(m_aGroupArr.size() > nPos, "group not available");
+ if(nPos < m_aGroupArr.size())
+ {
+ AutoTextGroup* pGroup = m_aGroupArr[nPos].get();
+ return pGroup->sTitle;
+ }
+ return OUString();
+}
+
+sal_uInt16 SwGlossaryList::GetBlockCount(size_t nGroup)
+{
+ OSL_ENSURE(m_aGroupArr.size() > nGroup, "group not available");
+ if(nGroup < m_aGroupArr.size())
+ {
+ AutoTextGroup* pGroup = m_aGroupArr[nGroup].get();
+ return pGroup->nCount;
+ }
+ return 0;
+}
+
+OUString SwGlossaryList::GetBlockLongName(size_t nGroup, sal_uInt16 nBlock)
+{
+ OSL_ENSURE(m_aGroupArr.size() > nGroup, "group not available");
+ if(nGroup < m_aGroupArr.size())
+ {
+ AutoTextGroup* pGroup = m_aGroupArr[nGroup].get();
+ return pGroup->sLongNames.getToken(nBlock, STRING_DELIM);
+ }
+ return OUString();
+}
+
+OUString SwGlossaryList::GetBlockShortName(size_t nGroup, sal_uInt16 nBlock)
+{
+ OSL_ENSURE(m_aGroupArr.size() > nGroup, "group not available");
+ if(nGroup < m_aGroupArr.size())
+ {
+ AutoTextGroup* pGroup = m_aGroupArr[nGroup].get();
+ return pGroup->sShortNames.getToken(nBlock, STRING_DELIM);
+ }
+ return OUString();
+}
+
+void SwGlossaryList::Update()
+{
+ if(!IsActive())
+ Start();
+
+ SvtPathOptions aPathOpt;
+ const OUString& sTemp( aPathOpt.GetAutoTextPath() );
+ if(sTemp != m_sPath)
+ {
+ m_sPath = sTemp;
+ m_bFilled = false;
+ ClearGroups();
+ }
+ SwGlossaries* pGlossaries = ::GetGlossaries();
+ const std::vector<OUString> & rPathArr = pGlossaries->GetPathArray();
+ const OUString sExt( SwGlossaries::GetExtension() );
+ if(!m_bFilled)
+ {
+ const size_t nGroupCount = pGlossaries->GetGroupCnt();
+ for(size_t i = 0; i < nGroupCount; ++i)
+ {
+ OUString sGrpName = pGlossaries->GetGroupName(i);
+ const size_t nPath = static_cast<size_t>(
+ o3tl::toInt32(o3tl::getToken(sGrpName, 1, GLOS_DELIM)));
+ if( nPath < rPathArr.size() )
+ {
+ std::unique_ptr<AutoTextGroup> pGroup(new AutoTextGroup);
+ pGroup->sName = sGrpName;
+
+ FillGroup(pGroup.get(), pGlossaries);
+ OUString sName = rPathArr[nPath] + "/" +
+ o3tl::getToken(pGroup->sName, 0, GLOS_DELIM) + sExt;
+ FStatHelper::GetModifiedDateTimeOfFile( sName,
+ &pGroup->aDateModified,
+ &pGroup->aDateModified );
+
+ m_aGroupArr.insert( m_aGroupArr.begin(), std::move(pGroup) );
+ }
+ }
+ m_bFilled = true;
+ }
+ else
+ {
+ for( size_t nPath = 0; nPath < rPathArr.size(); nPath++ )
+ {
+ std::vector<OUString> aFoundGroupNames;
+ std::vector<OUString> aFiles;
+ std::vector<DateTime> aDateTimeArr;
+
+ SWUnoHelper::UCB_GetFileListOfFolder( rPathArr[nPath], aFiles,
+ &sExt, &aDateTimeArr );
+ for( size_t nFiles = 0; nFiles < aFiles.size(); ++nFiles )
+ {
+ const OUString aTitle = aFiles[ nFiles ];
+ ::DateTime& rDT = aDateTimeArr[ nFiles ];
+
+ OUString sName( aTitle.copy( 0, aTitle.getLength() - sExt.getLength() ));
+
+ aFoundGroupNames.push_back(sName);
+ sName += OUStringChar(GLOS_DELIM) + OUString::number( o3tl::narrowing<sal_uInt16>(nPath) );
+ AutoTextGroup* pFound = FindGroup( sName );
+ if( !pFound )
+ {
+ pFound = new AutoTextGroup;
+ pFound->sName = sName;
+ FillGroup( pFound, pGlossaries );
+ pFound->aDateModified = rDT;
+
+ m_aGroupArr.push_back(std::unique_ptr<AutoTextGroup>(pFound));
+ }
+ else if( pFound->aDateModified != rDT )
+ {
+ FillGroup(pFound, pGlossaries);
+ pFound->aDateModified = rDT;
+ }
+ }
+
+ for( size_t i = m_aGroupArr.size(); i>0; )
+ {
+ --i;
+ // maybe remove deleted groups
+ AutoTextGroup* pGroup = m_aGroupArr[i].get();
+ const size_t nGroupPath = static_cast<size_t>(
+ o3tl::toInt32(o3tl::getToken(pGroup->sName, 1, GLOS_DELIM)));
+ // Only the groups will be checked which are registered
+ // for the current subpath.
+ if( nGroupPath == nPath )
+ {
+ std::u16string_view sCompareGroup = o3tl::getToken(pGroup->sName, 0, GLOS_DELIM);
+ bool bFound = std::any_of(aFoundGroupNames.begin(), aFoundGroupNames.end(),
+ [&sCompareGroup](const OUString& rGroupName) { return sCompareGroup == rGroupName; });
+
+ if(!bFound)
+ {
+ m_aGroupArr.erase(m_aGroupArr.begin() + i);
+ }
+ }
+ }
+ }
+ }
+}
+
+void SwGlossaryList::Invoke()
+{
+ // Only update automatically if a SwView has the focus.
+ if(::GetActiveView())
+ Update();
+}
+
+AutoTextGroup* SwGlossaryList::FindGroup(std::u16string_view rGroupName)
+{
+ for(const auto & pRet : m_aGroupArr)
+ {
+ if(pRet->sName == rGroupName)
+ return pRet.get();
+ }
+ return nullptr;
+}
+
+void SwGlossaryList::FillGroup(AutoTextGroup* pGroup, SwGlossaries* pGlossaries)
+{
+ std::unique_ptr<SwTextBlocks> pBlock = pGlossaries->GetGroupDoc(pGroup->sName);
+ pGroup->nCount = pBlock ? pBlock->GetCount() : 0;
+ pGroup->sLongNames.clear();
+ pGroup->sShortNames.clear();
+ if(pBlock)
+ pGroup->sTitle = pBlock->GetName();
+
+ for(sal_uInt16 j = 0; j < pGroup->nCount; j++)
+ {
+ pGroup->sLongNames += pBlock->GetLongName(j)
+ + OUStringChar(STRING_DELIM);
+ pGroup->sShortNames += pBlock->GetShortName(j)
+ + OUStringChar(STRING_DELIM);
+ }
+}
+
+// Give back all (not exceeding FIND_MAX_GLOS) found modules
+// with matching beginning.
+
+void SwGlossaryList::HasLongName(const std::vector<OUString>& rBeginCandidates,
+ std::vector<std::pair<OUString, sal_uInt16>>& rLongNames)
+{
+ if(!m_bFilled)
+ Update();
+ const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
+ // We store results for all candidate words in separate lists, so that later
+ // we can sort them according to the candidate position
+ std::vector<std::vector<OUString>> aResults(rBeginCandidates.size());
+
+ // We can't break after FIND_MAX_GLOS items found, since first items may have ended up in
+ // lower-priority lists, and those from higher-priority lists are yet to come. So process all.
+ for (const auto& pGroup : m_aGroupArr)
+ {
+ sal_Int32 nIdx{ 0 };
+ for(sal_uInt16 j = 0; j < pGroup->nCount; j++)
+ {
+ OUString sBlock = pGroup->sLongNames.getToken(0, STRING_DELIM, nIdx);
+ for (size_t i = 0; i < rBeginCandidates.size(); ++i)
+ {
+ const OUString& s = rBeginCandidates[i];
+ if (s.getLength() + 1 < sBlock.getLength()
+ && rSCmp.isEqual(sBlock.copy(0, s.getLength()), s))
+ {
+ aResults[i].push_back(sBlock);
+ }
+ }
+ }
+ }
+
+ std::vector<std::pair<OUString, sal_uInt16>> aAllResults;
+ // Sort and concatenate all result lists. See QuickHelpData::SortAndFilter
+ for (size_t i = 0; i < rBeginCandidates.size(); ++i)
+ {
+ std::sort(aResults[i].begin(), aResults[i].end(),
+ [origWord = rBeginCandidates[i]](const OUString& s1, const OUString& s2) {
+ int nRet = s1.compareToIgnoreAsciiCase(s2);
+ if (nRet == 0)
+ {
+ // fdo#61251 sort stuff that starts with the exact rOrigWord before
+ // another ignore-case candidate
+ int n1StartsWithOrig = s1.startsWith(origWord) ? 0 : 1;
+ int n2StartsWithOrig = s2.startsWith(origWord) ? 0 : 1;
+ return n1StartsWithOrig < n2StartsWithOrig;
+ }
+ return nRet < 0;
+ });
+ // All suggestions must be accompanied with length of the text they would replace
+ std::transform(aResults[i].begin(), aResults[i].end(), std::back_inserter(aAllResults),
+ [nLen = sal_uInt16(rBeginCandidates[i].getLength())](const OUString& s) {
+ return std::make_pair(s, nLen);
+ });
+ }
+
+ const auto& it = std::unique(
+ aAllResults.begin(), aAllResults.end(),
+ [](const std::pair<OUString, sal_uInt16>& s1, const std::pair<OUString, sal_uInt16>& s2) {
+ return s1.first.equalsIgnoreAsciiCase(s2.first);
+ });
+ if (const auto nCount = std::min<size_t>(std::distance(aAllResults.begin(), it), FIND_MAX_GLOS))
+ {
+ rLongNames.insert(rLongNames.end(), aAllResults.begin(), aAllResults.begin() + nCount);
+ }
+}
+
+void SwGlossaryList::ClearGroups()
+{
+ m_aGroupArr.clear();
+ m_bFilled = false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/gotodlg.cxx b/sw/source/uibase/utlui/gotodlg.cxx
new file mode 100644
index 0000000000..711717ee44
--- /dev/null
+++ b/sw/source/uibase/utlui/gotodlg.cxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <swmodule.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <gotodlg.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+
+using namespace com::sun::star;
+
+SwGotoPageDlg::SwGotoPageDlg(weld::Window* pParent, SfxBindings& rBindings)
+ : GenericDialogController(pParent, "modules/swriter/ui/gotopagedialog.ui", "GotoPageDialog")
+ , m_pCreateView(nullptr)
+ , m_rBindings(rBindings)
+ , mnMaxPageCnt(1)
+ , mxMtrPageCtrl(m_xBuilder->weld_spin_button("page"))
+ , mxPageNumberLbl(m_xBuilder->weld_label("page_count"))
+{
+ sal_uInt16 nTotalPage = GetPageInfo();
+
+ if (nTotalPage)
+ {
+ OUString sStr = mxPageNumberLbl->get_label();
+ mxPageNumberLbl->set_label(sStr.replaceFirst("$1", OUString::number(nTotalPage)));
+ mnMaxPageCnt = nTotalPage;
+ }
+ mxMtrPageCtrl->connect_changed(LINK(this, SwGotoPageDlg, PageModifiedHdl));
+ mxMtrPageCtrl->set_position(-1);
+ mxMtrPageCtrl->select_region(0, -1);
+}
+
+IMPL_LINK_NOARG(SwGotoPageDlg, PageModifiedHdl, weld::Entry&, void)
+{
+ if (mxMtrPageCtrl->get_text().isEmpty())
+ return;
+
+ int page_value = mxMtrPageCtrl->get_text().toInt32();
+
+ if (page_value <= 0)
+ mxMtrPageCtrl->set_value(1);
+ else if (page_value > mnMaxPageCnt)
+ mxMtrPageCtrl->set_value(mnMaxPageCnt);
+ else
+ mxMtrPageCtrl->set_value(page_value);
+
+ mxMtrPageCtrl->set_position(-1);
+}
+
+SwView* SwGotoPageDlg::GetCreateView() const
+{
+ if (!m_pCreateView)
+ {
+ SwView* pView = SwModule::GetFirstView();
+ while (pView)
+ {
+ if (&pView->GetViewFrame().GetBindings() == &m_rBindings)
+ {
+ const_cast<SwGotoPageDlg*>(this)->m_pCreateView = pView;
+ break;
+ }
+ pView = SwModule::GetNextView(pView);
+ }
+ }
+
+ return m_pCreateView;
+}
+
+// If the page can be set here, the maximum is set.
+
+sal_uInt16 SwGotoPageDlg::GetPageInfo()
+{
+ SwView* pView = GetCreateView();
+ SwWrtShell* pSh = pView ? &pView->GetWrtShell() : nullptr;
+ mxMtrPageCtrl->set_value(1);
+ if (pSh)
+ {
+ const sal_uInt16 nPageCnt = pSh->GetPageCnt();
+ sal_uInt16 nPhyPage, nVirPage;
+ pSh->GetPageNum(nPhyPage, nVirPage);
+ mxMtrPageCtrl->set_max(nPageCnt);
+ mxMtrPageCtrl->set_value(nPhyPage);
+ return nPageCnt;
+ }
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/initui.cxx b/sw/source/uibase/utlui/initui.cxx
new file mode 100644
index 0000000000..f24cded867
--- /dev/null
+++ b/sw/source/uibase/utlui/initui.cxx
@@ -0,0 +1,311 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <libxml/xmlwriter.h>
+
+#include <unotools/localedatawrapper.hxx>
+#include <viewsh.hxx>
+#include <initui.hxx>
+#include <edtwin.hxx>
+#include <shellres.hxx>
+#include <fldbas.hxx>
+#include <glosdoc.hxx>
+#include <gloslst.hxx>
+#include <comcore.hxx>
+#include <strings.hrc>
+#include <utlui.hrc>
+#include <authfld.hxx>
+#include <unotools/syslocale.hxx>
+
+// Global Pointer
+
+static std::unique_ptr<SwGlossaries> pGlossaries;
+
+// Provides all needed paths. Is initialized by UI.
+static SwGlossaryList* pGlossaryList = nullptr;
+
+namespace
+{
+OUString CurrGlosGroup;
+}
+
+const OUString& GetCurrGlosGroup()
+{
+ return CurrGlosGroup;
+}
+
+void SetCurrGlosGroup(const OUString& sStr)
+{
+ CurrGlosGroup = sStr;
+}
+
+namespace
+{
+
+std::vector<OUString>* pAuthFieldNameList = nullptr;
+std::vector<OUString>* pAuthFieldTypeList = nullptr;
+
+}
+
+// Finish UI
+
+void FinitUI()
+{
+ delete SwViewShell::GetShellRes();
+ SwViewShell::SetShellRes( nullptr );
+
+ SwEditWin::FinitStaticData();
+
+ pGlossaries.reset();
+
+ delete SwFieldType::s_pFieldNames;
+
+ delete pGlossaryList;
+ delete pAuthFieldNameList;
+ delete pAuthFieldTypeList;
+
+}
+
+// Initialise
+
+void InitUI()
+{
+ // ShellResource gives the CORE the possibility to work with resources.
+ SwViewShell::SetShellRes( new ShellResource );
+ SwEditWin::InitStaticData();
+}
+
+const TranslateId FLD_DOCINFO_ARY[] =
+{
+ FLD_DOCINFO_TITLE,
+ FLD_DOCINFO_SUBJECT,
+ FLD_DOCINFO_KEYS,
+ FLD_DOCINFO_COMMENT,
+ FLD_DOCINFO_CREATE,
+ FLD_DOCINFO_CHANGE,
+ FLD_DOCINFO_PRINT,
+ FLD_DOCINFO_DOCNO,
+ FLD_DOCINFO_EDIT
+};
+
+ShellResource::ShellResource()
+ : aPostItAuthor( SwResId( STR_POSTIT_AUTHOR ) ),
+ aPostItPage( SwResId( STR_POSTIT_PAGE ) ),
+ aPostItLine( SwResId( STR_POSTIT_LINE ) ),
+
+ aCalc_Syntax( SwResId( STR_CALC_SYNTAX ) ),
+ aCalc_ZeroDiv( SwResId( STR_CALC_ZERODIV ) ),
+ aCalc_Brack( SwResId( STR_CALC_BRACK ) ),
+ aCalc_Pow( SwResId( STR_CALC_POW ) ),
+ aCalc_Overflow( SwResId( STR_CALC_OVERFLOW ) ),
+ aCalc_Default( SwResId( STR_CALC_DEFAULT ) ),
+ aCalc_Error( SwResId( STR_CALC_ERROR ) ),
+
+ // #i81002#
+ aGetRefField_RefItemNotFound( SwResId( STR_GETREFFLD_REFITEMNOTFOUND ) ),
+ aStrNone( SwResId( STR_TEMPLATE_NONE )),
+ aFixedStr( SwResId( STR_FIELD_FIXED )),
+ sDurationFormat( SwResId( STR_DURATION_FORMAT )),
+
+ aTOXIndexName( SwResId(STR_TOI)),
+ aTOXUserName( SwResId(STR_TOU)),
+ aTOXContentName( SwResId(STR_TOC)),
+ aTOXIllustrationsName( SwResId(STR_TOX_ILL)),
+ aTOXObjectsName( SwResId(STR_TOX_OBJ)),
+ aTOXTablesName( SwResId(STR_TOX_TBL)),
+ aTOXAuthoritiesName( SwResId(STR_TOX_AUTH)),
+ aTOXCitationName( SwResId(STR_TOX_CITATION)),
+ sPageDescFirstName( SwResId(STR_PAGEDESC_FIRSTNAME)),
+ sPageDescFollowName( SwResId(STR_PAGEDESC_FOLLOWNAME)),
+ sPageDescName( SwResId(STR_PAGEDESC_NAME))
+{
+ for (auto const& aID : FLD_DOCINFO_ARY)
+ aDocInfoLst.push_back(SwResId(aID));
+}
+
+OUString ShellResource::GetPageDescName(sal_uInt16 nNo, PageNameMode eMode)
+{
+ OUString sRet;
+
+ switch (eMode)
+ {
+ case NORMAL_PAGE:
+ sRet = sPageDescName;
+ break;
+ case FIRST_PAGE:
+ sRet = sPageDescFirstName;
+ break;
+ case FOLLOW_PAGE:
+ sRet = sPageDescFollowName;
+ break;
+ }
+
+ return sRet.replaceFirst( "$(ARG1)", OUString::number( nNo ));
+}
+
+SwGlossaries* GetGlossaries()
+{
+ if (!pGlossaries)
+ pGlossaries.reset( new SwGlossaries );
+ return pGlossaries.get();
+}
+
+bool HasGlossaryList()
+{
+ return pGlossaryList != nullptr;
+}
+
+SwGlossaryList* GetGlossaryList()
+{
+ if(!pGlossaryList)
+ pGlossaryList = new SwGlossaryList();
+
+ return pGlossaryList;
+}
+
+void ShellResource::GetAutoFormatNameLst_() const
+{
+ assert(!mxAutoFormatNameLst);
+ mxAutoFormatNameLst.emplace();
+ mxAutoFormatNameLst->reserve(STR_AUTOFMTREDL_END);
+
+ static_assert(SAL_N_ELEMENTS(RID_SHELLRES_AUTOFMTSTRS) == STR_AUTOFMTREDL_END);
+ for (sal_uInt16 n = 0; n < STR_AUTOFMTREDL_END; ++n)
+ {
+ OUString p(SwResId(RID_SHELLRES_AUTOFMTSTRS[n]));
+ if (STR_AUTOFMTREDL_TYPO == n)
+ {
+ const SvtSysLocale aSysLocale;
+ const LocaleDataWrapper& rLclD = aSysLocale.GetLocaleData();
+ p = p.replaceFirst("%1", rLclD.getDoubleQuotationMarkStart());
+ p = p.replaceFirst("%2", rLclD.getDoubleQuotationMarkEnd());
+ }
+ mxAutoFormatNameLst->push_back(p);
+ }
+}
+
+namespace
+{
+ const TranslateId STR_AUTH_FIELD_ARY[] =
+ {
+ STR_AUTH_FIELD_IDENTIFIER,
+ STR_AUTH_FIELD_AUTHORITY_TYPE,
+ STR_AUTH_FIELD_ADDRESS,
+ STR_AUTH_FIELD_ANNOTE,
+ STR_AUTH_FIELD_AUTHOR,
+ STR_AUTH_FIELD_BOOKTITLE,
+ STR_AUTH_FIELD_CHAPTER,
+ STR_AUTH_FIELD_EDITION,
+ STR_AUTH_FIELD_EDITOR,
+ STR_AUTH_FIELD_HOWPUBLISHED,
+ STR_AUTH_FIELD_INSTITUTION,
+ STR_AUTH_FIELD_JOURNAL,
+ STR_AUTH_FIELD_MONTH,
+ STR_AUTH_FIELD_NOTE,
+ STR_AUTH_FIELD_NUMBER,
+ STR_AUTH_FIELD_ORGANIZATIONS,
+ STR_AUTH_FIELD_PAGES,
+ STR_AUTH_FIELD_PUBLISHER,
+ STR_AUTH_FIELD_SCHOOL,
+ STR_AUTH_FIELD_SERIES,
+ STR_AUTH_FIELD_TITLE,
+ STR_AUTH_FIELD_TYPE,
+ STR_AUTH_FIELD_VOLUME,
+ STR_AUTH_FIELD_YEAR,
+ STR_AUTH_FIELD_URL,
+ STR_AUTH_FIELD_CUSTOM1,
+ STR_AUTH_FIELD_CUSTOM2,
+ STR_AUTH_FIELD_CUSTOM3,
+ STR_AUTH_FIELD_CUSTOM4,
+ STR_AUTH_FIELD_CUSTOM5,
+ STR_AUTH_FIELD_ISBN,
+ STR_AUTH_FIELD_LOCAL_URL,
+ STR_AUTH_FIELD_TARGET_TYPE,
+ STR_AUTH_FIELD_TARGET_URL,
+ };
+}
+
+OUString const & SwAuthorityFieldType::GetAuthFieldName(ToxAuthorityField eType)
+{
+ if(!pAuthFieldNameList)
+ {
+ pAuthFieldNameList = new std::vector<OUString>;
+ pAuthFieldNameList->reserve(AUTH_FIELD_END);
+ for (sal_uInt16 i = 0; i < AUTH_FIELD_END; ++i)
+ pAuthFieldNameList->push_back(SwResId(STR_AUTH_FIELD_ARY[i]));
+ }
+ return (*pAuthFieldNameList)[static_cast< sal_uInt16 >(eType)];
+}
+
+const TranslateId STR_AUTH_TYPE_ARY[] =
+{
+ STR_AUTH_TYPE_ARTICLE,
+ STR_AUTH_TYPE_BOOK,
+ STR_AUTH_TYPE_BOOKLET,
+ STR_AUTH_TYPE_CONFERENCE,
+ STR_AUTH_TYPE_INBOOK,
+ STR_AUTH_TYPE_INCOLLECTION,
+ STR_AUTH_TYPE_INPROCEEDINGS,
+ STR_AUTH_TYPE_JOURNAL,
+ STR_AUTH_TYPE_MANUAL,
+ STR_AUTH_TYPE_MASTERSTHESIS,
+ STR_AUTH_TYPE_MISC,
+ STR_AUTH_TYPE_PHDTHESIS,
+ STR_AUTH_TYPE_PROCEEDINGS,
+ STR_AUTH_TYPE_TECHREPORT,
+ STR_AUTH_TYPE_UNPUBLISHED,
+ STR_AUTH_TYPE_EMAIL,
+ STR_AUTH_TYPE_WWW,
+ STR_AUTH_TYPE_CUSTOM1,
+ STR_AUTH_TYPE_CUSTOM2,
+ STR_AUTH_TYPE_CUSTOM3,
+ STR_AUTH_TYPE_CUSTOM4,
+ STR_AUTH_TYPE_CUSTOM5
+};
+
+OUString const & SwAuthorityFieldType::GetAuthTypeName(ToxAuthorityType eType)
+{
+ if(!pAuthFieldTypeList)
+ {
+ pAuthFieldTypeList = new std::vector<OUString>;
+ pAuthFieldTypeList->reserve(AUTH_TYPE_END);
+ for (sal_uInt16 i = 0; i < AUTH_TYPE_END; ++i)
+ pAuthFieldTypeList->push_back(SwResId(STR_AUTH_TYPE_ARY[i]));
+ }
+ return (*pAuthFieldTypeList)[static_cast< sal_uInt16 >(eType)];
+}
+
+void SwAuthorityFieldType::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwAuthorityFieldType"));
+ SwFieldType::dumpAsXml(pWriter);
+
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("DataArr"));
+ for (const auto& xAuthEntry : m_DataArr)
+ {
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("AuthEntry"));
+ (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", xAuthEntry.get());
+ (void)xmlTextWriterEndElement(pWriter);
+ }
+ (void)xmlTextWriterEndElement(pWriter);
+
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/navicfg.cxx b/sw/source/uibase/utlui/navicfg.cxx
new file mode 100644
index 0000000000..dfda882729
--- /dev/null
+++ b/sw/source/uibase/utlui/navicfg.cxx
@@ -0,0 +1,196 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <swtypes.hxx>
+#include <navicfg.hxx>
+#include <swcont.hxx>
+#include <o3tl/any.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <map>
+
+using namespace ::utl;
+using namespace ::com::sun::star::uno;
+
+namespace {
+ std::map<OUString, ContentTypeId> mPropNameToContentTypeId
+ {
+ {"TableTracking", ContentTypeId::TABLE},
+ {"FrameTracking", ContentTypeId::FRAME},
+ {"ImageTracking", ContentTypeId::GRAPHIC},
+ {"OLEobjectTracking", ContentTypeId::OLE},
+ {"BookmarkTracking", ContentTypeId::BOOKMARK},
+ {"SectionTracking", ContentTypeId::REGION},
+ {"HyperlinkTracking", ContentTypeId::URLFIELD},
+ {"ReferenceTracking", ContentTypeId::REFERENCE},
+ {"IndexTracking", ContentTypeId::INDEX},
+ {"CommentTracking", ContentTypeId::POSTIT},
+ {"DrawingObjectTracking", ContentTypeId::DRAWOBJECT},
+ {"FieldTracking", ContentTypeId::TEXTFIELD},
+ {"FootnoteTracking", ContentTypeId::FOOTNOTE},
+ {"EndnoteTracking", ContentTypeId::ENDNOTE}
+ };
+}
+
+Sequence<OUString> SwNavigationConfig::GetPropertyNames()
+{
+ return css::uno::Sequence<OUString>{
+ OUString("RootType"),
+ OUString("SelectedPosition"),
+ OUString("OutlineLevel"),
+ OUString("InsertMode"),
+ OUString("ActiveBlock"),
+ OUString("ShowListBox"),
+ OUString("GlobalDocMode"),
+ OUString("OutlineTracking"),
+ OUString("TableTracking"),
+ OUString("SectionTracking"),
+ OUString("FrameTracking"),
+ OUString("ImageTracking"),
+ OUString("OLEobjectTracking"),
+ OUString("BookmarkTracking"),
+ OUString("HyperlinkTracking"),
+ OUString("ReferenceTracking"),
+ OUString("IndexTracking"),
+ OUString("CommentTracking"),
+ OUString("DrawingObjectTracking"),
+ OUString("FieldTracking"),
+ OUString("FootnoteTracking"),
+ OUString("EndnoteTracking"),
+ OUString("NavigateOnSelect"),
+ OUString("SortAlphabeticallyBlock")};
+}
+
+SwNavigationConfig::SwNavigationConfig() :
+ utl::ConfigItem("Office.Writer/Navigator"),
+ m_nRootType(ContentTypeId::UNKNOWN),
+ m_nSelectedPos(0),
+ m_nOutlineLevel(MAXLEVEL),
+ m_nRegionMode(RegionMode::NONE),
+ m_nActiveBlock(0),
+ m_bIsSmall(false),
+ m_bIsGlobalActive(true),
+ m_nOutlineTracking(1),
+ m_bIsNavigateOnSelect(false)
+{
+ Load();
+ EnableNotification(GetPropertyNames());
+}
+
+void SwNavigationConfig::Load()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ const Any* pValues = aValues.getConstArray();
+ OSL_ENSURE(aValues.getLength() == aNames.getLength(), "GetProperties failed");
+ if(aValues.getLength() != aNames.getLength())
+ return;
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ if(pValues[nProp].hasValue())
+ {
+ switch(nProp)
+ {
+ case 0:
+ {
+ sal_Int32 nTmp = {}; // spurious -Werror=maybe-uninitialized
+ if (pValues[nProp] >>= nTmp)
+ {
+ if (nTmp < sal_Int32(ContentTypeId::UNKNOWN)
+ || nTmp > sal_Int32(ContentTypeId::LAST))
+ {
+ SAL_WARN(
+ "sw",
+ "out-of-bounds ContentTypeId " << nTmp);
+ nTmp = sal_Int32(ContentTypeId::UNKNOWN);
+ }
+ m_nRootType = static_cast<ContentTypeId>(nTmp);
+ }
+ break;
+ }
+ case 1: pValues[nProp] >>= m_nSelectedPos; break;
+ case 2: pValues[nProp] >>= m_nOutlineLevel; break;
+ case 3:
+ {
+ sal_Int32 nTmp;
+ if (pValues[nProp] >>= nTmp)
+ m_nRegionMode = static_cast<RegionMode>(nTmp);
+ break;
+ }
+ case 4: pValues[nProp] >>= m_nActiveBlock; break;
+ case 5: m_bIsSmall = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 6: m_bIsGlobalActive = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 7: pValues[nProp] >>= m_nOutlineTracking; break;
+ case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16:
+ case 17: case 18: case 19: case 20: case 21:
+ {
+ mContentTypeTrack[mPropNameToContentTypeId[aNames[nProp]]] =
+ *o3tl::doAccess<bool>(pValues[nProp]);
+ break;
+ }
+ case 22: m_bIsNavigateOnSelect = *o3tl::doAccess<bool>(pValues[nProp]); break;
+ case 23: pValues[nProp] >>= m_nSortAlphabeticallyBlock; break;
+ }
+ }
+ }
+}
+
+SwNavigationConfig::~SwNavigationConfig()
+{
+}
+
+void SwNavigationConfig::ImplCommit()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case 0: pValues[nProp] <<= static_cast<sal_Int32>(m_nRootType); break;
+ case 1: pValues[nProp] <<= m_nSelectedPos; break;
+ case 2: pValues[nProp] <<= m_nOutlineLevel; break;
+ case 3: pValues[nProp] <<= static_cast<sal_uInt16>(m_nRegionMode); break;
+ case 4: pValues[nProp] <<= m_nActiveBlock; break;
+ case 5: pValues[nProp] <<= m_bIsSmall; break;
+ case 6: pValues[nProp] <<= m_bIsGlobalActive; break;
+ case 7: pValues[nProp] <<= m_nOutlineTracking; break;
+ case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16:
+ case 17: case 18: case 19: case 20: case 21:
+ {
+ pValues[nProp] <<= mContentTypeTrack[mPropNameToContentTypeId[aNames[nProp]]];
+ break;
+ }
+ case 22: pValues[nProp] <<= m_bIsNavigateOnSelect; break;
+ case 23: pValues[nProp] <<= m_nSortAlphabeticallyBlock; break;
+ }
+ }
+ PutProperties(aNames, aValues);
+}
+
+void SwNavigationConfig::Notify( const css::uno::Sequence< OUString >& )
+{
+ Load();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/navipi.cxx b/sw/source/uibase/utlui/navipi.cxx
new file mode 100644
index 0000000000..3fd5b7f9b6
--- /dev/null
+++ b/sw/source/uibase/utlui/navipi.cxx
@@ -0,0 +1,1277 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <comphelper/string.hxx>
+#include <svl/urlbmk.hxx>
+#include <svl/stritem.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <sot/formats.hxx>
+#include <sot/filelist.hxx>
+#include <sfx2/event.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <tools/urlobj.hxx>
+#include <osl/diagnose.h>
+#include <swtypes.hxx>
+#include <swmodule.hxx>
+#include <view.hxx>
+#include <navicfg.hxx>
+#include <wrtsh.hxx>
+#include <docsh.hxx>
+#include <navipi.hxx>
+#include <edtwin.hxx>
+#include <sfx2/app.hxx>
+#include <cmdid.h>
+#include <helpids.h>
+
+#include <strings.hrc>
+#include <bitmaps.hlst>
+
+#include <memory>
+
+#include <o3tl/enumrange.hxx>
+
+#include <workctrl.hxx>
+
+#include <comphelper/lok.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::frame;
+
+// Filter the control characters out of the Outline-Entry
+OUString SwNavigationPI::CleanEntry(const OUString& rEntry)
+{
+ if (rEntry.isEmpty())
+ return rEntry;
+
+ OUStringBuffer aEntry(rEntry);
+ for (sal_Int32 i = 0; i < rEntry.getLength(); ++i)
+ if(aEntry[i] == 10 || aEntry[i] == 9)
+ aEntry[i] = 0x20;
+
+ return aEntry.makeStringAndClear();
+}
+
+// Execution of the drag operation with and without the children.
+
+void SwNavigationPI::MoveOutline(SwOutlineNodes::size_type nSource, SwOutlineNodes::size_type nTarget)
+{
+ SwView *pView = GetCreateView();
+ SwWrtShell &rSh = pView->GetWrtShell();
+ if(nTarget < nSource || nTarget == SwOutlineNodes::npos)
+ nTarget ++;
+ if ( !rSh.IsOutlineMovable( nSource ))
+ return;
+
+ SwOutlineNodes::difference_type nMove = nTarget-nSource; //( nDir<0 ) ? 1 : 0 ;
+ rSh.GotoOutline(nSource);
+ rSh.MakeOutlineSel(nSource, nSource, true);
+ // While moving, the selected children does not counting.
+ const SwOutlineNodes::size_type nLastOutlinePos = rSh.GetOutlinePos(MAXLEVEL);
+ if(nMove > 1 && nLastOutlinePos < nTarget)
+ {
+ if(!rSh.IsCursorPtAtEnd())
+ rSh.SwapPam();
+ nMove -= nLastOutlinePos - nSource;
+ }
+ if( nMove < 1 || nLastOutlinePos < nTarget )
+ rSh.MoveOutlinePara( nMove );
+ rSh.ClearMark();
+ rSh.GotoOutline( nSource + nMove);
+
+}
+
+// After goto cancel the status frame selection
+static void lcl_UnSelectFrame(SwWrtShell *pSh)
+{
+ if (pSh->IsFrameSelected())
+ {
+ pSh->UnSelectFrame();
+ pSh->LeaveSelFrameMode();
+ }
+}
+
+// Select the document view
+IMPL_LINK(SwNavigationPI, DocListBoxSelectHdl, weld::ComboBox&, rBox, void)
+{
+ int nEntryIdx = rBox.get_active();
+ SwView *pView ;
+ pView = SwModule::GetFirstView();
+ while (nEntryIdx-- && pView)
+ {
+ pView = SwModule::GetNextView(pView);
+ }
+ if(!pView)
+ {
+ nEntryIdx == 0 ?
+ m_xContentTree->ShowHiddenShell():
+ m_xContentTree->ShowActualView();
+
+ }
+ else
+ {
+ m_xContentTree->SetConstantShell(pView->GetWrtShellPtr());
+ }
+}
+
+void SwNavigationPI::UpdateNavigateBy()
+{
+ if (!m_pNavigateByComboBox)
+ return;
+ SfxUInt32Item aParam(FN_NAV_ELEMENT, m_pNavigateByComboBox->get_active_id().toUInt32());
+ const SfxPoolItem* aArgs[2];
+ aArgs[0] = &aParam;
+ aArgs[1] = nullptr;
+ SfxDispatcher* pDispatcher = GetCreateView()->GetFrame()->GetDispatcher();
+ pDispatcher->Execute(FN_NAV_ELEMENT, SfxCallMode::SYNCHRON, aArgs);
+}
+
+IMPL_LINK(SwNavigationPI, NavigateByComboBoxSelectHdl, weld::ComboBox&, rComboBox, void)
+{
+ m_xContentTree->SelectContentType(rComboBox.get_active_text());
+ UpdateNavigateBy();
+}
+
+// Filling of the list box for outline view or documents
+// The PI will be set to full size
+void SwNavigationPI::FillBox()
+{
+ if(m_pContentWrtShell)
+ {
+ m_xContentTree->SetHiddenShell( m_pContentWrtShell );
+ m_xContentTree->Display( false );
+ }
+ else
+ {
+ SwView *pView = GetCreateView();
+ if(!pView)
+ {
+ m_xContentTree->SetActiveShell(nullptr);
+ }
+ else if( pView != m_pActContView)
+ {
+ SwWrtShell* pWrtShell = pView->GetWrtShellPtr();
+ m_xContentTree->SetActiveShell(pWrtShell);
+ }
+ else
+ m_xContentTree->Display( true );
+ m_pActContView = pView;
+ if (m_pActContView)
+ m_xContentTree->UpdateTracking();
+ }
+}
+
+void SwNavigationPI::UsePage()
+{
+ SwView *pView = GetCreateView();
+ SwWrtShell *pSh = pView ? &pView->GetWrtShell() : nullptr;
+ m_xEdit->set_value(1);
+ if (pSh)
+ {
+ const sal_uInt16 nPageCnt = pSh->GetPageCnt();
+ sal_uInt16 nPhyPage, nVirPage;
+ pSh->GetPageNum(nPhyPage, nVirPage);
+
+ m_xEdit->set_max(nPageCnt);
+ m_xEdit->set_width_chars(3);
+ m_xEdit->set_value(nPhyPage);
+ }
+}
+
+// Select handler of the toolboxes
+IMPL_LINK(SwNavigationPI, ToolBoxSelectHdl, const OUString&, rCommand, void)
+{
+ SwView *pView = GetCreateView();
+ if (!pView)
+ return;
+ SwWrtShell &rSh = pView->GetWrtShell();
+ // Get MouseModifier for Outline-Move
+
+ int nFuncId = 0;
+ bool bFocusToDoc = false;
+ if (rCommand == ".uno:ScrollToPrevious" || rCommand == ".uno:ScrollToNext")
+ {
+ bool *pbNext = new bool(true);
+ if (rCommand == ".uno:ScrollToPrevious")
+ *pbNext = false;
+ pView->MoveNavigationHdl(pbNext);
+ }
+ else if (rCommand == "root")
+ {
+ m_xContentTree->ToggleToRoot();
+ }
+ else if (rCommand == "listbox")
+ {
+ if (ParentIsFloatingWindow(m_xNavigatorDlg))
+ {
+ if (IsZoomedIn())
+ {
+ ZoomOut();
+ }
+ else
+ {
+ ZoomIn();
+ }
+ }
+ return;
+ }
+ // Functions that will trigger a direct action.
+ else if (rCommand == "footer")
+ {
+ rSh.MoveCursor();
+ const FrameTypeFlags eType = rSh.GetFrameType(nullptr,false);
+ if (eType & FrameTypeFlags::FOOTER)
+ {
+ if (rSh.EndPg())
+ nFuncId = FN_END_OF_PAGE;
+ }
+ else if (rSh.GotoFooterText())
+ nFuncId = FN_TO_FOOTER;
+ bFocusToDoc = true;
+ }
+ else if (rCommand == "header")
+ {
+ rSh.MoveCursor();
+ const FrameTypeFlags eType = rSh.GetFrameType(nullptr,false);
+ if (eType & FrameTypeFlags::HEADER)
+ {
+ if (rSh.SttPg())
+ nFuncId = FN_START_OF_PAGE;
+ }
+ else if (rSh.GotoHeaderText())
+ nFuncId = FN_TO_HEADER;
+ bFocusToDoc = true;
+ }
+ else if (rCommand == "anchor")
+ {
+ rSh.MoveCursor();
+ const FrameTypeFlags eFrameType = rSh.GetFrameType(nullptr,false);
+ // Jump from the footnote to the anchor.
+ if (eFrameType & FrameTypeFlags::FOOTNOTE)
+ {
+ if (rSh.GotoFootnoteAnchor())
+ nFuncId = FN_FOOTNOTE_TO_ANCHOR;
+ }
+ // Otherwise, jump to the first footnote text;
+ // go to the next footnote if this is not possible;
+ // if this is also not possible got to the footnote before.
+ else
+ {
+ if (rSh.GotoFootnoteText())
+ nFuncId = FN_FOOTNOTE_TO_ANCHOR;
+ else if (rSh.GotoNextFootnoteAnchor())
+ nFuncId = FN_NEXT_FOOTNOTE;
+ else if (rSh.GotoPrevFootnoteAnchor())
+ nFuncId = FN_PREV_FOOTNOTE;
+ }
+ bFocusToDoc = true;
+ }
+ else if (rCommand == "reminder")
+ {
+ rSh.GetView().GetViewFrame().GetDispatcher()->Execute(FN_SET_REMINDER, SfxCallMode::ASYNCHRON);
+ }
+ else if (rCommand == "chapterdown" ||
+ rCommand == "movedown" ||
+ rCommand == "chapterup" ||
+ rCommand == "moveup" ||
+ rCommand == "promote" ||
+ rCommand == "demote" ||
+ rCommand == "edit")
+ {
+ if (IsGlobalMode())
+ m_xGlobalTree->ExecCommand(rCommand);
+ else
+ {
+ // Standard: sublevels are taken
+ // do not take sublevels with Ctrl
+ bool bOutlineWithChildren = (KEY_MOD1 != m_xContent6ToolBox->get_modifier_state());
+ m_xContentTree->ExecCommand(rCommand, bOutlineWithChildren);
+ }
+ }
+ else if (rCommand == "contenttoggle" || rCommand == "globaltoggle")
+ {
+ ToggleTree();
+ bool bGlobalMode = IsGlobalMode();
+ m_pConfig->SetGlobalActive(bGlobalMode);
+ m_xGlobalToolBox->set_item_active("globaltoggle", bGlobalMode);
+ m_xContent1ToolBox->set_item_active("contenttoggle", bGlobalMode);
+ }
+ else if (rCommand == "save")
+ {
+ bool bSave = rSh.IsGlblDocSaveLinks();
+ rSh.SetGlblDocSaveLinks( !bSave );
+ m_xGlobalToolBox->set_item_active(rCommand, !bSave);
+ }
+ else if (rCommand == "dragmode")
+ m_xContent6ToolBox->set_menu_item_active("dragmode", !m_xContent6ToolBox->get_menu_item_active("dragmode"));
+ else if (rCommand == "headings")
+ m_xContent5ToolBox->set_menu_item_active("headings", !m_xContent5ToolBox->get_menu_item_active("headings"));
+ else if (rCommand == "update")
+ m_xGlobalToolBox->set_menu_item_active("update", !m_xGlobalToolBox->get_menu_item_active("update"));
+ else if (rCommand == "insert")
+ m_xGlobalToolBox->set_menu_item_active("insert", !m_xGlobalToolBox->get_menu_item_active("insert"));
+
+ if (nFuncId)
+ lcl_UnSelectFrame(&rSh);
+ if (bFocusToDoc)
+ pView->GetEditWin().GrabFocus();
+}
+
+// Click handler of the toolboxes
+IMPL_LINK(SwNavigationPI, ToolBoxClickHdl, const OUString&, rCommand, void)
+{
+ if (!m_xGlobalToolBox->get_menu_item_active(rCommand))
+ return;
+
+ if (rCommand == "update")
+ m_xGlobalTree->TbxMenuHdl(rCommand, *m_xUpdateMenu);
+ else if (rCommand == "insert")
+ m_xGlobalTree->TbxMenuHdl(rCommand, *m_xInsertMenu);
+}
+
+IMPL_LINK(SwNavigationPI, ToolBox6DropdownClickHdl, const OUString&, rCommand, void)
+{
+ if (!m_xContent6ToolBox->get_menu_item_active(rCommand))
+ return;
+
+ if (rCommand != "dragmode")
+ return;
+
+ switch (m_nRegionMode)
+ {
+ case RegionMode::NONE:
+ m_xDragModeMenu->set_active("hyperlink", true);
+ break;
+ case RegionMode::LINK:
+ m_xDragModeMenu->set_active("link", true);
+ break;
+ case RegionMode::EMBEDDED:
+ m_xDragModeMenu->set_active("copy", true);
+ break;
+ }
+}
+
+IMPL_LINK(SwNavigationPI, DropModeMenuSelectHdl, const OUString&, rIdent, void)
+{
+ if (rIdent == "hyperlink")
+ SetRegionDropMode(RegionMode::NONE);
+ else if (rIdent == "link")
+ SetRegionDropMode(RegionMode::LINK);
+ else if (rIdent == "copy")
+ SetRegionDropMode(RegionMode::EMBEDDED);
+}
+
+IMPL_LINK(SwNavigationPI, GlobalMenuSelectHdl, const OUString&, rIdent, void)
+{
+ m_xGlobalTree->ExecuteContextMenuAction(rIdent);
+}
+
+IMPL_LINK(SwNavigationPI, ToolBox5DropdownClickHdl, const OUString&, rCommand, void)
+{
+ if (!m_xContent5ToolBox->get_menu_item_active(rCommand))
+ return;
+
+ if (rCommand == "headings")
+ m_xHeadingsMenu->set_active(OUString::number(m_xContentTree->GetOutlineLevel()), true);
+}
+
+// Action-Handler Edit:
+// Switches to the page if the structure view is not turned on.
+bool SwNavigationPI::EditAction()
+{
+ SwView *pView = GetCreateView();
+ if (!pView)
+ return false;
+
+ if (m_aPageChgIdle.IsActive())
+ m_aPageChgIdle.Stop();
+
+ // if the user has clicked into the document, forget about changing the page
+ if (pView->GetEditWin().HasFocus())
+ return false;
+
+ if (m_xEdit->get_text().isEmpty())
+ return false;
+ sal_Int64 nNewPage = m_xEdit->get_text().toInt32();
+ SwWrtShell& rSh = m_pCreateView->GetWrtShell();
+ sal_Int64 max = rSh.GetPageCnt();
+ if (nNewPage <= 0)
+ nNewPage = 1;
+ else if (nNewPage > max)
+ nNewPage = max;
+ m_xEdit->set_value(nNewPage);
+ m_xEdit->set_position(-1);
+
+ rSh.GotoPage(nNewPage, true);
+ m_pCreateView->GetViewFrame().GetBindings().Invalidate(FN_STAT_PAGE);
+
+ return true;
+}
+
+void SwNavigationPI::ZoomOut()
+{
+ if (!IsZoomedIn())
+ return;
+ SfxNavigator* pNav = m_xNavigatorDlg.get();
+ if (!pNav)
+ return;
+ m_bIsZoomedIn = false;
+ FillBox();
+ if (IsGlobalMode())
+ {
+ m_xGlobalBox->show();
+ m_xGlobalTree->ShowTree();
+ }
+ else
+ {
+ m_xContentBox->show();
+ m_xContentTree->ShowTree();
+ m_xDocListBox->show();
+ }
+
+ pNav->InvalidateChildSizeCache();
+ Size aOptimalSize(pNav->GetOptimalSize());
+ Size aNewSize(pNav->GetOutputSizePixel());
+ aNewSize.setHeight( m_aExpandedSize.Height() );
+ pNav->SetMinOutputSizePixel(aOptimalSize);
+ pNav->SetOutputSizePixel(aNewSize);
+
+ m_xContentTree->Select(); // Enable toolbox
+ m_pConfig->SetSmall(false);
+ m_xContent6ToolBox->set_item_active("listbox", true);
+}
+
+void SwNavigationPI::ZoomIn()
+{
+ if (IsZoomedIn())
+ return;
+ SfxNavigator* pNav = m_xNavigatorDlg.get();
+ if (!pNav)
+ return;
+
+ m_aExpandedSize = m_xNavigatorDlg->GetSizePixel();
+
+ m_xContentBox->hide();
+ m_xContentTree->HideTree();
+ m_xGlobalBox->hide();
+ m_xGlobalTree->HideTree();
+ m_xDocListBox->hide();
+ m_bIsZoomedIn = true;
+
+ pNav->InvalidateChildSizeCache();
+ Size aOptimalSize(pNav->GetOptimalSize());
+ Size aNewSize(pNav->GetOutputSizePixel());
+ aNewSize.setHeight( aOptimalSize.Height() );
+ pNav->SetMinOutputSizePixel(aOptimalSize);
+ pNav->SetOutputSizePixel(aNewSize);
+
+ m_xContentTree->Select(); // Enable toolbox
+
+ m_pConfig->SetSmall(true);
+ m_xContent6ToolBox->set_item_active("listbox", false);
+}
+
+namespace {
+
+enum StatusIndex
+{
+ IDX_STR_HIDDEN = 0,
+ IDX_STR_ACTIVE = 1,
+ IDX_STR_INACTIVE = 2
+};
+
+}
+
+std::unique_ptr<PanelLayout> SwNavigationPI::Create(weld::Widget* pParent,
+ const css::uno::Reference<css::frame::XFrame>& rxFrame,
+ SfxBindings* pBindings)
+{
+ if( pParent == nullptr )
+ throw css::lang::IllegalArgumentException("no parent window given to SwNavigationPI::Create", nullptr, 0);
+ if( !rxFrame.is() )
+ throw css::lang::IllegalArgumentException("no XFrame given to SwNavigationPI::Create", nullptr, 0);
+ if( pBindings == nullptr )
+ throw css::lang::IllegalArgumentException("no SfxBindings given to SwNavigationPI::Create", nullptr, 0);
+ return std::make_unique<SwNavigationPI>(pParent, rxFrame, pBindings, nullptr);
+}
+
+IMPL_LINK_NOARG(SwNavigationPI, PageModifiedHdl, weld::Entry&, void)
+{
+ SwView* pView = GetCreateView();
+ if (!pView)
+ return;
+ if (m_xEdit->get_text().isEmpty())
+ return;
+ sal_Int64 page_value = m_xEdit->get_text().toInt32();
+ SwWrtShell& rSh = m_pCreateView->GetWrtShell();
+ sal_Int64 max = rSh.GetPageCnt();
+ if (page_value <= 0)
+ m_xEdit->set_value(1);
+ else if (page_value > max)
+ m_xEdit->set_value(max);
+ else
+ m_xEdit->set_value(page_value);
+ m_xEdit->set_position(-1);
+}
+
+SwNavigationPI::SwNavigationPI(weld::Widget* pParent,
+ const css::uno::Reference<css::frame::XFrame>& rxFrame,
+ SfxBindings* _pBindings, SfxNavigator* pNavigatorDlg)
+ : PanelLayout(pParent, "NavigatorPanel", "modules/swriter/ui/navigatorpanel.ui")
+ , m_aDocFullName(SID_DOCFULLNAME, *_pBindings, *this)
+ , m_aPageStats(FN_STAT_PAGE, *_pBindings, *this)
+ , m_xContent1ToolBox(m_xBuilder->weld_toolbar("content1"))
+ , m_xContent2ToolBox(m_xBuilder->weld_toolbar("content2"))
+ , m_xContent3ToolBox(m_xBuilder->weld_toolbar("content3"))
+ , m_xContent4ToolBox(m_xBuilder->weld_toolbar("content4"))
+ , m_xContent5ToolBox(m_xBuilder->weld_toolbar("content5"))
+ , m_xContent6ToolBox(m_xBuilder->weld_toolbar("content6"))
+ , m_xContent2Dispatch(new ToolbarUnoDispatcher(*m_xContent2ToolBox, *m_xBuilder, rxFrame))
+ , m_xContent3Dispatch(new ToolbarUnoDispatcher(*m_xContent3ToolBox, *m_xBuilder, rxFrame))
+ , m_xHeadingsMenu(m_xBuilder->weld_menu("headingsmenu"))
+ , m_xDragModeMenu(m_xBuilder->weld_menu("dragmodemenu"))
+ , m_xUpdateMenu(m_xBuilder->weld_menu("updatemenu"))
+ , m_xInsertMenu(m_xBuilder->weld_menu("insertmenu"))
+ , m_xGlobalToolBox(m_xBuilder->weld_toolbar("global"))
+ , m_xEdit(m_xBuilder->weld_spin_button("spinbutton"))
+ , m_xContentBox(m_xBuilder->weld_widget("contentbox"))
+ , m_xContentTree(new SwContentTree(m_xBuilder->weld_tree_view("contenttree"), this))
+ , m_xGlobalBox(m_xBuilder->weld_widget("globalbox"))
+ , m_xGlobalTree(new SwGlobalTree(m_xBuilder->weld_tree_view("globaltree"), this))
+ , m_xDocListBox(m_xBuilder->weld_combo_box("documents"))
+ , m_aPageChgIdle("SwNavigationPI m_aPageChgIdle")
+ , m_xNavigatorDlg(pNavigatorDlg)
+ , m_pContentView(nullptr)
+ , m_pContentWrtShell(nullptr)
+ , m_pActContView(nullptr)
+ , m_pCreateView(nullptr)
+ , m_pConfig(SW_MOD()->GetNavigationConfig())
+ , m_rBindings(*_pBindings)
+ , m_nRegionMode(RegionMode::NONE)
+ , m_bIsZoomedIn(false)
+ , m_bGlobalMode(false)
+{
+ m_xContainer->connect_container_focus_changed(LINK(this, SwNavigationPI, SetFocusChildHdl));
+
+ Reference<XToolbarController> xController =
+ m_xContent2Dispatch->GetControllerForCommand(".uno:NavElement");
+ NavElementToolBoxControl* pToolBoxControl =
+ dynamic_cast<NavElementToolBoxControl*>(xController.get());
+
+ // In case of LOK, the xController may not a NavElementToolBoxControl
+ if (comphelper::LibreOfficeKit::isActive() && !pToolBoxControl)
+ {
+ m_pNavigateByComboBox = nullptr;
+ }
+ else
+ {
+ assert(pToolBoxControl);
+ m_pNavigateByComboBox = pToolBoxControl->GetComboBox();
+ }
+
+ // Restore content tree settings before calling UpdateInitShow. UpdateInitShow calls Fillbox,
+ // which calls Display and UpdateTracking. Incorrect outline levels could be displayed and
+ // unexpected content tracking could occur if these content tree settings are not done before.
+ m_xContentTree->SetOutlineLevel(static_cast<sal_uInt8>(m_pConfig->GetOutlineLevel()));
+ m_xContentTree->SetOutlineTracking(static_cast<sal_uInt8>(m_pConfig->GetOutlineTracking()));
+ for (ContentTypeId eCntTypeId : o3tl::enumrange<ContentTypeId>())
+ {
+ if (eCntTypeId != ContentTypeId::OUTLINE)
+ m_xContentTree->SetContentTypeTracking(
+ eCntTypeId, m_pConfig->IsContentTypeTrack(eCntTypeId));
+ }
+
+ if (const ContentTypeId nRootType = m_pConfig->GetRootType();
+ nRootType != ContentTypeId::UNKNOWN)
+ {
+ m_xContentTree->SetRootType(nRootType);
+ m_xContent5ToolBox->set_item_active("root", true);
+ if (nRootType == ContentTypeId::OUTLINE || nRootType == ContentTypeId::DRAWOBJECT)
+ m_xContentTree->set_selection_mode(SelectionMode::Multiple);
+ else
+ m_xContentTree->set_selection_mode(SelectionMode::Single);
+ }
+ else
+ m_xContentTree->set_selection_mode(SelectionMode::Single);
+
+ UpdateInitShow();
+
+ GetCreateView();
+
+ m_xContent1ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
+ m_xContent2ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
+ m_xContent3ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
+ m_xContent4ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
+ m_xContent5ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
+ m_xContent6ToolBox->set_help_id(HID_NAVIGATOR_TOOLBOX);
+ m_xGlobalToolBox->set_help_id(HID_NAVIGATOR_GLOBAL_TOOLBOX);
+ m_xDocListBox->set_help_id(HID_NAVIGATOR_LISTBOX);
+ m_xDocListBox->set_size_request(42, -1); // set a nominal width so it takes width of surroundings
+
+ // Insert the numeric field in the toolbox.
+ m_xEdit->set_accessible_name(m_xEdit->get_tooltip_text());
+ m_xEdit->set_width_chars(3);
+ m_xEdit->connect_activate(LINK(this, SwNavigationPI, EditActionHdl));
+ m_xEdit->connect_value_changed(LINK(this, SwNavigationPI, PageEditModifyHdl));
+ m_xEdit->connect_changed(LINK(this, SwNavigationPI, PageModifiedHdl));
+ m_xEdit->set_help_id("modules/swriter/ui/navigatorpanel/numericfield");
+
+ if (!IsGlobalDoc())
+ {
+ m_xContent1ToolBox->set_item_visible("contenttoggle", false);
+ }
+
+ const TranslateId REGIONNAME_ARY[] =
+ {
+ STR_HYPERLINK,
+ STR_LINK_REGION,
+ STR_COPY_REGION
+ };
+
+ const TranslateId REGIONMODE_ARY[] =
+ {
+ STR_HIDDEN,
+ STR_ACTIVE,
+ STR_INACTIVE
+ };
+
+ static_assert(SAL_N_ELEMENTS(REGIONNAME_ARY) == SAL_N_ELEMENTS(REGIONMODE_ARY), "### unexpected size!");
+ static_assert(SAL_N_ELEMENTS(REGIONNAME_ARY) == static_cast<sal_uInt16>(RegionMode::EMBEDDED) + 1, "### unexpected size!");
+
+ for (sal_uInt16 i = 0; i <= static_cast<sal_uInt16>(RegionMode::EMBEDDED); ++i)
+ {
+ m_aStatusArr[i] = SwResId(REGIONMODE_ARY[i]);
+ }
+
+ m_aStatusArr[3] = SwResId(STR_ACTIVE_VIEW);
+
+ bool bFloatingNavigator = ParentIsFloatingWindow(m_xNavigatorDlg);
+
+ SetRegionDropMode(m_pConfig->GetRegionMode());
+
+ m_xContentTree->ShowTree();
+ m_xContent6ToolBox->set_item_active("listbox", true);
+ m_xContent6ToolBox->set_item_sensitive("listbox", bFloatingNavigator);
+
+// TreeListBox for global document
+ m_xGlobalTree->set_selection_mode(SelectionMode::Multiple);
+
+// Handler
+ Link<const OUString&, void> aLk = LINK(this, SwNavigationPI, ToolBoxSelectHdl);
+ m_xContent1ToolBox->connect_clicked(aLk);
+ m_xContent3ToolBox->connect_clicked(aLk);
+ m_xContent5ToolBox->connect_clicked(aLk);
+ m_xContent6ToolBox->connect_clicked(aLk);
+ m_xGlobalToolBox->connect_clicked(aLk);
+ m_xDocListBox->connect_changed(LINK(this, SwNavigationPI, DocListBoxSelectHdl));
+ m_xContent5ToolBox->set_item_menu("headings", m_xHeadingsMenu.get());
+ m_xHeadingsMenu->connect_activate(LINK(this, SwNavigationPI, HeadingsMenuSelectHdl));
+ m_xContent5ToolBox->connect_menu_toggled(LINK(this, SwNavigationPI, ToolBox5DropdownClickHdl));
+ m_xContent6ToolBox->set_item_menu("dragmode", m_xDragModeMenu.get());
+ m_xDragModeMenu->connect_activate(LINK(this, SwNavigationPI, DropModeMenuSelectHdl));
+ m_xContent6ToolBox->connect_menu_toggled(LINK(this, SwNavigationPI, ToolBox6DropdownClickHdl));
+ m_xGlobalToolBox->set_item_menu("update", m_xUpdateMenu.get());
+ m_xUpdateMenu->connect_activate(LINK(this, SwNavigationPI, GlobalMenuSelectHdl));
+ m_xGlobalToolBox->set_item_menu("insert", m_xInsertMenu.get());
+ m_xInsertMenu->connect_activate(LINK(this, SwNavigationPI, GlobalMenuSelectHdl));
+ m_xGlobalToolBox->connect_menu_toggled(LINK(this, SwNavigationPI, ToolBoxClickHdl));
+ m_xGlobalToolBox->set_item_active("globaltoggle", true);
+ if (m_pNavigateByComboBox)
+ m_pNavigateByComboBox->connect_changed(
+ LINK(this, SwNavigationPI, NavigateByComboBoxSelectHdl));
+
+// set toolbar of both modes to widest of each
+ m_xGlobalToolBox->set_size_request(m_xContent1ToolBox->get_preferred_size().Width() +
+ m_xContent2ToolBox->get_preferred_size().Width() +
+ m_xContent3ToolBox->get_preferred_size().Width() +
+ m_xContent4ToolBox->get_preferred_size().Width(), -1);
+
+ StartListening(*SfxGetpApp());
+
+ if(IsGlobalDoc())
+ {
+ SwView *pActView = GetCreateView();
+ if (pActView && pActView->GetWrtShellPtr())
+ m_xGlobalToolBox->set_item_active("save",
+ pActView->GetWrtShellPtr()->IsGlblDocSaveLinks());
+ if (m_pConfig->IsGlobalActive())
+ ToggleTree();
+ if (bFloatingNavigator)
+ m_xGlobalTree->grab_focus();
+ }
+ else if (bFloatingNavigator)
+ m_xContentTree->grab_focus();
+ UsePage();
+ m_aPageChgIdle.SetInvokeHandler(LINK(this, SwNavigationPI, ChangePageHdl));
+ m_aPageChgIdle.SetPriority(TaskPriority::LOWEST);
+
+ m_xContentTree->set_accessible_name(SwResId(STR_ACCESS_TL_CONTENT));
+ m_xGlobalTree->set_accessible_name(SwResId(STR_ACCESS_TL_GLOBAL));
+ m_xDocListBox->set_accessible_name(m_aStatusArr[3]);
+
+ m_aExpandedSize = m_xContainer->get_preferred_size();
+
+ if(comphelper::LibreOfficeKit::isActive())
+ {
+ m_xBuilder->weld_container("gridcontent16")->hide();
+ m_xDocListBox->hide();
+ m_xGlobalBox->hide();
+ m_xGlobalToolBox->hide();
+ m_xGlobalTree->HideTree();
+
+ //Open Headings by default
+ SwView *pView = GetCreateView();
+ if (pView->m_nNaviExpandedStatus < 0)
+ {
+ pView->m_nNaviExpandedStatus = 1;
+ m_xContentTree->ExpandAllHeadings();
+ }
+ }
+}
+
+weld::Window* SwNavigationPI::GetFrameWeld() const
+{
+ if (m_xNavigatorDlg)
+ return m_xNavigatorDlg->GetFrameWeld();
+ return PanelLayout::GetFrameWeld();
+}
+
+SwNavigationPI::~SwNavigationPI()
+{
+ if (IsGlobalDoc() && !IsGlobalMode())
+ {
+ SwView *pView = GetCreateView();
+ SwWrtShell &rSh = pView->GetWrtShell();
+ if (!rSh.IsAllProtect())
+ pView->GetDocShell()->SetReadOnlyUI(false);
+ }
+
+ EndListening(*SfxGetpApp());
+
+ if (m_oObjectShell)
+ {
+ if (m_oObjectShell->Is())
+ (*m_oObjectShell)->DoClose();
+ m_oObjectShell.reset();
+ }
+
+ m_xDocListBox.reset();
+ m_xGlobalTree.reset();
+ m_xGlobalBox.reset();
+ m_xContentTree.reset();
+ m_xContentBox.reset();
+ m_xGlobalToolBox.reset();
+ m_xEdit.reset();
+ m_xHeadingsMenu.reset();
+ m_xDragModeMenu.reset();
+ m_xUpdateMenu.reset();
+ m_xInsertMenu.reset();
+ m_xContent2Dispatch.reset();
+ m_xContent3Dispatch.reset();
+ m_xContent1ToolBox.reset();
+ m_xContent2ToolBox.reset();
+ m_xContent3ToolBox.reset();
+ m_xContent4ToolBox.reset();
+ m_xContent5ToolBox.reset();
+ m_xContent6ToolBox.reset();
+
+ m_aPageChgIdle.Stop();
+
+ m_aDocFullName.dispose();
+ m_aPageStats.dispose();
+}
+
+void SwNavigationPI::NotifyItemUpdate(sal_uInt16 nSID, SfxItemState /*eState*/,
+ const SfxPoolItem* /*pState*/)
+{
+ if (nSID == SID_DOCFULLNAME)
+ {
+ SwView *pActView = GetCreateView();
+ if(pActView)
+ {
+ SwWrtShell* pWrtShell = pActView->GetWrtShellPtr();
+ m_xContentTree->SetActiveShell(pWrtShell);
+ bool bGlobal = IsGlobalDoc();
+ m_xContent1ToolBox->set_item_visible("contenttoggle", bGlobal);
+ if ((!bGlobal && IsGlobalMode()) || (!IsGlobalMode() && m_pConfig->IsGlobalActive()))
+ {
+ ToggleTree();
+ }
+ if (bGlobal)
+ {
+ m_xGlobalToolBox->set_item_active("save", pWrtShell->IsGlblDocSaveLinks());
+ }
+ }
+ else
+ {
+ m_xContentTree->SetActiveShell(nullptr);
+ }
+ UpdateListBox();
+ }
+ else if (nSID == FN_STAT_PAGE)
+ {
+ if(!comphelper::LibreOfficeKit::isActive())
+ {
+ SwView *pActView = GetCreateView();
+ if(pActView)
+ {
+ SwWrtShell &rSh = pActView->GetWrtShell();
+ m_xEdit->set_max(rSh.GetPageCnt());
+ m_xEdit->set_width_chars(3);
+ }
+ }
+ }
+}
+
+void SwNavigationPI::UpdateInitShow()
+{
+ // if the parent isn't a float, then the navigator is displayed in
+ // the sidebar or is otherwise docked. While the navigator could change
+ // its size, the sidebar can not, and the navigator would just waste
+ // space. Therefore disable this button.
+ bool bParentIsFloatingWindow(ParentIsFloatingWindow(m_xNavigatorDlg));
+ m_xContent6ToolBox->set_item_sensitive("listbox", bParentIsFloatingWindow);
+ // show content if docked
+ if (!bParentIsFloatingWindow && IsZoomedIn())
+ ZoomOut();
+ if (!IsZoomedIn())
+ FillBox();
+}
+
+IMPL_LINK_NOARG(SwNavigationPI, SetFocusChildHdl, weld::Container&, void)
+{
+ // update documents listbox
+ UpdateListBox();
+}
+
+// Notification on modified DocInfo
+void SwNavigationPI::Notify( SfxBroadcaster& rBrdc, const SfxHint& rHint )
+{
+ if(&rBrdc == m_pCreateView)
+ {
+ if (rHint.GetId() == SfxHintId::Dying)
+ {
+ EndListening(*m_pCreateView);
+ m_pCreateView = nullptr;
+ m_xContentTree->SetActiveShell(nullptr);
+ }
+ }
+ else
+ {
+ if (rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint)
+ {
+ SfxEventHintId eEventId = static_cast<const SfxEventHint&>(rHint).GetEventId();
+ if (eEventId == SfxEventHintId::OpenDoc)
+ {
+ SwView *pActView = GetCreateView();
+ if(pActView)
+ {
+ SwWrtShell* pWrtShell = pActView->GetWrtShellPtr();
+ m_xContentTree->SetActiveShell(pWrtShell);
+ if (m_xGlobalTree->get_visible())
+ {
+ bool bUpdateAll = m_xGlobalTree->Update(false);
+ // If no update is needed, then update the font colors
+ // at the entries of broken links.
+ m_xGlobalTree->Display(!bUpdateAll);
+ }
+ }
+ }
+ }
+ }
+}
+
+IMPL_LINK( SwNavigationPI, HeadingsMenuSelectHdl, const OUString&, rMenuId, void )
+{
+ if (!rMenuId.isEmpty())
+ m_xContentTree->SetOutlineLevel(rMenuId.toUInt32());
+}
+
+void SwNavigationPI::UpdateListBox()
+{
+ if (!m_xDocListBox) // disposed
+ return;
+
+ m_xDocListBox->freeze();
+ m_xDocListBox->clear();
+ SwView *pActView = GetCreateView();
+ bool bDisable = pActView == nullptr;
+ SwView *pView = SwModule::GetFirstView();
+ sal_Int32 nCount = 0;
+ sal_Int32 nAct = 0;
+ sal_Int32 nConstPos = 0;
+ const SwView* pConstView = m_xContentTree->IsConstantView() &&
+ m_xContentTree->GetActiveWrtShell() ?
+ &m_xContentTree->GetActiveWrtShell()->GetView():
+ nullptr;
+ while (pView)
+ {
+ SfxObjectShell* pDoc = pView->GetDocShell();
+ // #i53333# don't show help pages here
+ if ( !pDoc->IsHelpDocument() )
+ {
+ OUString sEntry = pDoc->GetTitle() + " (";
+ if (pView == pActView)
+ {
+ nAct = nCount;
+ sEntry += m_aStatusArr[IDX_STR_ACTIVE];
+ }
+ else
+ sEntry += m_aStatusArr[IDX_STR_INACTIVE];
+ sEntry += ")";
+ m_xDocListBox->append_text(sEntry);
+
+ if (pConstView && pView == pConstView)
+ nConstPos = nCount;
+
+ nCount++;
+ }
+ pView = SwModule::GetNextView(pView);
+ }
+ m_xDocListBox->append_text(m_aStatusArr[3]); // "Active Window"
+ nCount++;
+
+ if(m_xContentTree->GetHiddenWrtShell())
+ {
+ OUString sEntry = m_xContentTree->GetHiddenWrtShell()->GetView().
+ GetDocShell()->GetTitle() +
+ " (" +
+ m_aStatusArr[IDX_STR_HIDDEN] +
+ ")";
+ m_xDocListBox->append_text(sEntry);
+ bDisable = false;
+ }
+
+ m_xDocListBox->thaw();
+
+ if(m_xContentTree->IsActiveView())
+ {
+ //Either the name of the current Document or "Active Document".
+ m_xDocListBox->set_active(pActView ? nAct : --nCount);
+ }
+ else if(m_xContentTree->IsHiddenView())
+ {
+ m_xDocListBox->set_active(nCount);
+ }
+ else
+ m_xDocListBox->set_active(nConstPos);
+
+ m_xDocListBox->set_sensitive(!bDisable);
+}
+
+IMPL_LINK(SwNavigationPI, DoneLink, SfxPoolItem const *, pItem, void)
+{
+ const SfxViewFrameItem* pFrameItem = dynamic_cast<SfxViewFrameItem const *>( pItem );
+ if( !pFrameItem )
+ return;
+
+ SfxViewFrame* pFrame = pFrameItem->GetFrame();
+ if(pFrame)
+ {
+ m_xContentTree->clear();
+ m_pContentView = dynamic_cast<SwView*>( pFrame->GetViewShell() );
+ OSL_ENSURE(m_pContentView, "no SwView");
+ if(m_pContentView)
+ m_pContentWrtShell = m_pContentView->GetWrtShellPtr();
+ else
+ m_pContentWrtShell = nullptr;
+ m_oObjectShell.emplace( pFrame->GetObjectShell() );
+ FillBox();
+ }
+}
+
+OUString SwNavigationPI::CreateDropFileName( const TransferableDataHelper& rData )
+{
+ OUString sFileName;
+ SotClipboardFormatId nFormat;
+ if( rData.HasFormat( nFormat = SotClipboardFormatId::FILE_LIST ))
+ {
+ FileList aFileList;
+ rData.GetFileList( nFormat, aFileList );
+ sFileName = aFileList.GetFile( 0 );
+ }
+ else if( rData.HasFormat( nFormat = SotClipboardFormatId::STRING ) ||
+ rData.HasFormat( nFormat = SotClipboardFormatId::SIMPLE_FILE ) ||
+ rData.HasFormat( nFormat = SotClipboardFormatId::FILENAME ))
+ {
+ (void)rData.GetString(nFormat, sFileName);
+ }
+ else if( rData.HasFormat( nFormat = SotClipboardFormatId::SOLK ) ||
+ rData.HasFormat( nFormat = SotClipboardFormatId::NETSCAPE_BOOKMARK )||
+ rData.HasFormat( nFormat = SotClipboardFormatId::FILECONTENT ) ||
+ rData.HasFormat( nFormat = SotClipboardFormatId::FILEGRPDESCRIPTOR ) ||
+ rData.HasFormat( nFormat = SotClipboardFormatId::UNIFORMRESOURCELOCATOR ))
+ {
+ INetBookmark aBkmk { OUString(), OUString() };
+ if (rData.GetINetBookmark(nFormat, aBkmk))
+ sFileName = aBkmk.GetURL();
+ }
+ if( !sFileName.isEmpty() )
+ {
+ sFileName = INetURLObject( sFileName ).GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ }
+ return sFileName;
+}
+
+sal_Int8 SwNavigationPI::AcceptDrop()
+{
+ return ( !m_xContentTree->IsInDrag() &&
+ ( m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::SIMPLE_FILE ) ||
+ m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::STRING ) ||
+ m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::SOLK ) ||
+ m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::NETSCAPE_BOOKMARK )||
+ m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::FILECONTENT ) ||
+ m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::FILEGRPDESCRIPTOR ) ||
+ m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::UNIFORMRESOURCELOCATOR ) ||
+ m_xContentTree->IsDropFormatSupported( SotClipboardFormatId::FILENAME )))
+ ? DND_ACTION_COPY
+ : DND_ACTION_NONE;
+}
+
+sal_Int8 SwNavigationPI::ExecuteDrop( const ExecuteDropEvent& rEvt )
+{
+ TransferableDataHelper aData( rEvt.maDropEvent.Transferable );
+ sal_Int8 nRet = DND_ACTION_NONE;
+ if (m_xContentTree->IsInDrag())
+ return nRet;
+
+ OUString sFileName = SwNavigationPI::CreateDropFileName(aData);
+ if (sFileName.isEmpty())
+ return nRet;
+
+ INetURLObject aTemp(sFileName);
+ GraphicDescriptor aDesc(aTemp);
+ if (aDesc.Detect()) // accept no graphics
+ return nRet;
+
+ if (-1 != sFileName.indexOf('#'))
+ return nRet;
+
+ if (m_sContentFileName.isEmpty() || m_sContentFileName != sFileName)
+ {
+ nRet = rEvt.mnAction;
+ sFileName = comphelper::string::stripEnd(sFileName, 0);
+ m_sContentFileName = sFileName;
+ if(m_oObjectShell)
+ {
+ m_xContentTree->SetHiddenShell( nullptr );
+ (*m_oObjectShell)->DoClose();
+ m_oObjectShell.reset();
+ }
+ SfxStringItem aFileItem(SID_FILE_NAME, sFileName );
+ SfxStringItem aOptionsItem( SID_OPTIONS, "HRC" );
+ SfxLinkItem aLink( SID_DONELINK,
+ LINK( this, SwNavigationPI, DoneLink ) );
+ if (SwView* pView = GetActiveView())
+ pView->GetViewFrame().GetDispatcher()->ExecuteList(
+ SID_OPENDOC, SfxCallMode::ASYNCHRON,
+ { &aFileItem, &aOptionsItem, &aLink });
+ }
+ return nRet;
+}
+
+void SwNavigationPI::SetRegionDropMode(RegionMode nNewMode)
+{
+ m_nRegionMode = nNewMode;
+ m_pConfig->SetRegionMode( m_nRegionMode );
+
+ OUString sImageId;
+ switch (nNewMode)
+ {
+ case RegionMode::NONE:
+ sImageId = RID_BMP_DROP_REGION;
+ break;
+ case RegionMode::LINK:
+ sImageId = RID_BMP_DROP_LINK;
+ break;
+ case RegionMode::EMBEDDED:
+ sImageId = RID_BMP_DROP_COPY;
+ break;
+ }
+ m_xContent6ToolBox->set_item_icon_name("dragmode", sImageId);
+}
+
+void SwNavigationPI::ToggleTree()
+{
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ m_xGlobalTree->HideTree();
+ return;
+ }
+
+ bool bGlobalDoc = IsGlobalDoc();
+ if (!IsGlobalMode() && bGlobalDoc)
+ {
+ if (IsZoomedIn())
+ ZoomOut();
+ m_xGlobalBox->show();
+ m_xGlobalTree->ShowTree();
+ m_xGlobalToolBox->show();
+ m_xContentBox->hide();
+ m_xContentTree->HideTree();
+ m_xContent1ToolBox->hide();
+ m_xContent2ToolBox->hide();
+ m_xContent3ToolBox->hide();
+ m_xContent4ToolBox->hide();
+ m_xContent5ToolBox->hide();
+ m_xContent6ToolBox->hide();
+ m_xDocListBox->hide();
+ SetGlobalMode(true);
+ }
+ else
+ {
+ m_xGlobalBox->hide();
+ m_xGlobalTree->HideTree();
+ m_xGlobalToolBox->hide();
+ if (!IsZoomedIn())
+ {
+ m_xContentBox->show();
+ m_xContentTree->ShowTree();
+ m_xContent1ToolBox->show();
+ m_xContent2ToolBox->show();
+ m_xContent3ToolBox->show();
+ m_xContent4ToolBox->show();
+ m_xContent5ToolBox->show();
+ m_xContent6ToolBox->show();
+ m_xDocListBox->show();
+ }
+ SetGlobalMode(false);
+ }
+}
+
+bool SwNavigationPI::IsGlobalDoc() const
+{
+ bool bRet = false;
+ SwView *pView = GetCreateView();
+ if (pView)
+ {
+ SwWrtShell &rSh = pView->GetWrtShell();
+ bRet = rSh.IsGlobalDoc();
+ }
+ return bRet;
+}
+
+IMPL_LINK_NOARG(SwNavigationPI, ChangePageHdl, Timer *, void)
+{
+ if (!m_xDocListBox) // disposed
+ return;
+ // tdf#134959 if the SpinButton changed value this Timer was launched, now
+ // change to the desired page, but we leave focus where it currently is,
+ // i.e. typically remaining in the spinbutton, or whatever other widget the
+ // user moved to in the meantime
+ EditAction();
+}
+
+void SwNavigationPI::SelectNavigateByContentType(const OUString& rContentTypeName)
+{
+ if (!m_pNavigateByComboBox)
+ return;
+ if (auto nPos = m_pNavigateByComboBox->find_text(rContentTypeName); nPos != -1)
+ {
+ m_pNavigateByComboBox->set_active(nPos);
+ UpdateNavigateBy();
+ }
+}
+
+IMPL_LINK_NOARG(SwNavigationPI, EditActionHdl, weld::Entry&, bool)
+{
+ // tdf#134959 if the user presses enter to activate the Entry
+ // go to the page, and on success we move focus to the document
+ if (EditAction())
+ m_pCreateView->GetEditWin().GrabFocus();
+ return true;
+}
+
+IMPL_LINK_NOARG(SwNavigationPI, PageEditModifyHdl, weld::SpinButton&, void)
+{
+ if (m_aPageChgIdle.IsActive())
+ m_aPageChgIdle.Stop();
+ m_aPageChgIdle.Start();
+}
+
+SwView* SwNavigationPI::GetCreateView() const
+{
+ if (!m_pCreateView)
+ {
+ SwView* pView = SwModule::GetFirstView();
+ while (pView)
+ {
+ if(&pView->GetViewFrame().GetBindings() == &m_rBindings)
+ {
+ const_cast<SwNavigationPI*>(this)->m_pCreateView = pView;
+ const_cast<SwNavigationPI*>(this)->StartListening(*m_pCreateView);
+ break;
+ }
+ pView = SwModule::GetNextView(pView);
+ }
+ }
+ return m_pCreateView;
+}
+
+class SwNavigatorWin : public SfxNavigator
+{
+private:
+ std::unique_ptr<SwNavigationPI> m_xNavi;
+public:
+ SwNavigatorWin(SfxBindings* _pBindings, SfxChildWindow* _pMgr,
+ vcl::Window* pParent, SfxChildWinInfo* pInfo);
+ virtual void StateChanged(StateChangedType nStateChange) override;
+ virtual void dispose() override
+ {
+ m_xNavi.reset();
+ SfxNavigator::dispose();
+ }
+ virtual ~SwNavigatorWin() override
+ {
+ disposeOnce();
+ }
+};
+
+SwNavigatorWin::SwNavigatorWin(SfxBindings* _pBindings, SfxChildWindow* _pMgr,
+ vcl::Window* pParent, SfxChildWinInfo* pInfo)
+ : SfxNavigator(_pBindings, _pMgr, pParent, pInfo)
+ , m_xNavi(std::make_unique<SwNavigationPI>(m_xContainer.get(), _pBindings->GetActiveFrame(), _pBindings, this))
+{
+ _pBindings->Invalidate(SID_NAVIGATOR);
+
+ SwNavigationConfig* pNaviConfig = SW_MOD()->GetNavigationConfig();
+
+ SetMinOutputSizePixel(GetOptimalSize());
+ if (pNaviConfig->IsSmall())
+ m_xNavi->ZoomIn();
+}
+
+void SwNavigatorWin::StateChanged(StateChangedType nStateChange)
+{
+ SfxNavigator::StateChanged(nStateChange);
+ if (nStateChange == StateChangedType::InitShow)
+ m_xNavi->UpdateInitShow();
+}
+
+SFX_IMPL_DOCKINGWINDOW(SwNavigatorWrapper, SID_NAVIGATOR);
+
+SwNavigatorWrapper::SwNavigatorWrapper(vcl::Window *_pParent, sal_uInt16 nId,
+ SfxBindings* pBindings, SfxChildWinInfo* pInfo)
+ : SfxNavigatorWrapper(_pParent, nId)
+{
+ SetWindow(VclPtr<SwNavigatorWin>::Create(pBindings, this, _pParent, pInfo));
+ Initialize();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/numfmtlb.cxx b/sw/source/uibase/utlui/numfmtlb.cxx
new file mode 100644
index 0000000000..4dffed15d2
--- /dev/null
+++ b/sw/source/uibase/utlui/numfmtlb.cxx
@@ -0,0 +1,470 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <i18nlangtag/lang.h>
+#include <svl/numformat.hxx>
+#include <svl/zformat.hxx>
+#include <svl/eitem.hxx>
+#include <svx/svxids.hrc>
+#include <svx/numinf.hxx>
+#include <svx/flagsdef.hxx>
+#include <svl/itemset.hxx>
+#include <osl/diagnose.h>
+#include <docsh.hxx>
+#include <swtypes.hxx>
+#include <swmodule.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <numfmtlb.hxx>
+#include <strings.hrc>
+#include <swabstdlg.hxx>
+#include <memory>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+
+/**
+ * Description:
+ * nFormatType: Display the formats of this Type
+ * nDefaultFormat: Select this format and possibly insert it
+ */
+
+namespace
+{
+
+bool lcl_isSystemFormat(sal_uInt32 nDefaultFormat, SvNumberFormatter* pFormatter, LanguageType eCurLanguage)
+{
+ const sal_uInt32 nSysNumFormat = pFormatter->GetFormatIndex(NF_NUMBER_SYSTEM, eCurLanguage);
+ if (nDefaultFormat == nSysNumFormat)
+ return true;
+ const sal_uInt32 nSysShortDateFormat = pFormatter->GetFormatIndex(NF_DATE_SYSTEM_SHORT, eCurLanguage);
+ if (nDefaultFormat == nSysShortDateFormat)
+ return true;
+ const sal_uInt32 nSysLongDateFormat = pFormatter->GetFormatIndex(NF_DATE_SYSTEM_LONG, eCurLanguage);
+ if (nDefaultFormat == nSysLongDateFormat)
+ return true;
+
+ if ( eCurLanguage != GetAppLanguage() )
+ return false;
+
+ if (nDefaultFormat == pFormatter->GetFormatForLanguageIfBuiltIn(nSysNumFormat, LANGUAGE_SYSTEM))
+ return true;
+ if (nDefaultFormat == pFormatter->GetFormatForLanguageIfBuiltIn(nSysShortDateFormat, LANGUAGE_SYSTEM))
+ return true;
+ if (nDefaultFormat == pFormatter->GetFormatForLanguageIfBuiltIn(nSysLongDateFormat, LANGUAGE_SYSTEM))
+ return true;
+
+ return false;
+}
+
+}
+
+double SwNumFormatBase::GetDefValue(const SvNumFormatType nFormatType)
+{
+ SvxNumValCategory nDefValue = SvxNumValCategory::Standard;
+
+ switch (nFormatType)
+ {
+ case SvNumFormatType::DATE:
+ case SvNumFormatType::DATE|SvNumFormatType::TIME:
+ nDefValue = SvxNumValCategory::Date;
+ break;
+
+ case SvNumFormatType::TIME:
+ nDefValue = SvxNumValCategory::Time;
+ break;
+
+ case SvNumFormatType::TEXT:
+ case SvNumFormatType::UNDEFINED:
+ nDefValue = SvxNumValCategory::Standard;
+ break;
+
+ case SvNumFormatType::CURRENCY:
+ nDefValue = SvxNumValCategory::Currency;
+ break;
+
+ case SvNumFormatType::PERCENT:
+ nDefValue = SvxNumValCategory::Percent;
+ break;
+
+ case SvNumFormatType::LOGICAL:
+ nDefValue = SvxNumValCategory::Boolean;
+ break;
+
+ default:
+ nDefValue = SvxNumValCategory::Standard;
+ break;
+ }
+
+ return fSvxNumValConst[nDefValue];
+}
+
+SwNumFormatBase::SwNumFormatBase()
+ : m_nStdEntry(0)
+ , m_nDefFormat(0)
+ , m_nCurrFormatType(SvNumFormatType::ALL)
+ , m_bOneArea(false)
+ , mbCurrFormatTypeNeedsInit(true)
+ , m_bShowLanguageControl(false)
+ , m_bUseAutomaticLanguage(true)
+{
+}
+
+NumFormatListBox::NumFormatListBox(std::unique_ptr<weld::ComboBox> xControl)
+ : mxControl(std::move(xControl))
+{
+ Init();
+}
+
+SwNumFormatTreeView::SwNumFormatTreeView(std::unique_ptr<weld::TreeView> xControl)
+ : mxControl(std::move(xControl))
+{
+ Init();
+}
+
+void SwNumFormatBase::Init()
+{
+ if (SwView *pView = GetActiveView())
+ m_eCurLanguage = pView->GetWrtShell().GetCurLang();
+ else
+ m_eCurLanguage = SvtSysLocale().GetLanguageTag().getLanguageType();
+
+ SetFormatType(SvNumFormatType::NUMBER);
+ SetDefFormat(m_nDefFormat);
+}
+
+void NumFormatListBox::Init()
+{
+ SwNumFormatBase::Init();
+
+ mxControl->connect_changed(LINK(this, NumFormatListBox, SelectHdl));
+}
+
+void SwNumFormatTreeView::Init()
+{
+ SwNumFormatBase::Init();
+
+ mxControl->connect_changed(LINK(this, SwNumFormatTreeView, SelectHdl));
+}
+
+void SwNumFormatBase::SetFormatType(const SvNumFormatType nFormatType)
+{
+ if (!mbCurrFormatTypeNeedsInit &&
+ (m_nCurrFormatType & nFormatType)) // there are mixed formats, like for example DateTime
+ return;
+
+ SwView *pView = GetActiveView();
+ if(!pView)
+ return;
+ SwWrtShell &rSh = pView->GetWrtShell();
+ SvNumberFormatter* pFormatter = rSh.GetNumberFormatter();
+
+ clear(); // Remove all entries from the Listbox
+
+ NfIndexTableOffset eOffsetStart = NF_NUMBER_START;
+ NfIndexTableOffset eOffsetEnd = NF_NUMBER_START;
+
+ switch( nFormatType )
+ {
+ case SvNumFormatType::NUMBER:
+ eOffsetStart=NF_NUMBER_START;
+ eOffsetEnd=NF_NUMBER_END;
+ break;
+
+ case SvNumFormatType::PERCENT:
+ eOffsetStart=NF_PERCENT_START;
+ eOffsetEnd=NF_PERCENT_END;
+ break;
+
+ case SvNumFormatType::CURRENCY:
+ eOffsetStart=NF_CURRENCY_START;
+ eOffsetEnd=NF_CURRENCY_END;
+ break;
+
+ case SvNumFormatType::DATETIME:
+ eOffsetStart=NF_DATE_START;
+ eOffsetEnd=NF_TIME_END;
+ break;
+
+ case SvNumFormatType::DATE:
+ eOffsetStart=NF_DATE_START;
+ eOffsetEnd=NF_DATE_END;
+ break;
+
+ case SvNumFormatType::TIME:
+ eOffsetStart=NF_TIME_START;
+ eOffsetEnd=NF_TIME_END;
+ break;
+
+ case SvNumFormatType::SCIENTIFIC:
+ eOffsetStart=NF_SCIENTIFIC_START;
+ eOffsetEnd=NF_SCIENTIFIC_END;
+ break;
+
+ case SvNumFormatType::FRACTION:
+ eOffsetStart=NF_FRACTION_START;
+ eOffsetEnd=NF_FRACTION_END;
+ break;
+
+ case SvNumFormatType::LOGICAL:
+ eOffsetStart=NF_BOOLEAN;
+ eOffsetEnd=NF_BOOLEAN;
+ break;
+
+ case SvNumFormatType::TEXT:
+ eOffsetStart=NF_TEXT;
+ eOffsetEnd=NF_TEXT;
+ break;
+
+ case SvNumFormatType::ALL:
+ eOffsetStart=NF_NUMERIC_START;
+ eOffsetEnd = NfIndexTableOffset( NF_INDEX_TABLE_ENTRIES - 1 );
+ break;
+
+ default:
+ OSL_FAIL("what a format?");
+ break;
+ }
+
+ const SvNumberformat* pFormat;
+ sal_Int32 i = 0;
+ const Color* pCol;
+ double fVal = SwNumFormatBase::GetDefValue(nFormatType);
+ OUString sValue;
+
+ const sal_uInt32 nSysNumFormat = pFormatter->GetFormatIndex(
+ NF_NUMBER_SYSTEM, m_eCurLanguage );
+ const sal_uInt32 nSysShortDateFormat = pFormatter->GetFormatIndex(
+ NF_DATE_SYSTEM_SHORT, m_eCurLanguage );
+ const sal_uInt32 nSysLongDateFormat = pFormatter->GetFormatIndex(
+ NF_DATE_SYSTEM_LONG, m_eCurLanguage );
+
+ for( tools::Long nIndex = eOffsetStart; nIndex <= eOffsetEnd; ++nIndex )
+ {
+ const sal_uInt32 nFormat = pFormatter->GetFormatIndex(
+ static_cast<NfIndexTableOffset>(nIndex), m_eCurLanguage );
+ pFormat = pFormatter->GetEntry( nFormat );
+
+ if( nFormat == pFormatter->GetFormatIndex( NF_NUMBER_STANDARD,
+ m_eCurLanguage )
+ || const_cast<SvNumberformat*>(pFormat)->GetOutputString( fVal, sValue, &pCol )
+ || nFormatType == SvNumFormatType::UNDEFINED )
+ {
+ sValue = pFormat->GetFormatstring();
+ }
+ else if( nFormatType == SvNumFormatType::TEXT )
+ {
+ pFormatter->GetOutputString( "\"ABC\"", nFormat, sValue, &pCol);
+ }
+
+ if (nFormat != nSysNumFormat &&
+ nFormat != nSysShortDateFormat &&
+ nFormat != nSysLongDateFormat)
+ {
+ append(OUString::number(nFormat), sValue);
+
+ if( nFormat == pFormatter->GetStandardFormat(
+ nFormatType, m_eCurLanguage ) )
+ m_nStdEntry = i;
+ ++i;
+ }
+ }
+
+ append_text(SwResId(STR_DEFINE_NUMBERFORMAT));
+
+ set_active(m_nStdEntry);
+
+ m_nCurrFormatType = nFormatType;
+ mbCurrFormatTypeNeedsInit = false;
+
+}
+
+void SwNumFormatBase::SetDefFormat(const sal_uInt32 nDefaultFormat)
+{
+ if (nDefaultFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
+ {
+ m_nDefFormat = nDefaultFormat;
+ return;
+ }
+
+ SwView *pView = GetActiveView();
+ if(!pView)
+ return;
+ SwWrtShell &rSh = pView->GetWrtShell();
+ SvNumberFormatter* pFormatter = rSh.GetNumberFormatter();
+
+ SvNumFormatType nType = pFormatter->GetType(nDefaultFormat);
+
+ SetFormatType(nType);
+
+ sal_uInt32 nFormat = pFormatter->GetFormatForLanguageIfBuiltIn(nDefaultFormat, m_eCurLanguage);
+
+ for (sal_Int32 i = 0, nCount = get_count(); i < nCount; ++i)
+ {
+ if (nFormat == get_id(i).toUInt32())
+ {
+ set_active(i);
+ m_nStdEntry = i;
+ m_nDefFormat = GetFormat();
+ return;
+ }
+ }
+
+ // No entry found:
+ OUString sValue;
+ const Color* pCol = nullptr;
+
+ if (nType == SvNumFormatType::TEXT)
+ {
+ pFormatter->GetOutputString("\"ABC\"", nDefaultFormat, sValue, &pCol);
+ }
+ else
+ {
+ pFormatter->GetOutputString(SwNumFormatBase::GetDefValue(nType), nDefaultFormat, sValue, &pCol);
+ }
+
+ sal_Int32 nPos = 0;
+ while (get_id(nPos).toUInt32() == NUMBERFORMAT_ENTRY_NOT_FOUND)
+ nPos++;
+
+ if ( lcl_isSystemFormat(nDefaultFormat, pFormatter, m_eCurLanguage) )
+ {
+ sValue += SwResId(RID_STR_SYSTEM);
+ }
+
+ insert_text(nPos, sValue); // Insert as first numeric entry
+ set_id(nPos, OUString::number(nDefaultFormat));
+ set_active(nPos);
+ m_nDefFormat = GetFormat();
+}
+
+sal_uInt32 NumFormatListBox::GetFormat() const
+{
+ return mxControl->get_active_id().toUInt32();
+}
+
+sal_uInt32 SwNumFormatTreeView::GetFormat() const
+{
+ return mxControl->get_selected_id().toUInt32();
+}
+
+void SwNumFormatBase::CallSelectHdl()
+{
+ const sal_Int32 nPos = get_active();
+ OUString sDefine(SwResId( STR_DEFINE_NUMBERFORMAT ));
+ SwView *pView = GetActiveView();
+
+ if (!pView || nPos != get_count() - 1 || get_text(nPos) != sDefine)
+ return;
+
+ SwWrtShell &rSh = pView->GetWrtShell();
+ SvNumberFormatter* pFormatter = rSh.GetNumberFormatter();
+
+ SfxItemSetFixed<
+ SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_INFO,
+ SID_ATTR_NUMBERFORMAT_ONE_AREA, SID_ATTR_NUMBERFORMAT_ONE_AREA,
+ SID_ATTR_NUMBERFORMAT_NOLANGUAGE,
+ SID_ATTR_NUMBERFORMAT_NOLANGUAGE,
+ SID_ATTR_NUMBERFORMAT_ADD_AUTO,
+ SID_ATTR_NUMBERFORMAT_ADD_AUTO> aCoreSet( rSh.GetAttrPool() );
+
+ double fValue = SwNumFormatBase::GetDefValue(m_nCurrFormatType);
+
+ sal_uInt32 nFormat = pFormatter->GetStandardFormat( m_nCurrFormatType, m_eCurLanguage);
+ aCoreSet.Put( SfxUInt32Item( SID_ATTR_NUMBERFORMAT_VALUE, nFormat ));
+
+ aCoreSet.Put( SvxNumberInfoItem( pFormatter, fValue,
+ SID_ATTR_NUMBERFORMAT_INFO ) );
+
+ if( (SvNumFormatType::DATE | SvNumFormatType::TIME) & m_nCurrFormatType )
+ aCoreSet.Put(SfxBoolItem(SID_ATTR_NUMBERFORMAT_ONE_AREA, m_bOneArea));
+
+ aCoreSet.Put(SfxBoolItem(SID_ATTR_NUMBERFORMAT_NOLANGUAGE, !m_bShowLanguageControl));
+ aCoreSet.Put(SfxBoolItem(SID_ATTR_NUMBERFORMAT_ADD_AUTO, m_bUseAutomaticLanguage));
+
+ // force deselect to break mouse lock on selected entry
+ set_active(-1);
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateNumFormatDialog(&get_widget(), aCoreSet));
+
+ if (RET_OK == pDlg->Execute())
+ {
+ const SvxNumberInfoItem* pFormatInfoItem = pView->GetDocShell()->
+ GetItem( SID_ATTR_NUMBERFORMAT_INFO );
+
+ if( pFormatInfoItem )
+ {
+ for ( sal_uInt32 key : pFormatInfoItem->GetDelFormats() )
+ pFormatter->DeleteEntry( key );
+ }
+
+ const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
+ if( const SfxUInt32Item* pFormatValueItem = pOutSet->GetItemIfSet(
+ SID_ATTR_NUMBERFORMAT_VALUE, false ))
+ {
+ sal_uInt32 nNumberFormat = pFormatValueItem->GetValue();
+ // oj #105473# change order of calls
+ const SvNumberformat* pFormat = pFormatter->GetEntry(nNumberFormat);
+ if( pFormat )
+ m_eCurLanguage = pFormat->GetLanguage();
+ // SetDefFormat uses eCurLanguage to look for if this format already in the list
+ SetDefFormat(nNumberFormat);
+ }
+ const SfxBoolItem* pAddAutoItem;
+ if( m_bShowLanguageControl && (pAddAutoItem = pOutSet->GetItemIfSet(
+ SID_ATTR_NUMBERFORMAT_ADD_AUTO, false)))
+ {
+ m_bUseAutomaticLanguage = pAddAutoItem->GetValue();
+ }
+ }
+ else
+ SetDefFormat(nFormat);
+
+}
+
+IMPL_LINK_NOARG(NumFormatListBox, SelectHdl, weld::ComboBox&, void)
+{
+ CallSelectHdl();
+}
+
+IMPL_LINK_NOARG(SwNumFormatTreeView, SelectHdl, weld::TreeView&, void)
+{
+ CallSelectHdl();
+}
+
+void SwNumFormatBase::clear()
+{
+ mbCurrFormatTypeNeedsInit = true;
+ m_nCurrFormatType = SvNumFormatType::ALL;
+}
+
+void NumFormatListBox::clear()
+{
+ mxControl->clear();
+ SwNumFormatBase::clear();
+}
+
+void SwNumFormatTreeView::clear()
+{
+ mxControl->clear();
+ SwNumFormatBase::clear();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/prcntfld.cxx b/sw/source/uibase/utlui/prcntfld.cxx
new file mode 100644
index 0000000000..4c8eede661
--- /dev/null
+++ b/sw/source/uibase/utlui/prcntfld.cxx
@@ -0,0 +1,231 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <prcntfld.hxx>
+#include <vcl/fieldvalues.hxx>
+
+SwPercentField::SwPercentField(std::unique_ptr<weld::MetricSpinButton> pControl)
+ : m_pField(std::move(pControl))
+ , m_nOldMax(0)
+ , m_nOldMin(0)
+ , m_nLastPercent(-1)
+ , m_nLastValue(-1)
+ , m_nOldDigits(m_pField->get_digits())
+ , m_eOldUnit(FieldUnit::NONE)
+ , m_bLockAutoCalculation(false)
+{
+ sal_Int64 nMin, nMax;
+ m_pField->get_range(nMin, nMax, FieldUnit::TWIP);
+ m_nRefValue = DenormalizePercent(nMax);
+ m_pField->get_increments(m_nOldSpinSize, m_nOldPageSize, FieldUnit::NONE);
+}
+
+void SwPercentField::SetRefValue(sal_Int64 nValue)
+{
+ sal_Int64 nRealValue = GetRealValue(m_eOldUnit);
+
+ m_nRefValue = nValue;
+
+ if (!m_bLockAutoCalculation && (m_pField->get_unit() == FieldUnit::PERCENT))
+ set_value(nRealValue, m_eOldUnit);
+}
+
+void SwPercentField::ShowPercent(bool bPercent)
+{
+ if ((bPercent && m_pField->get_unit() == FieldUnit::PERCENT)
+ || (!bPercent && m_pField->get_unit() != FieldUnit::PERCENT))
+ return;
+
+ sal_Int64 nOldValue;
+
+ if (bPercent)
+ {
+ nOldValue = get_value();
+
+ m_eOldUnit = m_pField->get_unit();
+ m_nOldDigits = m_pField->get_digits();
+ m_pField->get_range(m_nOldMin, m_nOldMax, FieldUnit::NONE);
+ m_pField->get_increments(m_nOldSpinSize, m_nOldPageSize, FieldUnit::NONE);
+ m_pField->set_unit(FieldUnit::PERCENT);
+ m_pField->set_digits(0);
+
+ sal_Int64 nCurrentWidth
+ = vcl::ConvertValue(m_nOldMin, 0, m_nOldDigits, m_eOldUnit, FieldUnit::TWIP);
+ // round to 0.5 percent
+ int nPercent = m_nRefValue ? (((nCurrentWidth * 10) / m_nRefValue + 5) / 10) : 0;
+
+ m_pField->set_range(std::max(1, nPercent), 100, FieldUnit::NONE);
+ m_pField->set_increments(5, 10, FieldUnit::NONE);
+ if (nOldValue != m_nLastValue)
+ {
+ nCurrentWidth
+ = vcl::ConvertValue(nOldValue, 0, m_nOldDigits, m_eOldUnit, FieldUnit::TWIP);
+ nPercent = m_nRefValue ? (((nCurrentWidth * 10) / m_nRefValue + 5) / 10) : 0;
+ m_pField->set_value(nPercent, FieldUnit::NONE);
+ m_nLastPercent = nPercent;
+ m_nLastValue = nOldValue;
+ }
+ else
+ m_pField->set_value(m_nLastPercent, FieldUnit::NONE);
+ }
+ else
+ {
+ sal_Int64 nOldPercent = get_value(FieldUnit::PERCENT);
+
+ nOldValue = Convert(get_value(), m_pField->get_unit(), m_eOldUnit);
+
+ m_pField->set_unit(m_eOldUnit);
+ m_pField->set_digits(m_nOldDigits);
+ m_pField->set_range(m_nOldMin, m_nOldMax, FieldUnit::NONE);
+ m_pField->set_increments(m_nOldSpinSize, m_nOldPageSize, FieldUnit::NONE);
+
+ if (nOldPercent != m_nLastPercent)
+ {
+ set_value(nOldValue, m_eOldUnit);
+ m_nLastPercent = nOldPercent;
+ m_nLastValue = nOldValue;
+ }
+ else
+ set_value(m_nLastValue, m_eOldUnit);
+ }
+}
+
+void SwPercentField::set_value(sal_Int64 nNewValue, FieldUnit eInUnit)
+{
+ if (m_pField->get_unit() != FieldUnit::PERCENT || eInUnit == FieldUnit::PERCENT)
+ m_pField->set_value(Convert(nNewValue, eInUnit, m_pField->get_unit()), FieldUnit::NONE);
+ else
+ {
+ // Overwrite output value, do not restore later
+ sal_Int64 nPercent, nCurrentWidth;
+ if (eInUnit == FieldUnit::TWIP)
+ {
+ nCurrentWidth
+ = vcl::ConvertValue(nNewValue, 0, m_nOldDigits, FieldUnit::TWIP, FieldUnit::TWIP);
+ }
+ else
+ {
+ sal_Int64 nValue = Convert(nNewValue, eInUnit, m_eOldUnit);
+ nCurrentWidth = vcl::ConvertValue(nValue, 0, m_nOldDigits, m_eOldUnit, FieldUnit::TWIP);
+ }
+ nPercent = m_nRefValue ? (((nCurrentWidth * 10) / m_nRefValue + 5) / 10) : 0;
+ m_pField->set_value(nPercent, FieldUnit::NONE);
+ }
+}
+
+sal_Int64 SwPercentField::get_value(FieldUnit eOutUnit)
+{
+ return Convert(m_pField->get_value(FieldUnit::NONE), m_pField->get_unit(), eOutUnit);
+}
+
+void SwPercentField::set_min(sal_Int64 nNewMin, FieldUnit eInUnit)
+{
+ if (m_pField->get_unit() != FieldUnit::PERCENT)
+ m_pField->set_min(nNewMin, eInUnit);
+ else
+ {
+ if (eInUnit == FieldUnit::NONE)
+ eInUnit = m_eOldUnit;
+ m_nOldMin = Convert(nNewMin, eInUnit, m_eOldUnit);
+
+ int nPercent = Convert(nNewMin, eInUnit, FieldUnit::PERCENT);
+ m_pField->set_min(std::max(1, nPercent), FieldUnit::NONE);
+ }
+}
+
+void SwPercentField::set_max(sal_Int64 nNewMax, FieldUnit eInUnit)
+{
+ if (m_pField->get_unit() != FieldUnit::PERCENT)
+ m_pField->set_max(nNewMax, eInUnit);
+}
+
+sal_Int64 SwPercentField::NormalizePercent(sal_Int64 nValue)
+{
+ if (m_pField->get_unit() != FieldUnit::PERCENT)
+ nValue = m_pField->normalize(nValue);
+ else
+ nValue = nValue * ImpPower10(m_nOldDigits);
+ return nValue;
+}
+
+sal_Int64 SwPercentField::DenormalizePercent(sal_Int64 nValue)
+{
+ if (m_pField->get_unit() != FieldUnit::PERCENT)
+ nValue = m_pField->denormalize(nValue);
+ else
+ {
+ int nFactor = ImpPower10(m_nOldDigits);
+ nValue = ((nValue + (nFactor / 2)) / nFactor);
+ }
+ return nValue;
+}
+
+int SwPercentField::ImpPower10(sal_uInt16 n)
+{
+ int nValue = 1;
+
+ for (sal_uInt16 i = 0; i < n; ++i)
+ nValue *= 10;
+
+ return nValue;
+}
+
+sal_Int64 SwPercentField::GetRealValue(FieldUnit eOutUnit)
+{
+ if (m_pField->get_unit() != FieldUnit::PERCENT)
+ return get_value(eOutUnit);
+ else
+ return Convert(get_value(), m_pField->get_unit(), eOutUnit);
+}
+
+sal_Int64 SwPercentField::Convert(sal_Int64 nValue, FieldUnit eInUnit, FieldUnit eOutUnit)
+{
+ if (eInUnit == eOutUnit || (eInUnit == FieldUnit::NONE && eOutUnit == m_pField->get_unit())
+ || (eOutUnit == FieldUnit::NONE && eInUnit == m_pField->get_unit()))
+ return nValue;
+
+ if (eInUnit == FieldUnit::PERCENT)
+ {
+ // Convert to metric
+ sal_Int64 nTwipValue = (m_nRefValue * nValue + 50) / 100;
+
+ if (eOutUnit == FieldUnit::TWIP) // Only convert if necessary
+ return NormalizePercent(nTwipValue);
+ else
+ return vcl::ConvertValue(NormalizePercent(nTwipValue), 0, m_nOldDigits, FieldUnit::TWIP,
+ eOutUnit);
+ }
+
+ if (eOutUnit == FieldUnit::PERCENT)
+ {
+ // Convert to percent
+ sal_Int64 nCurrentWidth;
+ nValue = DenormalizePercent(nValue);
+
+ if (eInUnit == FieldUnit::TWIP) // Only convert if necessary
+ nCurrentWidth = nValue;
+ else
+ nCurrentWidth = vcl::ConvertValue(nValue, 0, m_nOldDigits, eInUnit, FieldUnit::TWIP);
+ // Round to 0.5 percent
+ return m_nRefValue ? (((nCurrentWidth * 1000) / m_nRefValue + 5) / 10) : 0;
+ }
+
+ return vcl::ConvertValue(nValue, 0, m_nOldDigits, eInUnit, eOutUnit);
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/shdwcrsr.cxx b/sw/source/uibase/utlui/shdwcrsr.cxx
new file mode 100644
index 0000000000..f897878408
--- /dev/null
+++ b/sw/source/uibase/utlui/shdwcrsr.cxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <shdwcrsr.hxx>
+#include <vcl/ptrstyle.hxx>
+
+using namespace ::com::sun::star;
+
+SwShadowCursor::~SwShadowCursor()
+{
+ if( USHRT_MAX != m_nOldMode )
+ DrawCursor( m_nOldMode);
+}
+
+void SwShadowCursor::SetPos( const Point& rPt, tools::Long nHeight, sal_uInt16 nMode )
+{
+ Point aPt( m_pWin->LogicToPixel( rPt ));
+ nHeight = m_pWin->LogicToPixel( Size( 0, nHeight )).Height();
+ if( m_aOldPt != aPt || m_nOldHeight != nHeight || m_nOldMode != nMode )
+ {
+ if( USHRT_MAX != m_nOldMode )
+ DrawCursor( m_nOldMode);
+
+ DrawCursor( nMode);
+ m_nOldMode = nMode;
+ m_nOldHeight = nHeight;
+ m_aOldPt = aPt;
+ }
+}
+
+void SwShadowCursor::DrawCursor( sal_uInt16 nMode )
+{
+ if( text::HoriOrientation::LEFT == nMode ) // Arrow to the right
+ m_pWin->SetPointer(PointerStyle::AutoScrollE);
+ else // Arrow to the left
+ m_pWin->SetPointer(PointerStyle::AutoScrollW);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/tmplctrl.cxx b/sw/source/uibase/utlui/tmplctrl.cxx
new file mode 100644
index 0000000000..2b68905cf4
--- /dev/null
+++ b/sw/source/uibase/utlui/tmplctrl.cxx
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/style.hxx>
+#include <svl/stritem.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/status.hxx>
+#include <vcl/weldutils.hxx>
+
+#include <swtypes.hxx>
+#include <strings.hrc>
+
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <swmodule.hxx>
+#include <cmdid.h>
+#include <docsh.hxx>
+#include <tmplctrl.hxx>
+
+SFX_IMPL_STATUSBAR_CONTROL( SwTemplateControl, SfxStringItem );
+
+SwTemplateControl::SwTemplateControl( sal_uInt16 _nSlotId,
+ sal_uInt16 _nId,
+ StatusBar& rStb ) :
+ SfxStatusBarControl( _nSlotId, _nId, rStb )
+{
+}
+
+SwTemplateControl::~SwTemplateControl()
+{
+}
+
+void SwTemplateControl::StateChangedAtStatusBarControl(
+ sal_uInt16 /*nSID*/, SfxItemState eState, const SfxPoolItem* pState )
+{
+ const SfxStringItem* pItem = nullptr;
+ if (SfxItemState::DEFAULT == eState && (pItem = dynamic_cast<const SfxStringItem*>(pState)))
+ {
+ m_sTemplate = pItem->GetValue();
+ GetStatusBar().SetItemText(GetId(), m_sTemplate);
+ GetStatusBar().SetQuickHelpText(GetId(), SwResId(STR_TMPLCTRL_HINT));
+ }
+ else
+ {
+ GetStatusBar().SetItemText(GetId(), OUString());
+ GetStatusBar().SetQuickHelpText(GetId(), u""_ustr);
+ }
+}
+
+void SwTemplateControl::Paint( const UserDrawEvent& )
+{
+}
+
+void SwTemplateControl::Command( const CommandEvent& rCEvt )
+{
+ if ( rCEvt.GetCommand() != CommandEventId::ContextMenu ||
+ GetStatusBar().GetItemText( GetId() ).isEmpty())
+ return;
+
+ {
+ SwView* pView = ::GetActiveView();
+ SwWrtShell *const pWrtShell(pView ? pView->GetWrtShellPtr() : nullptr);
+ if (nullptr != pWrtShell &&
+ !pWrtShell->SwCursorShell::HasSelection()&&
+ !pWrtShell->IsSelFrameMode() &&
+ !pWrtShell->IsObjSelected())
+ {
+ SfxStyleSheetBasePool* pPool = pView->GetDocShell()->
+ GetStyleSheetPool();
+ auto xIter = pPool->CreateIterator(SfxStyleFamily::Page);
+ if (xIter->Count() > 1)
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, "modules/swriter/ui/pagestylemenu.ui"));
+ std::unique_ptr<weld::Menu> xPopup(xBuilder->weld_menu("menu"));
+
+ sal_uInt32 nCount = 0;
+ SfxStyleSheetBase* pStyle = xIter->First();
+ while( pStyle )
+ {
+ xPopup->append(OUString::number(++nCount), pStyle->GetName());
+ pStyle = xIter->Next();
+ }
+
+ ::tools::Rectangle aRect(rCEvt.GetMousePosPixel(), Size(1, 1));
+ weld::Window* pParent = weld::GetPopupParent(GetStatusBar(), aRect);
+ OUString sResult = xPopup->popup_at_rect(pParent, aRect);
+ if (!sResult.isEmpty())
+ {
+ sal_uInt32 nCurrId = sResult.toUInt32();
+ // looks a bit awkward, but another way is not possible
+ pStyle = xIter->operator[]( nCurrId - 1 );
+ SfxStringItem aStyle( FN_SET_PAGE_STYLE, pStyle->GetName() );
+ pWrtShell->GetView().GetViewFrame().GetDispatcher()->ExecuteList(
+ FN_SET_PAGE_STYLE,
+ SfxCallMode::SLOT|SfxCallMode::RECORD,
+ { &aStyle });
+ }
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/uiitems.cxx b/sw/source/uibase/utlui/uiitems.cxx
new file mode 100644
index 0000000000..b88751abdd
--- /dev/null
+++ b/sw/source/uibase/utlui/uiitems.cxx
@@ -0,0 +1,277 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <comphelper/servicehelper.hxx>
+#include <editeng/itemtype.hxx>
+#include <tools/UnitConversion.hxx>
+#include <unosett.hxx>
+
+#include <swtypes.hxx>
+#include <cmdid.h>
+#include <uiitems.hxx>
+
+#include <strings.hrc>
+#include <unomid.h>
+#include <numrule.hxx>
+
+#include <editeng/eerdll.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+SwPageFootnoteInfoItem::SwPageFootnoteInfoItem( SwPageFootnoteInfo const & rInfo) :
+ SfxPoolItem( FN_PARAM_FTN_INFO ),
+ m_aFootnoteInfo(rInfo)
+{
+}
+
+SwPageFootnoteInfoItem::~SwPageFootnoteInfoItem()
+{
+}
+
+SwPageFootnoteInfoItem* SwPageFootnoteInfoItem::Clone( SfxItemPool * /*pPool*/ ) const
+{
+ return new SwPageFootnoteInfoItem( *this );
+}
+
+bool SwPageFootnoteInfoItem::operator==( const SfxPoolItem& rAttr ) const
+{
+ return SfxPoolItem::operator==(rAttr)
+ && m_aFootnoteInfo == static_cast<const SwPageFootnoteInfoItem&>(rAttr).m_aFootnoteInfo;
+}
+
+bool SwPageFootnoteInfoItem::GetPresentation
+(
+ SfxItemPresentation /*ePres*/,
+ MapUnit eCoreUnit,
+ MapUnit ePresUnit,
+ OUString& rText,
+ const IntlWrapper& rIntl
+) const
+{
+ const SwTwips nHght = GetPageFootnoteInfo().GetHeight();
+ if ( nHght )
+ {
+ rText = SwResId( STR_MAX_FTN_HEIGHT ) + " " +
+ ::GetMetricText( nHght, eCoreUnit, ePresUnit, &rIntl ) + " " +
+ EditResId( ::GetMetricId( ePresUnit ) );
+ }
+ return true;
+}
+
+bool SwPageFootnoteInfoItem::QueryValue( Any& rVal, sal_uInt8 nMemberId ) const
+{
+ bool bRet = true;
+ switch(nMemberId & ~CONVERT_TWIPS)
+ {
+ case MID_FTN_HEIGHT : rVal <<= static_cast<sal_Int32>(convertTwipToMm100(m_aFootnoteInfo.GetHeight()));break;
+ case MID_LINE_WEIGHT : rVal <<= static_cast<sal_Int16>(convertTwipToMm100(m_aFootnoteInfo.GetLineWidth()));break;
+ case MID_LINE_COLOR : rVal <<= m_aFootnoteInfo.GetLineColor();break;
+ case MID_LINE_RELWIDTH :
+ {
+ Fraction aTmp( 100, 1 );
+ aTmp *= m_aFootnoteInfo.GetWidth();
+ rVal <<= static_cast<sal_Int8>(static_cast<tools::Long>(aTmp));
+ }
+ break;
+ case MID_LINE_ADJUST : rVal <<= static_cast<sal_Int16>(m_aFootnoteInfo.GetAdj());break;//text::HorizontalAdjust
+ case MID_LINE_TEXT_DIST : rVal <<= static_cast<sal_Int32>(convertTwipToMm100(m_aFootnoteInfo.GetTopDist()));break;
+ case MID_LINE_FOOTNOTE_DIST: rVal <<= static_cast<sal_Int32>(convertTwipToMm100(m_aFootnoteInfo.GetBottomDist()));break;
+ case MID_FTN_LINE_STYLE :
+ {
+ switch ( m_aFootnoteInfo.GetLineStyle( ) )
+ {
+ default:
+ case SvxBorderLineStyle::NONE : rVal <<= sal_Int8(0); break;
+ case SvxBorderLineStyle::SOLID: rVal <<= sal_Int8(1); break;
+ case SvxBorderLineStyle::DOTTED: rVal <<= sal_Int8(2); break;
+ case SvxBorderLineStyle::DASHED: rVal <<= sal_Int8(3); break;
+ }
+ break;
+ }
+ default:
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwPageFootnoteInfoItem::PutValue(const Any& rVal, sal_uInt8 nMemberId)
+{
+ sal_Int32 nSet32 = 0;
+ Color aColor;
+ bool bRet = true;
+ switch(nMemberId & ~CONVERT_TWIPS)
+ {
+ case MID_LINE_COLOR :
+ rVal >>= aColor;
+ m_aFootnoteInfo.SetLineColor(aColor);
+ break;
+ case MID_FTN_HEIGHT:
+ case MID_LINE_TEXT_DIST :
+ case MID_LINE_FOOTNOTE_DIST:
+ rVal >>= nSet32;
+ if(nSet32 < 0)
+ bRet = false;
+ else
+ {
+ nSet32 = o3tl::toTwips(nSet32, o3tl::Length::mm100);
+ switch(nMemberId & ~CONVERT_TWIPS)
+ {
+ case MID_FTN_HEIGHT: m_aFootnoteInfo.SetHeight(nSet32); break;
+ case MID_LINE_TEXT_DIST: m_aFootnoteInfo.SetTopDist(nSet32);break;
+ case MID_LINE_FOOTNOTE_DIST: m_aFootnoteInfo.SetBottomDist(nSet32);break;
+ }
+ }
+ break;
+ case MID_LINE_WEIGHT :
+ {
+ sal_Int16 nSet = 0;
+ rVal >>= nSet;
+ if(nSet >= 0)
+ m_aFootnoteInfo.SetLineWidth(o3tl::toTwips(nSet, o3tl::Length::mm100));
+ else
+ bRet = false;
+ }
+ break;
+ case MID_LINE_RELWIDTH :
+ {
+ sal_Int8 nSet = 0;
+ rVal >>= nSet;
+ if(nSet < 0)
+ bRet = false;
+ else
+ m_aFootnoteInfo.SetWidth(Fraction(nSet, 100));
+ }
+ break;
+ case MID_LINE_ADJUST :
+ {
+ sal_Int16 nSet = 0;
+ rVal >>= nSet;
+ if(nSet >= 0 && nSet < 3) //text::HorizontalAdjust
+ m_aFootnoteInfo.SetAdj(static_cast<css::text::HorizontalAdjust>(nSet));
+ else
+ bRet = false;
+ }
+ break;
+ case MID_FTN_LINE_STYLE:
+ {
+ SvxBorderLineStyle eStyle = SvxBorderLineStyle::NONE;
+ sal_Int8 nSet = 0;
+ rVal >>= nSet;
+ switch ( nSet )
+ {
+ case 1: eStyle = SvxBorderLineStyle::SOLID; break;
+ case 2: eStyle = SvxBorderLineStyle::DOTTED; break;
+ case 3: eStyle = SvxBorderLineStyle::DASHED; break;
+ default: break;
+ }
+ m_aFootnoteInfo.SetLineStyle( eStyle );
+ }
+ break;
+ default:
+ bRet = false;
+ }
+ return bRet;
+}
+
+SwPtrItem::SwPtrItem( const sal_uInt16 nId, void* pPtr ) :
+ SfxPoolItem( nId ),
+ m_pMisc(pPtr)
+{
+}
+
+// Cloning
+
+SwPtrItem* SwPtrItem::Clone( SfxItemPool * /*pPool*/ ) const
+{
+ return new SwPtrItem( *this );
+}
+
+bool SwPtrItem::operator==( const SfxPoolItem& rAttr ) const
+{
+ return SfxPoolItem::operator==(rAttr)
+ && m_pMisc == static_cast<const SwPtrItem&>(rAttr).m_pMisc;
+}
+
+// SwUINumRuleItem for the NumTabPages of the FormatNumRule/Styleists
+
+SwUINumRuleItem::SwUINumRuleItem( const SwNumRule& rRul )
+ : SfxPoolItem( FN_PARAM_ACT_NUMBER ), m_pRule( new SwNumRule( rRul ) )
+{
+}
+
+SwUINumRuleItem::SwUINumRuleItem( const SwUINumRuleItem& rItem )
+ : SfxPoolItem( rItem ),
+ m_pRule( new SwNumRule( *rItem.m_pRule ))
+{
+}
+
+SwUINumRuleItem::~SwUINumRuleItem()
+{
+}
+
+SwUINumRuleItem* SwUINumRuleItem::Clone( SfxItemPool * /*pPool*/ ) const
+{
+ return new SwUINumRuleItem( *this );
+}
+
+bool SwUINumRuleItem::operator==( const SfxPoolItem& rAttr ) const
+{
+ return SfxPoolItem::operator==(rAttr)
+ && *m_pRule == *static_cast<const SwUINumRuleItem&>(rAttr).m_pRule;
+}
+
+bool SwUINumRuleItem::QueryValue( uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const
+{
+ uno::Reference< container::XIndexReplace >xRules = new SwXNumberingRules(*m_pRule);
+ rVal <<= xRules;
+ return true;
+}
+bool SwUINumRuleItem::PutValue( const uno::Any& rVal, sal_uInt8 /*nMemberId*/ )
+{
+ uno::Reference< container::XIndexReplace> xRulesRef;
+ if(rVal >>= xRulesRef)
+ {
+ auto pSwXRules = dynamic_cast<SwXNumberingRules*>(xRulesRef.get());
+ if(pSwXRules)
+ {
+ *m_pRule = *pSwXRules->GetNumRule();
+ }
+ }
+ return true;
+}
+
+SwPaMItem::SwPaMItem( const sal_uInt16 nId, SwPaM* pPaM ) :
+ SfxPoolItem( nId ),
+ m_pPaM(pPaM)
+{
+}
+
+SwPaMItem* SwPaMItem::Clone( SfxItemPool * /*pPool*/ ) const
+{
+ return new SwPaMItem( *this );
+}
+
+bool SwPaMItem::operator==( const SfxPoolItem& rAttr ) const
+{
+ return SfxPoolItem::operator==(rAttr)
+ && m_pPaM == static_cast<const SwPaMItem&>(rAttr).m_pPaM;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/uitool.cxx b/sw/source/uibase/utlui/uitool.cxx
new file mode 100644
index 0000000000..fd50bf6678
--- /dev/null
+++ b/sw/source/uibase/utlui/uitool.cxx
@@ -0,0 +1,921 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+
+#include <osl/diagnose.h>
+#include <tools/datetime.hxx>
+#include <vcl/weld.hxx>
+#include <unotools/collatorwrapper.hxx>
+#include <svl/stritem.hxx>
+#include <svl/grabbagitem.hxx>
+#include <unotools/syslocale.hxx>
+#include <IDocumentStylePoolAccess.hxx>
+#include <editeng/pmdlitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/sizeitem.hxx>
+#include <editeng/brushitem.hxx>
+#include <svx/pageitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <svl/style.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <com/sun/star/awt/XPopupMenu.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/util/URLTransformer.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <comphelper/processfactory.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <fmtornt.hxx>
+#include <tabcol.hxx>
+#include <fmtfsize.hxx>
+#include <fmthdft.hxx>
+#include <fmtpdsc.hxx>
+#include <uiitems.hxx>
+#include <docsh.hxx>
+#include <wrtsh.hxx>
+#include <swmodule.hxx>
+#include <view.hxx>
+#include <uitool.hxx>
+#include <frmatr.hxx>
+#include <paratr.hxx>
+#include <fmtcol.hxx>
+#include <usrpref.hxx>
+
+#include <cmdid.h>
+#include <doc.hxx>
+#include <charfmt.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <strings.hrc>
+#include <docmodel/color/ComplexColor.hxx>
+
+// 50 cm 28350
+#define MAXHEIGHT 28350
+#define MAXWIDTH 28350
+
+using namespace ::com::sun::star;
+
+// General list of string pointer
+
+// Set boxinfo attribute
+
+void PrepareBoxInfo(SfxItemSet& rSet, const SwWrtShell& rSh)
+{
+ std::shared_ptr<SvxBoxInfoItem> aBoxInfo(std::make_shared<SvxBoxInfoItem>(SID_ATTR_BORDER_INNER));
+
+ if ( const SvxBoxInfoItem *pBoxInfo = rSet.GetItemIfSet( SID_ATTR_BORDER_INNER ))
+ {
+ aBoxInfo.reset(pBoxInfo->Clone());
+ }
+
+ // Table variant: If more than one table cells are selected
+ rSh.GetCursor(); //So that GetCursorCnt() returns the right thing
+ aBoxInfo->SetTable (rSh.IsTableMode() && rSh.GetCursorCnt() > 1);
+ // Always show the distance field
+ aBoxInfo->SetDist (true);
+ // Set minimal size in tables and paragraphs
+ aBoxInfo->SetMinDist (rSh.IsTableMode() || rSh.GetSelectionType() & (SelectionType::Text | SelectionType::Table));
+ // Set always the default distance
+ aBoxInfo->SetDefDist (MIN_BORDER_DIST);
+ // Single lines can have only in tables DontCare-Status
+ aBoxInfo->SetValid(SvxBoxInfoItemValidFlags::DISABLE, !rSh.IsTableMode());
+
+ rSet.Put(*aBoxInfo);
+}
+
+void ConvertAttrCharToGen(SfxItemSet& rSet, bool bIsPara)
+{
+ // Background / highlight
+ {
+ // Always use the visible background
+ if( const SvxBrushItem *pTmpBrush = rSet.GetItemIfSet( RES_CHRATR_HIGHLIGHT ) )
+ {
+ SvxBrushItem aTmpBrush( *pTmpBrush );
+ if( aTmpBrush.GetColor() != COL_TRANSPARENT )
+ {
+ aTmpBrush.SetWhich( RES_CHRATR_BACKGROUND );
+ rSet.Put( aTmpBrush );
+ }
+ }
+ }
+
+ if ( bIsPara )
+ return;
+
+ // Tell dialogs to use character-specific slots/whichIds
+ // tdf#126684: We use RES_PARATR_GRABBAG, because RES_CHRATR_GRABBAG may be overwritten later in
+ // SwDocStyleSheet::GetItemSet when applying attributes from char format
+ assert(SfxItemState::SET != rSet.GetItemState(RES_PARATR_GRABBAG, false));
+ SfxGrabBagItem aGrabBag(RES_PARATR_GRABBAG);
+ aGrabBag.GetGrabBag()["DialogUseCharAttr"] <<= true;
+ // Store initial ranges to allow restoring later
+ uno::Sequence<sal_uInt16> aOrigRanges(rSet.GetRanges().size() * 2 + 1);
+ int i = 0;
+ for (const auto& rPair : rSet.GetRanges())
+ {
+ aOrigRanges.getArray()[i++] = rPair.first;
+ aOrigRanges.getArray()[i++] = rPair.second;
+ }
+ aOrigRanges.getArray()[i++] = 0;
+ aGrabBag.GetGrabBag()["OrigItemSetRanges"] <<= aOrigRanges;
+ rSet.MergeRange(RES_PARATR_GRABBAG, RES_PARATR_GRABBAG);
+ rSet.Put(aGrabBag);
+}
+
+void ConvertAttrGenToChar(SfxItemSet& rSet, const SfxItemSet& rOrigSet, bool bIsPara)
+{
+ // Background / highlighting
+ if( SfxItemState::SET == rSet.GetItemState( RES_CHRATR_BACKGROUND, false ) )
+ {
+ // Highlight is an MS specific thing, so remove it at the first time when LO modifies
+ // this part of the imported document.
+ rSet.Put( SvxBrushItem(RES_CHRATR_HIGHLIGHT) );
+
+ // Remove shading marker
+ if (const SfxGrabBagItem* pGrabBagItem = rOrigSet.GetItemIfSet(RES_CHRATR_GRABBAG, false))
+ {
+ SfxGrabBagItem aGrabBag(*pGrabBagItem);
+ std::map<OUString, css::uno::Any>& rMap = aGrabBag.GetGrabBag();
+ auto aIterator = rMap.find("CharShadingMarker");
+ if( aIterator != rMap.end() )
+ {
+ aIterator->second <<= false;
+ }
+ rSet.Put( aGrabBag );
+ }
+ }
+
+ if ( bIsPara )
+ return;
+
+ rSet.ClearItem( RES_BACKGROUND );
+
+ if (const SfxGrabBagItem* pGrabBagItem = rOrigSet.GetItemIfSet(RES_PARATR_GRABBAG, false))
+ {
+ SfxGrabBagItem aGrabBag(*pGrabBagItem);
+ std::map<OUString, css::uno::Any>& rMap = aGrabBag.GetGrabBag();
+ auto aIterator = rMap.find("OrigItemSetRanges");
+ if (aIterator != rMap.end())
+ {
+ uno::Sequence<sal_uInt16> aOrigRanges;
+ if ( aIterator->second >>= aOrigRanges )
+ {
+ assert(aOrigRanges.getLength() % 2 == 1);
+ int numPairs = (aOrigRanges.getLength()-1)/2;
+ std::unique_ptr<WhichPair[]> xPairs(new WhichPair[numPairs]);
+ for(int i=0; i<aOrigRanges.getLength()-1; i += 2)
+ {
+ xPairs[i/2] = { aOrigRanges[i], aOrigRanges[i+1] };
+ }
+ rSet.SetRanges(WhichRangesContainer(std::move(xPairs), numPairs));
+ }
+ }
+ }
+ assert(SfxItemState::SET != rSet.GetItemState(RES_PARATR_GRABBAG, false));
+}
+
+void ApplyCharBackground(Color const& rBackgroundColor, model::ComplexColor const& rComplexColor, SwWrtShell& rShell)
+{
+ rShell.StartUndo(SwUndoId::INSATTR);
+
+ SfxItemSetFixed<RES_CHRATR_GRABBAG, RES_CHRATR_GRABBAG> aCoreSet(rShell.GetView().GetPool());
+
+ rShell.GetCurAttr(aCoreSet);
+
+ // Set char background
+ rShell.SetAttrItem(SvxBrushItem(rBackgroundColor, rComplexColor, RES_CHRATR_BACKGROUND));
+
+ // Highlight is an MS specific thing, so remove it at the first time when LO modifies
+ // this part of the imported document.
+ rShell.SetAttrItem(SvxBrushItem(RES_CHRATR_HIGHLIGHT));
+
+ // Remove shading marker
+ if (const SfxGrabBagItem* pGrabBagItem = aCoreSet.GetItemIfSet(RES_CHRATR_GRABBAG, false))
+ {
+ SfxGrabBagItem aGrabBag(*pGrabBagItem);
+ std::map<OUString, css::uno::Any>& rMap = aGrabBag.GetGrabBag();
+ auto aIterator = rMap.find("CharShadingMarker");
+ if (aIterator != rMap.end())
+ {
+ aIterator->second <<= false;
+ }
+ rShell.SetAttrItem(aGrabBag);
+ }
+
+ rShell.EndUndo(SwUndoId::INSATTR);
+}
+
+// Fill header footer
+
+static void FillHdFt(SwFrameFormat* pFormat, const SfxItemSet& rSet)
+{
+ SwAttrSet aSet(pFormat->GetAttrSet());
+ aSet.Put(rSet);
+
+ const SvxSizeItem& rSize = rSet.Get(SID_ATTR_PAGE_SIZE);
+ const SfxBoolItem& rDynamic = rSet.Get(SID_ATTR_PAGE_DYNAMIC);
+
+ // Convert size
+ SwFormatFrameSize aFrameSize(rDynamic.GetValue() ? SwFrameSize::Minimum : SwFrameSize::Fixed,
+ rSize.GetSize().Width(),
+ rSize.GetSize().Height());
+ aSet.Put(aFrameSize);
+ pFormat->SetFormatAttr(aSet);
+}
+
+/// Convert from UseOnPage to SvxPageUsage.
+static SvxPageUsage lcl_convertUseToSvx(UseOnPage nUse)
+{
+ SvxPageUsage nRet = SvxPageUsage::NONE;
+ if (nUse & UseOnPage::Left)
+ nRet = SvxPageUsage::Left;
+ if (nUse & UseOnPage::Right)
+ nRet = SvxPageUsage::Right;
+ if ((nUse & UseOnPage::All) == UseOnPage::All)
+ nRet = SvxPageUsage::All;
+ if ((nUse & UseOnPage::Mirror) == UseOnPage::Mirror)
+ nRet = SvxPageUsage::Mirror;
+ return nRet;
+}
+
+/// Convert from SvxPageUsage to UseOnPage.
+static UseOnPage lcl_convertUseFromSvx(SvxPageUsage nUse)
+{
+ UseOnPage nRet = UseOnPage::NONE;
+ if (nUse == SvxPageUsage::Left)
+ nRet = UseOnPage::Left;
+ else if (nUse == SvxPageUsage::Right)
+ nRet = UseOnPage::Right;
+ else if (nUse == SvxPageUsage::All)
+ nRet = UseOnPage::All;
+ else if (nUse == SvxPageUsage::Mirror)
+ nRet = UseOnPage::Mirror;
+ return nRet;
+}
+
+// PageDesc <-> convert into sets and back
+
+void ItemSetToPageDesc( const SfxItemSet& rSet, SwPageDesc& rPageDesc )
+{
+ SwFrameFormat& rMaster = rPageDesc.GetMaster();
+ bool bFirstShare = false;
+
+ // before SetFormatAttr() in case it contains RES_BACKGROUND_FULL_SIZE
+ // itself, as it does when called from SwXPageStyle
+ if (const SfxGrabBagItem* pGrabBag = rSet.GetItemIfSet(SID_ATTR_CHAR_GRABBAG))
+ {
+ bool bValue;
+ const auto pGrabBagInner = pGrabBag->GetGrabBag();
+ const auto iter = pGrabBagInner.find("BackgroundFullSize");
+ assert(iter != pGrabBagInner.end());
+ if (iter->second >>= bValue)
+ {
+ rMaster.SetFormatAttr(SfxBoolItem(RES_BACKGROUND_FULL_SIZE, bValue));
+ }
+ auto it = pGrabBagInner.find("RtlGutter");
+ if (it != pGrabBagInner.end() && (it->second >>= bValue))
+ {
+ rMaster.SetFormatAttr(SfxBoolItem(RES_RTL_GUTTER, bValue));
+ }
+ }
+
+ // Transfer all general frame attributes
+ rMaster.SetFormatAttr(rSet);
+
+ // PageData
+ if(rSet.GetItemState(SID_ATTR_PAGE) == SfxItemState::SET)
+ {
+ const SvxPageItem& rPageItem = rSet.Get(SID_ATTR_PAGE);
+
+ const SvxPageUsage nUse = rPageItem.GetPageUsage();
+ if(nUse != SvxPageUsage::NONE)
+ rPageDesc.SetUseOn( lcl_convertUseFromSvx(nUse) );
+ rPageDesc.SetLandscape(rPageItem.IsLandscape());
+ SvxNumberType aNumType;
+ aNumType.SetNumberingType( rPageItem.GetNumType() );
+ rPageDesc.SetNumType(aNumType);
+ }
+ // Size
+ if(rSet.GetItemState(SID_ATTR_PAGE_SIZE) == SfxItemState::SET)
+ {
+ const SvxSizeItem& rSizeItem = rSet.Get(SID_ATTR_PAGE_SIZE);
+ SwFormatFrameSize aSize(SwFrameSize::Fixed);
+ aSize.SetSize(rSizeItem.GetSize());
+ rMaster.SetFormatAttr(aSize);
+ }
+ // Evaluate header attributes
+ if( const SvxSetItem* pHeaderSetItem = rSet.GetItemIfSet( SID_ATTR_PAGE_HEADERSET,
+ false ) )
+ {
+ const SfxItemSet& rHeaderSet = pHeaderSetItem->GetItemSet();
+ const SfxBoolItem& rHeaderOn = rHeaderSet.Get(SID_ATTR_PAGE_ON);
+
+ if(rHeaderOn.GetValue())
+ {
+ // Take over values
+ if(!rMaster.GetHeader().IsActive())
+ rMaster.SetFormatAttr(SwFormatHeader(true));
+
+ // Pick out everything and adapt the header format
+ SwFormatHeader aHeaderFormat(rMaster.GetHeader());
+ SwFrameFormat *pHeaderFormat = aHeaderFormat.GetHeaderFormat();
+ OSL_ENSURE(pHeaderFormat != nullptr, "no header format");
+
+ ::FillHdFt(pHeaderFormat, rHeaderSet);
+
+ rPageDesc.ChgHeaderShare(rHeaderSet.Get(SID_ATTR_PAGE_SHARED).GetValue());
+ rPageDesc.ChgFirstShare(static_cast<const SfxBoolItem&>(
+ rHeaderSet.Get(SID_ATTR_PAGE_SHARED_FIRST)).GetValue());
+ bFirstShare = true;
+ }
+ else
+ {
+ // Disable header
+ if(rMaster.GetHeader().IsActive())
+ {
+ rMaster.SetFormatAttr(SwFormatHeader(false));
+ rPageDesc.ChgHeaderShare(false);
+ }
+ }
+ }
+
+ // Evaluate footer attributes
+ if( const SvxSetItem* pFooterSetItem = rSet.GetItemIfSet( SID_ATTR_PAGE_FOOTERSET,
+ false ) )
+ {
+ const SfxItemSet& rFooterSet = pFooterSetItem->GetItemSet();
+ const SfxBoolItem& rFooterOn = rFooterSet.Get(SID_ATTR_PAGE_ON);
+
+ if(rFooterOn.GetValue())
+ {
+ // Take over values
+ if(!rMaster.GetFooter().IsActive())
+ rMaster.SetFormatAttr(SwFormatFooter(true));
+
+ // Pick out everything and adapt the footer format
+ SwFormatFooter aFooterFormat(rMaster.GetFooter());
+ SwFrameFormat *pFooterFormat = aFooterFormat.GetFooterFormat();
+ OSL_ENSURE(pFooterFormat != nullptr, "no footer format");
+
+ ::FillHdFt(pFooterFormat, rFooterSet);
+
+ rPageDesc.ChgFooterShare(rFooterSet.Get(SID_ATTR_PAGE_SHARED).GetValue());
+ if (!bFirstShare)
+ {
+ rPageDesc.ChgFirstShare(static_cast<const SfxBoolItem&>(
+ rFooterSet.Get(SID_ATTR_PAGE_SHARED_FIRST)).GetValue());
+ }
+ }
+ else
+ {
+ // Disable footer
+ if(rMaster.GetFooter().IsActive())
+ {
+ rMaster.SetFormatAttr(SwFormatFooter(false));
+ rPageDesc.ChgFooterShare(false);
+ }
+ }
+ }
+
+ // Footnotes
+
+ if( const SwPageFootnoteInfoItem* pFootnoteItem = rSet.GetItemIfSet( FN_PARAM_FTN_INFO,
+ false ) )
+ rPageDesc.SetFootnoteInfo( pFootnoteItem->GetPageFootnoteInfo() );
+
+ // Columns
+
+ // Register compliant
+
+ const SfxBoolItem* pRegisterModeItem = rSet.GetItemIfSet(
+ SID_SWREGISTER_MODE, false);
+ if(!pRegisterModeItem)
+ return;
+
+ bool bSet = pRegisterModeItem->GetValue();
+ if(!bSet)
+ rPageDesc.SetRegisterFormatColl(nullptr);
+ else if(const SfxStringItem* pCollectionItem = rSet.GetItemIfSet(
+ SID_SWREGISTER_COLLECTION, false))
+ {
+ const OUString& rColl = pCollectionItem->GetValue();
+ SwDoc& rDoc = *rMaster.GetDoc();
+ SwTextFormatColl* pColl = rDoc.FindTextFormatCollByName( rColl );
+ if( !pColl )
+ {
+ const sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(
+ rColl, SwGetPoolIdFromName::TxtColl );
+ if( USHRT_MAX != nId )
+ pColl = rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool( nId );
+ else
+ pColl = rDoc.MakeTextFormatColl( rColl,
+ rDoc.GetDfltTextFormatColl() );
+ }
+ if( pColl )
+ pColl->SetFormatAttr( SwRegisterItem ( true ));
+ rPageDesc.SetRegisterFormatColl( pColl );
+ }
+}
+
+namespace
+{
+bool IsOwnFormat(const SwDoc& rDoc)
+{
+ const SwDocShell* pDocShell = rDoc.GetDocShell();
+ SfxMedium* pMedium = pDocShell->GetMedium();
+ if (!pMedium)
+ {
+ return false;
+ }
+
+ std::shared_ptr<const SfxFilter> pFilter = pMedium->GetFilter();
+ if (!pFilter)
+ {
+ return false;
+ }
+
+ return pFilter->IsOwnFormat();
+}
+}
+
+void PageDescToItemSet( const SwPageDesc& rPageDesc, SfxItemSet& rSet)
+{
+ const SwFrameFormat& rMaster = rPageDesc.GetMaster();
+
+ // Page data
+ SvxPageItem aPageItem(SID_ATTR_PAGE);
+ aPageItem.SetDescName(rPageDesc.GetName());
+ aPageItem.SetPageUsage(lcl_convertUseToSvx(rPageDesc.GetUseOn()));
+ aPageItem.SetLandscape(rPageDesc.GetLandscape());
+ aPageItem.SetNumType(rPageDesc.GetNumType().GetNumberingType());
+ rSet.Put(aPageItem);
+
+ // Size
+ SvxSizeItem aSizeItem(SID_ATTR_PAGE_SIZE, rMaster.GetFrameSize().GetSize());
+ rSet.Put(aSizeItem);
+
+ // Maximum size
+ SvxSizeItem aMaxSizeItem(SID_ATTR_PAGE_MAXSIZE, Size(MAXWIDTH, MAXHEIGHT));
+ rSet.Put(aMaxSizeItem);
+
+ // Margins, border and the other stuff.
+ rSet.Put(rMaster.GetAttrSet());
+
+ std::shared_ptr<SvxBoxInfoItem> aBoxInfo(std::make_shared<SvxBoxInfoItem>(SID_ATTR_BORDER_INNER));
+
+ if ( const SvxBoxInfoItem *pBoxInfo = rSet.GetItemIfSet( SID_ATTR_BORDER_INNER ) )
+ {
+ aBoxInfo.reset(pBoxInfo->Clone());
+ }
+
+ aBoxInfo->SetTable( false );
+ // Show always the distance field
+ aBoxInfo->SetDist( true);
+ // Set minimal size in tables and paragraphs
+ aBoxInfo->SetMinDist( false );
+ // Set always the default distance
+ aBoxInfo->SetDefDist( MIN_BORDER_DIST );
+ // Single lines can have only in tables DontCare-Status
+ aBoxInfo->SetValid( SvxBoxInfoItemValidFlags::DISABLE );
+ rSet.Put( *aBoxInfo );
+
+ SfxStringItem aFollow(SID_ATTR_PAGE_EXT1, OUString());
+ if(rPageDesc.GetFollow())
+ aFollow.SetValue(rPageDesc.GetFollow()->GetName());
+ rSet.Put(aFollow);
+
+ // Header
+ if(rMaster.GetHeader().IsActive())
+ {
+ const SwFormatHeader &rHeaderFormat = rMaster.GetHeader();
+ const SwFrameFormat *pHeaderFormat = rHeaderFormat.GetHeaderFormat();
+ OSL_ENSURE(pHeaderFormat != nullptr, "no header format");
+
+ // HeaderInfo, margins, background, border
+ SfxItemSetFixed<RES_FRMATR_BEGIN,RES_FRMATR_END - 1, // [82
+
+ // FillAttribute support
+ XATTR_FILL_FIRST, XATTR_FILL_LAST, // [1014
+
+ SID_ATTR_BORDER_INNER,SID_ATTR_BORDER_INNER, // [10023
+ SID_ATTR_PAGE_SIZE,SID_ATTR_PAGE_SIZE, // [10051
+ SID_ATTR_PAGE_ON,SID_ATTR_PAGE_SHARED, // [10060
+ SID_ATTR_PAGE_SHARED_FIRST,SID_ATTR_PAGE_SHARED_FIRST> aHeaderSet(*rSet.GetPool());
+
+ // set correct parent to get the XFILL_NONE FillStyle as needed
+ aHeaderSet.SetParent(&rMaster.GetDoc()->GetDfltFrameFormat()->GetAttrSet());
+
+ // Dynamic or fixed height
+ SfxBoolItem aOn(SID_ATTR_PAGE_ON, true);
+ aHeaderSet.Put(aOn);
+
+ const SwFormatFrameSize &rFrameSize = pHeaderFormat->GetFrameSize();
+ const SwFrameSize eSizeType = rFrameSize.GetHeightSizeType();
+ SfxBoolItem aDynamic(SID_ATTR_PAGE_DYNAMIC, eSizeType != SwFrameSize::Fixed);
+ aHeaderSet.Put(aDynamic);
+
+ // Left equal right
+ SfxBoolItem aShared(SID_ATTR_PAGE_SHARED, rPageDesc.IsHeaderShared());
+ aHeaderSet.Put(aShared);
+ SfxBoolItem aFirstShared(SID_ATTR_PAGE_SHARED_FIRST, rPageDesc.IsFirstShared());
+ aHeaderSet.Put(aFirstShared);
+
+ // Size
+ SvxSizeItem aSize(SID_ATTR_PAGE_SIZE, rFrameSize.GetSize());
+ aHeaderSet.Put(aSize);
+
+ // Shifting frame attributes
+ aHeaderSet.Put(pHeaderFormat->GetAttrSet());
+ aHeaderSet.Put( *aBoxInfo );
+
+ // Create SetItem
+ SvxSetItem aSetItem(SID_ATTR_PAGE_HEADERSET, aHeaderSet);
+ rSet.Put(aSetItem);
+ }
+
+ // Footer
+ if(rMaster.GetFooter().IsActive())
+ {
+ const SwFormatFooter &rFooterFormat = rMaster.GetFooter();
+ const SwFrameFormat *pFooterFormat = rFooterFormat.GetFooterFormat();
+ OSL_ENSURE(pFooterFormat != nullptr, "no footer format");
+
+ // FooterInfo, margins, background, border
+ SfxItemSetFixed<RES_FRMATR_BEGIN,RES_FRMATR_END - 1, // [82
+
+ // FillAttribute support
+ XATTR_FILL_FIRST, XATTR_FILL_LAST, // [1014
+
+ SID_ATTR_BORDER_INNER,SID_ATTR_BORDER_INNER, // [10023
+ SID_ATTR_PAGE_SIZE,SID_ATTR_PAGE_SIZE, // [10051
+ SID_ATTR_PAGE_ON,SID_ATTR_PAGE_SHARED, // [10060
+ SID_ATTR_PAGE_SHARED_FIRST,SID_ATTR_PAGE_SHARED_FIRST> aFooterSet(*rSet.GetPool());
+
+ // set correct parent to get the XFILL_NONE FillStyle as needed
+ aFooterSet.SetParent(&rMaster.GetDoc()->GetDfltFrameFormat()->GetAttrSet());
+
+ // Dynamic or fixed height
+ SfxBoolItem aOn(SID_ATTR_PAGE_ON, true);
+ aFooterSet.Put(aOn);
+
+ const SwFormatFrameSize &rFrameSize = pFooterFormat->GetFrameSize();
+ const SwFrameSize eSizeType = rFrameSize.GetHeightSizeType();
+ SfxBoolItem aDynamic(SID_ATTR_PAGE_DYNAMIC, eSizeType != SwFrameSize::Fixed);
+ aFooterSet.Put(aDynamic);
+
+ // Left equal right
+ SfxBoolItem aShared(SID_ATTR_PAGE_SHARED, rPageDesc.IsFooterShared());
+ aFooterSet.Put(aShared);
+ SfxBoolItem aFirstShared(SID_ATTR_PAGE_SHARED_FIRST, rPageDesc.IsFirstShared());
+ aFooterSet.Put(aFirstShared);
+
+ // Size
+ SvxSizeItem aSize(SID_ATTR_PAGE_SIZE, rFrameSize.GetSize());
+ aFooterSet.Put(aSize);
+
+ // Shifting Frame attributes
+ aFooterSet.Put(pFooterFormat->GetAttrSet());
+ aFooterSet.Put( *aBoxInfo );
+
+ // Create SetItem
+ SvxSetItem aSetItem(SID_ATTR_PAGE_FOOTERSET, aFooterSet);
+ rSet.Put(aSetItem);
+ }
+
+ // Integrate footnotes
+ SwPageFootnoteInfo& rInfo = const_cast<SwPageFootnoteInfo&>(rPageDesc.GetFootnoteInfo());
+ SwPageFootnoteInfoItem aFootnoteItem(rInfo);
+ rSet.Put(aFootnoteItem);
+
+ // Register compliant
+ const SwTextFormatColl* pCol = rPageDesc.GetRegisterFormatColl();
+ SwRegisterItem aReg(pCol != nullptr);
+ aReg.SetWhich(SID_SWREGISTER_MODE);
+ rSet.Put(aReg);
+ if(pCol)
+ rSet.Put(SfxStringItem(SID_SWREGISTER_COLLECTION, pCol->GetName()));
+
+ std::optional<SfxGrabBagItem> oGrabBag;
+ if (SfxGrabBagItem const* pItem = rSet.GetItemIfSet(SID_ATTR_CHAR_GRABBAG))
+ {
+ oGrabBag.emplace(*pItem);
+ }
+ else
+ {
+ oGrabBag.emplace(SID_ATTR_CHAR_GRABBAG);
+ }
+ oGrabBag->GetGrabBag()["BackgroundFullSize"] <<=
+ rMaster.GetAttrSet().GetItem<SfxBoolItem>(RES_BACKGROUND_FULL_SIZE)->GetValue();
+
+ if (IsOwnFormat(*rMaster.GetDoc()))
+ {
+ oGrabBag->GetGrabBag()["RtlGutter"]
+ <<= rMaster.GetAttrSet().GetItem<SfxBoolItem>(RES_RTL_GUTTER)->GetValue();
+ }
+
+ rSet.Put(*oGrabBag);
+}
+
+// Set DefaultTabs
+
+void MakeDefTabs(SwTwips nDefDist, SvxTabStopItem& rTabs)
+{
+ if( rTabs.Count() )
+ return;
+ {
+ SvxTabStop aSwTabStop( nDefDist, SvxTabAdjust::Default );
+ rTabs.Insert( aSwTabStop );
+ }
+}
+
+// Distance between two tabs
+
+SwTwips GetTabDist(const SvxTabStopItem& rTabs)
+{
+ return rTabs.Count() ? rTabs[0].GetTabPos() : 1134; // 1134 = 2 cm
+}
+
+// Inquire if in the set is a Sfx-PageDesc combination present and return it.
+void SfxToSwPageDescAttr( const SwWrtShell& rShell, SfxItemSet& rSet )
+{
+ const SfxPoolItem* pItem;
+ SwFormatPageDesc aPgDesc;
+
+ bool bChanged = false;
+ // Page number
+ switch (rSet.GetItemState(SID_ATTR_PARA_PAGENUM, false, &pItem))
+ {
+ case SfxItemState::SET:
+ {
+ aPgDesc.SetNumOffset(static_cast<const SfxUInt16Item*>(pItem)->GetValue());
+ bChanged = true;
+ break;
+ }
+ case SfxItemState::DISABLED:
+ {
+ bChanged = true; // default initialised aPgDesc clears the number
+ break;
+ }
+ case SfxItemState::UNKNOWN:
+ case SfxItemState::DEFAULT:
+ break;
+ default:
+ assert(false); // unexpected
+ break;
+ }
+ if( const SvxPageModelItem* pModelItem = rSet.GetItemIfSet( SID_ATTR_PARA_MODEL, false ))
+ {
+ const OUString& rDescName = pModelItem->GetValue();
+ if( !rDescName.isEmpty() ) // No name -> disable PageDesc!
+ {
+ // Delete only, if PageDesc will be enabled!
+ rSet.ClearItem( RES_BREAK );
+ SwPageDesc* pDesc = const_cast<SwWrtShell&>(rShell).FindPageDescByName(
+ rDescName, true );
+ if( pDesc )
+ aPgDesc.RegisterToPageDesc( *pDesc );
+ }
+ rSet.ClearItem( SID_ATTR_PARA_MODEL );
+ bChanged = true;
+ }
+ else
+ {
+ SfxItemSetFixed<RES_PAGEDESC, RES_PAGEDESC> aCoreSet(rShell.GetView().GetPool());
+ rShell.GetCurAttr( aCoreSet );
+ if(const SwFormatPageDesc* pPageDescItem = aCoreSet.GetItemIfSet( RES_PAGEDESC ) )
+ {
+ const SwPageDesc* pPageDesc = pPageDescItem->GetPageDesc();
+ if( pPageDesc )
+ {
+ aPgDesc.RegisterToPageDesc( *const_cast<SwPageDesc*>(pPageDesc) );
+ }
+ }
+ }
+
+ if(bChanged)
+ rSet.Put( aPgDesc );
+}
+
+// Inquire if in the set is a Sfx-PageDesc combination present and return it.
+void SwToSfxPageDescAttr( SfxItemSet& rCoreSet )
+{
+ const SwFormatPageDesc* pPageDescItem = nullptr;
+ OUString aName;
+ ::std::optional<sal_uInt16> oNumOffset;
+ bool bPut = true;
+ switch( rCoreSet.GetItemState( RES_PAGEDESC, true, &pPageDescItem ) )
+ {
+ case SfxItemState::SET:
+ {
+ if( pPageDescItem->GetPageDesc() )
+ {
+ aName = pPageDescItem->GetPageDesc()->GetName();
+ oNumOffset = pPageDescItem->GetNumOffset();
+ }
+ rCoreSet.ClearItem( RES_PAGEDESC );
+ // Page number
+ }
+ break;
+
+ case SfxItemState::DEFAULT:
+ break;
+
+ default:
+ bPut = false;
+ }
+
+ if (oNumOffset)
+ {
+ SfxUInt16Item aPageNum( SID_ATTR_PARA_PAGENUM, *oNumOffset );
+ rCoreSet.Put( aPageNum );
+ }
+
+ if(bPut)
+ rCoreSet.Put( SvxPageModelItem( aName, true, SID_ATTR_PARA_MODEL ) );
+}
+
+// Determine metric
+
+FieldUnit GetDfltMetric(bool bWeb)
+{
+ return SW_MOD()->GetUsrPref(bWeb)->GetMetric();
+}
+
+// Determine metric
+
+void SetDfltMetric( FieldUnit eMetric, bool bWeb )
+{
+ SW_MOD()->ApplyUserMetric(eMetric, bWeb);
+}
+
+void InsertStringSorted(const OUString& rId, const OUString& rEntry, weld::ComboBox& rToFill, int nOffset)
+{
+ CollatorWrapper& rCaseColl = ::GetAppCaseCollator();
+ const int nCount = rToFill.get_count();
+ while (nOffset < nCount)
+ {
+ if (0 < rCaseColl.compareString(rToFill.get_text(nOffset), rEntry))
+ break;
+ ++nOffset;
+ }
+ rToFill.insert(nOffset, rEntry, &rId, nullptr, nullptr);
+}
+
+void FillCharStyleListBox(weld::ComboBox& rToFill, SwDocShell* pDocSh, bool bSorted, bool bWithDefault)
+{
+ const int nOffset = rToFill.get_count() > 0 ? 1 : 0;
+ rToFill.freeze();
+ SfxStyleSheetBasePool* pPool = pDocSh->GetStyleSheetPool();
+ SwDoc* pDoc = pDocSh->GetDoc();
+ const SfxStyleSheetBase* pBase = pPool->First(SfxStyleFamily::Char);
+ const OUString sStandard(SwResId(STR_POOLCHR_STANDARD));
+ while(pBase)
+ {
+ if(bWithDefault || pBase->GetName() != sStandard)
+ {
+ sal_IntPtr nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( pBase->GetName(), SwGetPoolIdFromName::ChrFmt );
+ OUString sId(OUString::number(nPoolId));
+ if (bSorted)
+ InsertStringSorted(sId, pBase->GetName(), rToFill, nOffset);
+ else
+ rToFill.append(sId, pBase->GetName());
+ }
+ pBase = pPool->Next();
+ }
+ // non-pool styles
+ const SwCharFormats* pFormats = pDoc->GetCharFormats();
+ for(size_t i = 0; i < pFormats->size(); ++i)
+ {
+ const SwCharFormat* pFormat = (*pFormats)[i];
+ if(pFormat->IsDefault())
+ continue;
+ const OUString& rName = pFormat->GetName();
+ if (rToFill.find_text(rName) == -1)
+ {
+ OUString sId(OUString::number(USHRT_MAX));
+ if (bSorted)
+ InsertStringSorted(sId, rName, rToFill, nOffset);
+ else
+ rToFill.append(sId, rName);
+ }
+ }
+ rToFill.thaw();
+};
+
+SwTwips GetTableWidth( SwFrameFormat const * pFormat, SwTabCols const & rCols, sal_uInt16 *pPercent,
+ SwWrtShell* pSh )
+{
+ // To get the width is slightly more complicated.
+ SwTwips nWidth = 0;
+ const sal_Int16 eOri = pFormat->GetHoriOrient().GetHoriOrient();
+ switch(eOri)
+ {
+ case text::HoriOrientation::FULL: nWidth = rCols.GetRight(); break;
+ case text::HoriOrientation::LEFT_AND_WIDTH:
+ case text::HoriOrientation::LEFT:
+ case text::HoriOrientation::RIGHT:
+ case text::HoriOrientation::CENTER:
+ nWidth = pFormat->GetFrameSize().GetWidth();
+ break;
+ default:
+ {
+ if(pSh)
+ {
+ if ( nullptr == pSh->GetFlyFrameFormat() )
+ {
+ nWidth = pSh->GetAnyCurRect(CurRectType::PagePrt).Width();
+ }
+ else
+ {
+ nWidth = pSh->GetAnyCurRect(CurRectType::FlyEmbeddedPrt).Width();
+ }
+ }
+ else
+ {
+ OSL_FAIL("where to get the actual width from?");
+ }
+ const SvxLRSpaceItem& rLRSpace = pFormat->GetLRSpace();
+ nWidth -= (rLRSpace.GetRight() + rLRSpace.GetLeft());
+ }
+ }
+ if (pPercent)
+ *pPercent = pFormat->GetFrameSize().GetWidthPercent();
+ return nWidth;
+}
+
+OUString GetAppLangDateTimeString( const DateTime& rDT )
+{
+ const SvtSysLocale aSysLocale;
+ const LocaleDataWrapper& rAppLclData = aSysLocale.GetLocaleData();
+ OUString sRet = rAppLclData.getDate( rDT ) + " " + rAppLclData.getTime( rDT );
+ return sRet;
+}
+
+// Add a new function which can get and set the current "SID_ATTR_APPLYCHARUNIT" value
+
+bool HasCharUnit( bool bWeb)
+{
+ return SW_MOD()->GetUsrPref(bWeb)->IsApplyCharUnit();
+}
+
+void SetApplyCharUnit(bool bApplyChar, bool bWeb)
+{
+ SW_MOD()->ApplyUserCharUnit(bApplyChar, bWeb);
+}
+
+bool ExecuteMenuCommand(const css::uno::Reference<css::awt::XPopupMenu>& rMenu, const SfxViewFrame& rViewFrame, sal_uInt16 nId)
+{
+ bool bRet = false;
+ const sal_uInt16 nItemCount = rMenu->getItemCount();
+ OUString sCommand;
+ for (sal_uInt16 nItem = 0; nItem < nItemCount; ++nItem)
+ {
+ sal_Int16 nItemId = rMenu->getItemId(nItem);
+ css::uno::Reference<css::awt::XPopupMenu> xPopup = rMenu->getPopupMenu(nItemId);
+ if (xPopup.is())
+ {
+ sCommand = xPopup->getCommand(nId);
+ if(!sCommand.isEmpty())
+ break;
+ }
+ }
+ if(!sCommand.isEmpty())
+ {
+ uno::Reference< frame::XFrame > xFrame = rViewFrame.GetFrame().GetFrameInterface();
+ uno::Reference < frame::XDispatchProvider > xProv( xFrame, uno::UNO_QUERY );
+ util::URL aURL;
+ aURL.Complete = sCommand;
+ uno::Reference < util::XURLTransformer > xTrans( util::URLTransformer::create(::comphelper::getProcessComponentContext() ) );
+ xTrans->parseStrict( aURL );
+ uno::Reference< frame::XDispatch > xDisp = xProv->queryDispatch( aURL, OUString(), 0 );
+ if( xDisp.is() )
+ {
+ uno::Sequence< beans::PropertyValue > aSeq;
+ xDisp->dispatch( aURL, aSeq );
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/unotools.cxx b/sw/source/uibase/utlui/unotools.cxx
new file mode 100644
index 0000000000..93edfaad30
--- /dev/null
+++ b/sw/source/uibase/utlui/unotools.cxx
@@ -0,0 +1,496 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <swtypes.hxx>
+
+#include <strings.hrc>
+#include <unotools.hxx>
+#include <unoprnms.hxx>
+#include <unotextcursor.hxx>
+#include <i18nutil/unicode.hxx>
+#include <o3tl/string_view.hxx>
+#include <rtl/string.h>
+#include <svtools/colorcfg.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/jobset.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/weld.hxx>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/text/XTextViewCursorSupplier.hpp>
+#include <com/sun/star/view/XScreenCursor.hpp>
+#include <com/sun/star/view/DocumentZoomType.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/style/XStyle.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/view/XViewSettingsSupplier.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/frame/XLayoutManager.hpp>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/string.hxx>
+#include <docsh.hxx>
+#include <editsh.hxx>
+#include <wrtsh.hxx>
+#include <swmodule.hxx>
+#include <TextCursorHelper.hxx>
+#include <doc.hxx>
+
+using namespace ::com::sun::star;
+
+constexpr OUStringLiteral cFactory = u"private:factory/swriter";
+
+static void disableScrollBars(uno::Reference< beans::XPropertySet > const & xViewProps,
+ bool bEnableOnlineMode)
+{
+ //the scrollbar logic is kind of busted looking in writer, when the hori scrollbar
+ //property is changed then the hori scrollbar is enabled if the property is
+ //true or browse (online) mode is enabled. So...
+ //disable online mode
+ //turn off scrollbars
+ //turn back on online mode if that's what we want
+ //which subverts the (dodgy/buggy) scrollbar setting
+
+ //To reproduce this problem, in edit->autotext and click through
+ //the examples and see if the preview gets a horizontal scrollbar
+ uno::Any aFalseSet(uno::Any(false));
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_ONLINE_LAYOUT, aFalseSet);
+
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_HORI_SCROLL_BAR, aFalseSet);
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_VERT_SCROLL_BAR, aFalseSet);
+
+ if (bEnableOnlineMode)
+ {
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_ONLINE_LAYOUT, uno::Any(true));
+ }
+}
+
+SwOneExampleFrame::SwOneExampleFrame(sal_uInt32 nFlags,
+ const Link<SwOneExampleFrame&,void>* pInitializedLink,
+ const OUString* pURL)
+ : m_aLoadedIdle("sw uibase SwOneExampleFrame Loaded")
+ , m_pModuleView(SW_MOD()->GetView())
+ , m_nStyleFlags(nFlags)
+ , m_bIsInitialized(false)
+{
+ if (pURL && !pURL->isEmpty())
+ m_sArgumentURL = *pURL;
+
+ if( pInitializedLink )
+ m_aInitializedLink = *pInitializedLink;
+
+ // the controller is asynchronously set
+ m_aLoadedIdle.SetInvokeHandler(LINK(this, SwOneExampleFrame, TimeoutHdl));
+ m_aLoadedIdle.SetPriority(TaskPriority::HIGH_IDLE);
+}
+
+void SwOneExampleFrame::SetDrawingArea(weld::DrawingArea* pDrawingArea)
+{
+ CustomWidgetController::SetDrawingArea(pDrawingArea);
+ m_xVirDev = VclPtr<VirtualDevice>::Create();
+ Size aSize(m_xVirDev->LogicToPixel(Size(150, 188), MapMode(MapUnit::MapAppFont)));
+ pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
+ SetOutputSizePixel(aSize);
+ CreateControl();
+}
+
+bool SwOneExampleFrame::Command(const CommandEvent& rCEvt)
+{
+ switch (rCEvt.GetCommand())
+ {
+ case CommandEventId::ContextMenu:
+ {
+ //#125881# quickly clicking crashes because the control is not fully initialized
+ if (m_xController.is())
+ return CreatePopup(rCEvt.GetMousePosPixel());
+ }
+ break;
+ default:;
+ break;
+ }
+ return CustomWidgetController::Command(rCEvt);
+}
+
+void SwOneExampleFrame::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
+{
+ Size aSize(GetOutputSizePixel());
+ // m_xVirDev instead of rRenderContext just to avoid overlays in writer re-triggering
+ // invalidate on rRenderContext if it is a vcl::Window, which is the "classic" gen mode
+ m_xVirDev->SetOutputSizePixel(aSize);
+
+ Color aBgColor = SW_MOD()->GetColorConfig().GetColorValue(::svtools::DOCCOLOR).nColor;
+ m_xVirDev->DrawWallpaper(tools::Rectangle(Point(), aSize), aBgColor);
+
+ if (m_xCursor)
+ {
+ uno::Reference<view::XViewSettingsSupplier> xSettings(m_xController, uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xViewProps = xSettings->getViewSettings();
+ uno::Any aZoom = xViewProps->getPropertyValue(UNO_NAME_ZOOM_VALUE);
+ sal_Int16 nZoom = 100;
+ aZoom >>= nZoom;
+
+ double fZoom = 100.0 / nZoom;
+
+ m_xVirDev->Push(vcl::PushFlags::ALL);
+ m_xVirDev->SetMapMode(MapMode(MapUnit::MapTwip));
+ SwDoc *pDoc = m_xCursor->GetDoc();
+ SwDocShell* pShell = pDoc->GetDocShell();
+ tools::Rectangle aRect(Point(), m_xVirDev->PixelToLogic(aSize));
+ pShell->SetVisArea(tools::Rectangle(Point(), Size(aRect.GetWidth() * fZoom,
+ aRect.GetHeight() * fZoom)));
+ pShell->DoDraw(m_xVirDev.get(), aRect.TopLeft(), aRect.GetSize(), JobSetup(), ASPECT_CONTENT, true);
+ m_xVirDev->Pop();
+ }
+
+ rRenderContext.DrawOutDev(Point(), aSize, Point(), aSize, *m_xVirDev);
+}
+
+SwOneExampleFrame::~SwOneExampleFrame()
+{
+ DisposeControl();
+}
+
+void SwOneExampleFrame::CreateControl()
+{
+ // create new doc
+ OUString sTempURL(cFactory);
+ if(!m_sArgumentURL.isEmpty())
+ sTempURL = m_sArgumentURL;
+
+ uno::Reference<frame::XDesktop2> xDesktop = frame::Desktop::create(::comphelper::getProcessComponentContext());
+ uno::Sequence<beans::PropertyValue> args( comphelper::InitPropertySequence({
+ { "DocumentService", uno::Any(OUString("com.sun.star.text.TextDocument")) },
+ { "OpenFlags", uno::Any(OUString("-RB")) },
+ { "Referer", uno::Any(OUString("private:user")) },
+ { "ReadOnly", uno::Any(true) },
+ { "Hidden", uno::Any(true) }
+ }));
+
+ m_xModel.set(xDesktop->loadComponentFromURL(sTempURL, "_blank", 0, args), uno::UNO_QUERY);
+
+ m_aLoadedIdle.Start();
+}
+
+void SwOneExampleFrame::DisposeControl()
+{
+ m_aLoadedIdle.Stop();
+ m_xCursor = nullptr;
+ if (m_xModel)
+ {
+ m_xModel->dispose();
+ m_xModel = nullptr;
+ }
+ m_xController = nullptr;
+}
+
+IMPL_LINK( SwOneExampleFrame, TimeoutHdl, Timer*, pTimer, void )
+{
+ if (!m_xModel.is())
+ return;
+
+ m_xController = m_xModel->getCurrentController();
+
+ if (m_xController.is())
+ {
+ uno::Reference<frame::XFrame> xFrame = m_xController->getFrame();
+ uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY );
+ if ( xPropSet.is() )
+ {
+ try
+ {
+ uno::Reference< frame::XLayoutManager > xLayoutManager;
+ uno::Any aValue = xPropSet->getPropertyValue("LayoutManager");
+ aValue >>= xLayoutManager;
+ if ( xLayoutManager.is() )
+ xLayoutManager->setVisible( false );
+ }
+ catch (const uno::Exception&)
+ {
+ }
+ }
+
+ //now the ViewOptions should be set properly
+ uno::Reference< view::XViewSettingsSupplier > xSettings(m_xController, uno::UNO_QUERY);
+ uno::Reference< beans::XPropertySet > xViewProps = xSettings->getViewSettings();
+
+ const uno::Any aTrueSet( true );
+ const uno::Any aFalseSet( false );
+
+ if( !m_bIsInitialized )
+ {
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_BREAKS, aFalseSet);
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_DRAWINGS, aTrueSet);
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_FIELD_COMMANDS, aFalseSet);
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_GRAPHICS, aTrueSet);
+ xViewProps->setPropertyValue(UNO_NAME_HIDE_WHITESPACE, aFalseSet);
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_HIDDEN_PARAGRAPHS, aFalseSet);
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_HIDDEN_TEXT, aFalseSet);
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_HORI_RULER, aFalseSet);
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_PARA_BREAKS, aFalseSet);
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_PROTECTED_SPACES, aFalseSet);
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_SOFT_HYPHENS, aFalseSet);
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_SPACES, aFalseSet);
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_TABLES, aTrueSet);
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_TABSTOPS, aFalseSet);
+ xViewProps->setPropertyValue(UNO_NAME_SHOW_VERT_RULER, aFalseSet);
+
+ if(0 ==(m_nStyleFlags&EX_SHOW_ONLINE_LAYOUT))
+ {
+ uno::Any aZoom;
+ aZoom <<= sal_Int16(view::DocumentZoomType::PAGE_WIDTH_EXACT);
+ xViewProps->setPropertyValue(UNO_NAME_ZOOM_TYPE, aZoom);
+ }
+ else
+ {
+ uno::Any aZoom;
+ aZoom <<= sal_Int16(view::DocumentZoomType::BY_VALUE);
+ xViewProps->setPropertyValue(UNO_NAME_ZOOM_TYPE, aZoom);
+
+ sal_Int16 nZoomValue = 75;
+ if(EX_SHOW_BUSINESS_CARDS == m_nStyleFlags)
+ {
+ nZoomValue = 80;
+ }
+ aZoom <<= nZoomValue;
+ xViewProps->setPropertyValue(UNO_NAME_ZOOM_VALUE, aZoom);
+ }
+
+ // set onlinelayout property after setting the zoom
+ disableScrollBars(xViewProps, (m_nStyleFlags&EX_SHOW_ONLINE_LAYOUT) != 0);
+ m_bIsInitialized = true;
+ }
+
+ uno::Reference< text::XTextDocument > xDoc(m_xModel, uno::UNO_QUERY);
+ uno::Reference< text::XText > xText = xDoc->getText();
+ uno::Reference< text::XTextCursor > xTextCursor = xText->createTextCursor();
+ m_xCursor = dynamic_cast<SwXTextCursor*>(xTextCursor.get());
+ assert(bool(xTextCursor) == bool(m_xCursor) && "expect to get SwXTextCursor type here");
+
+ //From here, a cursor is defined, which goes through the template,
+ //and overwrites the template words where it is necessary.
+
+ SwDoc *pDoc = m_xCursor ? m_xCursor->GetDoc() : nullptr;
+ if (pDoc && (m_nStyleFlags & EX_LOCALIZE_TOC_STRINGS))
+ {
+ SwEditShell* pSh = pDoc->GetEditShell();
+
+ do
+ {
+ if (pSh->GetCurWord() == "HEADING1")
+ {
+ pSh->Overwrite(SwResId(STR_IDXEXAMPLE_IDXTXT_HEADING1));
+ }
+ else if (pSh->GetCurWord() == "ENTRY1")
+ {
+ pSh->Overwrite(SwResId(STR_IDXEXAMPLE_IDXTXT_ENTRY1));
+ }
+ else if (pSh->GetCurWord() == "HEADING11")
+ {
+ pSh->Overwrite(SwResId(STR_IDXEXAMPLE_IDXTXT_HEADING11));
+ }
+ else if (pSh->GetCurWord() == "ENTRY11")
+ {
+ pSh->Overwrite(SwResId(STR_IDXEXAMPLE_IDXTXT_ENTRY11));
+ }
+ else if (pSh->GetCurWord() == "HEADING12")
+ {
+ pSh->Overwrite(SwResId(STR_IDXEXAMPLE_IDXTXT_HEADING12));
+ }
+ else if (pSh->GetCurWord() == "ENTRY12")
+ {
+ pSh->Overwrite(SwResId(STR_IDXEXAMPLE_IDXTXT_ENTRY12));
+ }
+ else if (pSh->GetCurWord() == "TABLE1")
+ {
+ pSh->Overwrite(SwResId(STR_IDXEXAMPLE_IDXTXT_TABLE1));
+ }
+ else if (pSh->GetCurWord() == "IMAGE1")
+ {
+ pSh->Overwrite(SwResId(STR_IDXEXAMPLE_IDXTXT_IMAGE1));
+ }
+ }
+ while(pSh->Right(sal_uInt16(1), SwCursorSkipMode::Cells, true));
+
+ TOXTypes eTypes[] = { TOX_INDEX, TOX_USER, TOX_CONTENT };
+ for (auto eType : eTypes)
+ {
+ const SwTOXType* pTOXType = pDoc->GetTOXType(eType, 0);
+ SwTOXMarks aMarks;
+ pTOXType->CollectTextMarks(aMarks);
+ for (auto pMark : aMarks)
+ {
+ if (pMark->GetAlternativeText() == "Chapter")
+ pMark->SetAlternativeText(SwResId(STR_IDXEXAMPLE_IDXMARK_CHAPTER));
+ else if (pMark->GetAlternativeText() == "Keyword")
+ pMark->SetAlternativeText(SwResId(STR_IDXEXAMPLE_IDXMARK_KEYWORD));
+ else if (pMark->GetAlternativeText() == "this")
+ pMark->SetAlternativeText(SwResId(STR_IDXEXAMPLE_IDXMARK_THIS));
+ else if (pMark->GetAlternativeText() == "User Directory Entry")
+ pMark->SetAlternativeText(SwResId(STR_IDXEXAMPLE_IDXMARK_USER_DIR_ENTRY));
+ else if (pMark->GetAlternativeText() == "Entry")
+ pMark->SetAlternativeText(SwResId(STR_IDXEXAMPLE_IDXMARK_ENTRY));
+
+ if (pMark->GetPrimaryKey() == "Primary key")
+ pMark->SetPrimaryKey(SwResId(STR_IDXEXAMPLE_IDXMARK_PRIMARY_KEY));
+
+ if (pMark->GetSecondaryKey() == "Secondary key")
+ pMark->SetSecondaryKey(SwResId(STR_IDXEXAMPLE_IDXMARK_SECONDARY_KEY));
+ }
+ }
+ }
+
+ uno::Any aPageStyle = m_xCursor->getPropertyValue(UNO_NAME_PAGE_STYLE_NAME);
+ OUString sPageStyle;
+ aPageStyle >>= sPageStyle;
+
+ uno::Reference< style::XStyleFamiliesSupplier > xSSupp( xDoc, uno::UNO_QUERY);
+ uno::Reference< container::XNameAccess > xStyles = xSSupp->getStyleFamilies();
+ uno::Any aPFamily = xStyles->getByName( "PageStyles" );
+ uno::Reference< container::XNameContainer > xPFamily;
+
+ if( EX_SHOW_DEFAULT_PAGE != m_nStyleFlags
+ && (aPFamily >>= xPFamily) && !sPageStyle.isEmpty() )
+ {
+ uno::Any aPStyle = xPFamily->getByName( sPageStyle );
+ uno::Reference< style::XStyle > xPStyle;
+ aPStyle >>= xPStyle;
+ uno::Reference< beans::XPropertySet > xPProp(xPStyle, uno::UNO_QUERY);
+ uno::Any aSize = xPProp->getPropertyValue(UNO_NAME_SIZE);
+ awt::Size aPSize;
+ aSize >>= aPSize;
+ //TODO: set page width to card width
+ aPSize.Width = 10000;
+ aSize <<= aPSize;
+ xPProp->setPropertyValue(UNO_NAME_SIZE, aSize);
+
+ uno::Any aZero; aZero <<= sal_Int32(0);
+ xPProp->setPropertyValue(UNO_NAME_LEFT_MARGIN, aZero);
+ xPProp->setPropertyValue(UNO_NAME_RIGHT_MARGIN, aZero);
+ }
+
+ uno::Reference<awt::XWindow> xWin = xFrame->getContainerWindow();
+ Size aWinSize(GetOutputSizePixel());
+ xWin->setPosSize(0, 0, aWinSize.Width(), aWinSize.Height(), awt::PosSize::SIZE);
+
+ // can only be done here - the SFX changes the ScrollBar values
+ disableScrollBars(xViewProps, (m_nStyleFlags&EX_SHOW_ONLINE_LAYOUT) != 0);
+
+ m_aInitializedLink.Call(*this);
+
+ uno::Reference< text::XTextViewCursorSupplier > xCursorSupp(m_xController, uno::UNO_QUERY);
+ uno::Reference< view::XScreenCursor > xScrCursor(xCursorSupp->getViewCursor(), uno::UNO_QUERY);
+ if(xScrCursor.is())
+ xScrCursor->screenUp();
+
+ if (pDoc)
+ {
+ SwEditShell* pSh = pDoc->GetEditShell();
+ if( pSh->ActionCount() )
+ {
+ pSh->EndAllAction();
+ pSh->UnlockPaint();
+ }
+ }
+
+ SW_MOD()->SetView(m_pModuleView);
+
+ Invalidate();
+ }
+ else
+ pTimer->Start();
+}
+
+void SwOneExampleFrame::ClearDocument()
+{
+ if( !m_xCursor )
+ return;
+
+ SwDoc* pDoc = m_xCursor->GetDoc();
+ SwEditShell* pSh = pDoc->GetEditShell();
+ pSh->LockPaint(LockPaintReason::ExampleFrame);
+ pSh->StartAllAction();
+ pSh->KillPams();
+ pSh->ClearMark();
+ pDoc->ClearDoc();
+ pSh->ClearUpCursors();
+
+ if( m_aLoadedIdle.IsActive())
+ {
+ pSh->EndAllAction();
+ pSh->UnlockPaint();
+ }
+ m_aLoadedIdle.Start();
+}
+
+bool SwOneExampleFrame::CreatePopup(const Point& rPt)
+{
+ if (EX_SHOW_ONLINE_LAYOUT != m_nStyleFlags)
+ return false;
+
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, "modules/swriter/ui/previewmenu.ui"));
+ std::unique_ptr<weld::Menu> xPop(xBuilder->weld_menu("previewmenu"));
+
+ uno::Reference< view::XViewSettingsSupplier > xSettings(m_xController, uno::UNO_QUERY);
+ uno::Reference< beans::XPropertySet > xViewProps = xSettings->getViewSettings();
+
+ uno::Any aZoom = xViewProps->getPropertyValue(UNO_NAME_ZOOM_VALUE);
+ sal_Int16 nZoom = 0;
+ aZoom >>= nZoom;
+
+ for (auto const nZoomPreset : { 20, 40, 50, 75, 100 })
+ {
+ OUString sTemp = unicode::formatPercent(nZoomPreset,
+ Application::GetSettings().GetUILanguageTag());
+ OUString sIdent = "zoom" + OUString::number(nZoomPreset);
+ xPop->set_label(sIdent, sTemp);
+ if (nZoom == nZoomPreset)
+ xPop->set_active(sIdent, true);
+ }
+
+ PopupHdl(xPop->popup_at_rect(GetDrawingArea(), tools::Rectangle(rPt, Size(1, 1))));
+
+ return true;
+}
+
+void SwOneExampleFrame::PopupHdl(std::u16string_view rId)
+{
+ std::u16string_view sZoomValue;
+ if (o3tl::starts_with(rId, u"zoom", &sZoomValue))
+ {
+ sal_Int16 nZoom = o3tl::toInt32(sZoomValue);
+ uno::Reference< view::XViewSettingsSupplier > xSettings(m_xController, uno::UNO_QUERY);
+ uno::Reference< beans::XPropertySet > xViewProps = xSettings->getViewSettings();
+
+ uno::Any aZoom;
+ aZoom <<= nZoom;
+ xViewProps->setPropertyValue(UNO_NAME_ZOOM_VALUE, aZoom);
+ aZoom <<= sal_Int16(view::DocumentZoomType::BY_VALUE);
+ xViewProps->setPropertyValue(UNO_NAME_ZOOM_TYPE, aZoom);
+ }
+ Invalidate();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/viewlayoutctrl.cxx b/sw/source/uibase/utlui/viewlayoutctrl.cxx
new file mode 100644
index 0000000000..89dcc30175
--- /dev/null
+++ b/sw/source/uibase/utlui/viewlayoutctrl.cxx
@@ -0,0 +1,213 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <viewlayoutctrl.hxx>
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include <comphelper/propertyvalue.hxx>
+#include <vcl/event.hxx>
+#include <vcl/status.hxx>
+#include <vcl/image.hxx>
+#include <svx/viewlayoutitem.hxx>
+#include <strings.hrc>
+#include <bitmaps.hlst>
+#include <swtypes.hxx>
+
+SFX_IMPL_STATUSBAR_CONTROL( SwViewLayoutControl, SvxViewLayoutItem );
+
+struct SwViewLayoutControl::SwViewLayoutControl_Impl
+{
+ sal_uInt16 mnState; // 0 = auto, 1= single, 2 = book, 3 = none, 4 = off
+ Image maImageSingleColumn;
+ Image maImageSingleColumn_Active;
+ Image maImageAutomatic;
+ Image maImageAutomatic_Active;
+ Image maImageBookMode;
+ Image maImageBookMode_Active;
+};
+
+SwViewLayoutControl::SwViewLayoutControl( sal_uInt16 _nSlotId, sal_uInt16 _nId, StatusBar& rStatusBar ) :
+ SfxStatusBarControl( _nSlotId, _nId, rStatusBar ),
+ mpImpl( new SwViewLayoutControl_Impl )
+{
+ mpImpl->mnState = 1;
+
+ mpImpl->maImageSingleColumn = Image(StockImage::Yes, RID_BMP_VIEWLAYOUT_SINGLECOLUMN);
+ mpImpl->maImageSingleColumn_Active = Image(StockImage::Yes, RID_BMP_VIEWLAYOUT_SINGLECOLUMN_ACTIVE);
+ mpImpl->maImageAutomatic = Image(StockImage::Yes, RID_BMP_VIEWLAYOUT_AUTOMATIC);
+ mpImpl->maImageAutomatic_Active = Image(StockImage::Yes, RID_BMP_VIEWLAYOUT_AUTOMATIC_ACTIVE);
+ mpImpl->maImageBookMode = Image(StockImage::Yes, RID_BMP_VIEWLAYOUT_BOOKMODE);
+ mpImpl->maImageBookMode_Active = Image(StockImage::Yes, RID_BMP_VIEWLAYOUT_BOOKMODE_ACTIVE);
+}
+
+SwViewLayoutControl::~SwViewLayoutControl()
+{
+}
+
+void SwViewLayoutControl::StateChangedAtStatusBarControl( sal_uInt16 /*nSID*/, SfxItemState eState, const SfxPoolItem* pState )
+{
+ if (SfxItemState::DEFAULT != eState || SfxItemState::DISABLED == eState)
+ {
+ GetStatusBar().SetItemText( GetId(), OUString() );
+ mpImpl->mnState = 4; //tdf#148441 switch off, if disabled
+ }
+ else
+ {
+ assert( dynamic_cast< const SvxViewLayoutItem *>( pState ) && "invalid item type" );
+ const sal_uInt16 nColumns = static_cast<const SvxViewLayoutItem*>( pState )->GetValue();
+ const bool bBookMode = static_cast<const SvxViewLayoutItem*>( pState )->IsBookMode();
+
+ // SingleColumn Mode
+ if ( 1 == nColumns )
+ mpImpl->mnState = 0;
+ // Automatic Mode
+ else if ( 0 == nColumns )
+ mpImpl->mnState = 1;
+ // Book Mode
+ else if ( bBookMode && 2 == nColumns )
+ mpImpl->mnState = 2;
+ else
+ mpImpl->mnState = 3;
+ }
+
+ GetStatusBar().SetItemData( GetId(), nullptr ); // force repaint
+}
+
+void SwViewLayoutControl::Paint( const UserDrawEvent& rUsrEvt )
+{
+ vcl::RenderContext* pDev = rUsrEvt.GetRenderContext();
+ tools::Rectangle aRect(rUsrEvt.GetRect());
+
+ const tools::Rectangle aControlRect = getControlRect();
+
+ if (mpImpl->mnState < 4)
+ {
+ const bool bSingleColumn = 0 == mpImpl->mnState;
+ const bool bAutomatic = 1 == mpImpl->mnState;
+ const bool bBookMode = 2 == mpImpl->mnState;
+ const int nDistance = 6;
+
+ const tools::Long nImageWidthSum = mpImpl->maImageSingleColumn.GetSizePixel().Width() +
+ mpImpl->maImageAutomatic.GetSizePixel().Width() +
+ mpImpl->maImageBookMode.GetSizePixel().Width();
+
+ const tools::Long nXOffset = (aRect.GetWidth() - nImageWidthSum - (2* nDistance)) / 2;
+ const tools::Long nYOffset = (aControlRect.GetHeight() - mpImpl->maImageSingleColumn.GetSizePixel().Height()) / 2;
+
+ aRect.AdjustLeft( nXOffset );
+ aRect.AdjustTop( nYOffset );
+
+ // draw single column image:
+ pDev->DrawImage( aRect.TopLeft(), bSingleColumn ? mpImpl->maImageSingleColumn_Active : mpImpl->maImageSingleColumn );
+
+ // draw automatic image:
+ aRect.AdjustLeft(mpImpl->maImageSingleColumn.GetSizePixel().Width() + nDistance);
+ pDev->DrawImage( aRect.TopLeft(), bAutomatic ? mpImpl->maImageAutomatic_Active : mpImpl->maImageAutomatic );
+
+ // draw bookmode image:
+ aRect.AdjustLeft(mpImpl->maImageAutomatic.GetSizePixel().Width() + nDistance);
+ pDev->DrawImage( aRect.TopLeft(), bBookMode ? mpImpl->maImageBookMode_Active : mpImpl->maImageBookMode );
+ }
+ else
+ {
+ pDev->DrawRect( aControlRect );
+ }
+}
+
+bool SwViewLayoutControl::MouseButtonDown( const MouseEvent & rEvt )
+{
+ if (mpImpl->mnState < 4)
+ {
+ const tools::Rectangle aRect = getControlRect();
+ const Point aPoint = rEvt.GetPosPixel();
+ const tools::Long nXDiff = aPoint.X() - aRect.Left();
+
+ sal_uInt16 nColumns = 1;
+ bool bBookMode = false;
+
+ const tools::Long nImageWidthSingle = mpImpl->maImageSingleColumn.GetSizePixel().Width();
+ const tools::Long nImageWidthAuto = mpImpl->maImageAutomatic.GetSizePixel().Width();
+ const tools::Long nImageWidthBook = mpImpl->maImageBookMode.GetSizePixel().Width();
+ const tools::Long nImageWidthSum = nImageWidthSingle + nImageWidthAuto + nImageWidthBook;
+
+ const tools::Long nXOffset = (aRect.GetWidth() - nImageWidthSum)/2;
+
+ if ( nXDiff < nXOffset + nImageWidthSingle )
+ {
+ mpImpl->mnState = 0; // single
+ nColumns = 1;
+ }
+ else if ( nXDiff < nXOffset + nImageWidthSingle + nImageWidthAuto )
+ {
+ mpImpl->mnState = 1; // auto
+ nColumns = 0;
+ }
+ else
+ {
+ mpImpl->mnState = 2; // book
+ nColumns = 2;
+ bBookMode = true;
+ }
+
+ // commit state change
+ SvxViewLayoutItem aViewLayout( nColumns, bBookMode );
+
+ css::uno::Any a;
+ aViewLayout.QueryValue( a );
+
+ css::uno::Sequence< css::beans::PropertyValue > aArgs{ comphelper::makePropertyValue("ViewLayout",
+ a) };
+ execute( aArgs );
+ }
+ return true;
+}
+
+bool SwViewLayoutControl::MouseMove( const MouseEvent & rEvt )
+{
+ if (mpImpl->mnState < 4)
+ {
+ const tools::Rectangle aRect = getControlRect();
+ const Point aPoint = rEvt.GetPosPixel();
+ const tools::Long nXDiff = aPoint.X() - aRect.Left();
+
+ const tools::Long nImageWidthSingle = mpImpl->maImageSingleColumn.GetSizePixel().Width();
+ const tools::Long nImageWidthAuto = mpImpl->maImageAutomatic.GetSizePixel().Width();
+ const tools::Long nImageWidthBook = mpImpl->maImageBookMode.GetSizePixel().Width();
+ const tools::Long nImageWidthSum = nImageWidthSingle + nImageWidthAuto + nImageWidthBook;
+
+ const tools::Long nXOffset = (aRect.GetWidth() - nImageWidthSum)/2;
+
+ if ( nXDiff < nXOffset + nImageWidthSingle )
+ {
+ GetStatusBar().SetQuickHelpText(GetId(), SwResId(STR_VIEWLAYOUT_ONE));
+ }
+ else if ( nXDiff < nXOffset + nImageWidthSingle + nImageWidthAuto )
+ {
+ GetStatusBar().SetQuickHelpText(GetId(), SwResId(STR_VIEWLAYOUT_MULTI));
+ }
+ else
+ {
+ GetStatusBar().SetQuickHelpText(GetId(), SwResId(STR_VIEWLAYOUT_BOOK));
+ }
+ }
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/wordcountctrl.cxx b/sw/source/uibase/utlui/wordcountctrl.cxx
new file mode 100644
index 0000000000..4185969189
--- /dev/null
+++ b/sw/source/uibase/utlui/wordcountctrl.cxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <swtypes.hxx>
+#include <strings.hrc>
+#include <wordcountctrl.hxx>
+#include <svl/stritem.hxx>
+#include <vcl/status.hxx>
+
+SFX_IMPL_STATUSBAR_CONTROL(SwWordCountStatusBarControl, SfxStringItem);
+
+SwWordCountStatusBarControl::SwWordCountStatusBarControl(
+ sal_uInt16 _nSlotId,
+ sal_uInt16 _nId,
+ StatusBar& rStb) :
+ SfxStatusBarControl(_nSlotId, _nId, rStb)
+{
+}
+
+SwWordCountStatusBarControl::~SwWordCountStatusBarControl()
+{
+}
+
+void SwWordCountStatusBarControl::StateChangedAtStatusBarControl(
+ sal_uInt16 /*nSID*/, SfxItemState eState, const SfxPoolItem* pState )
+{
+ if (eState == SfxItemState::DEFAULT) // Can access pState
+ {
+ GetStatusBar().SetItemText( GetId(), static_cast<const SfxStringItem*>(pState)->GetValue() );
+ GetStatusBar().SetQuickHelpText(GetId(), SwResId(STR_WORDCOUNT_HINT));
+ }
+ else
+ {
+ GetStatusBar().SetItemText(GetId(), u""_ustr);
+ GetStatusBar().SetQuickHelpText(GetId(), u""_ustr);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/utlui/zoomctrl.cxx b/sw/source/uibase/utlui/zoomctrl.cxx
new file mode 100644
index 0000000000..4489432464
--- /dev/null
+++ b/sw/source/uibase/utlui/zoomctrl.cxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/status.hxx>
+#include <svl/stritem.hxx>
+#include <sfx2/zoomitem.hxx>
+
+#include <zoomctrl.hxx>
+
+SFX_IMPL_STATUSBAR_CONTROL( SwZoomControl, SvxZoomItem );
+
+SwZoomControl::SwZoomControl( sal_uInt16 _nSlotId,
+ sal_uInt16 _nId,
+ StatusBar& rStb ) :
+ SvxZoomStatusBarControl( _nSlotId, _nId, rStb )
+{
+}
+
+SwZoomControl::~SwZoomControl()
+{
+}
+
+void SwZoomControl::StateChangedAtStatusBarControl( sal_uInt16 nSID, SfxItemState eState,
+ const SfxPoolItem* pState )
+{
+ const SfxStringItem* pItem = nullptr;
+ if (SfxItemState::DEFAULT == eState && (pItem = dynamic_cast<const SfxStringItem*>(pState)))
+ {
+ m_sPreviewZoom = pItem->GetValue();
+ GetStatusBar().SetItemText(GetId(), m_sPreviewZoom);
+ }
+ else
+ {
+ m_sPreviewZoom.clear();
+ SvxZoomStatusBarControl::StateChangedAtStatusBarControl(nSID, eState, pState);
+ }
+}
+
+void SwZoomControl::Paint( const UserDrawEvent& )
+{
+}
+
+void SwZoomControl::Command( const CommandEvent& rCEvt )
+{
+ if (m_sPreviewZoom.isEmpty())
+ SvxZoomStatusBarControl::Command(rCEvt);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/web/wdocsh.cxx b/sw/source/uibase/web/wdocsh.cxx
new file mode 100644
index 0000000000..05242544f4
--- /dev/null
+++ b/sw/source/uibase/web/wdocsh.cxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svxids.hrc>
+
+#include <comphelper/fileformat.h>
+#include <comphelper/classids.hxx>
+#include <sfx2/objface.hxx>
+#include <tools/globname.hxx>
+#include <osl/diagnose.h>
+
+#include <sfx2/msg.hxx>
+#include <swtypes.hxx>
+
+#include <wdocsh.hxx>
+#include <strings.hrc>
+
+ // needed for -fsanitize=function visibility of typeinfo for functions of
+ // type void(SfxShell*,SfxRequest&) defined in swslots.hxx
+#define ShellClass_SwWebDocShell
+#include <swslots.hxx>
+
+SFX_IMPL_SUPERCLASS_INTERFACE(SwWebDocShell, SfxObjectShell)
+
+void SwWebDocShell::InitInterface_Impl()
+{
+}
+
+
+SFX_IMPL_OBJECTFACTORY(SwWebDocShell, SvGlobalName(SO3_SWWEB_CLASSID), "swriter/web" )
+
+SwWebDocShell::SwWebDocShell()
+ : SwDocShell(SfxObjectCreateMode::STANDARD)
+ , m_nSourcePara(0)
+{
+}
+
+SwWebDocShell::~SwWebDocShell()
+{
+}
+
+void SwWebDocShell::FillClass( SvGlobalName * pClassName,
+ SotClipboardFormatId * pClipFormat,
+ OUString * pLongUserName,
+ sal_Int32 nVersion,
+ bool bTemplate /* = false */) const
+{
+ OSL_ENSURE( !bTemplate, "No template for Writer Web" );
+
+ if (nVersion == SOFFICE_FILEFORMAT_60)
+ {
+ *pClassName = SvGlobalName( SO3_SWWEB_CLASSID_60 );
+ *pClipFormat = SotClipboardFormatId::STARWRITERWEB_60;
+ *pLongUserName = SwResId(STR_WRITER_WEBDOC_FULLTYPE);
+ }
+ else if (nVersion == SOFFICE_FILEFORMAT_8)
+ {
+ *pClassName = SvGlobalName( SO3_SWWEB_CLASSID_60 );
+ *pClipFormat = SotClipboardFormatId::STARWRITERWEB_8;
+ *pLongUserName = SwResId(STR_WRITER_WEBDOC_FULLTYPE);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/web/wformsh.cxx b/sw/source/uibase/web/wformsh.cxx
new file mode 100644
index 0000000000..1d65b62b36
--- /dev/null
+++ b/sw/source/uibase/web/wformsh.cxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/msg.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/sfxsids.hrc>
+
+#include <wformsh.hxx>
+
+ // needed for -fsanitize=function visibility of typeinfo for functions of
+ // type void(SfxShell*,SfxRequest&) defined in swslots.hxx
+#define ShellClass_SwWebDrawFormShell
+#include <swslots.hxx>
+
+SFX_IMPL_SUPERCLASS_INTERFACE(SwWebDrawFormShell, SwDrawFormShell)
+
+void SwWebDrawFormShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("form");
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Text_Toolbox_Sw);
+}
+
+
+SwWebDrawFormShell::SwWebDrawFormShell(SwView& rVw) :
+ SwDrawFormShell(rVw)
+{
+}
+
+SwWebDrawFormShell::~SwWebDrawFormShell()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/web/wfrmsh.cxx b/sw/source/uibase/web/wfrmsh.cxx
new file mode 100644
index 0000000000..a9bac1962b
--- /dev/null
+++ b/sw/source/uibase/web/wfrmsh.cxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/objface.hxx>
+#include <cmdid.h>
+#include <view.hxx>
+#include <wfrmsh.hxx>
+
+ // needed for -fsanitize=function visibility of typeinfo for functions of
+ // type void(SfxShell*,SfxRequest&) defined in swslots.hxx
+#define ShellClass_SwWebFrameShell
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+
+SFX_IMPL_INTERFACE(SwWebFrameShell, SwFrameShell)
+
+void SwWebFrameShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("frame");
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Webframe_Toolbox);
+}
+
+
+SwWebFrameShell::SwWebFrameShell(SwView &_rView) :
+ SwFrameShell(_rView)
+{
+}
+
+SwWebFrameShell::~SwWebFrameShell()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/web/wgrfsh.cxx b/sw/source/uibase/web/wgrfsh.cxx
new file mode 100644
index 0000000000..66fc2235d6
--- /dev/null
+++ b/sw/source/uibase/web/wgrfsh.cxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/msg.hxx>
+
+#include <sfx2/objface.hxx>
+
+#include <cmdid.h>
+#include <view.hxx>
+#include <wgrfsh.hxx>
+
+ // needed for -fsanitize=function visibility of typeinfo for functions of
+ // type void(SfxShell*,SfxRequest&) defined in swslots.hxx
+#define ShellClass_SwWebGrfShell
+#include <swslots.hxx>
+
+SFX_IMPL_INTERFACE(SwWebGrfShell, SwGrfShell)
+
+void SwWebGrfShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("graphic");
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Webgraphic_Toolbox);
+}
+
+
+SwWebGrfShell::SwWebGrfShell(SwView &_rView) :
+ SwGrfShell(_rView)
+
+{
+ SetName("Graphic");
+}
+
+SwWebGrfShell::~SwWebGrfShell()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/web/wlistsh.cxx b/sw/source/uibase/web/wlistsh.cxx
new file mode 100644
index 0000000000..c7789c1e41
--- /dev/null
+++ b/sw/source/uibase/web/wlistsh.cxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/msg.hxx>
+#include <sfx2/objface.hxx>
+
+#include <cmdid.h>
+#include <wlistsh.hxx>
+
+ // needed for -fsanitize=function visibility of typeinfo for functions of
+ // type void(SfxShell*,SfxRequest&) defined in swslots.hxx
+#define ShellClass_SwWebListShell
+#include <swslots.hxx>
+
+SFX_IMPL_INTERFACE(SwWebListShell, SwListShell)
+
+void SwWebListShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Num_Toolbox);
+}
+
+
+SwWebListShell::SwWebListShell(SwView &_rView) :
+ SwListShell(_rView)
+{
+ SetName("List");
+}
+
+SwWebListShell::~SwWebListShell()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/web/wolesh.cxx b/sw/source/uibase/web/wolesh.cxx
new file mode 100644
index 0000000000..15bab538b3
--- /dev/null
+++ b/sw/source/uibase/web/wolesh.cxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/msg.hxx>
+#include <sfx2/objface.hxx>
+
+#include <view.hxx>
+#include <wolesh.hxx>
+
+#define ShellClass_SwWebOleShell
+#include <swslots.hxx>
+
+SFX_IMPL_INTERFACE(SwWebOleShell, SwOleShell)
+
+void SwWebOleShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("oleobject");
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Webole_Toolbox);
+}
+
+SwWebOleShell::SwWebOleShell(SwView &_rView) :
+ SwOleShell(_rView)
+{
+ SetName("Object");
+}
+
+SwWebOleShell::~SwWebOleShell()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/web/wtabsh.cxx b/sw/source/uibase/web/wtabsh.cxx
new file mode 100644
index 0000000000..88008034c6
--- /dev/null
+++ b/sw/source/uibase/web/wtabsh.cxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/objface.hxx>
+
+#include <cmdid.h>
+#include <wrtsh.hxx>
+#include <wtabsh.hxx>
+
+ // needed for -fsanitize=function visibility of typeinfo for functions of
+ // type void(SfxShell*,SfxRequest&) defined in swslots.hxx
+#define ShellClass_SwWebTableShell
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+
+SFX_IMPL_INTERFACE(SwWebTableShell, SwTableShell)
+
+void SwWebTableShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("table");
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Table_Toolbox);
+}
+
+
+SwWebTableShell::SwWebTableShell(SwView &_rView) :
+ SwTableShell(_rView)
+{
+ GetShell().UpdateTable();
+ SetName("Table");
+}
+
+SwWebTableShell::~SwWebTableShell()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/web/wtextsh.cxx b/sw/source/uibase/web/wtextsh.cxx
new file mode 100644
index 0000000000..c655bdf2cb
--- /dev/null
+++ b/sw/source/uibase/web/wtextsh.cxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/objface.hxx>
+
+#include <cmdid.h>
+#include <view.hxx>
+#include <wtextsh.hxx>
+#include <basesh.hxx>
+#include <globals.hrc>
+
+ // needed for -fsanitize=function visibility of typeinfo for functions of
+ // type void(SfxShell*,SfxRequest&) defined in swslots.hxx
+#define ShellClass_SwWebTextShell
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+
+SFX_IMPL_INTERFACE(SwWebTextShell, SwBaseShell)
+
+void SwWebTextShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("text");
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Text_Toolbox_Sw);
+
+ GetStaticInterface()->RegisterChildWindow(FN_EDIT_FORMULA);
+ GetStaticInterface()->RegisterChildWindow(FN_INSERT_FIELD);
+}
+
+
+SwWebTextShell::SwWebTextShell(SwView &_rView) :
+ SwTextShell(_rView)
+{
+}
+
+SwWebTextShell::~SwWebTextShell()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/web/wview.cxx b/sw/source/uibase/web/wview.cxx
new file mode 100644
index 0000000000..766c1a5ccb
--- /dev/null
+++ b/sw/source/uibase/web/wview.cxx
@@ -0,0 +1,292 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_feature_desktop.h>
+
+#include <sfx2/msg.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/infobar.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svx/srchdlg.hxx>
+#include <uivwimp.hxx>
+#include <svx/fmshell.hxx>
+#include <svx/fmview.hxx>
+#include <svx/extrusionbar.hxx>
+#include <svx/fontworkbar.hxx>
+#include <vcl/inputctx.hxx>
+
+#include <sfx2/objface.hxx>
+#include <swmodule.hxx>
+#include <unotxvw.hxx>
+#include <cmdid.h>
+#include <globals.hrc>
+#include <wrtsh.hxx>
+#include <edtwin.hxx>
+#include <wgrfsh.hxx>
+#include <wfrmsh.hxx>
+#include <wolesh.hxx>
+#include <wtabsh.hxx>
+#include <wlistsh.hxx>
+#include <wformsh.hxx>
+#include <wtextsh.hxx>
+#include <barcfg.hxx>
+#include <doc.hxx>
+
+// TECHNICALLY not possible !!
+#include <beziersh.hxx>
+#include <drawsh.hxx>
+#include <drwtxtsh.hxx>
+#include <annotsh.hxx>
+
+#include <wview.hxx>
+#include <wdocsh.hxx>
+
+ // needed for -fsanitize=function visibility of typeinfo for functions of
+ // type void(SfxShell*,SfxRequest&) defined in swslots.hxx
+#include <sfx2/viewfac.hxx>
+#define ShellClass_SwWebView
+#define ShellClass_Text
+#include <swslots.hxx>
+
+SFX_IMPL_NAMED_VIEWFACTORY(SwWebView, "Default")
+{
+ SFX_VIEW_REGISTRATION(SwWebDocShell);
+}
+
+SFX_IMPL_INTERFACE(SwWebView, SwView)
+
+void SwWebView::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterChildWindow(SvxSearchDialogWrapper::GetChildWindowId());
+ GetStaticInterface()->RegisterChildWindow(SfxInfoBarContainerChild::GetChildWindowId());
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_TOOLS, SfxVisibilityFlags::Standard|SfxVisibilityFlags::Server,
+ ToolbarId::Webtools_Toolbox);
+}
+
+
+SwWebView::SwWebView(SfxViewFrame& _rFrame, SfxViewShell* _pShell) :
+ SwView(_rFrame, _pShell)
+{
+}
+
+SwWebView::~SwWebView()
+{
+}
+
+void SwWebView::SelectShell()
+{
+#if HAVE_FEATURE_DESKTOP
+ // Decision whether UpdateTable must be called
+ bool bUpdateTable = false;
+ const SwFrameFormat* pCurTableFormat = GetWrtShell().GetTableFormat();
+ if(pCurTableFormat && pCurTableFormat != GetLastTableFrameFormat())
+ {
+ bUpdateTable = true; // can only be executed later
+ }
+ SetLastTableFrameFormat(pCurTableFormat);
+ //SEL_TBL and SEL_TBL_CELLS can be ored!
+ SelectionType nNewSelectionType = GetWrtShell().GetSelectionType()
+ & ~SelectionType::TableCell;
+
+ SelectionType _nSelectionType = GetSelectionType();
+ if ( nNewSelectionType == _nSelectionType )
+ {
+ GetViewFrame().GetBindings().InvalidateAll( false );
+ if ( _nSelectionType & SelectionType::Ole ||
+ _nSelectionType & SelectionType::Graphic )
+ //The verb may of course change for graphics and OLE!
+ ImpSetVerb( nNewSelectionType );
+ }
+ else
+ {
+ SfxDispatcher &rDispatcher = *GetViewFrame().GetDispatcher();
+ SwToolbarConfigItem *pBarCfg = SW_MOD()->GetWebToolbarConfig();
+
+ if( GetCurShell() )
+ {
+ rDispatcher.Flush(); // really delete all cached shells
+
+ //Additional to the old selection remember which toolbar was visible.
+ ToolbarId eId = rDispatcher.GetObjectBarId(SFX_OBJECTBAR_OBJECT);
+ if (eId != ToolbarId::None)
+ pBarCfg->SetTopToolbar( _nSelectionType, eId );
+
+ SfxShell *pSfxShell;
+ sal_uInt16 i;
+ for ( i = 0; true; ++i )
+ {
+ pSfxShell = rDispatcher.GetShell( i );
+ if ( !( dynamic_cast< const SwBaseShell *>( pSfxShell ) != nullptr ||
+ dynamic_cast< const SwDrawTextShell *>( pSfxShell ) || dynamic_cast< const SwAnnotationShell *>( pSfxShell ) != nullptr ) )
+ break;
+ }
+ if (i)
+ {
+ pSfxShell = rDispatcher.GetShell( --i );
+ OSL_ENSURE( pSfxShell, "My Shell is lost in space" );
+ rDispatcher.Pop( *pSfxShell, SfxDispatcherPopFlags::POP_UNTIL | SfxDispatcherPopFlags::POP_DELETE);
+ }
+ }
+
+ bool bInitFormShell = false;
+ if( !GetFormShell() )
+ {
+ bInitFormShell = true;
+ SetFormShell( new FmFormShell( this ) );
+ rDispatcher.Push( *GetFormShell() );
+ }
+
+ bool bSetExtInpCntxt = false;
+ _nSelectionType = nNewSelectionType;
+ SetSelectionType( _nSelectionType );
+ ShellMode eShellMode;
+
+ if ( _nSelectionType & SelectionType::Ole )
+ {
+ eShellMode = ShellMode::Object;
+ SetShell( new SwWebOleShell( *this ));
+ rDispatcher.Push( *GetCurShell() );
+ }
+ else if ( _nSelectionType & SelectionType::Frame
+ || _nSelectionType & SelectionType::Graphic)
+ {
+ eShellMode = ShellMode::Frame;
+ SetShell( new SwWebFrameShell( *this ));
+ rDispatcher.Push( *GetCurShell() );
+ if(_nSelectionType & SelectionType::Graphic )
+ {
+ eShellMode = ShellMode::Graphic;
+ SetShell( new SwWebGrfShell( *this ));
+ rDispatcher.Push( *GetCurShell() );
+ }
+ }
+ else if ( _nSelectionType & SelectionType::Frame )
+ {
+ eShellMode = ShellMode::Frame;
+ SetShell( new SwWebFrameShell( *this ));
+ rDispatcher.Push( *GetCurShell() );
+ }
+ else if ( _nSelectionType & SelectionType::DrawObject )
+ {
+ eShellMode = ShellMode::Draw;
+ SetShell( new svx::ExtrusionBar( this ) );
+ rDispatcher.Push( *GetCurShell() );
+
+ SetShell( new svx::FontworkBar( this ) );
+ rDispatcher.Push( *GetCurShell() );
+
+ SetShell( new SwDrawShell( *this ));
+ rDispatcher.Push( *GetCurShell() );
+ if ( _nSelectionType & SelectionType::Ornament )
+ {
+ eShellMode = ShellMode::Bezier;
+ SetShell( new SwBezierShell( *this ));
+ rDispatcher.Push( *GetCurShell() );
+ }
+
+ }
+ else if ( _nSelectionType & SelectionType::DbForm )
+ {
+ eShellMode = ShellMode::DrawForm;
+ SetShell( new SwWebDrawFormShell( *this ));
+
+ rDispatcher.Push( *GetCurShell() );
+ }
+ else if ( _nSelectionType & SelectionType::DrawObjectEditMode )
+ {
+ eShellMode = ShellMode::DrawText;
+ rDispatcher.Push( *(new SwBaseShell( *this )) );
+ SetShell( new SwDrawTextShell( *this ));
+ rDispatcher.Push( *GetCurShell() );
+ }
+ else if ( _nSelectionType & SelectionType::PostIt )
+ {
+ eShellMode = ShellMode::PostIt;
+ SetShell( new SwAnnotationShell( *this ) );
+ rDispatcher.Push( *GetCurShell() );
+ }
+ else
+ {
+ bSetExtInpCntxt = true;
+ eShellMode = ShellMode::Text;
+ if ( _nSelectionType & SelectionType::NumberList )
+ {
+ eShellMode = ShellMode::ListText;
+ SetShell( new SwWebListShell( *this ));
+ rDispatcher.Push( *GetCurShell() );
+ }
+ SetShell( new SwWebTextShell(*this));
+ rDispatcher.Push( *GetCurShell() );
+ if ( _nSelectionType & SelectionType::Table )
+ {
+ eShellMode = eShellMode == ShellMode::ListText ? ShellMode::TableListText
+ : ShellMode::TableText;
+ SetShell( new SwWebTableShell( *this ));
+ rDispatcher.Push( *GetCurShell() );
+ }
+ }
+ ImpSetVerb( _nSelectionType );
+ GetViewImpl()->SetShellMode(eShellMode);
+
+ if( !GetDocShell()->IsReadOnly() )
+ {
+ if( bSetExtInpCntxt && GetWrtShell().HasReadonlySel() )
+ bSetExtInpCntxt = false;
+
+ InputContext aCntxt( GetEditWin().GetInputContext() );
+ aCntxt.SetOptions( bSetExtInpCntxt
+ ? (aCntxt.GetOptions() |
+ ( InputContextFlags::Text |
+ InputContextFlags::ExtText ))
+ : (aCntxt.GetOptions() & ~
+ InputContextFlags( InputContextFlags::Text |
+ InputContextFlags::ExtText )) );
+ GetEditWin().SetInputContext( aCntxt );
+ }
+
+ //Additional to the selection enable the toolbar, which was
+ //activated last time
+ //Before must be a Flush(), but concerns according to MBA not the
+ //user interface and is not a performance issue.
+ // TODO/LATER: maybe now the Flush() command is superfluous?!
+ rDispatcher.Flush();
+
+ Point aPnt = GetEditWin().GetPointerPosPixel();
+ aPnt = GetEditWin().PixelToLogic(aPnt);
+ GetEditWin().UpdatePointer(aPnt);
+
+ if ( bInitFormShell && GetWrtShell().GetDrawView() )
+ GetFormShell()->SetView( dynamic_cast< FmFormView* >(
+ GetWrtShell().GetDrawView()));
+
+ }
+ GetViewImpl()->GetUNOObject_Impl()->NotifySelChanged();
+
+ //Opportune time for the communication with OLE objects?
+ if ( GetDocShell()->GetDoc()->IsOLEPrtNotifyPending() )
+ GetDocShell()->GetDoc()->PrtOLENotify( false );
+
+ //now the table update
+ if(bUpdateTable)
+ GetWrtShell().UpdateTable();
+#endif
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/wrtsh/delete.cxx b/sw/source/uibase/wrtsh/delete.cxx
new file mode 100644
index 0000000000..e7a09d0165
--- /dev/null
+++ b/sw/source/uibase/wrtsh/delete.cxx
@@ -0,0 +1,665 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+#include <wrtsh.hxx>
+#include <swcrsr.hxx>
+#include <editeng/lrspitem.hxx>
+#include <view.hxx>
+#include <drawbase.hxx>
+#include <unobaseclass.hxx>
+#include <fmtanchr.hxx>
+#include <flyfrm.hxx>
+#include <ndtxt.hxx>
+#include <txtfld.hxx>
+#include <docufld.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <i18nutil/unicode.hxx>
+#include <o3tl/temporary.hxx>
+#include <rtl/character.hxx>
+#include <osl/diagnose.h>
+#include <doc.hxx>
+#include <IDocumentRedlineAccess.hxx>
+
+inline void SwWrtShell::OpenMark()
+{
+ StartAllAction();
+ ResetCursorStack();
+ KillPams();
+ SetMark();
+}
+
+inline void SwWrtShell::CloseMark( bool bOkFlag )
+{
+ if( bOkFlag )
+ UpdateAttr();
+ else
+ SwapPam();
+
+ ClearMark();
+ EndAllAction();
+}
+
+
+
+// #i23725#
+bool SwWrtShell::TryRemoveIndent()
+{
+ bool bResult = false;
+
+ SfxItemSetFixed<RES_MARGIN_FIRSTLINE, RES_MARGIN_FIRSTLINE> aAttrSet(GetAttrPool());
+ GetCurAttr(aAttrSet);
+
+ SvxFirstLineIndentItem firstLine(aAttrSet.Get(RES_MARGIN_FIRSTLINE));
+ SvxTextLeftMarginItem leftMargin(aAttrSet.Get(RES_MARGIN_TEXTLEFT));
+ short aOldFirstLineOfst = firstLine.GetTextFirstLineOffset();
+
+ if (aOldFirstLineOfst > 0)
+ {
+ firstLine.SetTextFirstLineOffset(0);
+ bResult = true;
+ }
+ else if (aOldFirstLineOfst < 0)
+ {
+ // this used to call SetLeft() but this should be the same result
+ firstLine.SetTextFirstLineOffset(0);
+ leftMargin.SetTextLeft(leftMargin.GetTextLeft() + aOldFirstLineOfst);
+ bResult = true;
+ }
+ else if (leftMargin.GetTextLeft() != 0)
+ {
+ leftMargin.SetTextLeft(0);
+ bResult = true;
+ }
+
+ if (bResult)
+ {
+ aAttrSet.Put(firstLine);
+ aAttrSet.Put(leftMargin);
+ SetAttrSet(aAttrSet);
+ }
+
+ return bResult;
+}
+
+/** Description: Erase the line. */
+
+void SwWrtShell::DelLine()
+{
+ SwActContext aActContext(this);
+ ResetCursorStack();
+ // remember the old cursor
+ Push();
+ ClearMark();
+ SwCursorShell::LeftMargin();
+ SetMark();
+ SwCursorShell::RightMargin();
+
+ bool bRet = Delete(false);
+ Pop(SwCursorShell::PopMode::DeleteCurrent);
+ if( bRet )
+ UpdateAttr();
+}
+
+void SwWrtShell::DelToStartOfLine()
+{
+ OpenMark();
+ SwCursorShell::LeftMargin();
+ bool bRet = Delete(false);
+ CloseMark( bRet );
+}
+
+void SwWrtShell::DelToEndOfLine()
+{
+ OpenMark();
+ SwCursorShell::RightMargin();
+ bool bRet = Delete(false);
+ CloseMark( bRet );
+}
+
+bool SwWrtShell::DelLeft()
+{
+ // If it's a Fly, throw it away
+ SelectionType nSelType = GetSelectionType();
+ const SelectionType nCmp = SelectionType::Frame | SelectionType::Graphic | SelectionType::Ole | SelectionType::DrawObject;
+ if( nCmp & nSelType )
+ {
+ // #108205# Remember object's position.
+ Point aTmpPt = GetObjRect().TopLeft();
+
+ DelSelectedObj();
+
+ // #108205# Set cursor to remembered position.
+ SetCursor(&aTmpPt);
+
+ LeaveSelFrameMode();
+ UnSelectFrame();
+
+ nSelType = GetSelectionType();
+ if ( nCmp & nSelType )
+ {
+ EnterSelFrameMode();
+ GotoNextFly();
+ }
+
+ return true;
+ }
+
+ // If a selection exists, erase this
+ if ( IsSelection() )
+ {
+ if( !IsBlockMode() || HasSelection() )
+ {
+ //OS: Once again Basic: SwActContext must be leaved
+ //before EnterStdMode!
+ {
+ SwActContext aActContext(this);
+ ResetCursorStack();
+ Delete(false);
+ UpdateAttr();
+ }
+ if( IsBlockMode() )
+ {
+ NormalizePam();
+ ClearMark();
+ EnterBlockMode();
+ }
+ else
+ EnterStdMode();
+ return true;
+ }
+ else
+ EnterStdMode();
+ }
+
+ // JP 29.06.95: never erase a table standing in front of it.
+ bool bSwap = false;
+ const SwTableNode * pWasInTableNd = SwCursorShell::IsCursorInTable();
+
+ if( SwCursorShell::IsSttPara())
+ {
+ // Start/EndAllAction to avoid cursor flickering
+ UnoActionContext c(GetDoc());
+ SwCursorShell::Push();
+
+ // #i4032# Don't actually call a 'delete' if we
+ // changed the table cell, compare DelRight().
+ const SwStartNode * pSNdOld = pWasInTableNd ?
+ GetCursor()->GetPointNode().FindTableBoxStartNode() :
+ nullptr;
+
+ // If the cursor is at the beginning of a paragraph, try to step
+ // backwards. On failure we are done.
+ bool bDoSomething = SwCursorShell::Left(1,SwCursorSkipMode::Chars);
+
+ if (bDoSomething)
+ {
+ // If the cursor entered or left a table (or both) we are done.
+ const SwTableNode* pIsInTableNd = SwCursorShell::IsCursorInTable();
+ bDoSomething = pIsInTableNd == pWasInTableNd;
+
+ if (bDoSomething)
+ {
+ const SwStartNode* pSNdNew = pIsInTableNd ?
+ GetCursor()->GetPointNode().FindTableBoxStartNode() :
+ nullptr;
+
+ // #i4032# Don't actually call a 'delete' if we
+ // changed the table cell, compare DelRight().
+ bDoSomething = pSNdOld == pSNdNew;
+ }
+ }
+
+ if (!bDoSomething)
+ {
+ // tdf#115132 Restore previous position and we are done
+ SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent);
+ return false;
+ }
+
+ SwCursorShell::Pop(SwCursorShell::PopMode::DeleteStack);
+
+ OpenMark();
+ SwCursorShell::Right(1,SwCursorSkipMode::Chars);
+ SwCursorShell::SwapPam();
+ bSwap = true;
+ }
+ else
+ {
+ // If we are just to the right to a fieldmark, then remove it completely
+ const SwPosition* pCurPos = GetCursor()->GetPoint();
+ SwPosition aPrevChar(*pCurPos->GetContentNode(), pCurPos->GetContentIndex() - 1);
+ sw::mark::IFieldmark* pFm = getIDocumentMarkAccess()->getFieldmarkAt(aPrevChar);
+ if (pFm && pFm->GetMarkEnd() == *pCurPos)
+ {
+ mxDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY, nullptr);
+ IDocumentMarkAccess::DeleteFieldmarkCommand(*pFm);
+ getIDocumentMarkAccess()->deleteMark(pFm);
+ mxDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr);
+ return true;
+ }
+
+ OpenMark();
+ SwCursorShell::Left(1, SwCursorSkipMode::Chars);
+
+ // If we are deleting a variation selector, we want to delete the
+ // whole sequence.
+ sal_uInt32 nCode = GetChar(false);
+ if ( rtl::isSurrogate( nCode ) )
+ {
+ OUString sStr = GetSelText();
+ nCode = sStr.iterateCodePoints( &o3tl::temporary(sal_Int32(0)) );
+ }
+
+ if ( unicode::isVariationSelector( nCode ) )
+ {
+ SwCursorShell::Push();
+ SwCursorShell::Left(1, SwCursorSkipMode::Chars);
+ SwCursorShell::Pop( SwCursorShell::PopMode::DeleteStack );
+ }
+ }
+ bool bRet = Delete(true);
+ if( !bRet && bSwap )
+ SwCursorShell::SwapPam();
+ CloseMark( bRet );
+
+ return bRet;
+}
+
+bool SwWrtShell::DelRight(bool const isReplaceHeuristic)
+{
+ // Will be or'ed, if a tableselection exists;
+ // will here be implemented on SelectionType::Table
+ bool bRet = false;
+ SelectionType nSelection = GetSelectionType();
+ if(nSelection & SelectionType::TableCell)
+ nSelection = SelectionType::Table;
+ if(nSelection & SelectionType::Text)
+ nSelection = SelectionType::Text;
+
+ switch( nSelection & ~SelectionType::Ornament & ~SelectionType::Media )
+ {
+ case SelectionType::PostIt:
+ case SelectionType::Text:
+ case SelectionType::Table:
+ case SelectionType::NumberList:
+ // If a selection exists, erase it.
+ if( IsSelection() )
+ {
+ if( !IsBlockMode() || HasSelection() )
+ {
+ //OS: And once again Basic: SwActContext must be
+ //leaved before EnterStdMode !
+ {
+ SwActContext aActContext(this);
+ ResetCursorStack();
+ Delete(isReplaceHeuristic);
+ UpdateAttr();
+ }
+ if( IsBlockMode() )
+ {
+ NormalizePam();
+ ClearMark();
+ EnterBlockMode();
+ }
+ else
+ EnterStdMode();
+ bRet = true;
+ break;
+ }
+ else
+ EnterStdMode();
+ }
+
+ if (SwCursorShell::IsEndPara())
+ {
+ // Start/EndAllAction to avoid cursor flickering
+ UnoActionContext c(GetDoc());
+
+ const SwTableNode* pWasInTableNd = IsCursorInTable();
+ // #108049# Save the startnode of the current cell
+ const SwStartNode* pSNdOld = pWasInTableNd ?
+ GetCursor()->GetPointNode().FindTableBoxStartNode() : nullptr;
+ bool bCheckDelFull = SelectionType::Text & nSelection && SwCursorShell::IsSttPara();
+ bool bDelFull = false;
+ bool bDoNothing = false;
+
+ // #i41424# Introduced a couple of
+ // Push()-Pop() pairs here. The reason for this is that a
+ // Right()-Left() combination does not make sure, that
+ // the cursor will be in its initial state, because there
+ // may be a numbering in front of the next paragraph.
+ SwCursorShell::Push();
+
+ if (SwCursorShell::Right(1, SwCursorSkipMode::Chars))
+ {
+ const SwTableNode* pCurrTableNd = IsCursorInTable();
+ bDelFull = bCheckDelFull && pCurrTableNd && pCurrTableNd != pWasInTableNd;
+ if (!bDelFull && (IsCursorInTable() || (pCurrTableNd != pWasInTableNd)))
+ {
+ // #108049# Save the startnode of the current cell.
+ // May be different to pSNdOld as we have moved.
+ const SwStartNode* pSNdNew = pCurrTableNd ?
+ GetCursor()->GetPointNode().FindTableBoxStartNode() : nullptr;
+
+ // tdf#115132 Only keep cursor position instead of deleting
+ // if we have moved to a different cell
+ bDoNothing = pSNdOld != pSNdNew;
+ }
+ }
+
+ // restore cursor
+ SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent);
+
+ if (bDelFull)
+ {
+ DelFullPara();
+ UpdateAttr();
+ }
+ if (bDelFull || bDoNothing)
+ break;
+ }
+
+ {
+ // If we are just ahead of a fieldmark, then remove it completely
+ sw::mark::IFieldmark *const pFm = getIDocumentMarkAccess()->getFieldmarkAt(*GetCursor()->GetPoint());
+ if (pFm && pFm->GetMarkStart() == *GetCursor()->GetPoint())
+ {
+ mxDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY, nullptr);
+ IDocumentMarkAccess::DeleteFieldmarkCommand(*pFm);
+ getIDocumentMarkAccess()->deleteMark(pFm);
+ mxDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr);
+ bRet = true;
+ break;
+ }
+ }
+
+ OpenMark();
+ SwCursorShell::Right(1, SwCursorSkipMode::Cells);
+ bRet = Delete(true);
+ CloseMark( bRet );
+ break;
+
+ case SelectionType::Frame:
+ case SelectionType::Graphic:
+ case SelectionType::Ole:
+ case SelectionType::DrawObject:
+ case SelectionType::DrawObjectEditMode:
+ case SelectionType::DbForm:
+ {
+ // Group deletion of the object and its comment together
+ // (also as-character anchor conversion at track changes)
+ mxDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY, nullptr);
+
+ // #108205# Remember object's position.
+ Point aTmpPt = GetObjRect().TopLeft();
+
+ // Remember the anchor of the selected object before deletion.
+ std::optional<SwPosition> oAnchor;
+ RndStdIds eAnchorId = RndStdIds::FLY_AT_PARA;
+ SwFlyFrame* pFly = GetSelectedFlyFrame();
+ SwFrameFormat* pFormat = nullptr;
+ if (pFly)
+ {
+ pFormat = pFly->GetFormat();
+ if (pFormat)
+ {
+ eAnchorId = pFormat->GetAnchor().GetAnchorId();
+ // to-character anchor conversion at track changes
+ if ( IsRedlineOn() && (eAnchorId != RndStdIds::FLY_AS_CHAR &&
+ eAnchorId != RndStdIds::FLY_AT_CHAR) )
+ {
+ SfxItemSetFixed<RES_ANCHOR, RES_ANCHOR> aSet(GetAttrPool());
+ GetFlyFrameAttr(aSet);
+ SwFormatAnchor aAnch(RndStdIds::FLY_AT_CHAR);
+ aSet.Put(aAnch);
+ SetFlyFrameAttr(aSet);
+ eAnchorId = pFormat->GetAnchor().GetAnchorId();
+ }
+ if ((eAnchorId == RndStdIds::FLY_AS_CHAR || eAnchorId == RndStdIds::FLY_AT_CHAR)
+ && pFormat->GetAnchor().GetAnchorNode())
+ {
+ oAnchor.emplace(*pFormat->GetAnchor().GetContentAnchor());
+ // set cursor before the anchor point
+ if ( IsRedlineOn() )
+ *GetCurrentShellCursor().GetPoint() = *oAnchor;
+ }
+ }
+ }
+
+ // track changes: create redline at anchor point of the image to record the deletion
+ if ( IsRedlineOn() && oAnchor && SelectionType::Graphic & nSelection && pFormat &&
+ ( eAnchorId == RndStdIds::FLY_AT_CHAR || eAnchorId == RndStdIds::FLY_AS_CHAR ) )
+ {
+ sal_Int32 nRedlineLength = 1;
+ // create a double CH_TXT_TRACKED_DUMMY_CHAR anchor point of the image to record the
+ // deletion, if needed (otherwise use the existing anchor point of the image anchored
+ // *as* character)
+ if ( eAnchorId == RndStdIds::FLY_AT_CHAR )
+ {
+ nRedlineLength = 2;
+ LeaveSelFrameMode();
+ UnSelectFrame();
+ RedlineFlags eOld = GetRedlineFlags();
+ SetRedlineFlags( eOld | RedlineFlags::Ignore );
+ Insert( OUStringChar(CH_TXT_TRACKED_DUMMY_CHAR) +
+ OUStringChar(CH_TXT_TRACKED_DUMMY_CHAR) );
+ SwFormatAnchor anchor(RndStdIds::FLY_AT_CHAR);
+ SwCursorShell::Left(1, SwCursorSkipMode::Chars);
+ anchor.SetAnchor(GetCursor()->GetPoint());
+ GetDoc()->SetAttr(anchor, *pFormat);
+ SetRedlineFlags( eOld );
+ SwCursorShell::Left(1, SwCursorSkipMode::Chars);
+ }
+ OpenMark();
+ SwCursorShell::Right(nRedlineLength, SwCursorSkipMode::Chars);
+ bRet = Delete(false);
+ CloseMark( bRet );
+ }
+ else
+ DelSelectedObj();
+
+ if (oAnchor)
+ {
+ SwTextNode* pTextNode = oAnchor->GetNode().GetTextNode();
+ if (pTextNode)
+ {
+ const SwTextField* pField(
+ pTextNode->GetFieldTextAttrAt(oAnchor->GetContentIndex(), ::sw::GetTextAttrMode::Default));
+ if (pField
+ && dynamic_cast<const SwPostItField*>(pField->GetFormatField().GetField()))
+ {
+ // Remove the comment of the deleted object.
+ *GetCurrentShellCursor().GetPoint() = *oAnchor;
+ DelRight();
+ }
+ }
+ }
+
+ mxDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr);
+
+ // #108205# Set cursor to remembered position.
+ SetCursor(&aTmpPt);
+
+ LeaveSelFrameMode();
+ UnSelectFrame();
+ OSL_ENSURE( !IsFrameSelected(),
+ "<SwWrtShell::DelRight(..)> - <SwWrtShell::UnSelectFrame()> should unmark all objects" );
+ // leave draw mode, if necessary.
+ {
+ if (GetView().GetDrawFuncPtr())
+ {
+ GetView().GetDrawFuncPtr()->Deactivate();
+ GetView().SetDrawFuncPtr(nullptr);
+ }
+ if ( GetView().IsDrawMode() )
+ {
+ GetView().LeaveDrawCreate();
+ }
+ }
+ }
+
+ // <IsFrameSelected()> can't be true - see above.
+ {
+ nSelection = GetSelectionType();
+ if ( SelectionType::Frame & nSelection ||
+ SelectionType::Graphic & nSelection ||
+ SelectionType::Ole & nSelection ||
+ SelectionType::DrawObject & nSelection )
+ {
+ EnterSelFrameMode();
+ GotoNextFly();
+ }
+ }
+ bRet = true;
+ break;
+ default: break;
+ }
+ return bRet;
+}
+
+void SwWrtShell::DelToEndOfPara()
+{
+ SwActContext aActContext(this);
+ ResetCursorStack();
+ Push();
+ SetMark();
+ if( !MovePara(GoCurrPara,fnParaEnd))
+ {
+ Pop(SwCursorShell::PopMode::DeleteCurrent);
+ return;
+ }
+ bool bRet = Delete(false);
+ Pop(SwCursorShell::PopMode::DeleteCurrent);
+ if( bRet )
+ UpdateAttr();
+}
+
+void SwWrtShell::DelToStartOfPara()
+{
+ SwActContext aActContext(this);
+ ResetCursorStack();
+ Push();
+ SetMark();
+ if( !MovePara(GoCurrPara,fnParaStart))
+ {
+ Pop(SwCursorShell::PopMode::DeleteCurrent);
+ return;
+ }
+ bool bRet = Delete(false);
+ Pop(SwCursorShell::PopMode::DeleteCurrent);
+ if( bRet )
+ UpdateAttr();
+}
+
+// All erase operations should work with Find instead with
+// Nxt-/PrvDelim, because the latter works with Wrap Around
+// -- that's probably not wished.
+
+void SwWrtShell::DelToStartOfSentence()
+{
+ if(IsStartOfDoc())
+ return;
+ OpenMark();
+ bool bRet = BwdSentence_() && Delete(false);
+ CloseMark( bRet );
+}
+
+bool SwWrtShell::DelToEndOfSentence()
+{
+ if(IsEndOfDoc())
+ return false;
+ OpenMark();
+ bool bRet(false);
+ // fdo#60967: special case that is documented in help: delete
+ // paragraph following table if cursor is at end of last cell in table
+ if (IsEndOfTable())
+ {
+ Push();
+ ClearMark();
+ if (SwCursorShell::Right(1,SwCursorSkipMode::Chars))
+ {
+ SetMark();
+ if (!IsEndPara()) // can only be at the end if it's empty
+ { // for an empty paragraph this would actually select the _next_
+ SwCursorShell::MovePara(GoCurrPara, fnParaEnd);
+ }
+ if (!IsEndOfDoc()) // do not delete last paragraph in body text
+ {
+ bRet = DelFullPara();
+ }
+ }
+ Pop(SwCursorShell::PopMode::DeleteCurrent);
+ }
+ else
+ {
+ bRet = FwdSentence_() && Delete(false);
+ }
+ CloseMark( bRet );
+ return bRet;
+}
+
+void SwWrtShell::DelNxtWord()
+{
+ if(IsEndOfDoc())
+ return;
+ SwActContext aActContext(this);
+ ResetCursorStack();
+ EnterStdMode();
+ SetMark();
+ if(IsEndWrd() && !IsStartWord())
+ NxtWrdForDelete(); // #i92468#
+ if(IsStartWord() || IsEndPara())
+ NxtWrdForDelete(); // #i92468#
+ else
+ EndWrd();
+
+ bool bRet = Delete(false);
+ if( bRet )
+ UpdateAttr();
+ else
+ SwapPam();
+ ClearMark();
+}
+
+void SwWrtShell::DelPrvWord()
+{
+ if(IsStartOfDoc())
+ return;
+ SwActContext aActContext(this);
+ ResetCursorStack();
+ EnterStdMode();
+ SetMark();
+ if ( !IsStartWord() ||
+ !PrvWrdForDelete() ) // #i92468#
+ {
+ if (IsEndWrd() || IsSttPara())
+ PrvWrdForDelete(); // #i92468#
+ else
+ SttWrd();
+ }
+ bool bRet = Delete(false);
+ if( bRet )
+ UpdateAttr();
+ else
+ SwapPam();
+ ClearMark();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/wrtsh/move.cxx b/sw/source/uibase/wrtsh/move.cxx
new file mode 100644
index 0000000000..cda2b32112
--- /dev/null
+++ b/sw/source/uibase/wrtsh/move.cxx
@@ -0,0 +1,773 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <viewopt.hxx>
+#include <drawbase.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <drawdoc.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdview.hxx>
+
+/**
+ Always:
+ - Reset of the cursor stack
+ - retrigger timer
+ - if applicable: GCAttr
+
+ on selection
+ - SttSelect()
+
+ else
+ - EndSelect()
+ */
+
+const tools::Long nReadOnlyScrollOfst = 10;
+
+namespace {
+
+class ShellMoveCursor
+{
+ SwWrtShell* pSh;
+ bool bAct;
+public:
+ ShellMoveCursor( SwWrtShell* pWrtSh, bool bSel )
+ {
+ bAct = !pWrtSh->ActionPend() && (pWrtSh->GetFrameType(nullptr,false) & FrameTypeFlags::FLY_ANY);
+ pSh = pWrtSh;
+ pSh->MoveCursor( bSel );
+ pWrtSh->GetView().GetViewFrame().GetBindings().Invalidate(SID_HYPERLINK_GETLINK);
+ }
+ ~ShellMoveCursor() COVERITY_NOEXCEPT_FALSE
+ {
+ if( bAct )
+ {
+ // The action is used for scrolling in "single paragraph"
+ // frames with fixed height.
+ pSh->StartAllAction();
+ pSh->EndAllAction();
+ }
+ }
+};
+
+}
+
+void SwWrtShell::MoveCursor( bool bWithSelect )
+{
+ ResetCursorStack();
+ if ( IsGCAttr() )
+ {
+ GCAttr();
+ ClearGCAttr();
+ }
+ if ( bWithSelect )
+ SttSelect();
+ else
+ {
+ EndSelect();
+ (this->*m_fnKillSel)( nullptr, false );
+ }
+}
+
+bool SwWrtShell::SimpleMove( FNSimpleMove FnSimpleMove, bool bSelect )
+{
+ bool bRet;
+ if( bSelect )
+ {
+ SttCursorMove();
+ MoveCursor( true );
+ bRet = (this->*FnSimpleMove)();
+ EndCursorMove();
+ }
+ else
+ {
+ bRet = (this->*FnSimpleMove)();
+ if( bRet )
+ MoveCursor();
+ }
+ return bRet;
+}
+
+bool SwWrtShell::Left( SwCursorSkipMode nMode, bool bSelect,
+ sal_uInt16 nCount, bool bBasicCall, bool bVisual )
+{
+ if ( !bSelect && !bBasicCall && IsCursorReadonly() && !GetViewOptions()->IsSelectionInReadonly())
+ {
+ Point aTmp( VisArea().Pos() );
+ aTmp.AdjustX( -(VisArea().Width() * nReadOnlyScrollOfst / 100) );
+ m_rView.SetVisArea( aTmp );
+ return true;
+ }
+ else
+ {
+ ShellMoveCursor aTmp( this, bSelect );
+ return SwCursorShell::Left( nCount, nMode, bVisual );
+ }
+}
+
+bool SwWrtShell::Right( SwCursorSkipMode nMode, bool bSelect,
+ sal_uInt16 nCount, bool bBasicCall, bool bVisual )
+{
+ if ( !bSelect && !bBasicCall && IsCursorReadonly() && !GetViewOptions()->IsSelectionInReadonly() )
+ {
+ Point aTmp( VisArea().Pos() );
+ aTmp.AdjustX(VisArea().Width() * nReadOnlyScrollOfst / 100 );
+ aTmp.setX( m_rView.SetHScrollMax( aTmp.X() ) );
+ m_rView.SetVisArea( aTmp );
+ return true;
+ }
+ else
+ {
+ ShellMoveCursor aTmp( this, bSelect );
+ return SwCursorShell::Right( nCount, nMode, bVisual );
+ }
+}
+
+bool SwWrtShell::Up( bool bSelect, sal_uInt16 nCount, bool bBasicCall )
+{
+ if ( !bSelect && !bBasicCall && IsCursorReadonly() && !GetViewOptions()->IsSelectionInReadonly())
+ {
+ Point aTmp( VisArea().Pos() );
+ aTmp.AdjustY( -(VisArea().Height() * nReadOnlyScrollOfst / 100) );
+ m_rView.SetVisArea( aTmp );
+ return true;
+ }
+
+ ShellMoveCursor aTmp( this, bSelect );
+ return SwCursorShell::Up(nCount);
+}
+
+bool SwWrtShell::Down( bool bSelect, sal_uInt16 nCount, bool bBasicCall )
+{
+ if ( !bSelect && !bBasicCall && IsCursorReadonly() && !GetViewOptions()->IsSelectionInReadonly())
+ {
+ Point aTmp( VisArea().Pos() );
+ aTmp.AdjustY(VisArea().Height() * nReadOnlyScrollOfst / 100 );
+ aTmp.setY( m_rView.SetVScrollMax( aTmp.Y() ) );
+ m_rView.SetVisArea( aTmp );
+ return true;
+ }
+
+ ShellMoveCursor aTmp( this, bSelect );
+ return SwCursorShell::Down(nCount);
+}
+
+bool SwWrtShell::LeftMargin( bool bSelect, bool bBasicCall )
+{
+ if ( !bSelect && !bBasicCall && IsCursorReadonly() )
+ {
+ Point aTmp( VisArea().Pos() );
+ aTmp.setX( DOCUMENTBORDER );
+ m_rView.SetVisArea( aTmp );
+ return true;
+ }
+ else
+ {
+ ShellMoveCursor aTmp( this, bSelect );
+ return SwCursorShell::LeftMargin();
+ }
+}
+
+bool SwWrtShell::RightMargin( bool bSelect, bool bBasicCall )
+{
+ if ( !bSelect && !bBasicCall && IsCursorReadonly() )
+ {
+ Point aTmp( VisArea().Pos() );
+ aTmp.setX( GetDocSize().Width() - VisArea().Width() + DOCUMENTBORDER );
+ if( DOCUMENTBORDER > aTmp.X() )
+ aTmp.setX( DOCUMENTBORDER );
+ m_rView.SetVisArea( aTmp );
+ return true;
+ }
+ else
+ {
+ ShellMoveCursor aTmp( this, bSelect );
+ return SwCursorShell::RightMargin(bBasicCall);
+ }
+}
+
+bool SwWrtShell::GoStart( bool bKeepArea, bool *pMoveTable,
+ bool bSelect, bool bDontMoveRegion )
+{
+ if ( IsCursorInTable() )
+ {
+ const bool bBoxSelection = HasBoxSelection();
+ if( !m_bBlockMode )
+ {
+ if ( !bSelect )
+ EnterStdMode();
+ else
+ SttSelect();
+ }
+ // Table cell ?
+ if ( !bBoxSelection && (MoveSection( GoCurrSection, fnSectionStart)
+ || bDontMoveRegion))
+ {
+ if ( pMoveTable )
+ *pMoveTable = false;
+ return true;
+ }
+ SwTableNode const*const pTable(getShellCursor(false)->GetPoint()->GetNode().FindTableNode());
+ assert(pTable);
+ if( MoveTable( GotoCurrTable, fnTableStart ) || bDontMoveRegion )
+ {
+ if ( pMoveTable )
+ *pMoveTable = true;
+ return true;
+ }
+ else if (SwCursor const*const pCursor = getShellCursor(false);
+ pTable->GetNodes()[pTable->GetIndex()+1]->EndOfSectionIndex()
+ < pCursor->GetPoint()->GetNode().GetIndex()
+ && pMoveTable != nullptr // only set by SelAll()
+ // problem: cursor isn't inside 1st cell, and didn't move there
+ // workaround: try to move cursor outside of table for SelAll()
+ && MoveOutOfTable())
+ {
+ assert(!*pMoveTable);
+ return true;
+ }
+ else if( bBoxSelection && pMoveTable )
+ {
+ // JP 09.01.96: We have a box selection (or an empty cell)
+ // and we want select (pMoveTable will be
+ // set in SelAll). Then the table must not
+ // be left, otherwise there is no selection
+ // of the entire table possible!
+ *pMoveTable = true;
+ return true;
+ }
+ }
+
+ if( !m_bBlockMode )
+ {
+ if ( !bSelect )
+ EnterStdMode();
+ else
+ SttSelect();
+ }
+ const FrameTypeFlags nFrameType = GetFrameType(nullptr,false);
+ if ( FrameTypeFlags::FLY_ANY & nFrameType )
+ {
+ if( MoveSection( GoCurrSection, fnSectionStart ) )
+ return true;
+ else if ( FrameTypeFlags::FLY_FREE & nFrameType || bDontMoveRegion )
+ return false;
+ }
+ if(( FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER | FrameTypeFlags::FOOTNOTE ) & nFrameType )
+ {
+ if ( MoveSection( GoCurrSection, fnSectionStart ) )
+ return true;
+ else if ( bKeepArea )
+ return true;
+ }
+
+ // first try to move to the start of the current SwSection
+ return SwCursorShell::MoveRegion( GotoCurrRegionAndSkip, fnRegionStart ) ||
+ (pMoveTable != nullptr
+ // move to start of text - if in different table, move out
+ ? MoveStartText()
+ // TODO who needs SttEndDoc for other case?
+ : SwCursorShell::SttEndDoc(true));
+}
+
+bool SwWrtShell::GoEnd(bool bKeepArea, const bool *pMoveTable)
+{
+ if (pMoveTable && *pMoveTable) // only in SelAll()
+ {
+ SwTableNode const*const pTable(getShellCursor(false)->GetPoint()->GetNode().FindTableNode());
+ assert(pTable);
+ if (MoveTable(GotoCurrTable, fnTableEnd))
+ {
+ return true;
+ }
+ else if (SwCursor const*const pCursor = getShellCursor(false);
+ pCursor->GetPoint()->GetNode().GetIndex()
+ < pTable->GetNodes()[pTable->EndOfSectionIndex()-1]->StartOfSectionIndex()
+ // problem: cursor isn't inside 1st cell, and didn't move there
+ // workaround: try to move cursor outside of table for SelAll()
+ && MoveOutOfTable())
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if ( IsCursorInTable() )
+ {
+ if ( MoveSection( GoCurrSection, fnSectionEnd ) ||
+ MoveTable( GotoCurrTable, fnTableEnd ) )
+ return true;
+ }
+ else
+ {
+ const FrameTypeFlags nFrameType = GetFrameType(nullptr,false);
+ if ( FrameTypeFlags::FLY_ANY & nFrameType )
+ {
+ if ( MoveSection( GoCurrSection, fnSectionEnd ) )
+ return true;
+ else if ( FrameTypeFlags::FLY_FREE & nFrameType )
+ return false;
+ }
+ if(( FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER | FrameTypeFlags::FOOTNOTE ) & nFrameType )
+ {
+ if ( MoveSection( GoCurrSection, fnSectionEnd) )
+ return true;
+ else if ( bKeepArea )
+ return true;
+ }
+ }
+ // Regions ???
+ return SwCursorShell::MoveRegion( GotoCurrRegionAndSkip, fnRegionEnd ) ||
+ SwCursorShell::SttEndDoc(false);
+}
+
+bool SwWrtShell::StartOfSection(bool const bSelect)
+{
+ ShellMoveCursor aTmp( this, bSelect );
+ return GoStart(false, nullptr, bSelect );
+}
+
+bool SwWrtShell::EndOfSection(bool const bSelect)
+{
+ ShellMoveCursor aTmp( this, bSelect );
+ return GoEnd();
+}
+
+bool SwWrtShell::SttNxtPg( bool bSelect )
+{
+ ShellMoveCursor aTmp( this, bSelect );
+ return MovePage( GetNextFrame, GetFirstSub );
+}
+
+void SwWrtShell::SttPrvPg( bool bSelect )
+{
+ ShellMoveCursor aTmp( this, bSelect );
+ MovePage( GetPrevFrame, GetFirstSub );
+}
+
+void SwWrtShell::EndNxtPg( bool bSelect )
+{
+ ShellMoveCursor aTmp( this, bSelect );
+ MovePage( GetNextFrame, GetLastSub );
+}
+
+bool SwWrtShell::EndPrvPg( bool bSelect )
+{
+ ShellMoveCursor aTmp( this, bSelect );
+ return MovePage( GetPrevFrame, GetLastSub );
+}
+
+bool SwWrtShell::SttPg( bool bSelect )
+{
+ ShellMoveCursor aTmp( this, bSelect );
+ return MovePage( GetThisFrame, GetFirstSub );
+}
+
+bool SwWrtShell::EndPg( bool bSelect )
+{
+ ShellMoveCursor aTmp( this, bSelect );
+ return MovePage( GetThisFrame, GetLastSub );
+}
+
+bool SwWrtShell::SttPara( bool bSelect )
+{
+ ShellMoveCursor aTmp( this, bSelect );
+ return MovePara( GoCurrPara, fnParaStart );
+}
+
+void SwWrtShell::EndPara( bool bSelect )
+{
+ ShellMoveCursor aTmp( this, bSelect );
+ MovePara(GoCurrPara,fnParaEnd);
+}
+
+// Column-by-jumping.
+// SSelection with or without
+// returns success or failure
+
+void SwWrtShell::StartOfColumn()
+{
+ ShellMoveCursor aTmp( this, false/*bSelect*/);
+ MoveColumn(GetCurrColumn, GetColumnStt);
+}
+
+void SwWrtShell::EndOfColumn()
+{
+ ShellMoveCursor aTmp( this, false/*bSelect*/);
+ MoveColumn(GetCurrColumn, GetColumnEnd);
+}
+
+void SwWrtShell::StartOfNextColumn()
+{
+ ShellMoveCursor aTmp( this, false/*bSelect*/);
+ MoveColumn( GetNextColumn, GetColumnStt);
+}
+
+void SwWrtShell::EndOfNextColumn()
+{
+ ShellMoveCursor aTmp( this, false/*bSelect*/);
+ MoveColumn(GetNextColumn, GetColumnEnd);
+}
+
+void SwWrtShell::StartOfPrevColumn()
+{
+ ShellMoveCursor aTmp( this, false/*bSelect*/);
+ MoveColumn(GetPrevColumn, GetColumnStt);
+}
+
+void SwWrtShell::EndOfPrevColumn()
+{
+ ShellMoveCursor aTmp( this, false/*bSelect*/);
+ MoveColumn(GetPrevColumn, GetColumnEnd);
+}
+
+bool SwWrtShell::PushCursor(SwTwips lOffset, bool bSelect)
+{
+ bool bDiff = false;
+ SwRect aOldRect( GetCharRect() ), aTmpArea( VisArea() );
+
+ // m_bDestOnStack indicates if I could not set the coursor at the current
+ // position, because in this region is no content.
+ if( !m_bDestOnStack )
+ {
+ Point aPt( aOldRect.Center() );
+
+ if( !IsCursorVisible() )
+ // set CursorPos to top-/bottom left pos. So the pagescroll is not
+ // be dependent on the current cursor, but on the visarea.
+ aPt.setY( aTmpArea.Top() + aTmpArea.Height() / 2 );
+
+ aPt.AdjustY(lOffset );
+ m_aDest = GetContentPos(aPt,lOffset > 0);
+ m_aDest.setX( aPt.X() );
+ m_bDestOnStack = true;
+ }
+
+ // If we had a frame selection, it must be removed after the m_fnSetCursor
+ // and we have to remember the position on the stack to return to it later.
+ bool bIsFrameSel = false;
+
+ //Target position is now within the viewable region -->
+ //Place the cursor at the target position; remember that no target
+ //position is longer on the stack.
+ //The new visible region is to be determined beforehand.
+ aTmpArea.Pos().AdjustY(lOffset );
+ if( aTmpArea.Contains(m_aDest) )
+ {
+ if( bSelect )
+ SttSelect();
+ else
+ EndSelect();
+
+ bIsFrameSel = IsFrameSelected();
+ bool bIsObjSel = 0 != IsObjSelected();
+
+ // unselect frame
+ if( bIsFrameSel || bIsObjSel )
+ {
+ UnSelectFrame();
+ LeaveSelFrameMode();
+ if ( bIsObjSel )
+ {
+ GetView().SetDrawFuncPtr( nullptr );
+ GetView().LeaveDrawCreate();
+ }
+
+ CallChgLnk();
+ }
+
+ (this->*m_fnSetCursor)( &m_aDest, true );
+
+ bDiff = aOldRect != GetCharRect();
+
+ if( bIsFrameSel )
+ {
+ // In frames take only the upper corner
+ // so that it can be re-selected.
+ aOldRect.SSize( 5, 5 );
+ }
+
+ // reset Dest. SPoint Flags
+ m_bDestOnStack = false;
+ }
+
+ // Position into the stack; bDiff indicates if there is a
+ // difference between the old and the new cursor position.
+ m_pCursorStack.reset( new CursorStack( bDiff, bIsFrameSel, aOldRect.Center(),
+ lOffset, std::move(m_pCursorStack) ) );
+ return !m_bDestOnStack && bDiff;
+}
+
+bool SwWrtShell::PopCursor(bool bUpdate, bool bSelect)
+{
+ if( nullptr == m_pCursorStack)
+ return false;
+
+ const bool bValidPos = m_pCursorStack->bValidCurPos;
+ if( bUpdate && bValidPos )
+ {
+ // If a predecessor is on the stack,
+ // use the flag for a valid position.
+ SwRect aTmpArea(VisArea());
+ aTmpArea.Pos().AdjustY( -(m_pCursorStack->lOffset) );
+ if( aTmpArea.Contains( m_pCursorStack->aDocPos ) )
+ {
+ if( bSelect )
+ SttSelect();
+ else
+ EndSelect();
+
+ (this->*m_fnSetCursor)(&m_pCursorStack->aDocPos, !m_pCursorStack->bIsFrameSel);
+ if( m_pCursorStack->bIsFrameSel && IsObjSelectable(m_pCursorStack->aDocPos))
+ {
+ HideCursor();
+ SelectObj( m_pCursorStack->aDocPos );
+ EnterSelFrameMode( &m_pCursorStack->aDocPos );
+ }
+ }
+ // If a discrepancy between the visible range and the
+ // remembered cursor position occurs, all of the remembered
+ // positions are thrown away.
+ else
+ {
+ ResetCursorStack_();
+ return false;
+ }
+ }
+ m_pCursorStack = std::move(m_pCursorStack->pNext);
+ if( nullptr == m_pCursorStack )
+ {
+ m_ePageMove = MV_NO;
+ m_bDestOnStack = false;
+ }
+ return bValidPos;
+}
+
+// Reset of all pushed cursor positions; these will
+// not be displayed ( --> No Start-/EndAction!!)
+
+void SwWrtShell::ResetCursorStack_()
+{
+ while(m_pCursorStack)
+ m_pCursorStack = std::move(m_pCursorStack->pNext);
+ m_ePageMove = MV_NO;
+ m_bDestOnStack = false;
+}
+/**
+ if no stack exists --> cancel selection
+ if stack && change of direction
+ --> pop cursor and return
+ else
+ --> push cursor
+ transpose cursor
+*/
+
+bool SwWrtShell::PageCursor(SwTwips lOffset, bool bSelect)
+{
+ // Do nothing if an offset of 0 was indicated
+ if(!lOffset) return false;
+ // Was once used to force a reformat of the layout.
+ // This has not work that way, because the cursor was not set
+ // because this does not happen within a
+ // Start-/EndActionParentheses.
+ // Because only SwViewShell::EndAction() is called at the end,
+ // no updating of the display of the cursor position takes place.
+ // The CursorShell-Actionparentheses cannot be used, because it
+ // always leads to displaying the cursor, thus also,
+ // if after the scroll scrolled in a region without a valid position.
+ // SwViewShell::StartAction();
+ PageMove eDir = lOffset > 0? MV_PAGE_DOWN: MV_PAGE_UP;
+ // Change of direction and stack present
+ if( eDir != m_ePageMove && m_ePageMove != MV_NO && PopCursor( true, bSelect ))
+ return true;
+
+ const bool bRet = PushCursor(lOffset, bSelect);
+ m_ePageMove = eDir;
+ return bRet;
+}
+
+bool SwWrtShell::GotoPage(sal_uInt16 nPage, bool bRecord)
+{
+ addCurrentPosition();
+ ShellMoveCursor aTmp( this, false);
+ if( SwCursorShell::GotoPage(nPage) && bRecord)
+ {
+ if(IsSelFrameMode())
+ {
+ UnSelectFrame();
+ LeaveSelFrameMode();
+ }
+ return true;
+ }
+ return false;
+}
+
+bool SwWrtShell::GotoMark( const ::sw::mark::IMark* const pMark, bool bSelect )
+{
+ ShellMoveCursor aTmp( this, bSelect );
+ SwPosition aPos = *GetCursor()->GetPoint();
+ bool bRet = SwCursorShell::GotoMark( pMark, true/*bStart*/ );
+ if (bRet)
+ m_aNavigationMgr.addEntry(aPos);
+ return bRet;
+}
+
+bool SwWrtShell::GotoFly( const OUString& rName, FlyCntType eType, bool bSelFrame )
+{
+ SwPosition aPos = *GetCursor()->GetPoint();
+ bool bRet = SwFEShell::GotoFly(rName, eType, bSelFrame);
+ if (bRet)
+ m_aNavigationMgr.addEntry(aPos);
+ return bRet;
+}
+
+bool SwWrtShell::GotoINetAttr( const SwTextINetFormat& rAttr )
+{
+ SwPosition aPos = *GetCursor()->GetPoint();
+ bool bRet = SwCursorShell::GotoINetAttr(rAttr);
+ if (bRet)
+ m_aNavigationMgr.addEntry(aPos);
+ return bRet;
+}
+
+void SwWrtShell::GotoOutline( SwOutlineNodes::size_type nIdx )
+{
+ addCurrentPosition();
+ SwCursorShell::GotoOutline (nIdx);
+}
+
+bool SwWrtShell::GotoOutline( const OUString& rName )
+{
+ SwPosition aPos = *GetCursor()->GetPoint();
+ bool bRet = SwCursorShell::GotoOutline (rName);
+ if (bRet)
+ m_aNavigationMgr.addEntry(aPos);
+ return bRet;
+}
+
+bool SwWrtShell::GotoDrawingObject(std::u16string_view rName)
+{
+ SwPosition aPos = *GetCursor()->GetPoint();
+ bool bRet = false;
+ SdrView* pDrawView = GetDrawView();
+ if (pDrawView)
+ {
+ pDrawView->SdrEndTextEdit();
+ pDrawView->UnmarkAll();
+ SdrPage* pPage = getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
+ for (const rtl::Reference<SdrObject>& pObj : *pPage)
+ {
+ if (pObj->GetName() == rName)
+ {
+ SdrPageView* pPageView = pDrawView->GetSdrPageView();
+ if(pPageView)
+ {
+ pDrawView->MarkObj(pObj.get(), pPageView);
+ m_aNavigationMgr.addEntry(aPos);
+ EnterStdMode();
+ HideCursor();
+ EnterSelFrameMode();
+ bRet = true;
+ }
+ break;
+ }
+ }
+ }
+ return bRet;
+}
+
+bool SwWrtShell::GotoRegion( std::u16string_view rName )
+{
+ SwPosition aPos = *GetCursor()->GetPoint();
+ bool bRet = SwCursorShell::GotoRegion (rName);
+ if (bRet)
+ m_aNavigationMgr.addEntry(aPos);
+ return bRet;
+ }
+
+bool SwWrtShell::GotoRefMark( const OUString& rRefMark, sal_uInt16 nSubType,
+ sal_uInt16 nSeqNo, sal_uInt16 nFlags )
+{
+ SwPosition aPos = *GetCursor()->GetPoint();
+ bool bRet = SwCursorShell::GotoRefMark(rRefMark, nSubType, nSeqNo, nFlags);
+ if (bRet)
+ m_aNavigationMgr.addEntry(aPos);
+ return bRet;
+}
+
+bool SwWrtShell::GotoNextTOXBase( const OUString* pName )
+{
+ SwPosition aPos = *GetCursor()->GetPoint();
+ bool bRet = SwCursorShell::GotoNextTOXBase(pName);
+ if (bRet)
+ m_aNavigationMgr.addEntry(aPos);
+ return bRet;
+}
+
+bool SwWrtShell::GotoTable( const OUString& rName )
+{
+ SwPosition aPos = *GetCursor()->GetPoint();
+ bool bRet = SwCursorShell::GotoTable(rName);
+ if (bRet)
+ m_aNavigationMgr.addEntry(aPos);
+ return bRet;
+}
+
+void SwWrtShell::GotoFormatField( const SwFormatField& rField ) {
+ SwPosition aPos = *GetCursor()->GetPoint();
+ bool bRet = SwCursorShell::GotoFormatField(rField);
+ if (bRet)
+ m_aNavigationMgr.addEntry(aPos);
+}
+
+void SwWrtShell::GotoFootnoteAnchor(const SwTextFootnote& rTextFootnote)
+{
+ SwPosition aPos = *GetCursor()->GetPoint();
+ bool bRet = SwCursorShell::GotoFootnoteAnchor(rTextFootnote);
+ if (bRet)
+ m_aNavigationMgr.addEntry(aPos);
+}
+
+const SwRangeRedline* SwWrtShell::GotoRedline( SwRedlineTable::size_type nArrPos, bool bSelect ) {
+ SwPosition aPos = *GetCursor()->GetPoint();
+ const SwRangeRedline *pRedline = SwCursorShell::GotoRedline(nArrPos, bSelect);
+ if (pRedline)
+ m_aNavigationMgr.addEntry(aPos);
+ return pRedline;
+}
+
+bool SwWrtShell::SelectTextAttr( sal_uInt16 nWhich, const SwTextAttr* pAttr )
+{
+ bool bRet;
+ {
+ SwMvContext aMvContext(this);
+ SttSelect();
+ bRet = SwCursorShell::SelectTextAttr( nWhich, false, pAttr );
+ }
+ EndSelect();
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/wrtsh/navmgr.cxx b/sw/source/uibase/wrtsh/navmgr.cxx
new file mode 100644
index 0000000000..eea6cda7dc
--- /dev/null
+++ b/sw/source/uibase/wrtsh/navmgr.cxx
@@ -0,0 +1,221 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <navmgr.hxx>
+#include <wrtsh.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <vcl/svapp.hxx>
+#include <cmdid.h>
+#include <view.hxx>
+#include <doc.hxx>
+#include <unocrsr.hxx>
+
+// This method positions the cursor to the position rPos.
+
+void SwNavigationMgr::GotoSwPosition(const SwPosition &rPos) {
+
+ // EnterStdMode() prevents the cursor to 'block' the current
+ // shell when it should move from the image back to the normal shell
+ m_rMyShell.EnterStdMode();
+ m_rMyShell.StartAllAction();
+ // cursor consists of two SwPositions: Point and Mark.
+ // Such a pair is called a PaM. SwPaM is derived from SwRing.
+ // The Ring contains the single regions of a multi-selection.
+ SwPaM* pPaM = m_rMyShell.GetCursor();
+
+ if(pPaM->HasMark())
+ pPaM->DeleteMark(); // If there was a selection, get rid of it
+ *pPaM->GetPoint() = rPos; // Position Cursor
+
+ m_rMyShell.EndAllAction();
+}
+
+// Ctor for the SwNavigationMgr class
+// Sets the shell to the current shell
+// and the index of the current position to 0
+
+SwNavigationMgr::SwNavigationMgr(SwWrtShell & rShell)
+ : m_nCurrent(0), m_rMyShell(rShell)
+{
+}
+
+SwNavigationMgr::~SwNavigationMgr()
+{
+ SolarMutexGuard g;
+ for (auto & it : m_entries)
+ {
+ EndListening(it->m_aNotifier);
+ }
+ m_entries.clear();
+}
+
+void SwNavigationMgr::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
+{
+ // our cursors may now spontaneously self-destruct: remove from
+ // m_entries if that happens
+ if (typeid(rHint) == typeid(sw::UnoCursorHint))
+ {
+ auto it = std::find_if(m_entries.begin(), m_entries.end(),
+ [&rBC](const sw::UnoCursorPointer& rItem) { return !rItem || &rBC == &rItem->m_aNotifier; });
+ if (it != m_entries.end())
+ {
+ EndListening(rBC);
+ m_entries.erase(it);
+ }
+ }
+}
+
+// This method is used by the navigation shell - defined in sw/source/uibase/inc/navsh.hxx
+// and implemented in sw/source/uibase/shells/navsh.cxx
+// It is called when we want to check if the back button should be enabled or not.
+// The back button should be enabled only if there are some entries in the navigation history
+
+bool SwNavigationMgr::backEnabled() {
+ return (m_nCurrent > 0);
+}
+
+// Similar to backEnabled() method.
+// The forward button should be enabled if we ever clicked back
+// Due to the implementation of the navigation class, this is when the
+// current position within the navigation history entries in not the last one
+// i.e. when the m_nCurrent index is not at the end of the m_entries vector
+
+bool SwNavigationMgr::forwardEnabled() {
+ return m_nCurrent+1 < m_entries.size();
+}
+
+// The goBack() method positions the cursor to the previous entry in the navigation history
+// If there was no history to go forward to, it adds the current position of the cursor
+// to the history so we could go forward to where we came from
+
+void SwNavigationMgr::goBack() {
+
+ // Although the button should be disabled whenever the backEnabled() returns false,
+ // the UI is sometimes not as responsive as we would like it to be :)
+ // this check prevents segmentation faults and in this way the class is not relying on the UI
+
+ if (!backEnabled()) return;
+
+ /* Trying to get the current cursor */
+ SwPaM* pPaM = m_rMyShell.GetCursor();
+ if (!pPaM) {
+ return;
+ }
+ // This flag will be used to manually refresh the buttons
+
+ bool bForwardWasDisabled = !forwardEnabled();
+
+ // If we're going backwards in our history, but the current location is not
+ // in the history then we need to add *here* to it so that we can "go
+ // forward" to here again.
+
+ if (bForwardWasDisabled) {
+
+ // the cursor consists of two SwPositions: Point and Mark.
+ // We are adding the current Point to the navigation history
+ // so we could later navigate forward to it
+
+ // The addEntry() method returns true iff we should decrement
+ // the index before navigating back
+
+ if (addEntry(*pPaM->GetPoint()) ) {
+ m_nCurrent--;
+ }
+ }
+ m_nCurrent--;
+ // Position cursor to appropriate navigation history entry
+ GotoSwPosition(*m_entries[m_nCurrent]->GetPoint());
+ // Refresh the buttons
+ if (bForwardWasDisabled)
+ m_rMyShell.GetView().GetViewFrame().GetBindings().Invalidate(FN_NAVIGATION_FORWARD);
+ if (!backEnabled())
+ m_rMyShell.GetView().GetViewFrame().GetBindings().Invalidate(FN_NAVIGATION_BACK);
+}
+
+// The goForward() method positions the cursor to the next entry in the navigation history
+
+void SwNavigationMgr::goForward() {
+
+ // Although the button should be disabled whenever the backForward() returns false,
+ // the UI is sometimes not as responsive as we would like it to be :)
+ // this check prevents segmentation faults and in this way the class is not relying on the UI
+
+ if (!forwardEnabled()) return;
+
+ // This flag will be used to manually refresh the buttons
+ bool bBackWasDisabled = !backEnabled();
+ // The current index is positioned at the current entry in the navigation history
+ // We have to increment it to go to the next entry
+ m_nCurrent++;
+ GotoSwPosition(*m_entries[m_nCurrent]->GetPoint());
+ // Refresh the buttons
+ if (bBackWasDisabled)
+ m_rMyShell.GetView().GetViewFrame().GetBindings().Invalidate(FN_NAVIGATION_BACK);
+ if (!forwardEnabled())
+ m_rMyShell.GetView().GetViewFrame().GetBindings().Invalidate(FN_NAVIGATION_FORWARD);
+}
+
+// This method adds the SwPosition rPos to the navigation history
+// rPos is usually the current position of the cursor in the document
+
+bool SwNavigationMgr::addEntry(const SwPosition& rPos) {
+
+ // Flags that will be used for refreshing the buttons
+ bool bBackWasDisabled = !backEnabled();
+ bool bForwardWasEnabled = forwardEnabled();
+
+ bool bRet = false; // return value of the function.
+ // Indicates whether the index should be decremented before
+ // jumping back or not
+ // The navigation history has recency with temporal ordering enhancement,
+ // as described on http://zing.ncsl.nist.gov/hfweb/proceedings/greenberg/
+ // If any forward history exists, twist the tail of the
+ // list from the current position to the end
+ if (bForwardWasEnabled) {
+
+ size_t number_ofm_entries = m_entries.size(); // To avoid calling m_entries.size() multiple times
+ int curr = m_nCurrent; // Index from which we'll twist the tail.
+ int n = (number_ofm_entries - curr) / 2; // Number of entries that will swap places
+ for (int i = 0; i < n; i++) {
+ std::swap(m_entries[curr + i], m_entries[number_ofm_entries -1 - i]);
+ }
+
+ if (*m_entries.back()->GetPoint() != rPos)
+ {
+ sw::UnoCursorPointer pCursor(m_rMyShell.GetDoc()->CreateUnoCursor(rPos));
+ StartListening(pCursor->m_aNotifier);
+ m_entries.push_back(pCursor);
+ }
+ bRet = true;
+ }
+ else {
+ if ( (!m_entries.empty() && *m_entries.back()->GetPoint() != rPos) || m_entries.empty() ) {
+ sw::UnoCursorPointer pCursor(m_rMyShell.GetDoc()->CreateUnoCursor(rPos));
+ StartListening(pCursor->m_aNotifier);
+ m_entries.push_back(pCursor);
+ bRet = true;
+ }
+ if (m_entries.size() > 1 && *m_entries.back()->GetPoint() == rPos)
+ bRet = true;
+ if (m_entries.size() == 1 && *m_entries.back()->GetPoint() == rPos)
+ bRet = false;
+ }
+ m_nCurrent = m_entries.size();
+
+ // Refresh buttons
+ if (bBackWasDisabled)
+ m_rMyShell.GetView().GetViewFrame().GetBindings().Invalidate(FN_NAVIGATION_BACK);
+ if (bForwardWasEnabled)
+ m_rMyShell.GetView().GetViewFrame().GetBindings().Invalidate(FN_NAVIGATION_FORWARD);
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/wrtsh/select.cxx b/sw/source/uibase/wrtsh/select.cxx
new file mode 100644
index 0000000000..3ae5842f61
--- /dev/null
+++ b/sw/source/uibase/wrtsh/select.cxx
@@ -0,0 +1,1057 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <limits.h>
+#include <hintids.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/eitem.hxx>
+#include <svl/macitem.hxx>
+#include <unotools/charclass.hxx>
+#include <sfx2/event.hxx>
+#include <osl/diagnose.h>
+#include <cmdid.h>
+#include <view.hxx>
+#include <basesh.hxx>
+#include <wrtsh.hxx>
+#include <frmatr.hxx>
+#include <mdiexp.hxx>
+#include <fmtcol.hxx>
+#include <frmfmt.hxx>
+#include <swdtflvr.hxx>
+#include <doc.hxx>
+#include <wordcountdialog.hxx>
+#include <memory>
+#include <vcl/uitest/logger.hxx>
+#include <vcl/uitest/eventdescription.hxx>
+
+#include <vcl/weld.hxx>
+#include <vcl/builder.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <unotools/configmgr.hxx>
+#include <bitmaps.hlst>
+
+#include <svx/svdview.hxx>
+
+namespace com::sun::star::util {
+ struct SearchOptions2;
+}
+
+using namespace ::com::sun::star::util;
+
+static tools::Long nStartDragX = 0, nStartDragY = 0;
+static bool bStartDrag = false;
+
+void SwWrtShell::Invalidate()
+{
+ // to avoid making the slot volatile, invalidate it every time if something could have been changed
+ // this is still much cheaper than asking for the state every 200 ms (and avoid background processing)
+ GetView().GetViewFrame().GetBindings().Invalidate( FN_STAT_SELMODE );
+ GetView().GetViewFrame().GetBindings().Update(FN_STAT_SELMODE); // make selection mode control icon update immediately
+ SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame().GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
+ if (pWrdCnt)
+ pWrdCnt->UpdateCounts();
+}
+
+bool SwWrtShell::SelNearestWrd()
+{
+ SwMvContext aMvContext(this);
+ if( !IsInWord() && !IsEndWrd() && !IsStartWord() )
+ PrvWrd();
+ if( IsEndWrd() )
+ Left(SwCursorSkipMode::Cells, false, 1, false );
+ return SelWrd();
+}
+
+bool SwWrtShell::SelWrd(const Point *pPt )
+{
+ bool bRet;
+ {
+ SwMvContext aMvContext(this);
+ SttSelect();
+ bRet = SwCursorShell::SelectWord( pPt );
+ }
+ EndSelect();
+ if( bRet )
+ {
+ m_bSelWrd = true;
+ if(pPt)
+ m_aStart = *pPt;
+ }
+ return bRet;
+}
+
+void SwWrtShell::SelSentence(const Point *pPt )
+{
+ {
+ SwMvContext aMvContext(this);
+ ClearMark();
+ SwCursorShell::GoStartSentence();
+ SttSelect();
+ SwCursorShell::GoEndSentence();
+ }
+ EndSelect();
+ if(pPt)
+ m_aStart = *pPt;
+ m_bSelLn = true;
+ m_bSelWrd = false; // disable SelWord, otherwise no SelLine goes on
+}
+
+void SwWrtShell::SelPara(const Point *pPt )
+{
+ {
+ SwMvContext aMvContext(this);
+ ClearMark();
+ SwCursorShell::MovePara( GoCurrPara, fnParaStart );
+ SttSelect();
+ SwCursorShell::MovePara( GoCurrPara, fnParaEnd );
+ }
+ EndSelect();
+ if(pPt)
+ m_aStart = *pPt;
+ m_bSelLn = false;
+ m_bSelWrd = false; // disable SelWord, otherwise no SelLine goes on
+}
+
+void SwWrtShell::SelAll()
+{
+ const bool bLockedView = IsViewLocked();
+ LockView( true );
+ {
+ if(m_bBlockMode)
+ LeaveBlockMode();
+ SwMvContext aMvContext(this);
+ bool bMoveTable = false;
+ std::optional<SwPosition> oStartPos;
+ std::optional<SwPosition> oEndPos;
+ SwShellCursor* pTmpCursor = nullptr;
+
+ // Query these early, before we move the cursor.
+ bool bHasWholeTabSelection = HasWholeTabSelection();
+ bool bIsCursorInTable = IsCursorInTable();
+
+ if (!bHasWholeTabSelection
+ && ( !bIsCursorInTable
+ || getShellCursor(false)->GetMarkNode().FindTableNode() == nullptr
+ || !ExtendedSelectedAll())) // ESA inside table -> else branch
+ {
+ if ( IsSelection() && IsCursorPtAtEnd() )
+ SwapPam();
+ pTmpCursor = getShellCursor( false );
+ if( pTmpCursor )
+ {
+ oStartPos.emplace( *pTmpCursor->GetPoint() );
+ oEndPos.emplace( *pTmpCursor->GetMark() );
+ }
+ Push();
+ bool bIsFullSel = !MoveSection( GoCurrSection, fnSectionStart);
+ SwapPam();
+ bIsFullSel &= !MoveSection( GoCurrSection, fnSectionEnd);
+ Pop(SwCursorShell::PopMode::DeleteCurrent);
+ GoStart(true, &bMoveTable, false, !bIsFullSel);
+ SttSelect();
+ GoEnd(true, &bMoveTable);
+ }
+ else
+ {
+ if (MoveOutOfTable())
+ { // select outer text
+ EnterStdMode(); // delete m_pTableCursor
+// GoStart(true, &bMoveTable, false, true);
+ MoveSection(GoCurrSection, fnSectionStart); // don't move into prev table
+ SttSelect();
+ MoveSection(GoCurrSection, fnSectionEnd); // don't move to different cell
+ }
+ else
+ {
+ TrySelectOuterTable();
+ }
+ }
+
+ bool bNeedsExtendedSelectAll = StartsWith_() != StartsWith::None;
+
+ // the GoEnd() could have created a table selection, if so avoid ESA.
+ if (bNeedsExtendedSelectAll && bIsCursorInTable)
+ {
+ bNeedsExtendedSelectAll = !HasWholeTabSelection();
+ }
+
+ if (bNeedsExtendedSelectAll)
+ {
+ ExtendedSelectAll(/*bFootnotes =*/ false);
+ }
+
+ SwDoc *pDoc = GetDoc();
+ if ( pDoc )
+ {
+ pDoc->SetPrepareSelAll();
+ }
+
+ if( oStartPos )
+ {
+ pTmpCursor = getShellCursor( false );
+ if( pTmpCursor )
+ {
+ // Some special handling for sections (e.g. TOC) at the beginning of the document body
+ // to avoid the selection of the first section
+ // if the last selection was behind the first section or
+ // if the last selection was already the first section
+ // In this both cases we select to the end of document
+ if( ( *pTmpCursor->GetPoint() < *oEndPos ||
+ ( *oStartPos == *pTmpCursor->GetMark() &&
+ *oEndPos == *pTmpCursor->GetPoint() ) ) && !bNeedsExtendedSelectAll)
+ SwCursorShell::SttEndDoc(false);
+ }
+ }
+ }
+ EndSelect();
+ LockView( bLockedView );
+}
+
+// Description: Text search
+
+sal_Int32 SwWrtShell::SearchPattern( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes,
+ SwDocPositions eStt, SwDocPositions eEnd,
+ FindRanges eFlags, bool bReplace )
+{
+ // no enhancement of existing selections
+ if(!(eFlags & FindRanges::InSel))
+ ClearMark();
+ bool bCancel = false;
+ sal_Int32 nRet = Find_Text(rSearchOpt, bSearchInNotes, eStt, eEnd, bCancel, eFlags, bReplace);
+ if(bCancel)
+ {
+ Undo();
+ nRet = SAL_MAX_INT32;
+ }
+ return nRet;
+}
+
+// Description: search for templates
+
+sal_Int32 SwWrtShell::SearchTempl( const OUString &rTempl,
+ SwDocPositions eStt, SwDocPositions eEnd,
+ FindRanges eFlags, const OUString* pReplTempl )
+{
+ // no enhancement of existing selections
+ if(!(eFlags & FindRanges::InSel))
+ ClearMark();
+ SwTextFormatColl *pColl = GetParaStyle(rTempl, SwWrtShell::GETSTYLE_CREATESOME);
+ SwTextFormatColl *pReplaceColl = nullptr;
+ if( pReplTempl )
+ pReplaceColl = GetParaStyle(*pReplTempl, SwWrtShell::GETSTYLE_CREATESOME );
+
+ bool bCancel = false;
+ sal_Int32 nRet = FindFormat(pColl ? *pColl : GetDfltTextFormatColl(),
+ eStt,eEnd, bCancel, eFlags, pReplaceColl);
+ if(bCancel)
+ {
+ Undo();
+ nRet = SAL_MAX_INT32;
+ }
+ return nRet;
+}
+
+// search for attributes
+
+sal_Int32 SwWrtShell::SearchAttr( const SfxItemSet& rFindSet, bool bNoColls,
+ SwDocPositions eStart, SwDocPositions eEnd,
+ FindRanges eFlags, const i18nutil::SearchOptions2* pSearchOpt,
+ const SfxItemSet* pReplaceSet )
+{
+ // no enhancement of existing selections
+ if (!(eFlags & FindRanges::InSel))
+ ClearMark();
+
+ // Searching
+ bool bCancel = false;
+ sal_Int32 nRet = FindAttrs(rFindSet, bNoColls, eStart, eEnd, bCancel, eFlags, pSearchOpt, pReplaceSet);
+
+ if(bCancel)
+ {
+ Undo();
+ nRet = SAL_MAX_INT32;
+ }
+ return nRet;
+}
+
+// Selection modes
+
+void SwWrtShell::PushMode()
+{
+ m_pModeStack = new ModeStack( m_pModeStack, m_bIns, m_bExtMode, m_bAddMode, m_bBlockMode );
+}
+
+void SwWrtShell::PopMode()
+{
+ if ( nullptr == m_pModeStack )
+ return;
+
+ if ( m_bExtMode && !m_pModeStack->bExt )
+ LeaveExtMode();
+ if ( m_bAddMode && !m_pModeStack->bAdd )
+ LeaveAddMode();
+ if ( m_bBlockMode && !m_pModeStack->bBlock )
+ LeaveBlockMode();
+ m_bIns = m_pModeStack->bIns;
+
+ m_pModeStack = std::move(m_pModeStack->pNext);
+}
+
+// Two methods for setting cursors: the first maps at the
+// eponymous methods in the CursorShell, the second removes
+// all selections at first.
+
+tools::Long SwWrtShell::SetCursor(const Point *pPt, bool bTextOnly)
+{
+ // Remove a possibly present selection at the position
+ // of the mouseclick
+
+ if(!IsInSelect() && TestCurrPam(*pPt)) {
+ ClearMark();
+ }
+
+ return SwCursorShell::SetCursor(*pPt, bTextOnly);
+}
+
+tools::Long SwWrtShell::SetCursorKillSel(const Point *pPt, bool bTextOnly )
+{
+ SwActContext aActContext(this);
+ ResetSelect(pPt,false);
+ return SwCursorShell::SetCursor(*pPt, bTextOnly);
+}
+
+void SwWrtShell::UnSelectFrame()
+{
+ // Remove Frame selection with guaranteed invalid position
+ Point aPt(LONG_MIN, LONG_MIN);
+ SelectObj(aPt);
+ SwTransferable::ClearSelection( *this );
+}
+
+// Remove of all selections
+
+tools::Long SwWrtShell::ResetSelect(const Point *,bool)
+{
+ if(IsSelFrameMode())
+ {
+ UnSelectFrame();
+ LeaveSelFrameMode();
+ }
+ else
+ {
+ // SwActContext opens an Action -
+ // to avoid problems in the basic process with the
+ // shell switching, GetChgLnk().Call() may be called
+ // after EndAction().
+ {
+ SwActContext aActContext(this);
+ m_bSelWrd = m_bSelLn = false;
+ KillPams();
+ ClearMark();
+ m_fnKillSel = &SwWrtShell::Ignore;
+ m_fnSetCursor = &SwWrtShell::SetCursor;
+ }
+
+ // After canceling of all selections an update of Attr-Controls
+ // could be necessary.
+ GetChgLnk().Call(nullptr);
+
+ if ( GetEnhancedTableSelection() != SwTable::SEARCH_NONE )
+ UnsetEnhancedTableSelection();
+ }
+ Invalidate();
+ SwTransferable::ClearSelection( *this );
+ return 1;
+}
+
+bool SwWrtShell::IsSplitVerticalByDefault() const
+{
+ return GetDoc()->IsSplitVerticalByDefault();
+}
+
+void SwWrtShell::SetSplitVerticalByDefault(bool value)
+{
+ GetDoc()->SetSplitVerticalByDefault(value);
+}
+
+// Do nothing
+
+tools::Long SwWrtShell::Ignore(const Point *, bool ) {
+ return 1;
+}
+
+// Begin of a selection process.
+
+void SwWrtShell::SttSelect()
+{
+ if(m_bInSelect)
+ return;
+ if(!HasMark())
+ SetMark();
+ if( m_bBlockMode )
+ {
+ SwShellCursor* pTmp = getShellCursor( true );
+ if( !pTmp->HasMark() )
+ pTmp->SetMark();
+ }
+ m_fnKillSel = &SwWrtShell::Ignore;
+ m_fnSetCursor = &SwWrtShell::SetCursor;
+ m_bInSelect = true;
+ Invalidate();
+ SwTransferable::CreateSelection( *this );
+}
+
+namespace {
+
+void collectUIInformation(SwShellCursor* pCursor)
+{
+ EventDescription aDescription;
+ OUString aSelStart = OUString::number(pCursor->Start()->GetContentIndex());
+ OUString aSelEnd = OUString::number(pCursor->End()->GetContentIndex());
+
+ aDescription.aParameters = {{"START_POS", aSelStart}, {"END_POS", aSelEnd}};
+ aDescription.aAction = "SELECT";
+ aDescription.aID = "writer_edit";
+ aDescription.aKeyWord = "SwEditWinUIObject";
+ aDescription.aParent = "MainWindow";
+
+ UITestLogger::getInstance().logEvent(aDescription);
+}
+
+}
+
+// End of a selection process.
+
+void SwWrtShell::EndSelect()
+{
+ if(m_bInSelect && !m_bExtMode)
+ {
+ m_bInSelect = false;
+ if (m_bAddMode)
+ {
+ AddLeaveSelect();
+ }
+ else
+ {
+ SttLeaveSelect();
+ m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
+ m_fnKillSel = &SwWrtShell::ResetSelect;
+ }
+ }
+ SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame().GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
+ if (pWrdCnt)
+ pWrdCnt->UpdateCounts();
+
+ collectUIInformation(GetCursor_());
+}
+
+void SwWrtShell::ExtSelWrd(const Point *pPt, bool )
+{
+ SwMvContext aMvContext(this);
+ if( IsTableMode() )
+ return;
+
+ // Bug 66823: actual crsr has in additional mode no selection?
+ // Then destroy the actual and go to prev, this will be expand
+ if( !HasMark() && GoPrevCursor() )
+ {
+ bool bHasMark = HasMark(); // that's wrong!
+ GoNextCursor();
+ if( bHasMark )
+ {
+ DestroyCursor();
+ GoPrevCursor();
+ }
+ }
+
+ // check the direction of the selection with the new point
+ bool bMoveCursor = true, bToTop = false;
+ SwCursorShell::SelectWord( &m_aStart ); // select the startword
+ SwCursorShell::Push(); // save the cursor
+ SwCursorShell::SetCursor( *pPt ); // and check the direction
+
+ switch( SwCursorShell::CompareCursorStackMkCurrPt())
+ {
+ case -1: bToTop = false; break;
+ case 1: bToTop = true; break;
+ default: bMoveCursor = false; break;
+ }
+
+ SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent); // restore the saved cursor
+
+ if( !bMoveCursor )
+ return;
+
+ // select to Top but cursor select to Bottom? or
+ // select to Bottom but cursor select to Top? --> swap the cursor
+ if( bToTop )
+ SwapPam();
+
+ SwCursorShell::Push(); // save cur cursor
+ if( SwCursorShell::SelectWord( pPt )) // select the current word
+ {
+ if( bToTop )
+ SwapPam();
+ Combine();
+ }
+ else
+ {
+ SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent);
+ if( bToTop )
+ SwapPam();
+ }
+}
+
+void SwWrtShell::ExtSelLn(const Point *pPt, bool )
+{
+ SwMvContext aMvContext(this);
+ SwCursorShell::SetCursor(*pPt);
+ if( IsTableMode() )
+ return;
+
+ // Bug 66823: actual crsr has in additional mode no selection?
+ // Then destroy the actual and go to prev, this will be expand
+ if( !HasMark() && GoPrevCursor() )
+ {
+ bool bHasMark = HasMark(); // that's wrong!
+ GoNextCursor();
+ if( bHasMark )
+ {
+ DestroyCursor();
+ GoPrevCursor();
+ }
+ }
+
+ // if applicable fit the selection to the "Mark"
+ bool bToTop = !IsCursorPtAtEnd();
+ SwapPam();
+
+ // The "Mark" has to be at the end or the beginning of the line.
+ if( bToTop ? !IsEndSentence() : !IsStartSentence() )
+ {
+ if( bToTop )
+ {
+ if( !IsEndPara() )
+ SwCursorShell::Right(1,SwCursorSkipMode::Chars);
+ SwCursorShell::GoEndSentence();
+ }
+ else
+ SwCursorShell::GoStartSentence();
+ }
+ SwapPam();
+
+ if (bToTop)
+ SwCursorShell::GoStartSentence();
+ else
+ SwCursorShell::GoEndSentence();
+}
+
+// Back into the standard mode: no mode, no selections.
+
+void SwWrtShell::EnterStdMode()
+{
+ if(m_bAddMode)
+ LeaveAddMode();
+ if(m_bBlockMode)
+ LeaveBlockMode();
+ m_bBlockMode = false;
+ m_bExtMode = false;
+ m_bInSelect = false;
+ if(IsSelFrameMode())
+ {
+ UnSelectFrame();
+ LeaveSelFrameMode();
+ }
+ else
+ {
+ // SwActContext opens and action which has to be
+ // closed prior to the call of
+ // GetChgLnk().Call()
+ SwActContext aActContext(this);
+ m_bSelWrd = m_bSelLn = false;
+ if( !IsRetainSelection() )
+ KillPams();
+ ClearMark();
+ m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
+ m_fnKillSel = &SwWrtShell::ResetSelect;
+ }
+ Invalidate();
+ SwTransferable::ClearSelection( *this );
+}
+
+void SwWrtShell::AssureStdMode()
+{
+ // deselect any drawing or frame and leave editing mode
+ if (SdrView* pSdrView = GetDrawView())
+ {
+ if (pSdrView->IsTextEdit())
+ {
+ bool bLockView = IsViewLocked();
+ LockView(true);
+ EndTextEdit();
+ LockView(bLockView);
+ }
+ // go out of the frame
+ Point aPt(LONG_MIN, LONG_MIN);
+ SelectObj(aPt, SW_LEAVE_FRAME);
+ }
+ if (IsSelFrameMode() || IsObjSelected())
+ {
+ UnSelectFrame();
+ LeaveSelFrameMode();
+ GetView().LeaveDrawCreate();
+ EnterStdMode();
+ DrawSelChanged();
+ GetView().StopShellTimer();
+ }
+ else
+ EnterStdMode();
+}
+
+// Extended Mode
+
+void SwWrtShell::EnterExtMode()
+{
+ if(m_bBlockMode)
+ {
+ LeaveBlockMode();
+ KillPams();
+ ClearMark();
+ }
+ m_bExtMode = true;
+ m_bAddMode = false;
+ m_bBlockMode = false;
+ SttSelect();
+}
+
+void SwWrtShell::LeaveExtMode()
+{
+ m_bExtMode = false;
+ EndSelect();
+}
+
+// End of a selection; if the selection is empty,
+// ClearMark().
+
+void SwWrtShell::SttLeaveSelect()
+{
+ if(SwCursorShell::HasSelection() && !IsSelTableCells() && m_bClearMark) {
+ return;
+ }
+ ClearMark();
+}
+
+// Leaving of the selection mode in additional mode
+
+void SwWrtShell::AddLeaveSelect()
+{
+ if(IsTableMode()) LeaveAddMode();
+ else if(SwCursorShell::HasSelection())
+ CreateCursor();
+}
+
+// Additional Mode
+
+void SwWrtShell::EnterAddMode()
+{
+ if(IsTableMode()) return;
+ if(m_bBlockMode)
+ LeaveBlockMode();
+ m_fnKillSel = &SwWrtShell::Ignore;
+ m_fnSetCursor = &SwWrtShell::SetCursor;
+ m_bAddMode = true;
+ m_bBlockMode = false;
+ m_bExtMode = false;
+ if(SwCursorShell::HasSelection())
+ CreateCursor();
+ Invalidate();
+}
+
+void SwWrtShell::LeaveAddMode()
+{
+ m_fnKillSel = &SwWrtShell::ResetSelect;
+ m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
+ m_bAddMode = false;
+ Invalidate();
+}
+
+// Block Mode
+
+void SwWrtShell::EnterBlockMode()
+{
+ m_bBlockMode = false;
+ EnterStdMode();
+ m_bBlockMode = true;
+ CursorToBlockCursor();
+ Invalidate();
+}
+
+void SwWrtShell::LeaveBlockMode()
+{
+ m_bBlockMode = false;
+ BlockCursorToCursor();
+ EndSelect();
+ Invalidate();
+}
+
+// Insert mode
+
+void SwWrtShell::SetInsMode( bool bOn )
+{
+ const bool bDoAsk = officecfg::Office::Common::Misc::QuerySetInsMode::get();
+ if (!bOn && bDoAsk) {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetView().GetFrameWeld(), "cui/ui/querysetinsmodedialog.ui"));
+ std::unique_ptr<weld::Dialog> xQuery(xBuilder->weld_dialog("SetInsModeDialog"));
+ std::unique_ptr<weld::Image> xImage(xBuilder->weld_image("imSetInsMode"));
+ std::unique_ptr<weld::CheckButton> xCheckBox(xBuilder->weld_check_button("cbDontShowAgain"));
+
+ xImage->set_from_icon_name(RID_BMP_QUERYINSMODE);
+
+ const int nResult = xQuery->run();
+
+ std::shared_ptr<comphelper::ConfigurationChanges> xChanges(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Misc::QuerySetInsMode::set(!xCheckBox->get_active(), xChanges);
+ xChanges->commit();
+
+ if ( nResult == static_cast<int>(RET_NO) )
+ return;
+ }
+ m_bIns = bOn;
+ SwCursorShell::SetOverwriteCursor( !m_bIns );
+ const SfxBoolItem aTmp( SID_ATTR_INSERT, m_bIns );
+ GetView().GetViewFrame().GetBindings().SetState( aTmp );
+ StartAction();
+ EndAction();
+ Invalidate();
+}
+//Overwrite mode is incompatible with red-lining
+void SwWrtShell::SetRedlineFlagsAndCheckInsMode( RedlineFlags eMode )
+{
+ SetRedlineFlags( eMode );
+ if (IsRedlineOn())
+ SetInsMode();
+}
+
+// Edit frame
+
+void SwWrtShell::BeginFrameDrag(const Point *pPt, bool bIsShift)
+{
+ m_fnDrag = &SwFEShell::Drag;
+ if(bStartDrag)
+ {
+ Point aTmp( nStartDragX, nStartDragY );
+ SwFEShell::BeginDrag( &aTmp, bIsShift );
+ }
+ else
+ SwFEShell::BeginDrag( pPt, bIsShift );
+}
+
+void SwWrtShell::EnterSelFrameMode(const Point *pPos)
+{
+ if(pPos)
+ {
+ nStartDragX = pPos->X();
+ nStartDragY = pPos->Y();
+ bStartDrag = true;
+ }
+ m_bLayoutMode = true;
+ HideCursor();
+
+ // equal call of BeginDrag in the SwFEShell
+ m_fnDrag = &SwWrtShell::BeginFrameDrag;
+ m_fnEndDrag = &SwWrtShell::UpdateLayoutFrame;
+ SwBaseShell::SetFrameMode( FLY_DRAG_START, this );
+ Invalidate();
+}
+
+void SwWrtShell::LeaveSelFrameMode()
+{
+ m_fnDrag = &SwWrtShell::BeginDrag;
+ m_fnEndDrag = &SwWrtShell::DefaultEndDrag;
+ m_bLayoutMode = false;
+ bStartDrag = false;
+ Edit();
+ SwBaseShell::SetFrameMode( FLY_DRAG_END, this );
+ Invalidate();
+}
+
+// Description: execute framebound macro
+
+IMPL_LINK( SwWrtShell, ExecFlyMac, const SwFlyFrameFormat*, pFlyFormat, void )
+{
+ const SwFrameFormat *pFormat = pFlyFormat ? static_cast<const SwFrameFormat*>(pFlyFormat) : GetFlyFrameFormat();
+ OSL_ENSURE(pFormat, "no frame format");
+ const SvxMacroItem &rFormatMac = pFormat->GetMacro();
+
+ if(rFormatMac.HasMacro(SvMacroItemId::SwObjectSelect))
+ {
+ const SvxMacro &rMac = rFormatMac.GetMacro(SvMacroItemId::SwObjectSelect);
+ if( IsFrameSelected() )
+ m_bLayoutMode = true;
+ CallChgLnk();
+ ExecMacro( rMac );
+ }
+}
+
+void SwWrtShell::UpdateLayoutFrame(const Point *, bool )
+{
+ // still a dummy
+ SwFEShell::EndDrag();
+ m_fnDrag = &SwWrtShell::BeginFrameDrag;
+}
+
+// Handler for toggling the modes. Returns back the old mode.
+
+void SwWrtShell::ToggleAddMode()
+{
+ m_bAddMode ? LeaveAddMode(): EnterAddMode();
+ Invalidate();
+}
+
+void SwWrtShell::ToggleBlockMode()
+{
+ m_bBlockMode ? LeaveBlockMode(): EnterBlockMode();
+ Invalidate();
+}
+
+void SwWrtShell::ToggleExtMode()
+{
+ m_bExtMode ? LeaveExtMode() : EnterExtMode();
+ Invalidate();
+}
+
+// Dragging in standard mode (Selecting of content)
+
+void SwWrtShell::BeginDrag(const Point * /*pPt*/, bool )
+{
+ if(m_bSelWrd)
+ {
+ m_bInSelect = true;
+ if( !IsCursorPtAtEnd() )
+ SwapPam();
+
+ m_fnDrag = &SwWrtShell::ExtSelWrd;
+ m_fnSetCursor = &SwWrtShell::Ignore;
+ }
+ else if(m_bSelLn)
+ {
+ m_bInSelect = true;
+ m_fnDrag = &SwWrtShell::ExtSelLn;
+ m_fnSetCursor = &SwWrtShell::Ignore;
+ }
+ else
+ {
+ m_fnDrag = &SwWrtShell::DefaultDrag;
+ SttSelect();
+ }
+}
+
+void SwWrtShell::DefaultDrag(const Point *, bool )
+{
+ if( IsSelTableCells() )
+ m_aSelTableLink.Call(*this);
+}
+
+void SwWrtShell::DefaultEndDrag(const Point * /*pPt*/, bool )
+{
+ m_fnDrag = &SwWrtShell::BeginDrag;
+ if( IsExtSel() )
+ LeaveExtSel();
+
+ if( IsSelTableCells() )
+ m_aSelTableLink.Call(*this);
+ EndSelect();
+}
+
+// #i32329# Enhanced table selection
+bool SwWrtShell::SelectTableRowCol( const Point& rPt, const Point* pEnd, bool bRowDrag )
+{
+ SwMvContext aMvContext(this);
+ SttSelect();
+ if(SelTableRowCol( rPt, pEnd, bRowDrag ))
+ {
+ m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
+ m_fnKillSel = &SwWrtShell::ResetSelect;
+ return true;
+ }
+ return false;
+}
+
+// Description: Selection of a table line or column
+
+void SwWrtShell::SelectTableRow()
+{
+ if ( SelTableRow() )
+ {
+ m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
+ m_fnKillSel = &SwWrtShell::ResetSelect;
+ }
+}
+
+void SwWrtShell::SelectTableCol()
+{
+ if ( SelTableCol() )
+ {
+ m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
+ m_fnKillSel = &SwWrtShell::ResetSelect;
+ }
+}
+
+void SwWrtShell::SelectTableCell()
+{
+ if ( SelTableBox() )
+ {
+ m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
+ m_fnKillSel = &SwWrtShell::ResetSelect;
+ }
+}
+
+// Description: Check if a word selection is present.
+// According to the rules for intelligent cut / paste
+// surrounding spaces are cut out.
+// Return: Delivers the type of the word selection.
+
+int SwWrtShell::IntelligentCut(SelectionType nSelection, bool bCut)
+{
+ // On multiple selection no intelligent drag and drop
+ // there are multiple cursors, since a second was placed
+ // already at the target position.
+ if( IsAddMode() || !(nSelection & SelectionType::Text) )
+ return NO_WORD;
+
+ OUString sText;
+ CharClass& rCC = GetAppCharClass();
+
+ // If the first character is no word character,
+ // no word selected.
+ sal_Unicode cPrev = GetChar(false);
+ sal_Unicode cNext = GetChar(true, -1);
+ if( !cPrev || !cNext ||
+ !rCC.isLetterNumeric( ( sText = OUString(cPrev) ), 0 ) ||
+ !rCC.isLetterNumeric( ( sText = OUString(cNext) ), 0 ) )
+ return NO_WORD;
+
+ cPrev = GetChar(false, -1);
+ cNext = GetChar();
+
+ int cWord = NO_WORD;
+ // is a word selected?
+ if (cPrev && cNext &&
+ CH_TXTATR_BREAKWORD != cPrev && CH_TXTATR_INWORD != cPrev &&
+ CH_TXTATR_BREAKWORD != cNext && CH_TXTATR_INWORD != cNext &&
+ !rCC.isLetterNumeric( ( sText = OUString(cPrev) ), 0 ) &&
+ !rCC.isLetterNumeric( ( sText = OUString(cNext) ), 0 ) )
+ cWord = WORD_NO_SPACE;
+
+ if(cWord == WORD_NO_SPACE && ' ' == cPrev )
+ {
+ cWord = WORD_SPACE_BEFORE;
+ // delete the space before
+ if(bCut)
+ {
+ Push();
+ if(IsCursorPtAtEnd())
+ SwapPam();
+ ClearMark();
+ SetMark();
+ SwCursorShell::Left(1,SwCursorSkipMode::Chars);
+ SwFEShell::Delete(true);
+ Pop(SwCursorShell::PopMode::DeleteCurrent);
+ }
+ }
+ else if(cWord == WORD_NO_SPACE && cNext == ' ')
+ {
+ cWord = WORD_SPACE_AFTER;
+ // delete the space behind
+ if(bCut) {
+ Push();
+ if(!IsCursorPtAtEnd()) SwapPam();
+ ClearMark();
+ SetMark();
+ SwCursorShell::Right(1,SwCursorSkipMode::Chars);
+ SwFEShell::Delete(true);
+ Pop(SwCursorShell::PopMode::DeleteCurrent);
+ }
+ }
+ return cWord;
+}
+
+ // jump to the next / previous hyperlink - inside text and also
+ // on graphics
+void SwWrtShell::SelectNextPrevHyperlink( bool bNext )
+{
+ StartAction();
+ bool bRet = SwCursorShell::SelectNxtPrvHyperlink( bNext );
+ if( !bRet ) // didn't find? wrap and check again
+ {
+ SwShellCursor* pCursor = GetCursor_();
+ SwCursorSaveState aSaveState(*pCursor);
+ EnterStdMode();
+ if( bNext )
+ SttEndDoc(true);
+ else
+ SttEndDoc(false);
+ bRet = SwCursorShell::SelectNxtPrvHyperlink(bNext);
+ if (!bRet) // didn't find again? restore cursor position and bail
+ {
+ pCursor->RestoreSavePos();
+ EndAction(true); // don't scroll to restored cursor position
+ return;
+ }
+ }
+ EndAction();
+
+ bool bCreateXSelection = false;
+ const bool bFrameSelected = IsFrameSelected() || IsObjSelected();
+ if( IsSelection() )
+ {
+ if ( bFrameSelected )
+ UnSelectFrame();
+
+ // Set the function pointer for the canceling of the selection
+ // set at cursor
+ m_fnKillSel = &SwWrtShell::ResetSelect;
+ m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
+ bCreateXSelection = true;
+ }
+ else if( bFrameSelected )
+ {
+ EnterSelFrameMode();
+ bCreateXSelection = true;
+ }
+ else if( (CNT_GRF | CNT_OLE ) & GetCntType() )
+ {
+ SelectObj( GetCharRect().Pos() );
+ EnterSelFrameMode();
+ bCreateXSelection = true;
+ }
+
+ if( bCreateXSelection )
+ SwTransferable::CreateSelection( *this );
+}
+
+// For the preservation of the selection the cursor will be moved left
+// after SetMark(), so that the cursor is not moved by inserting text.
+// Because a present selection at the CORE page is cleared at the
+// current cursor position, the cursor will be pushed on the stack.
+// After moving, they will again resummarized.
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/wrtsh/wrtsh1.cxx b/sw/source/uibase/wrtsh/wrtsh1.cxx
new file mode 100644
index 0000000000..4b2402fc93
--- /dev/null
+++ b/sw/source/uibase/wrtsh/wrtsh1.cxx
@@ -0,0 +1,2731 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/embed/EmbedMisc.hpp>
+#include <com/sun/star/embed/EmbedStates.hpp>
+#include <com/sun/star/embed/EmbedVerbs.hpp>
+#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+
+#include <hintids.hxx>
+#include <sot/exchange.hxx>
+#include <svx/xfillit0.hxx>
+#include <svx/hdft.hxx>
+#include <svx/svdview.hxx>
+#include <svl/itemiter.hxx>
+#include <tools/bigint.hxx>
+#include <svtools/insdlg.hxx>
+#include <sfx2/ipclient.hxx>
+#include <editeng/formatbreakitem.hxx>
+#include <editeng/svxacorr.hxx>
+#include <editeng/ulspitem.hxx>
+#include <vcl/graph.hxx>
+#include <unotools/charclass.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <svx/svxdlg.hxx>
+#include <svx/extrusionbar.hxx>
+#include <svx/fontworkbar.hxx>
+#include <dialoghelp.hxx>
+#include <frmfmt.hxx>
+#include <fmtftn.hxx>
+#include <fmthdft.hxx>
+#include <fmtpdsc.hxx>
+#include <txtfrm.hxx>
+#include <wdocsh.hxx>
+#include <swmodule.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <cmdid.h>
+#include <pagedesc.hxx>
+#include <frmmgr.hxx>
+#include <swundo.hxx>
+#include <swcli.hxx>
+#include <poolfmt.hxx>
+#include <edtwin.hxx>
+#include <fmtcol.hxx>
+#include <swtable.hxx>
+#include <viscrs.hxx>
+#include <swdtflvr.hxx>
+#include <doc.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <SwCapObjType.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <sfx2/request.hxx>
+#include <paratr.hxx>
+#include <ndtxt.hxx>
+#include <editeng/acorrcfg.hxx>
+#include <IMark.hxx>
+#include <sfx2/bindings.hxx>
+#include <flyfrm.hxx>
+
+// -> #111827#
+#include <SwRewriter.hxx>
+#include <strings.hrc>
+// <- #111827#
+
+#include <toolkit/helper/vclunohelper.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <vcl/uitest/logger.hxx>
+#include <vcl/uitest/eventdescription.hxx>
+#include <osl/diagnose.h>
+#include <o3tl/unit_conversion.hxx>
+#include <officecfg/Office/Common.hxx>
+
+#include <PostItMgr.hxx>
+#include <FrameControlsManager.hxx>
+#include <fldmgr.hxx>
+#include <docufld.hxx>
+#include <IDocumentFieldsAccess.hxx>
+#include <fmtfld.hxx>
+
+#include <sfx2/msgpool.hxx>
+#include <sfx2/msg.hxx>
+#include <svtools/embedhlp.hxx>
+#include <svtools/strings.hrc>
+#include <svtools/svtresid.hxx>
+#include <svx/postattr.hxx>
+#include <comphelper/lok.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <svtools/optionsdrawinglayer.hxx>
+#include <svl/numformat.hxx>
+#include <svl/zformat.hxx>
+#include <memory>
+
+#include "../../core/crsr/callnk.hxx"
+#include <frmtool.hxx>
+#include <viewopt.hxx>
+
+#include <IDocumentUndoRedo.hxx>
+#include <UndoInsert.hxx>
+#include <UndoCore.hxx>
+#include <formatlinebreak.hxx>
+#include <formatcontentcontrol.hxx>
+#include <textcontentcontrol.hxx>
+
+using namespace sw::mark;
+using namespace com::sun::star;
+namespace {
+
+void collectUIInformation(const OUString& rAction, const OUString& aParameters)
+{
+ EventDescription aDescription;
+ aDescription.aAction = rAction;
+ aDescription.aParameters = {{"parameters", aParameters}};
+ aDescription.aID = "writer_edit";
+ aDescription.aKeyWord = "SwEditWinUIObject";
+ aDescription.aParent = "MainWindow";
+ UITestLogger::getInstance().logEvent(aDescription);
+}
+
+}
+
+sal_uInt32 MakeAllOutlineContentTemporarilyVisible::nLock = 0;
+
+static bool lcl_IsAllowed(const SwWrtShell* rSh)
+{
+ if (rSh->GetViewOptions()->IsShowOutlineContentVisibilityButton() && rSh->IsEndPara())
+ {
+ SwTextNode* pTextNode = rSh->GetCursor()->GetPointNode().GetTextNode();
+ if (pTextNode && pTextNode->IsOutline())
+ {
+ // disallow if this is an outline node having folded content
+ bool bVisible = true;
+ pTextNode->GetAttrOutlineContentVisible(bVisible);
+ if (!bVisible)
+ return false;
+ }
+ }
+ return true;
+}
+
+#define BITFLD_INI_LIST \
+ m_bClearMark = \
+ m_bIns = true;\
+ m_bAddMode = \
+ m_bBlockMode = \
+ m_bExtMode = \
+ m_bInSelect = \
+ m_bLayoutMode = \
+ m_bSelWrd = \
+ m_bSelLn = \
+ m_bRetainSelection = false; \
+ m_bIsInClickToEdit = false;
+
+static SvxAutoCorrect* lcl_IsAutoCorr()
+{
+ SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get().GetAutoCorrect();
+ if( pACorr && !pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
+ ACFlags::AddNonBrkSpace | ACFlags::ChgOrdinalNumber | ACFlags::TransliterateRTL |
+ ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr | ACFlags::Autocorrect |
+ ACFlags::SetDOIAttr ))
+ pACorr = nullptr;
+ return pACorr;
+}
+
+void SwWrtShell::NoEdit(bool bHideCursor)
+{
+ if(bHideCursor)
+ HideCursor();
+}
+
+void SwWrtShell::Edit()
+{
+ if (CanInsert())
+ {
+ ShowCursor();
+ }
+}
+
+bool SwWrtShell::IsEndWrd()
+{
+ SwMvContext aMvContext(this);
+ if(IsEndPara() && !IsSttPara())
+ return true;
+
+ return IsEndWord();
+}
+
+// Insert string
+void SwWrtShell::InsertByWord( const OUString & rStr)
+{
+ if( rStr.isEmpty() )
+ return;
+
+ bool bDelim = GetAppCharClass().isLetterNumeric( rStr, 0 );
+ sal_Int32 nPos = 0, nStt = 0;
+ for( ; nPos < rStr.getLength(); nPos++ )
+ {
+ bool bTmpDelim = GetAppCharClass().isLetterNumeric( rStr, nPos );
+ if( bTmpDelim != bDelim )
+ {
+ Insert( rStr.copy( nStt, nPos - nStt ));
+ nStt = nPos;
+ }
+ }
+ if( nStt != nPos )
+ Insert( rStr.copy( nStt, nPos - nStt ));
+}
+
+void SwWrtShell::Insert( const OUString &rStr )
+{
+ ResetCursorStack();
+ if( !CanInsert() )
+ return;
+
+ bool bStarted = false;
+ bool bHasSel = HasSelection(),
+ bCallIns = m_bIns /*|| bHasSel*/;
+ bool bDeleted = false;
+
+ if( bHasSel || ( !m_bIns && IsInHiddenRange(/*bSelect=*/true) ) )
+ {
+ // Only here parenthesizing, because the normal
+ // insert is already in parentheses at Editshell.
+ StartAllAction();
+
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UndoArg1, GetCursorDescr());
+ aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
+ {
+ OUString aTmpStr = SwResId(STR_START_QUOTE) +
+ rStr + SwResId(STR_END_QUOTE);
+
+ aRewriter.AddRule(UndoArg3, aTmpStr);
+ }
+
+ StartUndo(SwUndoId::REPLACE, &aRewriter);
+ bStarted = true;
+ Push();
+ // let's interpret a selection within the same node as "replace"
+ bDeleted = DelRight(GetCursor()->GetPoint()->GetNode() == GetCursor()->GetMark()->GetNode());
+ Pop(SwCursorShell::PopMode::DeleteCurrent); // Restore selection (if tracking changes)
+ NormalizePam(false); // tdf#127635 put point at the end of deletion
+ ClearMark();
+ }
+
+ bCallIns ?
+ SwEditShell::Insert2( rStr, bDeleted ) : SwEditShell::Overwrite( rStr );
+
+ // Check whether node is content control
+ SwTextContentControl* pTextContentControl = CursorInsideContentControl();
+ if (pTextContentControl)
+ {
+ std::shared_ptr<SwContentControl> pContentControl =
+ pTextContentControl->GetContentControl().GetContentControl();
+ if (pContentControl)
+ {
+ // Set showingPlcHdr to false as node has been edited
+ pContentControl->SetShowingPlaceHolder(false);
+ }
+ }
+
+ if( bStarted )
+ {
+ EndUndo();
+ EndAllAction();
+ }
+}
+
+// Maximum height limit not possible, because the maximum height
+// of the current frame can not be obtained.
+
+void SwWrtShell::InsertGraphic( const OUString &rPath, const OUString &rFilter,
+ const Graphic &rGrf, SwFlyFrameAttrMgr *pFrameMgr,
+ RndStdIds nAnchorType )
+{
+ ResetCursorStack();
+ if ( !CanInsert() )
+ return;
+
+ StartAllAction();
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, SwResId(STR_GRAPHIC));
+
+ StartUndo(SwUndoId::INSERT, &aRewriter);
+
+ if ( HasSelection() )
+ DelRight();
+ // Inserted graphics in its own paragraph,
+ // if at the end of a non-empty paragraph.
+ //For i120928,avoid to split node
+
+ EnterSelFrameMode();
+
+ bool bSetGrfSize = true;
+ bool bOwnMgr = false;
+
+ if ( !pFrameMgr )
+ {
+ bOwnMgr = true;
+ pFrameMgr = new SwFlyFrameAttrMgr( true, this, Frmmgr_Type::GRF, nullptr );
+
+ // CAUTION
+ // GetAttrSet makes an adjustment
+ // While pasting is a SwFrameSize present
+ // because of the DEF-Framesize
+ // These must be removed explicitly for the optimal size.
+ pFrameMgr->DelAttr(RES_FRM_SIZE);
+
+ if (nAnchorType != RndStdIds::FLY_AT_PARA)
+ // Something other than at-para was requested.
+ pFrameMgr->SetAnchor(nAnchorType);
+ }
+ else
+ {
+ Size aSz( pFrameMgr->GetSize() );
+ if ( !aSz.Width() || !aSz.Height() )
+ {
+ aSz.setWidth(o3tl::toTwips(1, o3tl::Length::cm));
+ aSz.setHeight(o3tl::toTwips(1, o3tl::Length::cm));
+ pFrameMgr->SetSize( aSz );
+ }
+ else if ( aSz.Width() != DFLT_WIDTH && aSz.Height() != DFLT_HEIGHT )
+ bSetGrfSize = false;
+
+ pFrameMgr->SetHeightSizeType(SwFrameSize::Fixed);
+ }
+
+ // during change tracking, insert the image anchored as character
+ // (to create an SwRangeRedline on its anchor point)
+ if ( IsRedlineOn() && nAnchorType != RndStdIds::FLY_AS_CHAR )
+ pFrameMgr->SetAnchor( RndStdIds::FLY_AS_CHAR );
+
+ // Insert the graphic
+ SwFEShell::Insert(rPath, rFilter, &rGrf, &pFrameMgr->GetAttrSet());
+ if ( bOwnMgr )
+ pFrameMgr->UpdateAttrMgr();
+
+ if( bSetGrfSize )
+ {
+ Size aSizePixel = rGrf.GetSizePixel();
+ Size aBound = GetGraphicDefaultSize();
+
+ sal_Int32 nPreferredDPI = mxDoc->getIDocumentSettingAccess().getImagePreferredDPI();
+ Size aGrfSize;
+
+ if (nPreferredDPI > 0)
+ {
+ auto nWidth = o3tl::toTwips(aSizePixel.Width() / double(nPreferredDPI), o3tl::Length::in);
+ auto nHeight = o3tl::toTwips(aSizePixel.Height() / double(nPreferredDPI), o3tl::Length::in);
+ aGrfSize = Size(nWidth, nHeight);
+ }
+ else
+ {
+ GetGrfSize(aGrfSize);
+ }
+
+ // Add the margin attributes to GrfSize,
+ // because these counts at the margin additionally
+ aGrfSize.AdjustWidth(pFrameMgr->CalcWidthBorder() );
+ aGrfSize.AdjustHeight(pFrameMgr->CalcHeightBorder() );
+
+ const BigInt aTempWidth( aGrfSize.Width() );
+ const BigInt aTempHeight( aGrfSize.Height());
+
+ // Fit width if necessary, scale down the height proportional thereafter.
+ if( aGrfSize.Width() > aBound.Width() )
+ {
+ aGrfSize.setWidth( aBound.Width() );
+ aGrfSize.setHeight( BigInt(aBound.Width()) * aTempHeight / aTempWidth );
+ }
+ // Fit height if necessary, scale down the width proportional thereafter.
+ if( aGrfSize.Height() > aBound.Height() )
+ {
+ aGrfSize.setHeight( aBound.Height() );
+ aGrfSize.setWidth( BigInt(aBound.Height()) * aTempWidth / aTempHeight );
+ }
+ pFrameMgr->SetSize( aGrfSize );
+ pFrameMgr->UpdateFlyFrame();
+ }
+ if ( bOwnMgr )
+ delete pFrameMgr;
+
+ EndUndo();
+ EndAllAction();
+}
+
+// Insert an OLE-Object into the CORE.
+// if no object is transferred, then one will be created.
+
+void SwWrtShell::InsertObject( const svt::EmbeddedObjectRef& xRef, SvGlobalName const *pName,
+ sal_uInt16 nSlotId )
+{
+ ResetCursorStack();
+ if( !CanInsert() )
+ return;
+
+ if( !xRef.is() )
+ {
+ // temporary storage
+ svt::EmbeddedObjectRef xObj;
+ uno::Reference < embed::XStorage > xStor = comphelper::OStorageHelper::GetTemporaryStorage();
+ bool bDoVerb = true;
+ if ( pName )
+ {
+ comphelper::EmbeddedObjectContainer aCnt( xStor );
+ OUString aName;
+ // TODO/LATER: get aspect?
+ xObj.Assign( aCnt.CreateEmbeddedObject( pName->GetByteSequence(), aName ), embed::Aspects::MSOLE_CONTENT );
+ }
+ else
+ {
+ SvObjectServerList aServerList;
+ switch (nSlotId)
+ {
+ case SID_INSERT_OBJECT:
+ {
+ if (officecfg::Office::Common::Security::Scripting::DisableActiveContent::get())
+ {
+ std::unique_ptr<weld::MessageDialog> xError(
+ Application::CreateMessageDialog(
+ nullptr, VclMessageType::Warning, VclButtonsType::Ok,
+ SvtResId(STR_WARNING_ACTIVE_CONTENT_DISABLED)));
+ xError->run();
+ break;
+ }
+ aServerList.FillInsertObjects();
+ aServerList.Remove( SwDocShell::Factory().GetClassId() );
+ [[fallthrough]];
+ }
+
+ // TODO/LATER: recording! Convert properties to items
+ case SID_INSERT_FLOATINGFRAME:
+ {
+ SfxSlotPool* pSlotPool = SW_MOD()->GetSlotPool();
+ const SfxSlot* pSlot = pSlotPool->GetSlot(nSlotId);
+ OUString aCmd = pSlot->GetCommand();
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractInsertObjectDialog> pDlg(pFact->CreateInsertObjectDialog(GetFrameWeld(mxDoc->GetDocShell()),
+ aCmd, xStor, &aServerList));
+ if (pDlg)
+ {
+ pDlg->Execute();
+ bDoVerb = pDlg->IsCreateNew();
+ OUString aIconMediaType;
+ uno::Reference< io::XInputStream > xIconMetaFile = pDlg->GetIconIfIconified( &aIconMediaType );
+ xObj.Assign( pDlg->GetObject(),
+ xIconMetaFile.is() ? embed::Aspects::MSOLE_ICON : embed::Aspects::MSOLE_CONTENT );
+ if ( xIconMetaFile.is() )
+ xObj.SetGraphicStream( xIconMetaFile, aIconMediaType );
+ }
+
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ if ( xObj.is() )
+ {
+ if( InsertOleObject( xObj ) && bDoVerb )
+ {
+ SfxInPlaceClient* pClient = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin() );
+ if ( !pClient )
+ {
+ pClient = new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
+ SetCheckForOLEInCaption( true );
+ }
+
+ if ( xObj.GetViewAspect() == embed::Aspects::MSOLE_ICON )
+ {
+ SwRect aArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() );
+ aArea.Pos() += GetAnyCurRect( CurRectType::FlyEmbedded, nullptr, xObj.GetObject() ).Pos();
+ MapMode aMapMode( MapUnit::MapTwip );
+ Size aSize = xObj.GetSize( &aMapMode );
+ aArea.Width( aSize.Width() );
+ aArea.Height( aSize.Height() );
+ RequestObjectResize( aArea, xObj.GetObject() );
+ }
+ else
+ CalcAndSetScale( xObj );
+
+ //#50270# We don't need to handle error, this is handled by the
+ //DoVerb in the SfxViewShell
+ pClient->DoVerb(embed::EmbedVerbs::MS_OLEVERB_SHOW);
+
+ // TODO/LATER: set document name - should be done in Client
+ }
+ }
+ }
+ else
+ {
+ if( HasSelection() )
+ DelRight();
+ InsertOleObject( xRef );
+ }
+}
+
+// Insert object into the Core.
+// From ClipBoard or Insert
+
+bool SwWrtShell::InsertOleObject( const svt::EmbeddedObjectRef& xRef, SwFlyFrameFormat **pFlyFrameFormat )
+{
+ //tdf#125100 Ensure that ole object is initially shown as pictogram
+ comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = mxDoc->GetDocShell()->getEmbeddedObjectContainer();
+ bool bSaveUserAllowsLinkUpdate = rEmbeddedObjectContainer.getUserAllowsLinkUpdate();
+ rEmbeddedObjectContainer.setUserAllowsLinkUpdate(true);
+
+ ResetCursorStack();
+ StartAllAction();
+
+ StartUndo(SwUndoId::INSERT);
+
+ //Some differences between StarMath and any other objects:
+ //1. Selections should be deleted. For StarMath the Text should be
+ // passed to the Object
+ //2. If the cursor is at the end of a non empty paragraph a paragraph
+ // break should be inserted. StarMath objects are character bound and
+ // no break should be inserted.
+ //3. If an selection is passed to a StarMath object, this object should
+ // not be activated. false should be returned then.
+ bool bStarMath = true;
+ bool bActivate = true;
+
+ // set parent to get correct VisArea(in case of object needing parent printer)
+ uno::Reference < container::XChild > xChild( xRef.GetObject(), uno::UNO_QUERY );
+ if ( xChild.is() )
+ xChild->setParent( mxDoc->GetDocShell()->GetModel() );
+
+ SvGlobalName aCLSID( xRef->getClassID() );
+ bStarMath = ( SotExchange::IsMath( aCLSID ) != 0 );
+ if( IsSelection() )
+ {
+ if( bStarMath )
+ {
+ OUString aMathData;
+ GetSelectedText( aMathData, ParaBreakType::ToOnlyCR );
+
+ if( !aMathData.isEmpty() && svt::EmbeddedObjectRef::TryRunningState( xRef.GetObject() ) )
+ {
+ uno::Reference < beans::XPropertySet > xSet( xRef->getComponent(), uno::UNO_QUERY );
+ if ( xSet.is() )
+ {
+ try
+ {
+ xSet->setPropertyValue("Formula", uno::Any( aMathData ) );
+ bActivate = false;
+ }
+ catch (const uno::Exception&)
+ {
+ }
+ }
+ }
+ }
+ DelRight();
+ }
+
+ if ( !bStarMath )
+ SwFEShell::SplitNode( false, false );
+
+ EnterSelFrameMode();
+
+ const SvGlobalName* pName = nullptr;
+ SvGlobalName aObjClsId;
+ if (xRef.is())
+ {
+ aObjClsId = SvGlobalName(xRef.GetObject()->getClassID());
+ pName = &aObjClsId;
+ }
+ SwFlyFrameAttrMgr aFrameMgr( true, this, Frmmgr_Type::OLE, pName );
+ aFrameMgr.SetHeightSizeType(SwFrameSize::Fixed);
+
+ SwRect aBound;
+ CalcBoundRect( aBound, aFrameMgr.GetAnchor() );
+
+ //The Size should be suggested by the OLE server
+ MapMode aMapMode( MapUnit::MapTwip );
+ Size aSz = xRef.GetSize( &aMapMode );
+
+ //Object size can be limited
+ if ( aSz.Width() > aBound.Width() )
+ {
+ //Always limit proportional.
+ aSz.setHeight( aSz.Height() * aBound.Width() / aSz.Width() );
+ aSz.setWidth( aBound.Width() );
+ }
+ aFrameMgr.SetSize( aSz );
+ SwFlyFrameFormat *pFormat = SwFEShell::InsertObject( xRef, &aFrameMgr.GetAttrSet() );
+
+ // --> #i972#
+ if ( bStarMath && mxDoc->getIDocumentSettingAccess().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT ) )
+ AlignFormulaToBaseline( xRef.GetObject() );
+
+ if (pFlyFrameFormat)
+ *pFlyFrameFormat = pFormat;
+
+ if ( SotExchange::IsChart( aCLSID ) )
+ {
+ uno::Reference< embed::XEmbeddedObject > xEmbeddedObj = xRef.GetObject();
+ if ( xEmbeddedObj.is() )
+ {
+ bool bDisableDataTableDialog = false;
+ svt::EmbeddedObjectRef::TryRunningState( xEmbeddedObj );
+ uno::Reference< beans::XPropertySet > xProps( xEmbeddedObj->getComponent(), uno::UNO_QUERY );
+ if ( xProps.is() &&
+ ( xProps->getPropertyValue("DisableDataTableDialog") >>= bDisableDataTableDialog ) &&
+ bDisableDataTableDialog )
+ {
+ xProps->setPropertyValue("DisableDataTableDialog",
+ uno::Any( false ) );
+ xProps->setPropertyValue("DisableComplexChartTypes",
+ uno::Any( false ) );
+ uno::Reference< util::XModifiable > xModifiable( xProps, uno::UNO_QUERY );
+ if ( xModifiable.is() )
+ {
+ xModifiable->setModified( true );
+ }
+ }
+ }
+ }
+
+ EndAllAction();
+ GetView().AutoCaption(OLE_CAP, &aCLSID);
+
+ SwRewriter aRewriter;
+
+ if ( bStarMath )
+ aRewriter.AddRule(UndoArg1, SwResId(STR_MATH_FORMULA));
+ else if ( SotExchange::IsChart( aCLSID ) )
+ aRewriter.AddRule(UndoArg1, SwResId(STR_CHART));
+ else
+ aRewriter.AddRule(UndoArg1, SwResId(STR_OLE));
+
+ EndUndo(SwUndoId::INSERT, &aRewriter);
+
+ rEmbeddedObjectContainer.setUserAllowsLinkUpdate(bSaveUserAllowsLinkUpdate);
+
+ return bActivate;
+}
+
+// The current selected OLE object will be loaded with the
+// verb into the server.
+void SwWrtShell::LaunchOLEObj(sal_Int32 nVerb)
+{
+ if ( GetCntType() != CNT_OLE ||
+ GetView().GetViewFrame().GetFrame().IsInPlace() )
+ return;
+
+ svt::EmbeddedObjectRef& xRef = GetOLEObject();
+ OSL_ENSURE( xRef.is(), "OLE not found" );
+
+ // LOK: we don't want to handle any other embedded objects than
+ // charts, there are too many problems with eg. embedded spreadsheets
+ // (like it creates a separate view for the calc sheet)
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ const auto classId = xRef->getClassID();
+ if (!SotExchange::IsChart(classId) && !SotExchange::IsMath(classId))
+ return;
+ }
+
+ SfxInPlaceClient* pCli = GetView().FindIPClient( xRef.GetObject(), &GetView().GetEditWin() );
+ if ( !pCli )
+ pCli = new SwOleClient( &GetView(), &GetView().GetEditWin(), xRef );
+
+ uno::Reference<lang::XInitialization> xOLEInit(xRef.GetObject(), uno::UNO_QUERY);
+ if (xOLEInit.is())
+ {
+ uno::Sequence<beans::PropertyValue> aArguments
+ = { comphelper::makePropertyValue("ReadOnly", pCli->IsProtected()) };
+ xOLEInit->initialize({ uno::Any(aArguments) });
+ }
+
+ static_cast<SwOleClient*>(pCli)->SetInDoVerb( true );
+
+ CalcAndSetScale( xRef );
+ pCli->DoVerb( nVerb );
+
+ static_cast<SwOleClient*>(pCli)->SetInDoVerb( false );
+ CalcAndSetScale( xRef );
+}
+
+void SwWrtShell::MoveObjectIfActive( svt::EmbeddedObjectRef& xObj, const Point& rOffset )
+{
+ try
+ {
+ sal_Int32 nState = xObj->getCurrentState();
+ if ( nState == css::embed::EmbedStates::INPLACE_ACTIVE
+ || nState == css::embed::EmbedStates::UI_ACTIVE )
+ {
+ SfxInPlaceClient* pCli =
+ GetView().FindIPClient( xObj.GetObject(), &(GetView().GetEditWin()) );
+ if ( pCli )
+ {
+ tools::Rectangle aArea = pCli->GetObjArea();
+ aArea += rOffset;
+ pCli->SetObjArea( aArea );
+ }
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ }
+}
+
+void SwWrtShell::CalcAndSetScale( svt::EmbeddedObjectRef& xObj,
+ const SwRect *pFlyPrtRect,
+ const SwRect *pFlyFrameRect,
+ const bool bNoTextFramePrtAreaChanged )
+{
+ // Setting the scale of the client. This arises from the difference
+ // between the VisArea of the object and the ObjArea.
+ OSL_ENSURE( xObj.is(), "ObjectRef not valid" );
+
+ sal_Int64 nAspect = xObj.GetViewAspect();
+ if ( nAspect == embed::Aspects::MSOLE_ICON )
+ return; // the replacement image is completely controlled by container in this case
+
+ sal_Int64 nMisc = 0;
+ bool bLinkingChart = false;
+
+ try
+ {
+ nMisc = xObj->getStatus( nAspect );
+
+ // This can surely only be a non-active object, if desired they
+ // get the new size set as VisArea (StarChart).
+ if( embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE & nMisc )
+ {
+ // TODO/MBA: testing
+ SwRect aRect( pFlyPrtRect ? *pFlyPrtRect
+ : GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ));
+ if( !aRect.IsEmpty() )
+ {
+ // TODO/LEAN: getMapUnit can switch object to running state
+ // xObj.TryRunningState();
+
+ MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
+
+ // TODO/LATER: needs complete VisArea?!
+ Size aSize( OutputDevice::LogicToLogic(aRect.SVRect(), MapMode(MapUnit::MapTwip), MapMode(aUnit)).GetSize() );
+ awt::Size aSz;
+ aSz.Width = aSize.Width();
+ aSz.Height = aSize.Height();
+
+ // Action 'setVisualAreaSize' doesn't have to turn on the
+ // modified state of the document, either.
+ bool bModified = false;
+ uno::Reference<util::XModifiable> xModifiable(xObj->getComponent(), uno::UNO_QUERY);
+ if (xModifiable.is())
+ bModified = xModifiable->isModified();
+ xObj->setVisualAreaSize( nAspect, aSz );
+ xModifiable.set(xObj->getComponent(), uno::UNO_QUERY);
+ if (xModifiable.is() && xModifiable->isModified() && !bModified)
+ xModifiable->setModified(bModified);
+
+ // #i48419# - action 'UpdateReplacement' doesn't
+ // have to change the modified state of the document.
+ // This is only a workaround for the defect, that this action
+ // modifies a document after load, because unnecessarily the
+ // replacement graphic is updated, in spite of the fact that
+ // nothing has been changed.
+ // If the replacement graphic changes by this action, the document
+ // will be already modified via other mechanisms.
+ {
+ bool bResetEnableSetModified(false);
+ if ( GetDoc()->GetDocShell()->IsEnableSetModified() )
+ {
+ GetDoc()->GetDocShell()->EnableSetModified( false );
+ bResetEnableSetModified = true;
+ }
+
+ //#i79576# don't destroy chart replacement images on load
+ //#i79578# don't request a new replacement image for charts to often
+ //a chart sends a modified call to the framework if it was changed
+ //thus the replacement update is already handled elsewhere
+ if ( !SotExchange::IsChart( xObj->getClassID() ) )
+ xObj.UpdateReplacement();
+
+ if ( bResetEnableSetModified )
+ {
+ GetDoc()->GetDocShell()->EnableSetModified();
+ }
+ }
+ }
+
+ // TODO/LATER: this is only a workaround,
+ uno::Reference< chart2::XChartDocument > xChartDocument( xObj->getComponent(), uno::UNO_QUERY );
+ bLinkingChart = ( xChartDocument.is() && !xChartDocument->hasInternalDataProvider() );
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ // TODO/LATER: handle the error
+ return;
+ }
+
+ SfxInPlaceClient* pCli = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin() );
+ if ( !pCli )
+ {
+ if ( (embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY & nMisc)
+ || bLinkingChart
+ // --> OD #i117189# - refine condition for non-resizable objects
+ // non-resizable objects need to be set the size back by this method
+ || ( bNoTextFramePrtAreaChanged && nMisc & embed::EmbedMisc::EMBED_NEVERRESIZE ) )
+ {
+ pCli = new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
+ }
+ else
+ return;
+ }
+
+ // TODO/LEAN: getMapUnit can switch object to running state
+ // xObj.TryRunningState();
+
+ awt::Size aSize;
+ try
+ {
+ aSize = xObj->getVisualAreaSize( nAspect );
+ }
+ catch (const embed::NoVisualAreaSizeException&)
+ {
+ OSL_FAIL("Can't get visual area size!" );
+ // the scaling will not be done
+ }
+ catch (const uno::Exception&)
+ {
+ // TODO/LATER: handle the error
+ OSL_FAIL("Can't get visual area size!" );
+ return;
+ }
+
+ Size _aVisArea( aSize.Width, aSize.Height );
+
+ Fraction aScaleWidth( 1, 1 );
+ Fraction aScaleHeight( 1, 1 );
+
+ bool bUseObjectSize = false;
+
+ // As long as there comes no reasonable size from the object,
+ // nothing can be scaled.
+ if( _aVisArea.Width() && _aVisArea.Height() )
+ {
+ const MapMode aTmp( MapUnit::MapTwip );
+ MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
+ _aVisArea = OutputDevice::LogicToLogic(_aVisArea, MapMode(aUnit), aTmp);
+ Size aObjArea;
+ if ( pFlyPrtRect )
+ aObjArea = pFlyPrtRect->SSize();
+ else
+ aObjArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ).SSize();
+
+ // differ the aObjArea and _aVisArea by 1 Pixel then set new VisArea
+ tools::Long nX, nY;
+ SwSelPaintRects::Get1PixelInLogic( *this, &nX, &nY );
+ if( !( _aVisArea.Width() - nX <= aObjArea.Width() &&
+ _aVisArea.Width() + nX >= aObjArea.Width() &&
+ _aVisArea.Height()- nY <= aObjArea.Height()&&
+ _aVisArea.Height()+ nY >= aObjArea.Height() ))
+ {
+ if ( nMisc & embed::EmbedMisc::EMBED_NEVERRESIZE )
+ {
+ // the object must not be scaled,
+ // the size stored in object must be used for restoring
+ bUseObjectSize = true;
+ }
+ else
+ {
+ aScaleWidth = Fraction( aObjArea.Width(), _aVisArea.Width() );
+ aScaleHeight = Fraction( aObjArea.Height(), _aVisArea.Height());
+ }
+ }
+ }
+
+ // Now is the favorable time to set the ObjArea.
+ // The Scaling must be considered.
+ SwRect aArea;
+ if ( pFlyPrtRect )
+ {
+ aArea = *pFlyPrtRect;
+ aArea += pFlyFrameRect->Pos();
+ }
+ else
+ {
+ aArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() );
+ aArea.Pos() += GetAnyCurRect( CurRectType::FlyEmbedded, nullptr, xObj.GetObject() ).Pos();
+ }
+
+ if ( bUseObjectSize )
+ {
+ // --> this moves non-resizable object so that when adding borders the baseline remains the same
+ const SwFlyFrameFormat *pFlyFrameFormat = dynamic_cast< const SwFlyFrameFormat * >( GetFlyFrameFormat() );
+ OSL_ENSURE( pFlyFrameFormat, "Could not find fly frame." );
+ if ( pFlyFrameFormat )
+ {
+ const Point &rPoint = pFlyFrameFormat->GetLastFlyFramePrtRectPos();
+ SwRect aRect( pFlyPrtRect ? *pFlyPrtRect
+ : GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ));
+ aArea += rPoint - aRect.Pos(); // adjust area by diff of printing area position in order to keep baseline alignment correct.
+ }
+ aArea.Width ( _aVisArea.Width() );
+ aArea.Height( _aVisArea.Height() );
+ RequestObjectResize( aArea, xObj.GetObject() );
+ }
+ else
+ {
+ double nWidth(pCli->GetScaleWidth());
+ double nHeight(pCli->GetScaleHeight());
+ if (nWidth && nHeight)
+ {
+ aArea.Width ( aArea.Width() / nWidth );
+ aArea.Height( aArea.Height() / nHeight );
+ }
+ }
+
+ pCli->SetObjAreaAndScale( aArea.SVRect(), aScaleWidth, aScaleHeight );
+}
+
+void SwWrtShell::ConnectObj( svt::EmbeddedObjectRef& xObj, const SwRect &rPrt,
+ const SwRect &rFrame )
+{
+ SfxInPlaceClient* pCli = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin());
+ if ( !pCli )
+ new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
+ CalcAndSetScale( xObj, &rPrt, &rFrame );
+}
+
+// Insert hard page break;
+// Selections will be overwritten
+void SwWrtShell::InsertPageBreak(const OUString *pPageDesc, const ::std::optional<sal_uInt16>& oPgNum )
+{
+ if (!lcl_IsAllowed(this))
+ return;
+
+ ResetCursorStack();
+ if( CanInsert() )
+ {
+ SwActContext aActContext(this);
+ StartUndo(SwUndoId::UI_INSERT_PAGE_BREAK);
+
+ if ( !IsCursorInTable() )
+ {
+ if(HasSelection())
+ DelRight();
+ SwFEShell::SplitNode();
+ // delete the numbered attribute of the last line if the last line is empty
+ GetDoc()->ClearLineNumAttrs( *GetCursor()->GetPoint() );
+ }
+
+ const SwPageDesc *pDesc = pPageDesc
+ ? FindPageDescByName( *pPageDesc, true ) : nullptr;
+ if( pDesc )
+ {
+ SwFormatPageDesc aDesc( pDesc );
+ aDesc.SetNumOffset( oPgNum );
+ SetAttrItem( aDesc );
+ }
+ else
+ SetAttrItem( SvxFormatBreakItem(SvxBreak::PageBefore, RES_BREAK) );
+ EndUndo(SwUndoId::UI_INSERT_PAGE_BREAK);
+ }
+ collectUIInformation("BREAK_PAGE", "parameter");
+}
+
+// Insert hard page break;
+// Selections will be overwritten
+
+void SwWrtShell::InsertLineBreak(std::optional<SwLineBreakClear> oClear)
+{
+ if (!lcl_IsAllowed(this))
+ return;
+
+ ResetCursorStack();
+ if( CanInsert() )
+ {
+ if(HasSelection())
+ DelRight();
+
+ const sal_Unicode cIns = 0x0A;
+ SwLineBreakClear eClear = SwLineBreakClear::NONE;
+ if (oClear.has_value())
+ {
+ eClear = *oClear;
+ }
+ SvxAutoCorrect* pACorr = lcl_IsAutoCorr();
+ if (pACorr && eClear == SwLineBreakClear::NONE)
+ AutoCorrect( *pACorr, cIns );
+ else
+ {
+ if (eClear == SwLineBreakClear::NONE)
+ {
+ SwWrtShell::Insert(OUString(cIns));
+ }
+ else
+ {
+ SwFormatLineBreak aLineBreak(eClear);
+ SetAttrItem(aLineBreak);
+ }
+ }
+ }
+}
+
+// Insert hard column break;
+// Selections will be overwritten
+
+void SwWrtShell::InsertColumnBreak()
+{
+ if (!lcl_IsAllowed(this))
+ return;
+
+ SwActContext aActContext(this);
+ ResetCursorStack();
+ if( !CanInsert() )
+ return;
+
+ StartUndo(SwUndoId::UI_INSERT_COLUMN_BREAK);
+
+ if ( !IsCursorInTable() )
+ {
+ if(HasSelection())
+ DelRight();
+ SwFEShell::SplitNode( false, false );
+ }
+ SetAttrItem(SvxFormatBreakItem(SvxBreak::ColumnBefore, RES_BREAK));
+
+ EndUndo(SwUndoId::UI_INSERT_COLUMN_BREAK);
+}
+
+void SwWrtShell::InsertContentControl(SwContentControlType eType)
+{
+ if (!lcl_IsAllowed(this))
+ {
+ return;
+ }
+
+ ResetCursorStack();
+ if (!CanInsert())
+ {
+ return;
+ }
+
+ auto pContentControl = std::make_shared<SwContentControl>(nullptr);
+ OUString aPlaceholder;
+ switch (eType)
+ {
+ case SwContentControlType::RICH_TEXT:
+ case SwContentControlType::PLAIN_TEXT:
+ {
+ pContentControl->SetShowingPlaceHolder(true);
+ if (eType == SwContentControlType::PLAIN_TEXT)
+ {
+ pContentControl->SetPlainText(true);
+ }
+ if (!HasSelection())
+ {
+ aPlaceholder = SwResId(STR_CONTENT_CONTROL_PLACEHOLDER);
+ }
+ break;
+ }
+ case SwContentControlType::CHECKBOX:
+ {
+ pContentControl->SetCheckbox(true);
+ // Ballot Box with X
+ pContentControl->SetCheckedState(u"\u2612"_ustr);
+ // Ballot Box
+ pContentControl->SetUncheckedState(u"\u2610"_ustr);
+ aPlaceholder = u"\u2610"_ustr;
+ break;
+ }
+ case SwContentControlType::COMBO_BOX:
+ case SwContentControlType::DROP_DOWN_LIST:
+ {
+ if (eType == SwContentControlType::COMBO_BOX)
+ {
+ pContentControl->SetComboBox(true);
+ }
+ else if (eType == SwContentControlType::DROP_DOWN_LIST)
+ {
+ pContentControl->SetDropDown(true);
+ }
+
+ pContentControl->SetShowingPlaceHolder(true);
+ if (!HasSelection())
+ {
+ aPlaceholder = SwResId(STR_DROPDOWN_CONTENT_CONTROL_PLACEHOLDER);
+ }
+ SwContentControlListItem aListItem;
+ aListItem.m_aValue = aPlaceholder;
+ pContentControl->SetListItems({ aListItem });
+ break;
+ }
+ case SwContentControlType::PICTURE:
+ {
+ // Set up the picture content control.
+ pContentControl->SetShowingPlaceHolder(true);
+ pContentControl->SetPicture(true);
+
+ // Create the placeholder bitmap.
+ BitmapEx aBitmap(Size(1, 1), vcl::PixelFormat::N24_BPP);
+ Color aColor = SvtOptionsDrawinglayer::getHilightColor();
+ aColor.IncreaseLuminance(255 * 0.75);
+ aBitmap.Erase(aColor);
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, SwResId(STR_GRAPHIC_DEFNAME));
+ StartUndo(SwUndoId::INSERT, &aRewriter);
+ LockPaint(LockPaintReason::InsertGraphic);
+ StartAction();
+ InsertGraphic(OUString(), OUString(), aBitmap, nullptr, RndStdIds::FLY_AS_CHAR);
+
+ // Set properties on the bitmap.
+ SfxItemSetFixed<RES_FRM_SIZE, RES_FRM_SIZE> aSet(GetDoc()->GetAttrPool());
+ GetFlyFrameAttr(aSet);
+ SwFormatFrameSize aSize(SwFrameSize::Fixed, 3000, 3000);
+ aSet.Put(aSize);
+ SetFlyFrameAttr(aSet);
+ SwFrameFormat* pFrameFormat = GetFlyFrameFormat();
+ EndAction();
+ UnlockPaint();
+ EndUndo();
+
+ // Go after the anchor position.
+ UnSelectFrame();
+ LeaveSelFrameMode();
+ {
+ SwCursor* pCursor = getShellCursor(true);
+ pCursor->DeleteMark();
+ const SwFormatAnchor& rFormatAnchor = pFrameFormat->GetAnchor();
+ pCursor->GetPoint()->Assign( *rFormatAnchor.GetAnchorContentNode(), rFormatAnchor.GetAnchorContentOffset() + 1);
+ }
+
+ // Select before the anchor position.
+ Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
+ break;
+ }
+ case SwContentControlType::DATE:
+ {
+ pContentControl->SetShowingPlaceHolder(true);
+ pContentControl->SetDate(true);
+ SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
+ sal_uInt32 nStandardFormat = pFormatter->GetStandardFormat(SvNumFormatType::DATE);
+ const SvNumberformat* pFormat = pFormatter->GetEntry(nStandardFormat);
+ pContentControl->SetDateFormat(pFormat->GetFormatstring());
+ pContentControl->SetDateLanguage(LanguageTag(pFormat->GetLanguage()).getBcp47());
+ if (!HasSelection())
+ {
+ aPlaceholder = SwResId(STR_DATE_CONTENT_CONTROL_PLACEHOLDER);
+ }
+ break;
+ }
+ }
+ if (aPlaceholder.getLength())
+ {
+ Insert(aPlaceholder);
+ Left(SwCursorSkipMode::Chars, /*bSelect=*/true, aPlaceholder.getLength(),
+ /*bBasicCall=*/false);
+ }
+ SwFormatContentControl aContentControl(pContentControl, RES_TXTATR_CONTENTCONTROL);
+ SetAttrItem(aContentControl);
+}
+
+// Insert footnote
+// rStr - optional footnote mark
+
+void SwWrtShell::InsertFootnote(const OUString &rStr, bool bEndNote, bool bEdit )
+{
+ ResetCursorStack();
+ if( !CanInsert() )
+ return;
+
+ if(HasSelection())
+ {
+ //collapse cursor to the end
+ if(!IsCursorPtAtEnd())
+ SwapPam();
+ ClearMark();
+ }
+ SwPosition aPos = *GetCursor()->GetPoint();
+ SwFormatFootnote aFootNote( bEndNote );
+ if(!rStr.isEmpty())
+ aFootNote.SetNumStr( rStr );
+
+ SetAttrItem(aFootNote);
+
+ if( bEdit )
+ {
+ // For editing the footnote text.
+ Left(SwCursorSkipMode::Chars, false, 1, false );
+ GotoFootnoteText();
+ }
+ m_aNavigationMgr.addEntry(aPos);
+}
+
+// tdf#141634
+static bool lcl_FoldedOutlineNodeEndOfParaSplit(SwWrtShell *pThis)
+{
+ SwTextNode* pTextNode = pThis->GetCursor()->GetPointNode().GetTextNode();
+ if (pTextNode && pTextNode->IsOutline())
+ {
+ bool bVisible = true;
+ pTextNode->GetAttrOutlineContentVisible(bVisible);
+ if (!bVisible)
+ {
+ const SwNodes& rNodes = pThis->GetNodes();
+ const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds();
+ SwOutlineNodes::size_type nPos;
+ (void) rOutlineNodes.Seek_Entry(pTextNode, &nPos);
+
+ SwNode* pSttNd = rOutlineNodes[nPos];
+
+ // determine end node of folded outline content
+ SwNode* pEndNd = &rNodes.GetEndOfContent();
+ if (rOutlineNodes.size() > nPos + 1)
+ pEndNd = rOutlineNodes[nPos + 1];
+
+ if (pThis->GetViewOptions()->IsTreatSubOutlineLevelsAsContent())
+ {
+ // get the next outline node after the folded outline content (iPos)
+ // it is the next outline node with the same level or less
+ int nLevel = pSttNd->GetTextNode()->GetAttrOutlineLevel();
+ SwOutlineNodes::size_type iPos = nPos;
+ while (++iPos < rOutlineNodes.size() &&
+ rOutlineNodes[iPos]->GetTextNode()->GetAttrOutlineLevel() > nLevel);
+
+ // get the correct end node
+ // the outline node may be in frames, headers, footers special section of doc model
+ SwNode* pStartOfSectionNodeSttNd = pSttNd->StartOfSectionNode();
+ while (pStartOfSectionNodeSttNd->StartOfSectionNode()
+ != pStartOfSectionNodeSttNd->StartOfSectionNode()->StartOfSectionNode())
+ {
+ pStartOfSectionNodeSttNd = pStartOfSectionNodeSttNd->StartOfSectionNode();
+ }
+ pEndNd = pStartOfSectionNodeSttNd->EndOfSectionNode();
+
+ if (iPos < rOutlineNodes.size())
+ {
+ SwNode* pStartOfSectionNode = rOutlineNodes[iPos]->StartOfSectionNode();
+ while (pStartOfSectionNode->StartOfSectionNode()
+ != pStartOfSectionNode->StartOfSectionNode()->StartOfSectionNode())
+ {
+ pStartOfSectionNode = pStartOfSectionNode->StartOfSectionNode();
+ }
+ if (pStartOfSectionNodeSttNd == pStartOfSectionNode)
+ pEndNd = rOutlineNodes[iPos];
+ }
+ }
+
+ // table, text box, header, footer
+ if (pSttNd->GetTableBox() || pSttNd->GetIndex() < rNodes.GetEndOfExtras().GetIndex())
+ {
+ // insert before section end node
+ if (pSttNd->EndOfSectionIndex() < pEndNd->GetIndex())
+ {
+ SwNodeIndex aIdx(*pSttNd->EndOfSectionNode());
+ while (aIdx.GetNode().IsEndNode())
+ --aIdx;
+ ++aIdx;
+ pEndNd = &aIdx.GetNode();
+ }
+ }
+ // if pSttNd isn't in table but pEndNd is then insert after table
+ else if (pEndNd->GetTableBox())
+ {
+ pEndNd = pEndNd->FindTableNode();
+ SwNodeIndex aIdx(*pEndNd, -1);
+ // account for nested tables
+ while (aIdx.GetNode().GetTableBox())
+ {
+ pEndNd = aIdx.GetNode().FindTableNode();
+ aIdx.Assign(*pEndNd, -1);
+ }
+ aIdx.Assign(*pEndNd->EndOfSectionNode(), +1);
+ pEndNd = &aIdx.GetNode();
+ }
+ // end node determined
+
+ // now insert the new outline node
+ SwDoc* pDoc = pThis->GetDoc();
+
+ // insert at end of tablebox doesn't work correct without
+ MakeAllOutlineContentTemporarilyVisible a(pDoc);
+
+ SwTextNode* pNd = pDoc->GetNodes().MakeTextNode(*pEndNd, pTextNode->GetTextColl(), true);
+
+ (void) rOutlineNodes.Seek_Entry(pNd, &nPos);
+ pThis->GotoOutline(nPos);
+
+ if (pDoc->GetIDocumentUndoRedo().DoesUndo())
+ {
+ pDoc->GetIDocumentUndoRedo().ClearRedo();
+ pDoc->GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoInsert>(*pNd));
+ pDoc->GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoFormatColl>
+ (SwPaM(*pNd), pNd->GetTextColl(), true, true));
+ }
+
+ pThis->SetModified();
+ return true;
+ }
+ }
+ return false;
+}
+
+// SplitNode; also, because
+// - of deleting selected content;
+// - of reset of the Cursorstack if necessary.
+
+void SwWrtShell::SplitNode( bool bAutoFormat )
+{
+ ResetCursorStack();
+ if( !CanInsert() )
+ return;
+
+ SwActContext aActContext(this);
+
+ m_rView.GetEditWin().FlushInBuffer();
+ StartUndo(SwUndoId::SPLITNODE);
+
+ bool bHasSel = HasSelection();
+ if (bHasSel)
+ DelRight();
+
+ bool bHandled = false;
+ if (GetViewOptions()->IsShowOutlineContentVisibilityButton() && IsEndPara())
+ bHandled = lcl_FoldedOutlineNodeEndOfParaSplit(this);
+
+ if (!bHandled)
+ SwFEShell::SplitNode( bAutoFormat );
+
+ EndUndo(SwUndoId::SPLITNODE);
+}
+
+// Turn on numbering
+// Parameter: Optional specification of a name for the named list;
+// this indicates a position if it is possible to convert them
+// into a number and less than nMaxRules.
+
+// To test the CharFormats at the numbering
+// external void SetNumChrFormat( SwWrtShell*, SwNumRules& );
+
+// -> #i40041#
+// Preconditions (as far as OD has figured out):
+// - <SwEditShell::HasNumber()> is false, if <bNum> is true
+// - <SwEditShell::HasBullet()> is false, if <bNum> is false
+// Behavior of method is determined by the current situation at the current
+// cursor position in the document.
+void SwWrtShell::NumOrBulletOn(bool bNum)
+{
+ StartUndo(SwUndoId::NUMORNONUM);
+
+ const SwNumRule* pNumRule = GetNumRuleAtCurrCursorPos();
+
+ // - activate outline rule respectively turning on outline rule for
+ // current text node. But, only for turning on a numbering (<bNum> == true).
+ // - overwrite found numbering rule at current cursor position, if
+ // no numbering rule can be retrieved from the paragraph style.
+ bool bContinueFoundNumRule( false );
+ bool bActivateOutlineRule( false );
+ int nActivateOutlineLvl( MAXLEVEL ); // only relevant, if <bActivateOutlineRule> == true
+ SwTextFormatColl * pColl = GetCurTextFormatColl();
+ if ( pColl )
+ {
+ // retrieve numbering rule at paragraph
+ // style, which is found at current cursor position in the document.
+ SwNumRule* pCollRule = mxDoc->FindNumRulePtr(pColl->GetNumRule().GetValue());
+ // #125993# - The outline numbering rule isn't allowed
+ // to be derived from a parent paragraph style to a derived one.
+ // Thus check, if the found outline numbering rule is directly
+ // set at the paragraph style <pColl>. If not, set <pCollRule> to NULL
+ if ( pCollRule && pCollRule == GetDoc()->GetOutlineNumRule() )
+ {
+ const SwNumRule* pDirectCollRule =
+ mxDoc->FindNumRulePtr(pColl->GetNumRule( false ).GetValue());
+ if ( !pDirectCollRule )
+ {
+ pCollRule = nullptr;
+ }
+ }
+
+ if ( !pCollRule )
+ {
+ pNumRule = pCollRule;
+ }
+ // no activation or continuation of outline numbering in Writer/Web document
+ else if ( bNum &&
+ !dynamic_cast<SwWebDocShell*>(GetDoc()->GetDocShell()) &&
+ pCollRule == GetDoc()->GetOutlineNumRule() )
+ {
+ if ( pNumRule == pCollRule )
+ {
+ // check, if text node at current cursor positioned is counted.
+ // If not, let it been counted. Then it has to be checked,
+ // of the outline numbering has to be activated or continued.
+ SwTextNode const*const pTextNode = sw::GetParaPropsNode(
+ *GetLayout(), GetCursor()->GetPoint()->GetNode());
+ if ( pTextNode && !pTextNode->IsCountedInList() )
+ {
+ // check, if numbering of the outline level of the paragraph
+ // style is active. If not, activate this outline level.
+ nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
+ OSL_ENSURE( pColl->IsAssignedToListLevelOfOutlineStyle(),
+ "<SwWrtShell::NumOrBulletOn(..)> - paragraph style with outline rule, but no outline level" );
+ if ( pColl->IsAssignedToListLevelOfOutlineStyle() &&
+ pCollRule->Get( o3tl::narrowing<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
+ == SVX_NUM_NUMBER_NONE )
+ {
+ // activate outline numbering
+ bActivateOutlineRule = true;
+ }
+ else
+ {
+ // turning on outline numbering at current cursor position
+ bContinueFoundNumRule = true;
+ }
+ }
+ else
+ {
+ // #i101234#
+ // activate outline numbering, because from the precondition
+ // it's known, that <SwEdit::HasNumber()> == false
+ bActivateOutlineRule = true;
+ nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
+ }
+ }
+ else if ( !pNumRule )
+ {
+ // #i101234#
+ // Check, if corresponding list level of the outline numbering
+ // has already a numbering format set.
+ nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
+ if ( pCollRule->Get( o3tl::narrowing<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
+ == SVX_NUM_NUMBER_NONE )
+ {
+ // activate outline numbering, because from the precondition
+ // it's known, that <SwEdit::HasNumber()> == false
+ bActivateOutlineRule = true;
+ }
+ else
+ {
+ // turning on outline numbering at current cursor position
+ bContinueFoundNumRule = true;
+ }
+ }
+ else
+ {
+ // check, if numbering of the outline level of the paragraph
+ // style is active. If not, activate this outline level.
+ nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
+ OSL_ENSURE( pColl->IsAssignedToListLevelOfOutlineStyle(),
+ "<SwWrtShell::NumOrBulletOn(..)> - paragraph style with outline rule, but no outline level" );
+ if ( pColl->IsAssignedToListLevelOfOutlineStyle() &&
+ pCollRule->Get( o3tl::narrowing<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
+ == SVX_NUM_NUMBER_NONE )
+ {
+ // activate outline numbering
+ bActivateOutlineRule = true;
+ }
+ else
+ {
+ // turning on outline numbering at current cursor position
+ bContinueFoundNumRule = true;
+ }
+ }
+ pNumRule = pCollRule;
+ }
+ }
+
+ // Only automatic numbering/bullet rules should be changed.
+ // Note: The outline numbering rule is also an automatic one. It's only
+ // changed, if it has to be activated.
+ if ( pNumRule )
+ {
+ if ( !pNumRule->IsAutoRule() )
+ {
+ pNumRule = nullptr;
+ }
+ else if ( pNumRule == GetDoc()->GetOutlineNumRule() &&
+ !bActivateOutlineRule && !bContinueFoundNumRule )
+ {
+ pNumRule = nullptr;
+ }
+ }
+
+ // Search for a previous numbering/bullet rule to continue it.
+ OUString sContinuedListId;
+ if ( !pNumRule )
+ {
+ pNumRule = GetDoc()->SearchNumRule( *GetCursor()->GetPoint(),
+ false, bNum, false, 0,
+ sContinuedListId, GetLayout() );
+ bContinueFoundNumRule = pNumRule != nullptr;
+ }
+
+ if (pNumRule)
+ {
+ SwNumRule aNumRule(*pNumRule);
+
+ // do not change found numbering/bullet rule, if it should only be continued.
+ if ( !bContinueFoundNumRule )
+ {
+ SwTextNode const*const pTextNode = sw::GetParaPropsNode(
+ *GetLayout(), GetCursor()->GetPoint()->GetNode());
+
+ if (pTextNode)
+ {
+ // use above retrieve outline level, if outline numbering has to be activated.
+ int nLevel = bActivateOutlineRule
+ ? nActivateOutlineLvl
+ : pTextNode->GetActualListLevel();
+
+ if (nLevel < 0)
+ nLevel = 0;
+
+ if (nLevel >= MAXLEVEL)
+ nLevel = MAXLEVEL - 1;
+
+ SwNumFormat aFormat(aNumRule.Get(o3tl::narrowing<sal_uInt16>(nLevel)));
+
+ if (bNum)
+ aFormat.SetNumberingType(SVX_NUM_ARABIC);
+ else
+ {
+ // #i63395# Only apply user defined default bullet font
+ if ( numfunc::IsDefBulletFontUserDefined() )
+ {
+ const vcl::Font* pFnt = &numfunc::GetDefBulletFont();
+ aFormat.SetBulletFont( pFnt );
+ }
+ aFormat.SetBulletChar( numfunc::GetBulletChar(static_cast<sal_uInt8>(nLevel)));
+ aFormat.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ // #i93908# clear suffix for bullet lists
+ aFormat.SetListFormat("", "", nLevel);
+ }
+ aNumRule.Set(o3tl::narrowing<sal_uInt16>(nLevel), aFormat);
+ }
+ }
+
+ // reset indent attribute on applying list style
+ SetCurNumRule( aNumRule, false, sContinuedListId, true );
+ }
+ else
+ {
+ // #i95907#
+ const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
+ numfunc::GetDefaultPositionAndSpaceMode() );
+ SwNumRule aNumRule( GetUniqueNumRuleName(), ePosAndSpaceMode );
+ // Append the character template at the numbering.
+ SwCharFormat* pChrFormat;
+ SwDocShell* pDocSh = GetView().GetDocShell();
+ // #i63395#
+ // Only apply user defined default bullet font
+ const vcl::Font* pFnt = numfunc::IsDefBulletFontUserDefined()
+ ? &numfunc::GetDefBulletFont()
+ : nullptr;
+
+ if (bNum)
+ {
+ pChrFormat = GetCharFormatFromPool( RES_POOLCHR_NUM_LEVEL );
+ }
+ else
+ {
+ pChrFormat = GetCharFormatFromPool( RES_POOLCHR_BULLET_LEVEL );
+ }
+
+ const SwTextNode *const pTextNode = sw::GetParaPropsNode(*GetLayout(),
+ GetCursor()->GetPoint()->GetNode());
+ const SwTwips nWidthOfTabs = pTextNode
+ ? pTextNode->GetWidthOfLeadingTabs()
+ : 0;
+ GetDoc()->getIDocumentContentOperations().RemoveLeadingWhiteSpace(*GetCursor());
+
+ const bool bHtml = dynamic_cast<SwWebDocShell*>( pDocSh ) != nullptr;
+ const bool bRightToLeft = IsInRightToLeftText();
+ for( sal_uInt8 nLvl = 0; nLvl < MAXLEVEL; ++nLvl )
+ {
+ SwNumFormat aFormat( aNumRule.Get( nLvl ) );
+ aFormat.SetCharFormat( pChrFormat );
+
+ if (! bNum)
+ {
+ // #i63395#
+ // Only apply user defined default bullet font
+ if ( pFnt )
+ {
+ aFormat.SetBulletFont( pFnt );
+ }
+ aFormat.SetBulletChar( numfunc::GetBulletChar(nLvl) );
+ aFormat.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ // #i93908# clear suffix for bullet lists
+ aFormat.SetListFormat("", "", nLvl);
+ }
+
+ // #i95907#
+ if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ if(bHtml && nLvl)
+ {
+ // 1/2" for HTML
+ aFormat.SetAbsLSpace(nLvl * 720);
+ }
+ else if ( nWidthOfTabs > 0 )
+ {
+ aFormat.SetAbsLSpace(nWidthOfTabs + nLvl * 720);
+ }
+ }
+
+ // #i38904# Default alignment for
+ // numbering/bullet should be rtl in rtl paragraph:
+ if ( bRightToLeft )
+ {
+ aFormat.SetNumAdjust( SvxAdjust::Right );
+ }
+
+ aNumRule.Set( nLvl, aFormat );
+ }
+
+ // #i95907#
+ if ( pTextNode &&
+ ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+
+ const SwTwips nTextNodeIndent = pTextNode->GetAdditionalIndentForStartingNewList();
+ if ( ( nTextNodeIndent + nWidthOfTabs ) != 0 )
+ {
+ // #i111172#/fdo#85666
+ // If text node is already inside a list, assure that the indents
+ // are the same. Thus, adjust the indent change value by subtracting
+ // indents of to be applied list style.
+ SwTwips nIndentChange = nTextNodeIndent + nWidthOfTabs;
+ if ( pTextNode->GetNumRule() )
+ {
+ int nLevel = pTextNode->GetActualListLevel();
+
+ if (nLevel < 0)
+ nLevel = 0;
+
+ if (nLevel >= MAXLEVEL)
+ nLevel = MAXLEVEL - 1;
+
+ const SwNumFormat& aFormat( aNumRule.Get( nLevel ) );
+ if ( aFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ nIndentChange -= aFormat.GetIndentAt() + aFormat.GetFirstLineIndent();
+ }
+ }
+ aNumRule.ChangeIndent( nIndentChange );
+ }
+ }
+ // reset indent attribute on applying list style
+ // start new list
+ SetCurNumRule( aNumRule, true, OUString(), true );
+ }
+
+ EndUndo(SwUndoId::NUMORNONUM);
+}
+// <- #i40041#
+
+void SwWrtShell::NumOn()
+{
+ NumOrBulletOn(true);
+}
+
+void SwWrtShell::NumOrBulletOff()
+{
+ const SwNumRule * pCurNumRule = GetNumRuleAtCurrCursorPos();
+
+ if (!pCurNumRule)
+ return;
+
+ if (pCurNumRule->IsOutlineRule())
+ {
+ SwNumRule aNumRule(*pCurNumRule);
+
+ SwTextNode * pTextNode =
+ sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->GetNode());
+
+ if (pTextNode)
+ {
+ int nLevel = pTextNode->GetActualListLevel();
+
+ if (nLevel < 0)
+ nLevel = 0;
+
+ if (nLevel >= MAXLEVEL)
+ nLevel = MAXLEVEL - 1;
+
+ SwNumFormat aFormat(aNumRule.Get(o3tl::narrowing<sal_uInt16>(nLevel)));
+
+ aFormat.SetNumberingType(SVX_NUM_NUMBER_NONE);
+ aNumRule.Set(nLevel, aFormat);
+
+ // no start or continuation of a list - the outline style is only changed.
+ SetCurNumRule( aNumRule, false );
+ }
+ }
+ else
+ {
+ DelNumRules();
+ }
+
+ // #126346# - Cursor can not be anymore in front of
+ // a label, because numbering/bullet is switched off.
+ SetInFrontOfLabel( false );
+}
+// <- #i29560#
+
+// Request Default-Bulletlist
+
+void SwWrtShell::BulletOn()
+{
+ NumOrBulletOn(false);
+}
+
+SelectionType SwWrtShell::GetSelectionType() const
+{
+ // ContentType cannot be determined within a Start-/EndAction.
+ // Because there is no invalid value TEXT will be returned.
+ // The value does not matter, it may be updated in EndAction anyway.
+
+ if (ActionPend())
+ return IsSelFrameMode() ? SelectionType::Frame : SelectionType::Text;
+
+ SwView &_rView = const_cast<SwView&>(GetView());
+ if (_rView.GetPostItMgr() && _rView.GetPostItMgr()->HasActiveSidebarWin() )
+ return SelectionType::PostIt;
+
+ // Inserting a frame is not a DrawMode
+ SelectionType nCnt;
+ if ( !_rView.GetEditWin().IsFrameAction() &&
+ (IsObjSelected() || (_rView.IsDrawMode() && !IsFrameSelected()) ))
+ {
+ if (GetDrawView()->IsTextEdit())
+ nCnt = SelectionType::DrawObjectEditMode;
+ else
+ {
+ if (GetView().IsFormMode()) // Only Form selected
+ nCnt = SelectionType::DbForm;
+ else
+ nCnt = SelectionType::DrawObject; // Any draw object
+
+ if (_rView.IsBezierEditMode())
+ nCnt |= SelectionType::Ornament;
+ else if( GetDrawView()->GetContext() == SdrViewContext::Media )
+ nCnt |= SelectionType::Media;
+
+ if (svx::checkForSelectedCustomShapes( GetDrawView(), true /* bOnlyExtruded */ ))
+ {
+ nCnt |= SelectionType::ExtrudedCustomShape;
+ }
+
+ if (svx::checkForSelectedFontWork( GetDrawView() ))
+ {
+ nCnt |= SelectionType::FontWork;
+ }
+ }
+
+ return nCnt;
+ }
+
+ nCnt = static_cast<SelectionType>(GetCntType());
+
+ if ( IsFrameSelected() )
+ {
+ if (_rView.IsDrawMode())
+ _rView.LeaveDrawCreate(); // clean up (Bug #45639)
+ if ( !(nCnt & (SelectionType::Graphic | SelectionType::Ole)) )
+ return SelectionType::Frame;
+ }
+
+ if ( IsCursorInTable() )
+ nCnt |= SelectionType::Table;
+
+ if ( IsTableMode() )
+ {
+ nCnt |= SelectionType::Table | SelectionType::TableCell;
+ SwTable::SearchType eTableSel = GetEnhancedTableSelection();
+ if ( eTableSel == SwTable::SEARCH_ROW )
+ nCnt |= SelectionType::TableRow;
+ else if ( eTableSel == SwTable::SEARCH_COL )
+ nCnt |= SelectionType::TableCol;
+ }
+
+ // Do not pop up numbering toolbar, if the text node has a numbering of type SVX_NUM_NUMBER_NONE.
+ const SwNumRule* pNumRule = GetNumRuleAtCurrCursorPos();
+ if ( pNumRule )
+ {
+ const SwTextNode* pTextNd =
+ sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->GetNode());
+
+ if ( pTextNd && pTextNd->IsInList() )
+ {
+ int nLevel = pTextNd->GetActualListLevel();
+
+ if (nLevel < 0)
+ nLevel = 0;
+
+ if (nLevel >= MAXLEVEL)
+ nLevel = MAXLEVEL - 1;
+
+ const SwNumFormat& rFormat = pNumRule->Get(nLevel);
+ if ( SVX_NUM_NUMBER_NONE != rFormat.GetNumberingType() )
+ nCnt |= SelectionType::NumberList;
+ }
+ }
+
+ return nCnt;
+}
+
+// Find the text collection with the name rCollname
+// Returns: Pointer at the collection or 0, if no
+// text collection with this name exists, or
+// this is a default template.
+
+SwTextFormatColl *SwWrtShell::GetParaStyle(const OUString &rCollName, GetStyle eCreate )
+{
+ SwTextFormatColl* pColl = FindTextFormatCollByName( rCollName );
+ if( !pColl && GETSTYLE_NOCREATE != eCreate )
+ {
+ sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( rCollName, SwGetPoolIdFromName::TxtColl );
+ if( USHRT_MAX != nId || GETSTYLE_CREATEANY == eCreate )
+ pColl = GetTextCollFromPool( nId );
+ }
+ return pColl;
+}
+
+// Find the text collection with the name rCollname
+// Returns: Pointer at the collection or 0, if no
+// character template with this name exists, or
+// this is a default template or template is automatic.
+
+SwCharFormat *SwWrtShell::GetCharStyle(const OUString &rFormatName, GetStyle eCreate )
+{
+ SwCharFormat* pFormat = FindCharFormatByName( rFormatName );
+ if( !pFormat && GETSTYLE_NOCREATE != eCreate )
+ {
+ sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( rFormatName, SwGetPoolIdFromName::ChrFmt );
+ if( USHRT_MAX != nId || GETSTYLE_CREATEANY == eCreate )
+ pFormat = static_cast<SwCharFormat*>(GetFormatFromPool( nId ));
+ }
+ return pFormat;
+}
+
+// Find the table format with the name rFormatname
+// Returns: Pointer at the collection or 0, if no
+// frame format with this name exists or
+// this is a default format or the format is automatic.
+
+SwFrameFormat *SwWrtShell::GetTableStyle(std::u16string_view rFormatName)
+{
+ for( size_t i = GetTableFrameFormatCount(); i; )
+ {
+ SwFrameFormat *pFormat = &GetTableFrameFormat( --i );
+ if( !pFormat->IsDefault() &&
+ pFormat->GetName() == rFormatName && IsUsed( *pFormat ) )
+ return pFormat;
+ }
+ return nullptr;
+}
+
+void SwWrtShell::addCurrentPosition() {
+ SwPaM* pPaM = GetCursor();
+ m_aNavigationMgr.addEntry(*pPaM->GetPoint());
+}
+
+// Applying templates
+
+void SwWrtShell::SetPageStyle(const OUString &rCollName)
+{
+ if( !SwCursorShell::HasSelection() && !IsSelFrameMode() && !IsObjSelected() )
+ {
+ SwPageDesc* pDesc = FindPageDescByName( rCollName, true );
+ if( pDesc )
+ ChgCurPageDesc( *pDesc );
+ }
+}
+
+// Access templates
+
+OUString const & SwWrtShell::GetCurPageStyle() const
+{
+ return GetPageDesc(GetCurPageDesc( false/*bCalcFrame*/ )).GetName();
+}
+
+// Change the current template referring to the existing change.
+
+void SwWrtShell::QuickUpdateStyle()
+{
+ SwTextFormatColl *pColl = GetCurTextFormatColl();
+
+ // Default cannot be changed
+ if(pColl && !pColl->IsDefault())
+ {
+ FillByEx(pColl);
+ // Also apply the template to remove hard attribute assignment.
+ SetTextFormatColl(pColl);
+ }
+}
+
+void SwWrtShell::AutoUpdatePara(SwTextFormatColl* pColl, const SfxItemSet& rStyleSet, SwPaM* pPaM )
+{
+ SwPaM* pCursor = pPaM ? pPaM : GetCursor( );
+ SfxItemSetFixed<
+ RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
+ RES_PARATR_BEGIN, RES_PARATR_END - 1,
+ RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
+ SID_ATTR_TABSTOP_DEFAULTS,SID_ATTR_TABSTOP_OFFSET,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
+ SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP,
+ SID_ATTR_PARA_PAGENUM, SID_ATTR_PARA_PAGENUM> aCoreSet( GetAttrPool() );
+ GetPaMAttr( pCursor, aCoreSet );
+ bool bReset = false;
+ SfxItemIter aParaIter( aCoreSet );
+ for (auto pParaItem = aParaIter.GetCurItem(); pParaItem; pParaItem = aParaIter.NextItem())
+ {
+ if(!IsInvalidItem(pParaItem))
+ {
+ sal_uInt16 nWhich = pParaItem->Which();
+ if(SfxItemState::SET == aParaIter.GetItemState() &&
+ SfxItemState::SET == rStyleSet.GetItemState(nWhich))
+ {
+ aParaIter.ClearItem();
+ bReset = true;
+ }
+ }
+ }
+ StartAction();
+ if(bReset)
+ {
+ ResetAttr({}, pCursor);
+ SetAttrSet(aCoreSet, SetAttrMode::DEFAULT, pCursor);
+ }
+ mxDoc->ChgFormat(*pColl, rStyleSet );
+ EndAction();
+}
+
+void SwWrtShell::AutoUpdateFrame( SwFrameFormat* pFormat, const SfxItemSet& rStyleSet )
+{
+ StartAction();
+
+ ResetFlyFrameAttr( &rStyleSet );
+ pFormat->SetFormatAttr( rStyleSet );
+
+ EndAction();
+}
+
+void SwWrtShell::AutoCorrect( SvxAutoCorrect& rACorr, sal_Unicode cChar )
+{
+ ResetCursorStack();
+ if(!CanInsert())
+ return;
+
+ bool bStarted = false;
+ SwRewriter aRewriter;
+
+ if(HasSelection())
+ {
+ // Only parentheses here, because the regular insert
+ // is already clipped to the editshell
+ StartAllAction();
+
+ OUString aTmpStr1 = SwResId(STR_START_QUOTE) +
+ GetSelText() +
+ SwResId(STR_END_QUOTE);
+ OUString aTmpStr3 = SwResId(STR_START_QUOTE) +
+ OUStringChar(cChar) +
+ SwResId(STR_END_QUOTE);
+ aRewriter.AddRule( UndoArg1, aTmpStr1 );
+ aRewriter.AddRule( UndoArg2, SwResId(STR_YIELDS) );
+ aRewriter.AddRule( UndoArg3, aTmpStr3 );
+
+ StartUndo( SwUndoId::REPLACE, &aRewriter );
+ bStarted = true;
+ DelRight(true);
+ }
+ SwEditShell::AutoCorrect( rACorr, IsInsMode(), cChar );
+
+ if(bStarted)
+ {
+ EndAllAction();
+ EndUndo( SwUndoId::REPLACE, &aRewriter );
+ }
+}
+
+// Some kind of controlled copy ctor
+
+SwWrtShell::SwWrtShell( SwWrtShell& rSh, vcl::Window *_pWin, SwView &rShell )
+ : SwFEShell(rSh, _pWin)
+ , m_rView(rShell)
+ , m_aNavigationMgr(*this)
+{
+ BITFLD_INI_LIST
+ CurrShell aCurr( this );
+
+ SetSfxViewShell( static_cast<SfxViewShell *>(&rShell) );
+ SetFlyMacroLnk( LINK(this, SwWrtShell, ExecFlyMac) );
+
+ // place the cursor on the first field...
+ IFieldmark *pBM = nullptr;
+ if (IsFormProtected() && (pBM = GetFieldmarkAfter(/*bLoop=*/true)) !=nullptr) {
+ GotoFieldmark(pBM);
+ }
+}
+
+SwWrtShell::SwWrtShell( SwDoc& rDoc, vcl::Window *_pWin, SwView &rShell,
+ const SwViewOption *pViewOpt )
+ : SwFEShell(rDoc, _pWin, pViewOpt)
+ , m_rView(rShell)
+ , m_aNavigationMgr(*this)
+{
+ BITFLD_INI_LIST
+ CurrShell aCurr( this );
+ SetSfxViewShell( static_cast<SfxViewShell *>(&rShell) );
+ SetFlyMacroLnk( LINK(this, SwWrtShell, ExecFlyMac) );
+
+ // place the cursor on the first field...
+ IFieldmark *pBM = nullptr;
+ if (IsFormProtected() && (pBM = GetFieldmarkAfter(/*bLoop=*/true)) !=nullptr) {
+ GotoFieldmark(pBM);
+ }
+}
+
+SwWrtShell::~SwWrtShell()
+{
+ CurrShell aCurr( this );
+ while(IsModePushed())
+ PopMode();
+ while(PopCursor(false))
+ ;
+ SwTransferable::ClearSelection( *this );
+}
+
+bool SwWrtShell::Pop(SwCursorShell::PopMode const eDelete)
+{
+ ::std::optional<SwCallLink> aLink(std::in_place, *this);
+ return Pop(eDelete, aLink);
+}
+
+bool SwWrtShell::Pop(SwCursorShell::PopMode const eDelete, ::std::optional<SwCallLink>& roLink)
+{
+ bool bRet = SwCursorShell::Pop(eDelete, roLink);
+ if( bRet && IsSelection() )
+ {
+ m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
+ m_fnKillSel = &SwWrtShell::ResetSelect;
+ }
+ return bRet;
+}
+
+bool SwWrtShell::CanInsert()
+{
+ if(IsSelFrameMode())
+ {
+ return false;
+ }
+
+ if(IsObjSelected())
+ {
+ return false;
+ }
+
+ if(GetView().GetDrawFuncPtr())
+ {
+ return false;
+ }
+
+ if(GetView().GetPostItMgr()->GetActiveSidebarWin())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void SwWrtShell::ChgDBData(const SwDBData& aDBData)
+{
+ SwEditShell::ChgDBData(aDBData);
+ //notify the db-beamer if available
+ GetView().NotifyDBChanged();
+}
+
+OUString SwWrtShell::GetSelDescr() const
+{
+ OUString aResult;
+
+ SelectionType nSelType = GetSelectionType();
+ switch (nSelType)
+ {
+ case SelectionType::Graphic:
+ aResult = SwResId(STR_GRAPHIC);
+
+ break;
+ case SelectionType::Frame:
+ {
+ const SwFrameFormat * pFrameFormat = GetSelectedFrameFormat();
+
+ if (pFrameFormat)
+ aResult = pFrameFormat->GetDescription();
+ }
+ break;
+ case SelectionType::DrawObject:
+ {
+ aResult = SwResId(STR_DRAWING_OBJECTS);
+ }
+ break;
+ default:
+ if (mxDoc)
+ aResult = GetCursorDescr();
+ }
+
+ return aResult;
+}
+
+void SwWrtShell::ApplyViewOptions( const SwViewOption &rOpt )
+{
+ SwFEShell::ApplyViewOptions( rOpt );
+ //#i115062# invalidate meta character slot
+ GetView().GetViewFrame().GetBindings().Invalidate( FN_VIEW_META_CHARS );
+}
+
+void SwWrtShell::SetReadonlyOption(bool bSet)
+{
+ GetView().GetEditWin().GetFrameControlsManager().SetReadonlyControls( bSet );
+ SwViewShell::SetReadonlyOption( bSet );
+}
+
+// Switch on/off header or footer of a page style - if an empty name is
+// given all styles are changed
+
+void SwWrtShell::ChangeHeaderOrFooter(
+ std::u16string_view rStyleName, bool bHeader, bool bOn, bool bShowWarning)
+{
+ SdrView *const pSdrView = GetDrawView();
+ if (pSdrView && pSdrView->IsTextEdit())
+ { // tdf#107474 deleting header may delete active drawing object
+ pSdrView->SdrEndTextEdit(true);
+ }
+ addCurrentPosition();
+ StartAllAction();
+ StartUndo( SwUndoId::HEADER_FOOTER ); // #i7983#
+ bool bExecute = true;
+ bool bCursorSet = false;
+ for( size_t nFrom = 0, nTo = GetPageDescCnt();
+ nFrom < nTo; ++nFrom )
+ {
+ SwPageDesc aDesc( GetPageDesc( nFrom ));
+ OUString sTmp(aDesc.GetName());
+ if( rStyleName.empty() || rStyleName == sTmp )
+ {
+ bool bChgd = false;
+
+ if( bShowWarning && !bOn && GetActiveView() && GetActiveView() == &GetView() &&
+ ( (bHeader && aDesc.GetMaster().GetHeader().IsActive()) ||
+ (!bHeader && aDesc.GetMaster().GetFooter().IsActive()) ) )
+ {
+ bShowWarning = false;
+ //Actions have to be closed while the dialog is showing
+ EndAllAction();
+
+ weld::Window* pParent = GetView().GetFrameWeld();
+ short nResult;
+ if (bHeader) {
+ nResult = DeleteHeaderDialog(pParent).run();
+ } else {
+ nResult = DeleteFooterDialog(pParent).run();
+ }
+
+ bExecute = nResult == RET_YES;
+ StartAllAction();
+ if (nResult == RET_YES)
+ ToggleHeaderFooterEdit();
+ }
+ if( bExecute )
+ {
+ bChgd = true;
+ SwFrameFormat &rMaster = aDesc.GetMaster();
+ if(bHeader)
+ rMaster.SetFormatAttr( SwFormatHeader( bOn ));
+ else
+ rMaster.SetFormatAttr( SwFormatFooter( bOn ));
+ if( bOn )
+ {
+ // keep in sync with FN_PGNUMBER_WIZARD
+ constexpr tools::Long constTwips_5mm = o3tl::toTwips(5, o3tl::Length::mm);
+ SvxULSpaceItem aUL(bHeader ? 0 : constTwips_5mm, bHeader ? constTwips_5mm : 0, RES_UL_SPACE );
+ SwFrameFormat* pFormat = bHeader ?
+ const_cast<SwFrameFormat*>(rMaster.GetHeader().GetHeaderFormat()) :
+ const_cast<SwFrameFormat*>(rMaster.GetFooter().GetFooterFormat());
+ pFormat->SetFormatAttr( aUL );
+ XFillStyleItem aFill(drawing::FillStyle_NONE);
+ pFormat->SetFormatAttr(aFill);
+ }
+ }
+ if( bChgd )
+ {
+ ChgPageDesc( nFrom, aDesc );
+
+ if( !bCursorSet && bOn )
+ {
+ if ( !IsHeaderFooterEdit() )
+ ToggleHeaderFooterEdit();
+ bCursorSet = SetCursorInHdFt(
+ rStyleName.empty() ? SIZE_MAX : nFrom,
+ bHeader );
+ }
+ }
+ }
+ }
+ EndUndo( SwUndoId::HEADER_FOOTER ); // #i7983#
+ EndAllAction();
+}
+
+void SwWrtShell::SetShowHeaderFooterSeparator( FrameControlType eControl, bool bShow )
+{
+ SwViewShell::SetShowHeaderFooterSeparator( eControl, bShow );
+ if ( !bShow )
+ GetView().GetEditWin().GetFrameControlsManager().HideControls( eControl );
+}
+
+void SwWrtShell::InsertPostIt(SwFieldMgr& rFieldMgr, const SfxRequest& rReq)
+{
+ SwPostItField* pPostIt = dynamic_cast<SwPostItField*>(rFieldMgr.GetCurField());
+ bool bNew = !(pPostIt && pPostIt->GetTyp()->Which() == SwFieldIds::Postit);
+ if (bNew || GetView().GetPostItMgr()->IsAnswer())
+ {
+ const SvxPostItAuthorItem* pAuthorItem = rReq.GetArg<SvxPostItAuthorItem>(SID_ATTR_POSTIT_AUTHOR);
+ OUString sAuthor;
+ if ( pAuthorItem )
+ sAuthor = pAuthorItem->GetValue();
+ else
+ {
+ std::size_t nAuthor = SW_MOD()->GetRedlineAuthor();
+ sAuthor = SW_MOD()->GetRedlineAuthor(nAuthor);
+ }
+
+ const SvxPostItTextItem* pTextItem = rReq.GetArg<SvxPostItTextItem>(SID_ATTR_POSTIT_TEXT);
+ OUString sText;
+ if ( pTextItem )
+ sText = pTextItem->GetValue();
+
+ // If we have a text already registered for answer, use that
+ if (GetView().GetPostItMgr()->IsAnswer() && !GetView().GetPostItMgr()->GetAnswerText().isEmpty())
+ {
+ sText = GetView().GetPostItMgr()->GetAnswerText();
+ GetView().GetPostItMgr()->RegisterAnswerText(OUString());
+ }
+
+ if ( HasSelection() && !IsTableMode() )
+ {
+ KillPams();
+ }
+
+ // #i120513# Inserting a comment into an autocompletion crashes
+ // --> suggestion has to be removed before
+ GetView().GetEditWin().StopQuickHelp();
+
+ SwInsertField_Data aData(SwFieldTypesEnum::Postit, 0, sAuthor, sText, 0);
+
+ if (IsSelFrameMode())
+ {
+ SwFlyFrame* pFly = GetSelectedFlyFrame();
+
+ // Remember the anchor of the selected object before deletion.
+ std::optional<SwPosition> oAnchor;
+ if (pFly)
+ {
+ SwFrameFormat* pFormat = pFly->GetFormat();
+ if (pFormat)
+ {
+ RndStdIds eAnchorId = pFormat->GetAnchor().GetAnchorId();
+ if ((eAnchorId == RndStdIds::FLY_AS_CHAR || eAnchorId == RndStdIds::FLY_AT_CHAR) && pFormat->GetAnchor().GetAnchorNode())
+ {
+ oAnchor.emplace(*pFormat->GetAnchor().GetContentAnchor());
+ }
+ }
+ }
+
+ // A frame is selected, end frame selection.
+ EnterStdMode();
+ GetView().AttrChangedNotify(nullptr);
+
+ // Set up text selection, so the anchor of the frame will be the anchor of the
+ // comment.
+ if (pFly)
+ {
+ if (oAnchor)
+ *GetCurrentShellCursor().GetPoint() = *oAnchor;
+ SwFrameFormat* pFormat = pFly->GetFormat();
+ if (pFormat && pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR)
+ {
+ Right(SwCursorSkipMode::Cells, /*bSelect=*/true, 1, /*bBasicCall=*/false, /*bVisual=*/true);
+ }
+ else if (pFormat && pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_CHAR)
+ {
+ aData.m_oAnnotationRange.emplace(*GetCurrentShellCursor().Start(),
+ *GetCurrentShellCursor().End());
+ }
+ }
+ }
+
+ rFieldMgr.InsertField( aData );
+
+ Push();
+ SwCursorShell::Left(1, SwCursorSkipMode::Chars);
+ pPostIt = static_cast<SwPostItField*>(rFieldMgr.GetCurField());
+ Pop(SwCursorShell::PopMode::DeleteCurrent); // Restore cursor position
+ }
+
+ // Client has disabled annotations rendering, no need to
+ // focus the postit field
+ if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations())
+ return;
+
+ if (pPostIt)
+ {
+ SwFieldType* pType = GetDoc()->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Postit, OUString(), false);
+ if(auto pFormat = pType->FindFormatForField(pPostIt))
+ pFormat->Broadcast( SwFormatFieldHint( nullptr, SwFormatFieldHintWhich::FOCUS, &GetView() ) );
+ }
+}
+
+bool SwWrtShell::IsOutlineContentVisible(const size_t nPos)
+{
+ const SwOutlineNodes& rOutlineNodes = GetDoc()->GetNodes().GetOutLineNds();
+ const SwNode* pOutlineNode = rOutlineNodes[nPos];
+
+ // no layout frame means outline folding is set to include sub levels and the outline node has
+ // a parent outline node with outline content visible attribute false (folded outline content)
+ if (!pOutlineNode->GetTextNode()->getLayoutFrame(GetLayout()))
+ return false;
+
+ // try the next node to determine if this outline node has visible content
+ SwNodeIndex aIdx(*pOutlineNode, +1);
+ if (aIdx.GetNode() == aIdx.GetNodes().GetEndOfContent()) // end of regular content
+ return false;
+
+ if (aIdx.GetNode().IsTextNode() || aIdx.GetNode().IsTableNode() ||
+ aIdx.GetNode().IsSectionNode())
+ {
+ // * sublevels treated as outline content
+ // If next node (aIdx) doesn't have a layout frame
+ // then this outline node does not have visible outline content.
+ // * sublevels NOT treated as outline content
+ // If the next node (aIdx) is the next outline node
+ // then return the outline content visible attribute value.
+ if (!GetViewOptions()->IsTreatSubOutlineLevelsAsContent() &&
+ nPos + 1 < rOutlineNodes.size() &&
+ rOutlineNodes[nPos + 1] == &aIdx.GetNode())
+ return GetAttrOutlineContentVisible(nPos);
+
+ if (aIdx.GetNode().IsTextNode())
+ return aIdx.GetNode().GetTextNode()->getLayoutFrame(GetLayout());
+ if (aIdx.GetNode().IsTableNode())
+ {
+ SwTable& rTable = aIdx.GetNode().GetTableNode()->GetTable();
+ return rTable.HasLayout();
+ }
+ if (aIdx.GetNode().IsSectionNode())
+ {
+ const auto pFormat = aIdx.GetNode().GetSectionNode()->GetSection().GetFormat();
+ return pFormat && pFormat->IsVisible();
+ }
+ }
+
+ return true;
+}
+
+void SwWrtShell::MakeOutlineLevelsVisible(const int nLevel)
+{
+ MakeAllOutlineContentTemporarilyVisible a(GetDoc());
+
+ m_rView.SetMaxOutlineLevelShown(nLevel);
+
+ bool bDocChanged = false;
+
+ const SwOutlineNodes& rOutlineNodes = GetNodes().GetOutLineNds();
+
+ // Make all missing frames.
+ for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNodes.size(); ++nPos)
+ {
+ SwNode* pNode = rOutlineNodes[nPos];
+ if (!pNode->GetTextNode()->getLayoutFrame(GetLayout()))
+ {
+ SwNodeIndex aIdx(*pNode, +1);
+ // Make the outline paragraph frame
+ MakeFrames(GetDoc(), *pNode, aIdx.GetNode());
+ // Make the outline content visible but don't set the outline visible attribute and
+ // don't make outline content made visible not visible that have outline visible
+ // attribute false. Visibility will be taken care of when
+ // MakeAllOutlineContentTemporarilyVisible goes out of scope.
+ MakeOutlineContentVisible(nPos, true, false);
+ bDocChanged = true;
+ }
+ }
+ // Remove outline paragraph frame and outline content frames above given level.
+ for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNodes.size(); ++nPos)
+ {
+ SwNode* pNode = rOutlineNodes[nPos];
+ auto nOutlineLevel = pNode->GetTextNode()->GetAttrOutlineLevel();
+ if (nOutlineLevel > nLevel)
+ {
+ // Remove the outline content but don't set the outline visible attribute. Visibility
+ // will be taken care of when MakeAllOutlineContentTemporarilyVisible goes out of scope.
+ MakeOutlineContentVisible(nPos, false, false);
+ // Remove the outline paragraph frame.
+ pNode->GetTextNode()->DelFrames(GetLayout());
+ bDocChanged = true;
+ }
+ }
+
+ // Broadcast DocChanged if document layout has changed so the Navigator will be updated.
+ if (bDocChanged)
+ GetDoc()->GetDocShell()->Broadcast(SfxHint(SfxHintId::DocChanged));
+}
+
+void SwWrtShell::MakeOutlineContentVisible(const size_t nPos, bool bMakeVisible, bool bSetAttrOutlineVisibility)
+{
+ const SwNodes& rNodes = GetNodes();
+ const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds();
+
+ SwNode* pSttNd = rOutlineNodes[nPos];
+
+ // determine end node
+ SwNode* pEndNd = &rNodes.GetEndOfContent();
+ if (rOutlineNodes.size() > nPos + 1)
+ pEndNd = rOutlineNodes[nPos + 1];
+
+ if (GetViewOptions()->IsTreatSubOutlineLevelsAsContent())
+ {
+ // get the last outline node to include (iPos)
+ int nLevel = pSttNd->GetTextNode()->GetAttrOutlineLevel();
+ int nMaxOutlineLevelShown = m_rView.GetMaxOutlineLevelShown();
+ SwOutlineNodes::size_type iPos = nPos;
+ while (++iPos < rOutlineNodes.size() &&
+ rOutlineNodes[iPos]->GetTextNode()->GetAttrOutlineLevel() > nLevel &&
+ rOutlineNodes[iPos]->GetTextNode()->GetAttrOutlineLevel() <= nMaxOutlineLevelShown);
+
+ // get the correct end node
+ // the outline node may be in frames, headers, footers special section of doc model
+ SwNode* pStartOfSectionNodeSttNd = pSttNd->StartOfSectionNode();
+ while (pStartOfSectionNodeSttNd->StartOfSectionNode()
+ != pStartOfSectionNodeSttNd->StartOfSectionNode()->StartOfSectionNode())
+ {
+ pStartOfSectionNodeSttNd = pStartOfSectionNodeSttNd->StartOfSectionNode();
+ }
+ pEndNd = pStartOfSectionNodeSttNd->EndOfSectionNode();
+
+ if (iPos < rOutlineNodes.size())
+ {
+ SwNode* pStartOfSectionNode = rOutlineNodes[iPos]->StartOfSectionNode();
+ while (pStartOfSectionNode->StartOfSectionNode()
+ != pStartOfSectionNode->StartOfSectionNode()->StartOfSectionNode())
+ {
+ pStartOfSectionNode = pStartOfSectionNode->StartOfSectionNode();
+ }
+ if (pStartOfSectionNodeSttNd == pStartOfSectionNode)
+ pEndNd = rOutlineNodes[iPos];
+ }
+ }
+
+ // table, text box, header, footer
+ if (pSttNd->GetTableBox() || pSttNd->GetIndex() < rNodes.GetEndOfExtras().GetIndex())
+ {
+ // limit to within section
+ if (pSttNd->EndOfSectionIndex() < pEndNd->GetIndex())
+ pEndNd = pSttNd->EndOfSectionNode();
+ }
+ // if pSttNd isn't in table but pEndNd is, skip over all outline nodes in table
+ else if (pEndNd->GetTableBox())
+ {
+ pEndNd = &rNodes.GetEndOfContent();
+ for (size_t nOutlinePos = nPos + 2; nOutlinePos < rOutlineNodes.size(); nOutlinePos++)
+ {
+ if (!(rOutlineNodes[nOutlinePos]->GetTableBox()))
+ {
+ pEndNd = rOutlineNodes[nOutlinePos];
+ break;
+ }
+ }
+ }
+ // end node determined
+
+ // Remove content frames from the next node after the starting outline node to
+ // the determined ending node. Always do this to prevent the chance of duplicate
+ // frames being made. They will be remade below if needed.
+ SwNodeIndex aIdx(*pSttNd, +1);
+ while (aIdx != *pEndNd)
+ {
+ SwNode* pNd = &aIdx.GetNode();
+ if (pNd->IsContentNode())
+ pNd->GetContentNode()->DelFrames(nullptr);
+ else if (pNd->IsTableNode())
+ pNd->GetTableNode()->DelFrames(nullptr);
+ ++aIdx;
+ }
+
+ if (bMakeVisible) // make outline nodes outline content visible
+ {
+ // reset the index marker and make frames
+ aIdx.Assign(*pSttNd, +1);
+ MakeFrames(GetDoc(), aIdx.GetNode(), *pEndNd);
+
+ if (bSetAttrOutlineVisibility)
+ {
+ pSttNd->GetTextNode()->SetAttrOutlineContentVisible(true);
+
+ // make outline content made visible that have outline visible attribute false not visible
+ while (aIdx != *pEndNd)
+ {
+ SwNode* pNd = &aIdx.GetNode();
+ if (pNd->IsTextNode() && pNd->GetTextNode()->IsOutline())
+ {
+ SwTextNode* pTextNd = pNd->GetTextNode();
+ bool bOutlineContentVisibleAttr = true;
+ pTextNd->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr);
+ if (!bOutlineContentVisibleAttr)
+ {
+ SwOutlineNodes::size_type iPos;
+ if (rOutlineNodes.Seek_Entry(pTextNd, &iPos))
+ {
+ if (pTextNd->getLayoutFrame(nullptr))
+ MakeOutlineContentVisible(iPos, false);
+ }
+ }
+ }
+ ++aIdx;
+ }
+ }
+ }
+ else if (bSetAttrOutlineVisibility)
+ pSttNd->GetTextNode()->SetAttrOutlineContentVisible(false);
+}
+
+// make content visible or not visible only if needed
+void SwWrtShell::InvalidateOutlineContentVisibility()
+{
+ GetView().GetEditWin().GetFrameControlsManager().HideControls(FrameControlType::Outline);
+
+ const SwOutlineNodes& rOutlineNds = GetNodes().GetOutLineNds();
+ for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNds.size(); ++nPos)
+ {
+ bool bIsOutlineContentVisible = IsOutlineContentVisible(nPos);
+ bool bOutlineContentVisibleAttr = true;
+ rOutlineNds[nPos]->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr);
+ if (!bIsOutlineContentVisible && bOutlineContentVisibleAttr)
+ MakeOutlineContentVisible(nPos);
+ else if (bIsOutlineContentVisible && !bOutlineContentVisibleAttr)
+ MakeOutlineContentVisible(nPos, false);
+ }
+}
+
+void SwWrtShell::MakeAllFoldedOutlineContentVisible(bool bMakeVisible)
+{
+ if (bMakeVisible)
+ {
+ // make all content visible
+
+ // When shortcut is assigned to the show outline content visibility button and used to
+ // toggle the feature and the mouse pointer is on an outline frame the button will not
+ // be removed. An easy way to make sure the button does not remain shown is to use the
+ // HideControls function.
+ GetView().GetEditWin().GetFrameControlsManager().HideControls(FrameControlType::Outline);
+
+ // temporarily set outline content visible attribute true for folded outline nodes
+ std::vector<SwNode*> aFoldedOutlineNodeArray;
+ for (SwNode* pNd: GetNodes().GetOutLineNds())
+ {
+ bool bOutlineContentVisibleAttr = true;
+ pNd->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr);
+ if (!bOutlineContentVisibleAttr)
+ {
+ aFoldedOutlineNodeArray.push_back(pNd);
+ pNd->GetTextNode()->SetAttrOutlineContentVisible(true);
+ }
+ }
+
+ StartAction();
+ InvalidateOutlineContentVisibility();
+ EndAction();
+
+ // restore outline content visible attribute for folded outline nodes
+ for (SwNode* pNd: aFoldedOutlineNodeArray)
+ pNd->GetTextNode()->SetAttrOutlineContentVisible(false);
+ }
+ else
+ {
+ AssureStdMode();
+
+ // Get the outline position of the cursor so the cursor can be place at a visible outline
+ // node if it is not visible after InvalidateOutlineContentVisiblity below.
+ SwOutlineNodes::size_type nPos = GetOutlinePos();
+
+ StartAction();
+ InvalidateOutlineContentVisibility();
+ EndAction();
+
+ // If needed, find a visible outline node to place the cursor.
+ if (nPos != SwOutlineNodes::npos && !IsOutlineContentVisible(nPos))
+ {
+ while (nPos != SwOutlineNodes::npos &&
+ !GetNodes().GetOutLineNds()[nPos]->GetTextNode()->getLayoutFrame(GetLayout()))
+ --nPos;
+ if (nPos != SwOutlineNodes::npos)
+ GotoOutline(nPos);
+ }
+ }
+ GetView().GetDocShell()->Broadcast(SfxHint(SfxHintId::DocChanged));
+}
+
+bool SwWrtShell::GetAttrOutlineContentVisible(const size_t nPos) const
+{
+ bool bVisibleAttr = true;
+ GetNodes().GetOutLineNds()[nPos]->GetTextNode()->GetAttrOutlineContentVisible(bVisibleAttr);
+ return bVisibleAttr;
+}
+
+bool SwWrtShell::HasFoldedOutlineContentSelected() const
+{
+ // No need to check for selection over folded outline content when there are no outline nodes.
+ if (GetDoc()->GetNodes().GetOutLineNds().empty())
+ return false;
+ for(const SwPaM& rPaM : GetCursor()->GetRingContainer())
+ {
+ SwPaM aPaM(*rPaM.GetMark(), *rPaM.GetPoint());
+ aPaM.Normalize();
+ SwNodeIndex aPointIdx(aPaM.GetPoint()->GetNode());
+ SwNodeIndex aMarkIdx(aPaM.GetMark()->GetNode());
+ // Prevent crash in the for loop below by adjusting the mark if it is set to the end of
+ // content node.
+ if (aMarkIdx.GetNode() == GetDoc()->GetNodes().GetEndOfContent())
+ --aMarkIdx;
+ if (aPointIdx == aMarkIdx)
+ continue;
+ // Return true if any nodes in PaM are folded outline content nodes.
+ SwOutlineNodes::size_type nPos;
+ for (SwNodeIndex aIdx = aPointIdx; aIdx <= aMarkIdx; ++aIdx)
+ {
+ // To allow delete when the start of the selection is at the start of a
+ // paragraph and the end of the selection is at the start of a paragraph and there
+ // are no folded outline content nodes in between.
+ if (aIdx == aMarkIdx && aPaM.GetPoint()->GetContentIndex() == 0 &&
+ aPaM.GetMark()->GetContentIndex() == 0)
+ return false;
+
+ if (GetDoc()->GetNodes().GetOutLineNds().Seek_Entry(&(aIdx.GetNode()), &nPos) &&
+ !GetAttrOutlineContentVisible(nPos))
+ return true;
+ }
+ }
+ return false;
+}
+
+void SwWrtShell::InfoReadOnlyDialog(bool bAsync) const
+{
+ if (bAsync)
+ {
+ auto xInfo = std::make_shared<weld::MessageDialogController>(
+ GetView().GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog");
+ if (GetViewOptions()->IsShowOutlineContentVisibilityButton() &&
+ HasFoldedOutlineContentSelected())
+ {
+ xInfo->set_primary_text(SwResId(STR_INFORODLG_FOLDED_PRIMARY));
+ xInfo->set_secondary_text(SwResId(STR_INFORODLG_FOLDED_SECONDARY));
+ }
+ weld::DialogController::runAsync(xInfo, [](int) {});
+ }
+ else
+ {
+ std::unique_ptr<weld::Builder>
+ xBuilder(Application::CreateBuilder(GetView().GetFrameWeld(),
+ "modules/swriter/ui/inforeadonlydialog.ui"));
+ std::unique_ptr<weld::MessageDialog>
+ xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog"));
+ if (GetViewOptions()->IsShowOutlineContentVisibilityButton() &&
+ HasFoldedOutlineContentSelected())
+ {
+ xInfo->set_primary_text(SwResId(STR_INFORODLG_FOLDED_PRIMARY));
+ xInfo->set_secondary_text(SwResId(STR_INFORODLG_FOLDED_SECONDARY));
+ }
+ xInfo->run();
+ }
+}
+
+bool SwWrtShell::WarnHiddenSectionDialog() const
+{
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(
+ GetView().GetFrameWeld(), "modules/swriter/ui/warnhiddensectiondialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xQuery(
+ xBuilder->weld_message_dialog("WarnHiddenSectionDialog"));
+ if (GetViewOptions()->IsShowOutlineContentVisibilityButton()
+ && HasFoldedOutlineContentSelected())
+ {
+ xQuery->set_primary_text(SwResId(STR_INFORODLG_FOLDED_PRIMARY));
+ xQuery->set_secondary_text(SwResId(STR_INFORODLG_FOLDED_SECONDARY));
+ }
+
+ return (RET_YES == xQuery->run());
+}
+
+bool SwWrtShell::WarnSwitchToDesignModeDialog() const
+{
+ std::unique_ptr<weld::MessageDialog> xQuery(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Question, VclButtonsType::YesNo, SwResId(STR_A11Y_DESIGN_MODE_PRIMARY)));
+ xQuery->set_default_response(RET_YES);
+ xQuery->set_title(SwResId(STR_A11Y_DESIGN_MODE_TITLE));
+ xQuery->set_secondary_text(SwResId(STR_A11Y_DESIGN_MODE_SECONDARY));
+
+ return (RET_YES == xQuery->run());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/wrtsh/wrtsh2.cxx b/sw/source/uibase/wrtsh/wrtsh2.cxx
new file mode 100644
index 0000000000..3a9e51136f
--- /dev/null
+++ b/sw/source/uibase/wrtsh/wrtsh2.cxx
@@ -0,0 +1,686 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/macitem.hxx>
+#include <sfx2/frame.hxx>
+#include <svl/eitem.hxx>
+#include <svl/listener.hxx>
+#include <svl/stritem.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sot/exchange.hxx>
+#include <osl/diagnose.h>
+#include <o3tl/string_view.hxx>
+#include <fmtinfmt.hxx>
+#include <wrtsh.hxx>
+#include <docsh.hxx>
+#include <fldbas.hxx>
+#include <expfld.hxx>
+#include <docufld.hxx>
+#include <reffld.hxx>
+#include <swundo.hxx>
+#include <doc.hxx>
+#include <frmfmt.hxx>
+#include <fmtfld.hxx>
+#include <view.hxx>
+#include <swevent.hxx>
+#include <section.hxx>
+#include <navicont.hxx>
+#include <txtinet.hxx>
+#include <cmdid.h>
+#include <swabstdlg.hxx>
+#include <SwRewriter.hxx>
+#include <authfld.hxx>
+#include <ndtxt.hxx>
+
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+
+#include <memory>
+
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <comphelper/lok.hxx>
+#include <sfx2/event.hxx>
+#include <sal/log.hxx>
+
+bool SwWrtShell::InsertField2(SwField const& rField, SwPaM* pAnnotationRange)
+{
+ ResetCursorStack();
+ if(!CanInsert())
+ return false;
+ StartAllAction();
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, rField.GetDescription());
+
+ StartUndo(SwUndoId::INSERT, &aRewriter);
+
+ bool bDeleted = false;
+ std::optional<SwPaM> pAnnotationTextRange;
+ if (pAnnotationRange)
+ {
+ pAnnotationTextRange.emplace(*pAnnotationRange->Start(), *pAnnotationRange->End());
+ }
+
+ if ( HasSelection() )
+ {
+ if ( rField.GetTyp()->Which() == SwFieldIds::Postit )
+ {
+ // for annotation fields:
+ // - keep the current selection in order to create a corresponding annotation mark
+ // - collapse cursor to its end
+ if ( IsTableMode() )
+ {
+ GetTableCrs()->Normalize( false );
+ const SwPosition rStartPos( *(GetTableCrs()->GetMark()->GetNode().GetContentNode()), 0 );
+ KillPams();
+ if ( !IsEndOfPara() )
+ {
+ EndPara();
+ }
+ const SwPosition rEndPos( *GetCurrentShellCursor().GetPoint() );
+ pAnnotationTextRange.emplace( rStartPos, rEndPos );
+ }
+ else
+ {
+ NormalizePam( false );
+ const SwPaM& rCurrPaM = GetCurrentShellCursor();
+ pAnnotationTextRange.emplace( *rCurrPaM.GetPoint(), *rCurrPaM.GetMark() );
+ ClearMark();
+ }
+ }
+ else
+ {
+ bDeleted = DelRight();
+ }
+ }
+
+ bool const isSuccess = SwEditShell::InsertField(rField, bDeleted);
+
+ if ( pAnnotationTextRange )
+ {
+ if ( GetDoc() != nullptr )
+ {
+ const SwPaM& rCurrPaM = GetCurrentShellCursor();
+ if (*rCurrPaM.Start() == *pAnnotationTextRange->Start()
+ && *rCurrPaM.End() == *pAnnotationTextRange->End())
+ {
+ // Annotation range was passed in externally, and inserting the postit field shifted
+ // its start/end positions right by one. Restore the original position for the range
+ // start. This allows commenting on the placeholder character of the field.
+ if (pAnnotationTextRange->Start()->GetContentIndex() > 0)
+ pAnnotationTextRange->Start()->AdjustContent(-1);
+ }
+ IDocumentMarkAccess* pMarksAccess = GetDoc()->getIDocumentMarkAccess();
+ pMarksAccess->makeAnnotationMark( *pAnnotationTextRange, OUString() );
+ }
+ pAnnotationTextRange.reset();
+ }
+
+ EndUndo();
+ EndAllAction();
+
+ return isSuccess;
+}
+
+// Start the field update
+
+void SwWrtShell::UpdateInputFields( SwInputFieldList* pLst )
+{
+ // Go through the list of fields and updating
+ std::unique_ptr<SwInputFieldList> pTmp;
+ if (!pLst)
+ {
+ pTmp.reset(new SwInputFieldList( this ));
+ pLst = pTmp.get();
+ }
+
+ const size_t nCnt = pLst->Count();
+ if(!nCnt)
+ return;
+
+ pLst->PushCursor();
+
+ bool bCancel = false;
+
+ size_t nIndex = 0;
+ FieldDialogPressedButton ePressedButton = FieldDialogPressedButton::NONE;
+
+ SwField* pField = GetCurField();
+ if (pField)
+ {
+ for (size_t i = 0; i < nCnt; i++)
+ {
+ if (pField == pLst->GetField(i))
+ {
+ nIndex = i;
+ break;
+ }
+ }
+ }
+
+ while (!bCancel)
+ {
+ bool bPrev = nIndex > 0;
+ bool bNext = nIndex < nCnt - 1;
+ pLst->GotoFieldPos(nIndex);
+ pField = pLst->GetField(nIndex);
+ if (pField->GetTyp()->Which() == SwFieldIds::Dropdown)
+ {
+ bCancel = StartDropDownFieldDlg(pField, bPrev, bNext, GetView().GetFrameWeld(), &ePressedButton);
+ }
+ else
+ bCancel = StartInputFieldDlg(pField, bPrev, bNext, GetView().GetFrameWeld(), &ePressedButton);
+
+ if (!bCancel)
+ {
+ // Otherwise update error at multi-selection:
+ pLst->GetField(nIndex)->GetTyp()->UpdateFields();
+
+ if (ePressedButton == FieldDialogPressedButton::Previous && nIndex > 0)
+ nIndex--;
+ else if (ePressedButton == FieldDialogPressedButton::Next && nIndex < nCnt - 1)
+ nIndex++;
+ else
+ bCancel = true;
+ }
+ }
+
+ pLst->PopCursor();
+}
+
+namespace {
+
+// Listener class: will close InputField dialog if input field(s)
+// is(are) deleted (for instance, by an extension) after the dialog shows up.
+// Otherwise, the for loop in SwWrtShell::UpdateInputFields will crash when doing:
+// 'pTmp->GetField( i )->GetTyp()->UpdateFields();'
+// on a deleted field.
+class FieldDeletionListener : public SvtListener
+{
+ public:
+ FieldDeletionListener(AbstractFieldInputDlg* pInputFieldDlg, SwField* pField)
+ : mpInputFieldDlg(pInputFieldDlg)
+ , mpFormatField(nullptr)
+ {
+ SwInputField *const pInputField(dynamic_cast<SwInputField*>(pField));
+ SwSetExpField *const pSetExpField(dynamic_cast<SwSetExpField*>(pField));
+
+ if (pInputField && pInputField->GetFormatField())
+ {
+ mpFormatField = pInputField->GetFormatField();
+ }
+ else if (pSetExpField && pSetExpField->GetFormatField())
+ {
+ mpFormatField = pSetExpField->GetFormatField();
+ }
+
+ // Register for possible field deletion while dialog is open
+ if (mpFormatField)
+ StartListening(mpFormatField->GetNotifier());
+ }
+
+ virtual ~FieldDeletionListener() override
+ {
+ // Dialog closed, remove modification listener
+ EndListeningAll();
+ }
+
+ virtual void Notify(const SfxHint& rHint) override
+ {
+ // Input field has been deleted: better to close the dialog
+ if(rHint.GetId() == SfxHintId::Dying)
+ {
+ mpFormatField = nullptr;
+ mpInputFieldDlg->EndDialog(RET_CANCEL);
+ }
+ }
+ private:
+ VclPtr<AbstractFieldInputDlg> mpInputFieldDlg;
+ SwFormatField* mpFormatField;
+};
+
+}
+
+// Start input dialog for a specific field
+bool SwWrtShell::StartInputFieldDlg(SwField* pField, bool bPrevButton, bool bNextButton,
+ weld::Widget* pParentWin, SwWrtShell::FieldDialogPressedButton* pPressedButton)
+{
+
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractFieldInputDlg> pDlg(pFact->CreateFieldInputDlg(pParentWin, *this, pField, bPrevButton, bNextButton));
+
+ bool bRet;
+
+ {
+ FieldDeletionListener aModify(pDlg.get(), pField);
+ bRet = RET_CANCEL == pDlg->Execute();
+ }
+
+ if (pPressedButton)
+ {
+ if (pDlg->PrevButtonPressed())
+ *pPressedButton = FieldDialogPressedButton::Previous;
+ else if (pDlg->NextButtonPressed())
+ *pPressedButton = FieldDialogPressedButton::Next;
+ }
+
+ pDlg.disposeAndClear();
+ GetWin()->PaintImmediately();
+ return bRet;
+}
+
+bool SwWrtShell::StartDropDownFieldDlg(SwField* pField, bool bPrevButton, bool bNextButton,
+ weld::Widget* pParentWin, SwWrtShell::FieldDialogPressedButton* pPressedButton)
+{
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractDropDownFieldDialog> pDlg(pFact->CreateDropDownFieldDialog(pParentWin, *this, pField, bPrevButton, bNextButton));
+ const short nRet = pDlg->Execute();
+
+ if (pPressedButton)
+ {
+ if (pDlg->PrevButtonPressed())
+ *pPressedButton = FieldDialogPressedButton::Previous;
+ else if (pDlg->NextButtonPressed())
+ *pPressedButton = FieldDialogPressedButton::Next;
+ }
+
+ pDlg.disposeAndClear();
+ bool bRet = RET_CANCEL == nRet;
+ GetWin()->PaintImmediately();
+ if(RET_YES == nRet)
+ {
+ GetView().GetViewFrame().GetDispatcher()->Execute(FN_EDIT_FIELD, SfxCallMode::SYNCHRON);
+ }
+ return bRet;
+}
+
+// Insert directory - remove selection
+
+void SwWrtShell::InsertTableOf(const SwTOXBase& rTOX, const SfxItemSet* pSet)
+{
+ if(!CanInsert())
+ return;
+
+ if(HasSelection())
+ DelRight();
+
+ SwEditShell::InsertTableOf(rTOX, pSet);
+}
+
+// Update directory - remove selection
+
+void SwWrtShell::UpdateTableOf(const SwTOXBase& rTOX, const SfxItemSet* pSet)
+{
+ if(CanInsert())
+ {
+ SwEditShell::UpdateTableOf(rTOX, pSet);
+ }
+}
+
+// handler for click on the field given as parameter.
+// the cursor is positioned on the field.
+
+void SwWrtShell::ClickToField(const SwField& rField, bool bExecHyperlinks)
+{
+ addCurrentPosition();
+
+ // Since the cross reference and bibliography mark move the cursor,
+ // only select the field if it's not a Ctrl+Click
+ if (!bExecHyperlinks
+ || (SwFieldIds::GetRef != rField.GetTyp()->Which()
+ && SwFieldIds::TableOfAuthorities != rField.GetTyp()->Which()))
+ {
+ StartAllAction();
+ Right( SwCursorSkipMode::Chars, true, 1, false ); // Select the field.
+ NormalizePam();
+ EndAllAction();
+ }
+
+ m_bIsInClickToEdit = true;
+ switch( rField.GetTyp()->Which() )
+ {
+ case SwFieldIds::JumpEdit:
+ {
+ sal_uInt16 nSlotId = 0;
+ switch( rField.GetFormat() )
+ {
+ case JE_FMT_TABLE:
+ nSlotId = FN_INSERT_TABLE;
+ break;
+
+ case JE_FMT_FRAME:
+ nSlotId = FN_INSERT_FRAME;
+ break;
+
+ case JE_FMT_GRAPHIC: nSlotId = SID_INSERT_GRAPHIC; break;
+ case JE_FMT_OLE: nSlotId = SID_INSERT_OBJECT; break;
+
+ }
+
+ if( nSlotId )
+ {
+ StartUndo( SwUndoId::START );
+ //#97295# immediately select the right shell
+ GetView().StopShellTimer();
+ GetView().GetViewFrame().GetDispatcher()->Execute( nSlotId,
+ SfxCallMode::SYNCHRON|SfxCallMode::RECORD );
+ EndUndo( SwUndoId::END );
+ }
+ }
+ break;
+
+ case SwFieldIds::Macro:
+ {
+ const SwMacroField *pField = static_cast<const SwMacroField*>(&rField);
+ const OUString sText( rField.GetPar2() );
+ OUString sRet( sText );
+ ExecMacro( pField->GetSvxMacro(), &sRet );
+
+ // return value changed?
+ if( sRet != sText )
+ {
+ StartAllAction();
+ const_cast<SwField&>(rField).SetPar2( sRet );
+ rField.GetTyp()->UpdateFields();
+ EndAllAction();
+ }
+ }
+ break;
+
+ case SwFieldIds::TableOfAuthorities:
+ {
+ if (!bExecHyperlinks)
+ break; // Since it's not a Ctrl+Click, do not jump anywhere
+
+ Point vStartPoint = GetCursor_()->GetPtPos();
+ const SwAuthorityField* pField = static_cast<const SwAuthorityField*>(&rField);
+
+ if (auto targetType = pField->GetTargetType();
+ targetType == SwAuthorityField::TargetType::UseDisplayURL
+ || targetType == SwAuthorityField::TargetType::UseTargetURL)
+ {
+ // Since the user selected target type with URL, try to use it if not empty
+ if (const OUString& rURL = pField->GetAbsoluteURL();
+ rURL.getLength() > 0)
+ ::LoadURL(*this, rURL, LoadUrlFlags::NewView, /*rTargetFrameName=*/OUString());
+ }
+ else if (targetType == SwAuthorityField::TargetType::BibliographyTableRow)
+ {
+ // Since the user selected to target Bibliography Table Row,
+ // try finding matching bibliography table line
+
+ const bool bWasViewLocked = IsViewLocked();
+ LockView(true);
+
+ // Note: This way of iterating doesn't seem to take into account TOXes
+ // that are in a frame, probably in some other cases too
+ GotoPage(1);
+ while (GotoNextTOXBase())
+ {
+ const SwTOXBase* pIteratedTOX = nullptr;
+ const SwTOXBase* pPreviousTOX = nullptr;
+ OUString vFieldText;
+ while ((pIteratedTOX = GetCurTOX()) != nullptr
+ && pIteratedTOX->GetType() == TOX_AUTHORITIES)
+ {
+ if (pIteratedTOX != pPreviousTOX)
+ vFieldText = pField->GetAuthority(GetLayout(), &pIteratedTOX->GetTOXForm());
+
+ if (const SwNode& rCurrentNode = GetCursor()->GetPoint()->GetNode();
+ rCurrentNode.GetNodeType() == SwNodeType::Text
+ && (GetCursor()->GetPoint()->GetNode().FindSectionNode()->GetSection().GetType()
+ == SectionType::ToxContent) // this checks it's not a heading
+ && static_cast<const SwTextNode*>(&rCurrentNode)->GetText() == vFieldText)
+ {
+ // Since a node has been found that is a text node, isn't a heading,
+ // and has text matching to text generated by the field, jump to it
+ LockView(bWasViewLocked);
+ ShowCursor();
+ return;
+ }
+ pPreviousTOX = pIteratedTOX;
+ FwdPara();
+ }
+ }
+ // Since a matching node has not been found, return to original position
+ SetCursor(&vStartPoint);
+ LockView(bWasViewLocked);
+ }
+ }
+ break;
+
+ case SwFieldIds::GetRef:
+ if (!bExecHyperlinks)
+ break;
+
+ StartAllAction();
+ SwCursorShell::GotoRefMark( static_cast<const SwGetRefField&>(rField).GetSetRefName(),
+ static_cast<const SwGetRefField&>(rField).GetSubType(),
+ static_cast<const SwGetRefField&>(rField).GetSeqNo(),
+ static_cast<const SwGetRefField&>(rField).GetFlags() );
+ EndAllAction();
+ break;
+
+ case SwFieldIds::Input:
+ {
+ const SwInputField* pInputField = dynamic_cast<const SwInputField*>(&rField);
+ if ( pInputField == nullptr )
+ {
+ StartInputFieldDlg(const_cast<SwField*>(&rField), false, false, GetView().GetFrameWeld());
+ }
+ }
+ break;
+
+ case SwFieldIds::SetExp:
+ if( static_cast<const SwSetExpField&>(rField).GetInputFlag() )
+ StartInputFieldDlg(const_cast<SwField*>(&rField), false, false, GetView().GetFrameWeld());
+ break;
+ case SwFieldIds::Dropdown :
+ StartDropDownFieldDlg(const_cast<SwField*>(&rField), false, false, GetView().GetFrameWeld());
+ break;
+ default:
+ SAL_WARN_IF(rField.IsClickable(), "sw", "unhandled clickable field!");
+ }
+
+ m_bIsInClickToEdit = false;
+}
+
+void SwWrtShell::ClickToINetAttr( const SwFormatINetFormat& rItem, LoadUrlFlags nFilter )
+{
+ addCurrentPosition();
+
+ if( rItem.GetValue().isEmpty() )
+ return ;
+
+ m_bIsInClickToEdit = true;
+
+ // At first run the possibly set ObjectSelect Macro
+ const SvxMacro* pMac = rItem.GetMacro( SvMacroItemId::OnClick );
+ if( pMac )
+ {
+ SwCallMouseEvent aCallEvent;
+ aCallEvent.Set( &rItem );
+ GetDoc()->CallEvent( SvMacroItemId::OnClick, aCallEvent );
+ }
+
+ // So that the implementation of templates is displayed immediately
+ ::LoadURL( *this, rItem.GetValue(), nFilter, rItem.GetTargetFrame() );
+ const SwTextINetFormat* pTextAttr = rItem.GetTextINetFormat();
+ if( pTextAttr )
+ {
+ const_cast<SwTextINetFormat*>(pTextAttr)->SetVisited( true );
+ const_cast<SwTextINetFormat*>(pTextAttr)->SetVisitedValid( true );
+ }
+
+ m_bIsInClickToEdit = false;
+}
+
+bool SwWrtShell::ClickToINetGrf( const Point& rDocPt, LoadUrlFlags nFilter )
+{
+ bool bRet = false;
+ OUString sURL;
+ OUString sTargetFrameName;
+ const SwFrameFormat* pFnd = IsURLGrfAtPos( rDocPt, &sURL, &sTargetFrameName );
+ if( pFnd && !sURL.isEmpty() )
+ {
+ bRet = true;
+ // At first run the possibly set ObjectSelect Macro
+ SwCallMouseEvent aCallEvent;
+ aCallEvent.Set(EVENT_OBJECT_URLITEM, pFnd);
+ GetDoc()->CallEvent(SvMacroItemId::OnClick, aCallEvent);
+
+ ::LoadURL(*this, sURL, nFilter, sTargetFrameName);
+ }
+ return bRet;
+}
+
+static void LoadURL(SwView& rView, const OUString& rURL, LoadUrlFlags nFilter,
+ const OUString& rTargetFrameName)
+{
+ SwDocShell* pDShell = rView.GetDocShell();
+ OSL_ENSURE( pDShell, "No DocShell?!");
+ SfxViewFrame& rViewFrame = rView.GetViewFrame();
+
+ if (!SfxObjectShell::AllowedLinkProtocolFromDocument(rURL, pDShell, rViewFrame.GetFrameWeld()))
+ return;
+
+ // We are doing tiledRendering, let the client handles the URL loading,
+ // unless we are jumping to a TOC mark.
+ if (comphelper::LibreOfficeKit::isActive() && !rURL.startsWith("#"))
+ {
+ rView.libreOfficeKitViewCallback(LOK_CALLBACK_HYPERLINK_CLICKED, rURL.toUtf8());
+ return;
+ }
+
+ OUString sTargetFrame(rTargetFrameName);
+ if (sTargetFrame.isEmpty() && pDShell)
+ {
+ using namespace ::com::sun::star;
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ pDShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps
+ = xDPS->getDocumentProperties();
+ sTargetFrame = xDocProps->getDefaultTarget();
+ }
+
+ OUString sReferer;
+ if( pDShell && pDShell->GetMedium() )
+ sReferer = pDShell->GetMedium()->GetName();
+ SfxFrameItem aView( SID_DOCFRAME, &rViewFrame );
+ SfxStringItem aName( SID_FILE_NAME, rURL );
+ SfxStringItem aTargetFrameName( SID_TARGETNAME, sTargetFrame );
+ SfxStringItem aReferer( SID_REFERER, sReferer );
+
+ SfxBoolItem aNewView( SID_OPEN_NEW_VIEW, false );
+ //#39076# Silent can be removed accordingly to SFX.
+ SfxBoolItem aBrowse( SID_BROWSE, true );
+
+ if ((nFilter & LoadUrlFlags::NewView) && !comphelper::LibreOfficeKit::isActive())
+ aTargetFrameName.SetValue( "_blank" );
+
+ rViewFrame.GetDispatcher()->ExecuteList(SID_OPENDOC,
+ SfxCallMode::ASYNCHRON|SfxCallMode::RECORD,
+ {
+ &aName,
+ &aNewView, /*&aSilent,*/
+ &aReferer,
+ &aView, &aTargetFrameName,
+ &aBrowse
+ });
+}
+
+void LoadURL( SwViewShell& rVSh, const OUString& rURL, LoadUrlFlags nFilter,
+ const OUString& rTargetFrameName )
+{
+ OSL_ENSURE( !rURL.isEmpty(), "what should be loaded here?" );
+ if( rURL.isEmpty() )
+ return ;
+
+ // The shell could be 0 also!!!!!
+ if (auto pSh = dynamic_cast<SwWrtShell*>(&rVSh))
+ ::LoadURL(pSh->GetView(), rURL, nFilter, rTargetFrameName);
+}
+
+void SwWrtShell::NavigatorPaste( const NaviContentBookmark& rBkmk,
+ const sal_uInt16 nAction )
+{
+ if( EXCHG_IN_ACTION_COPY == nAction )
+ {
+ // Insert
+ OUString sURL = rBkmk.GetURL();
+ // Is this is a jump within the current Doc?
+ const SwDocShell* pDocShell = GetView().GetDocShell();
+ if(pDocShell->HasName())
+ {
+ const OUString rName = pDocShell->GetMedium()->GetURLObject().GetURLNoMark();
+
+ if (sURL.startsWith(rName))
+ {
+ if (sURL.getLength()>rName.getLength())
+ {
+ sURL = sURL.copy(rName.getLength());
+ }
+ else
+ {
+ sURL.clear();
+ }
+ }
+ }
+ SwFormatINetFormat aFormat( sURL, OUString() );
+ InsertURL( aFormat, rBkmk.GetDescription() );
+ }
+ else
+ {
+ SwSectionData aSection( SectionType::FileLink, GetUniqueSectionName() );
+ OUString aLinkFile = o3tl::getToken(rBkmk.GetURL(), 0, '#')
+ + OUStringChar(sfx2::cTokenSeparator)
+ + OUStringChar(sfx2::cTokenSeparator)
+ + o3tl::getToken(rBkmk.GetURL(), 1, '#');
+ aSection.SetLinkFileName( aLinkFile );
+ aSection.SetProtectFlag( true );
+ const SwSection* pIns = InsertSection( aSection );
+ if( EXCHG_IN_ACTION_MOVE == nAction && pIns )
+ {
+ aSection = SwSectionData(*pIns);
+ aSection.SetLinkFileName( OUString() );
+ aSection.SetType( SectionType::Content );
+ aSection.SetProtectFlag( false );
+
+ // the update of content from linked section at time delete
+ // the undostack. Then the change of the section don't create
+ // any undoobject. - BUG 69145
+ bool bDoesUndo = DoesUndo();
+ SwUndoId nLastUndoId(SwUndoId::EMPTY);
+ if (GetLastUndoInfo(nullptr, & nLastUndoId))
+ {
+ if (SwUndoId::INSSECTION != nLastUndoId)
+ {
+ DoUndo(false);
+ }
+ }
+ UpdateSection( GetSectionFormatPos( *pIns->GetFormat() ), aSection );
+ DoUndo( bDoesUndo );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/wrtsh/wrtsh3.cxx b/sw/source/uibase/wrtsh/wrtsh3.cxx
new file mode 100644
index 0000000000..0907794d7c
--- /dev/null
+++ b/sw/source/uibase/wrtsh/wrtsh3.cxx
@@ -0,0 +1,392 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svxids.hrc>
+#include <sfx2/app.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svx/svdmark.hxx>
+#include <svx/svdview.hxx>
+#include <svx/svdouno.hxx>
+#include <svx/srchdlg.hxx>
+#include <com/sun/star/form/FormButtonType.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <osl/diagnose.h>
+#include <sfx2/dispatch.hxx>
+#include <comphelper/lok.hxx>
+#include <tools/json_writer.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+#include <swmodule.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <IMark.hxx>
+#include <doc.hxx>
+#include <formatcontentcontrol.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <SwRewriter.hxx>
+#include <strings.hrc>
+#include <textcontentcontrol.hxx>
+
+using namespace ::com::sun::star;
+
+bool SwWrtShell::MoveBookMark( BookMarkMove eFuncId, const ::sw::mark::IMark* const pMark)
+{
+ addCurrentPosition();
+ (this->*m_fnKillSel)( nullptr, false );
+
+ bool bRet = true;
+ switch(eFuncId)
+ {
+ case BOOKMARK_INDEX:bRet = SwCursorShell::GotoMark( pMark );break;
+ case BOOKMARK_NEXT: bRet = SwCursorShell::GoNextBookmark();break;
+ case BOOKMARK_PREV: bRet = SwCursorShell::GoPrevBookmark();break;
+ default:;//prevent warning
+ }
+
+ if( bRet && IsSelFrameMode() )
+ {
+ UnSelectFrame();
+ LeaveSelFrameMode();
+ }
+ if( IsSelection() )
+ {
+ m_fnKillSel = &SwWrtShell::ResetSelect;
+ m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
+ }
+ return bRet;
+}
+
+bool SwWrtShell::GotoField( const SwFormatField& rField )
+{
+ (this->*m_fnKillSel)( nullptr, false );
+
+ bool bRet = SwCursorShell::GotoFormatField( rField );
+ if( bRet && IsSelFrameMode() )
+ {
+ UnSelectFrame();
+ LeaveSelFrameMode();
+ }
+
+ if( IsSelection() )
+ {
+ m_fnKillSel = &SwWrtShell::ResetSelect;
+ m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
+ }
+
+ return bRet;
+}
+
+bool SwWrtShell::GotoContentControl(const SwFormatContentControl& rContentControl,
+ bool bOnlyRefresh)
+{
+ std::shared_ptr<SwContentControl> pContentControl = rContentControl.GetContentControl();
+ if (IsFrameSelected() && pContentControl && pContentControl->GetPicture())
+ {
+ // A frame is already selected, and its anchor is inside a picture content control.
+ if (pContentControl->GetShowingPlaceHolder())
+ {
+ // Replace the placeholder image with a real one.
+ GetView().StopShellTimer();
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ tools::JsonWriter aJson;
+ aJson.put("action", "change-picture");
+ OString pJson(aJson.finishAndGetAsOString());
+ GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CONTENT_CONTROL,
+ pJson);
+ }
+ else
+ {
+ GetView().GetViewFrame().GetDispatcher()->Execute(SID_CHANGE_PICTURE,
+ SfxCallMode::SYNCHRON);
+ }
+ pContentControl->SetShowingPlaceHolder(false);
+ }
+ return true;
+ }
+
+ (this->*m_fnKillSel)(nullptr, false);
+
+ bool bRet = SwCursorShell::GotoFormatContentControl(rContentControl);
+
+ if (bRet && pContentControl && pContentControl->GetCheckbox())
+ {
+ // Checkbox: GotoFormatContentControl() selected the old state.
+ LockView(/*bViewLocked=*/true);
+ OUString aOldState = GetCursorDescr();
+ OUString aNewState;
+ if (pContentControl->GetChecked())
+ aNewState = bOnlyRefresh ? pContentControl->GetCheckedState()
+ : pContentControl->GetUncheckedState();
+ else
+ aNewState = bOnlyRefresh ? pContentControl->GetUncheckedState()
+ : pContentControl->GetCheckedState();
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, aOldState);
+ aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
+ aRewriter.AddRule(UndoArg3, aNewState);
+ GetIDocumentUndoRedo().StartUndo(SwUndoId::REPLACE, &aRewriter);
+
+ // Toggle the state.
+ pContentControl->SetReadWrite(true);
+ DelLeft();
+ if (!bOnlyRefresh)
+ pContentControl->SetChecked(!pContentControl->GetChecked());
+ Insert(aNewState);
+ pContentControl->SetReadWrite(false);
+
+ GetIDocumentUndoRedo().EndUndo(SwUndoId::REPLACE, &aRewriter);
+ LockView(/*bViewLocked=*/false);
+ ShowCursor();
+ }
+ else if (bRet && pContentControl && pContentControl->GetSelectedListItem())
+ {
+ // Dropdown: GotoFormatContentControl() selected the old content.
+ size_t nSelectedListItem = *pContentControl->GetSelectedListItem();
+ LockView(/*bViewLocked=*/true);
+ OUString aOldState = GetCursorDescr();
+ OUString aNewState = pContentControl->GetListItems()[nSelectedListItem].ToString();
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, aOldState);
+ aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
+ aRewriter.AddRule(UndoArg3, SwResId(STR_START_QUOTE) + aNewState + SwResId(STR_END_QUOTE));
+ GetIDocumentUndoRedo().StartUndo(SwUndoId::REPLACE, &aRewriter);
+
+ // Update the content.
+ pContentControl->SetReadWrite(true);
+ DelLeft();
+ pContentControl->SetSelectedListItem(std::nullopt);
+ Insert(aNewState);
+ pContentControl->SetReadWrite(false);
+
+ GetIDocumentUndoRedo().EndUndo(SwUndoId::REPLACE, &aRewriter);
+ LockView(/*bViewLocked=*/false);
+ ShowCursor();
+ }
+ else if (bRet && pContentControl && pContentControl->GetSelectedDate())
+ {
+ // Date: GotoFormatContentControl() selected the old content.
+ LockView(/*bViewLocked=*/true);
+ OUString aOldState = GetCursorDescr();
+ OUString aNewState = pContentControl->GetDateString();
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, aOldState);
+ aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
+ aRewriter.AddRule(UndoArg3, SwResId(STR_START_QUOTE) + aNewState + SwResId(STR_END_QUOTE));
+ GetIDocumentUndoRedo().StartUndo(SwUndoId::REPLACE, &aRewriter);
+
+ // Write the doc model.
+ pContentControl->SetCurrentDateValue(*pContentControl->GetSelectedDate());
+ pContentControl->SetSelectedDate(std::nullopt);
+
+ // Update the content.
+ DelLeft();
+ Insert(aNewState);
+
+ GetIDocumentUndoRedo().EndUndo(SwUndoId::REPLACE, &aRewriter);
+ LockView(/*bViewLocked=*/false);
+ ShowCursor();
+ }
+
+ if (bRet && IsSelFrameMode())
+ {
+ UnSelectFrame();
+ LeaveSelFrameMode();
+ }
+
+ if (IsSelection())
+ {
+ m_fnKillSel = &SwWrtShell::ResetSelect;
+ m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
+ }
+
+ return bRet;
+}
+
+bool SwWrtShell::GotoFieldmark(::sw::mark::IFieldmark const * const pMark)
+{
+ (this->*m_fnKillSel)( nullptr, false );
+ bool bRet = SwCursorShell::GotoFieldmark(pMark);
+ if( bRet && IsSelFrameMode() )
+ {
+ UnSelectFrame();
+ LeaveSelFrameMode();
+ }
+ if( IsSelection() )
+ {
+ m_fnKillSel = &SwWrtShell::ResetSelect;
+ m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
+ }
+ return bRet;
+}
+
+// Invalidate FontWork-Slots
+
+void SwWrtShell::DrawSelChanged( )
+{
+ static sal_uInt16 const aInval[] =
+ {
+ SID_ATTR_FILL_STYLE, SID_ATTR_FILL_COLOR, SID_ATTR_LINE_STYLE,
+ SID_ATTR_LINE_WIDTH, SID_ATTR_LINE_COLOR,
+ /*AF: these may be needed for the sidebar.
+ SID_SVX_AREA_TRANSPARENCY, SID_SVX_AREA_TRANSP_GRADIENT,
+ SID_SVX_AREA_TRANS_TYPE,
+ */
+ 0
+ };
+
+ GetView().GetViewFrame().GetBindings().Invalidate(aInval);
+
+ bool bOldVal = g_bNoInterrupt;
+ g_bNoInterrupt = true; // Trick to run AttrChangedNotify by timer.
+ GetView().AttrChangedNotify(nullptr);
+ g_bNoInterrupt = bOldVal;
+}
+
+void SwWrtShell::GotoMark( const OUString& rName )
+{
+ IDocumentMarkAccess::const_iterator_t ppMark = getIDocumentMarkAccess()->findMark( rName );
+ if (ppMark == getIDocumentMarkAccess()->getAllMarksEnd())
+ return;
+ MoveBookMark( BOOKMARK_INDEX, *ppMark );
+}
+
+void SwWrtShell::GotoMark( const ::sw::mark::IMark* const pMark )
+{
+ MoveBookMark( BOOKMARK_INDEX, pMark );
+}
+
+bool SwWrtShell::GoNextBookmark()
+{
+ if ( !getIDocumentMarkAccess()->getBookmarksCount() )
+ {
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
+ return false;
+ }
+ LockView( true );
+ bool bRet = MoveBookMark( BOOKMARK_NEXT );
+ if ( !bRet )
+ {
+ MoveBookMark( BOOKMARK_INDEX, *getIDocumentMarkAccess()->getBookmarksBegin() );
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::EndWrapped );
+ }
+ else
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
+ LockView( false );
+ ShowCursor();
+ return true;
+}
+
+bool SwWrtShell::GoPrevBookmark()
+{
+ if ( !getIDocumentMarkAccess()->getBookmarksCount() )
+ {
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
+ return false;
+ }
+ LockView( true );
+ bool bRet = MoveBookMark( BOOKMARK_PREV );
+ if ( !bRet )
+ {
+ MoveBookMark( BOOKMARK_INDEX, *( getIDocumentMarkAccess()->getBookmarksEnd() - 1 ) );
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::StartWrapped );
+ }
+ else
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
+ LockView( false );
+ ShowCursor();
+ return true;
+}
+
+void SwWrtShell::ExecMacro( const SvxMacro& rMacro, OUString* pRet, SbxArray* pArgs )
+{
+ // execute macro, if it is allowed.
+ if ( IsMacroExecAllowed() )
+ {
+ GetDoc()->ExecMacro( rMacro, pRet, pArgs );
+ }
+}
+
+sal_uInt16 SwWrtShell::CallEvent( SvMacroItemId nEvent, const SwCallMouseEvent& rCallEvent,
+ bool bChkPtr)
+{
+ return GetDoc()->CallEvent( nEvent, rCallEvent, bChkPtr );
+}
+
+ // If a util::URL-Button is selected, return its util::URL
+ // otherwise an empty string.
+bool SwWrtShell::GetURLFromButton( OUString& rURL, OUString& rDescr ) const
+{
+ bool bRet = false;
+ const SdrView *pDView = GetDrawView();
+ if( pDView )
+ {
+ // A fly is precisely achievable if it is selected.
+ const SdrMarkList &rMarkList = pDView->GetMarkedObjectList();
+
+ if (rMarkList.GetMark(0))
+ {
+ SdrUnoObj* pUnoCtrl = dynamic_cast<SdrUnoObj*>( rMarkList.GetMark(0)->GetMarkedSdrObj() );
+ if (pUnoCtrl && SdrInventor::FmForm == pUnoCtrl->GetObjInventor())
+ {
+ const uno::Reference< awt::XControlModel >& xControlModel = pUnoCtrl->GetUnoControlModel();
+
+ OSL_ENSURE( xControlModel.is(), "UNO-Control without Model" );
+ if( !xControlModel.is() )
+ return bRet;
+
+ uno::Reference< beans::XPropertySet > xPropSet(xControlModel, uno::UNO_QUERY);
+
+ uno::Any aTmp;
+
+ uno::Reference< beans::XPropertySetInfo > xInfo = xPropSet->getPropertySetInfo();
+ if(xInfo->hasPropertyByName( "ButtonType" ))
+ {
+ aTmp = xPropSet->getPropertyValue( "ButtonType" );
+ form::FormButtonType eTmpButtonType;
+ aTmp >>= eTmpButtonType;
+ if( form::FormButtonType_URL == eTmpButtonType)
+ {
+ // Label
+ aTmp = xPropSet->getPropertyValue( "Label" );
+ OUString uTmp;
+ if( (aTmp >>= uTmp) && !uTmp.isEmpty())
+ {
+ rDescr = uTmp;
+ }
+
+ // util::URL
+ aTmp = xPropSet->getPropertyValue( "TargetURL" );
+ if( (aTmp >>= uTmp) && !uTmp.isEmpty())
+ {
+ rURL = uTmp;
+ }
+ bRet = true;
+ }
+ }
+ }
+ }
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/wrtsh/wrtsh4.cxx b/sw/source/uibase/wrtsh/wrtsh4.cxx
new file mode 100644
index 0000000000..0442e3152b
--- /dev/null
+++ b/sw/source/uibase/wrtsh/wrtsh4.cxx
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <wrtsh.hxx>
+
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+// Private methods, which move the cursor over search.
+// The removal of the selection must be made on the level above.
+
+// The beginning of a word is the follow of a
+// non-delimiter to delimiter. Furthermore, the follow of
+// non-sentence separators on sentence separator.
+// The begin of paragraph is also the word beginning.
+
+void SwWrtShell::SttWrd()
+{
+ if ( IsSttPara() )
+ return;
+ // Create temporary cursor without selection.
+ Push();
+ ClearMark();
+ if( !GoStartWord() )
+ // not found --> go to the beginning of the paragraph.
+ SwCursorShell::MovePara( GoCurrPara, fnParaStart );
+ ClearMark();
+ // If Mark was previously set, summarize.
+ Combine();
+}
+
+// The end of a word is the follow of separator to nonseparator.
+// The end of a word is also the sequence of word separators to
+// punctuation marks.
+// The end of a paragraph is also the end of a word.
+
+void SwWrtShell::EndWrd()
+{
+ if ( IsEndWrd() )
+ return;
+ // Create temporary cursor without selection.
+ Push();
+ ClearMark();
+ if( !GoEndWord() )
+ // not found --> go to the end of the paragraph.
+ SwCursorShell::MovePara(GoCurrPara, fnParaEnd);
+ ClearMark();
+ // If Mark was previously set, summarize.
+ Combine();
+}
+
+bool SwWrtShell::NxtWrd_()
+{
+ bool bRet = false;
+ while( IsEndPara() ) // If already at the end, then the next???
+ {
+ if(!SwCursorShell::Right(1,SwCursorSkipMode::Chars)) // Document - end ??
+ {
+ Pop(SwCursorShell::PopMode::DeleteCurrent);
+ return bRet;
+ }
+ bRet = IsStartWord();
+ }
+ Push();
+ ClearMark();
+ while( !bRet )
+ {
+ if( !GoNextWord() )
+ {
+ if( (!IsEndPara() && !SwCursorShell::MovePara( GoCurrPara, fnParaEnd ) )
+ || !SwCursorShell::Right(1,SwCursorSkipMode::Chars) )
+ break;
+ bRet = IsStartWord();
+ }
+ else
+ bRet = true;
+ }
+ ClearMark();
+ Combine();
+ return bRet;
+}
+
+bool SwWrtShell::PrvWrd_()
+{
+ bool bRet = false;
+ while( IsSttPara() )
+ { // if already at the beginning, then the next???
+ if(!SwCursorShell::Left(1,SwCursorSkipMode::Chars))
+ { // Document - beginning ??
+ Pop(SwCursorShell::PopMode::DeleteCurrent);
+ return bRet;
+ }
+ bRet = IsStartWord() || IsEndPara();
+ }
+ Push();
+ ClearMark();
+ while( !bRet )
+ {
+ if( !GoPrevWord() )
+ {
+ if( (!IsSttPara() && !SwCursorShell::MovePara( GoCurrPara, fnParaStart ) )
+ || !SwCursorShell::Left(1,SwCursorSkipMode::Chars) )
+ break;
+ bRet = IsStartWord();
+ }
+ else
+ bRet = true;
+ }
+ ClearMark();
+ Combine();
+ return bRet;
+}
+
+// #i92468#
+// method code of <SwWrtShell::NxtWrd_()> before fix for issue i72162
+bool SwWrtShell::NxtWrdForDelete()
+{
+ if ( IsEndPara() )
+ {
+ if ( !SwCursorShell::Right(1,SwCursorSkipMode::Chars) )
+ {
+ Pop(SwCursorShell::PopMode::DeleteCurrent);
+ return false;
+ }
+ return true;
+ }
+ Push();
+ ClearMark();
+ if ( !GoNextWord() )
+ {
+ SwCursorShell::MovePara( GoCurrPara, fnParaEnd );
+ }
+ ClearMark();
+ Combine();
+ return true;
+}
+
+// method code of <SwWrtShell::PrvWrd_()> before fix for issue i72162
+bool SwWrtShell::PrvWrdForDelete()
+{
+ if ( IsSttPara() )
+ {
+ if ( !SwCursorShell::Left(1,SwCursorSkipMode::Chars) )
+ {
+ Pop(SwCursorShell::PopMode::DeleteCurrent);
+ return false;
+ }
+ return true;
+ }
+ Push();
+ ClearMark();
+ if( !GoPrevWord() )
+ {
+ SwCursorShell::MovePara( GoCurrPara, fnParaStart );
+ }
+ ClearMark();
+ Combine();
+ return true;
+}
+
+bool SwWrtShell::FwdSentence_()
+{
+ Push();
+ ClearMark();
+ if(!SwCursorShell::Right(1,SwCursorSkipMode::Chars))
+ {
+ Pop(SwCursorShell::PopMode::DeleteCurrent);
+ return false;
+ }
+ if( !GoNextSentence() && !IsEndPara() )
+ SwCursorShell::MovePara(GoCurrPara, fnParaEnd);
+
+ ClearMark();
+ Combine();
+ return true;
+}
+
+bool SwWrtShell::BwdSentence_()
+{
+ Push();
+ ClearMark();
+ if(!SwCursorShell::Left(1,SwCursorSkipMode::Chars))
+ {
+ Pop(SwCursorShell::PopMode::DeleteCurrent);
+ return false;
+ }
+ if( !GoStartSentence() && !IsSttPara() )
+ // not found --> go to the beginning of the paragraph
+ SwCursorShell::MovePara( GoCurrPara, fnParaStart );
+ ClearMark();
+ Combine();
+ return true;
+}
+
+bool SwWrtShell::FwdPara_()
+{
+ Push();
+ ClearMark();
+ bool bRet = SwCursorShell::MovePara(GoNextPara, fnParaStart);
+
+ ClearMark();
+ Combine();
+ return bRet;
+}
+
+bool SwWrtShell::BwdPara_()
+{
+ Push();
+ ClearMark();
+
+ bool bRet = SwCursorShell::MovePara(GoPrevPara, fnParaStart);
+ if ( !bRet && !IsSttOfPara() )
+ {
+ SttPara();
+ }
+
+ ClearMark();
+ Combine();
+ return bRet;
+}
+
+std::optional<OString> SwWrtShell::getLOKPayload(int nType, int nViewId) const
+{
+ switch(nType)
+ {
+ case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR:
+ case LOK_CALLBACK_INVALIDATE_VIEW_CURSOR:
+ return GetVisibleCursor()->getLOKPayload(nType, nViewId);
+ case LOK_CALLBACK_TEXT_SELECTION:
+ case LOK_CALLBACK_TEXT_SELECTION_START:
+ case LOK_CALLBACK_TEXT_SELECTION_END:
+ case LOK_CALLBACK_TEXT_VIEW_SELECTION:
+ return GetCursor_()->getLOKPayload(nType, nViewId);
+ }
+ abort();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/wrtsh/wrtundo.cxx b/sw/source/uibase/wrtsh/wrtundo.cxx
new file mode 100644
index 0000000000..770c59367a
--- /dev/null
+++ b/sw/source/uibase/wrtsh/wrtundo.cxx
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/slstitm.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <wrtsh.hxx>
+#include <swundo.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <swdtflvr.hxx>
+#include <svtools/svtresid.hxx>
+#include <svtools/strings.hrc>
+#include <osl/diagnose.h>
+
+// Undo ends all modes. If a selection is emerged by the Undo,
+// this must be considered for further action.
+
+void SwWrtShell::Do(DoType eDoType, sal_uInt16 nCnt, sal_uInt16 nOffset)
+{
+ // #105332# save current state of DoesUndo()
+ bool bSaveDoesUndo = DoesUndo();
+
+ StartAllAction();
+ switch (eDoType)
+ {
+ case UNDO:
+ DoUndo(false); // #i21739#
+ // Reset modes
+ EnterStdMode();
+ SwEditShell::Undo(nCnt, nOffset);
+ break;
+ case REDO:
+ DoUndo(false); // #i21739#
+ // Reset modes
+ EnterStdMode();
+ SwEditShell::Redo( nCnt );
+ break;
+ case REPEAT:
+ // #i21739# do not touch undo flag here !!!
+ SwEditShell::Repeat( nCnt );
+ break;
+ }
+ EndAllAction();
+ // #105332# restore undo state
+ DoUndo(bSaveDoesUndo);
+
+ bool bCreateXSelection = false;
+ const bool bFrameSelected = IsFrameSelected() || IsObjSelected();
+ if ( IsSelection() )
+ {
+ if ( bFrameSelected )
+ UnSelectFrame();
+
+ // Set the function pointer for canceling the selection at the
+ // cursor position.
+ m_fnKillSel = &SwWrtShell::ResetSelect;
+ m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
+ bCreateXSelection = true;
+ }
+ else if ( bFrameSelected )
+ {
+ EnterSelFrameMode();
+ bCreateXSelection = true;
+ }
+ else if( (CNT_GRF | CNT_OLE ) & GetCntType() )
+ {
+ SelectObj( GetCharRect().Pos() );
+ EnterSelFrameMode();
+ bCreateXSelection = true;
+ }
+
+ if( bCreateXSelection )
+ SwTransferable::CreateSelection( *this );
+
+ // Bug 32918: After deleting of the numbering the object panel remains.
+ // Why is not here always a CallChgLink called?
+ CallChgLnk();
+}
+
+OUString SwWrtShell::GetDoString( DoType eDoType ) const
+{
+ OUString aUndoStr;
+ TranslateId pResStr = STR_UNDO;
+ switch( eDoType )
+ {
+ case UNDO:
+ pResStr = STR_UNDO;
+ (void)GetLastUndoInfo(&aUndoStr, nullptr, &m_rView);
+ break;
+ case REDO:
+ pResStr = STR_REDO;
+ (void)GetFirstRedoInfo(&aUndoStr, nullptr, &m_rView);
+ break;
+ default:;//prevent warning
+ }
+
+ return SvtResId(pResStr) + aUndoStr;
+}
+
+void SwWrtShell::GetDoStrings( DoType eDoType, SfxStringListItem& rStrs ) const
+{
+ SwUndoComments_t comments;
+ switch( eDoType )
+ {
+ case UNDO:
+ comments = GetIDocumentUndoRedo().GetUndoComments();
+ break;
+ case REDO:
+ comments = GetIDocumentUndoRedo().GetRedoComments();
+ break;
+ default:;//prevent warning
+ }
+
+ OUStringBuffer buf;
+ for (const OUString & comment : comments)
+ {
+ OSL_ENSURE(!comment.isEmpty(), "no Undo/Redo Text set");
+ buf.append(comment + "\n");
+ }
+ rStrs.SetString(buf.makeStringAndClear());
+}
+
+OUString SwWrtShell::GetRepeatString() const
+{
+ OUString str;
+ GetRepeatInfo(& str);
+
+ if (str.isEmpty())
+ {
+ return str;
+ }
+
+ return SvtResId(STR_REPEAT) + str;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */